20

I'm using

$ cargo --version
cargo 0.21.0-beta (7e00b82d9 2017-07-17)

I created a simple project with cargo new --bin test1, and then I added a dependency:

[dependencies]
lazy_static = "0.2.2"

to Cargo.toml (according to this such version exists) and

#[macro_use]
extern crate lazy_static;

to src/main.rs

When I run cargo build:

$ cargo build
   Compiling lazy_static v0.2.8
   Compiling test1 v0.1.0 (file:///tmp/test1)
warning: unused `#[macro_use]` import
 --> src/main.rs:1:1
  |
1 | #[macro_use]
  | ^^^^^^^^^^^^
  |
  = note: #[warn(unused_imports)] on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.49 secs

Why does cargo build compile last version 0.2.8 instead of 0.2.2 that I specified? What am I doing wrong?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
user1244932
  • 7,352
  • 5
  • 46
  • 103

2 Answers2

39

TL;DR:

my-crate = "=1.2.3"

Reading the documentation is generally a great idea. In this case, the Cargo documentation has an entire section on specifying dependencies:

Since this string does not have any operators in it, it is interpreted the same way as if we had specified "^0.1.12", which is called a caret requirement.

Caret requirements allow SemVer compatible updates to a specified version. An update is allowed if the new version number does not modify the left-most non-zero digit in the major, minor, patch grouping.

As well as

Inequality requirements allow manually specifying a version range or an exact version to depend on.

Here are some examples of inequality requirements:

= 1.2.3

What am I doing wrong?

I'd say that, without extenuating circumstances, trying to specify an exact version is wrong. There's generally very little reason to force the users of your code to be stuck to an older version of a crate and prevent them from getting bug fixes.

Cargo.lock is the correct tool to avoid deploying your application with an inconsistent set of dependencies.

Community
  • 1
  • 1
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 5
    There's an excellent, and depressingly common, reason: because someone in the dependency graph broke compatibility. But in that case, I generally specify a *maximum* version instead; there might be some other reason that specific dependency is being limited by some other package. – DK. Jul 20 '17 at 22:20
  • Agreed with DK, and the answer to exact pin or not depends on context. Binaries should exactly pin (can do via Cargo.lock), and libraries should be as flexible as possible so that binaries that pull in libraries that require the same sub dependencies can make a full picture decision. – SwimBikeRun Dec 25 '22 at 15:43
15

Exact versions are prepended by =. It's one of the comparison requirements (formerly called inequality requirement).

lazy_static = "= 0.2.2"

The default is the caret requirement (e.g. 0.2.2 is equivalent to ^0.2.2 ), which accepts minor and patch version updates (or just patch updates if the major is 0). Unless you have a very good reason to disallow this, it is often recommended to leave the default specifier as it is.

E_net4
  • 27,810
  • 13
  • 101
  • 139