Skip to content
Closed
185 changes: 131 additions & 54 deletions src/doc/src/reference/specifying-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,88 +2,113 @@

Your crates can depend on other libraries from [crates.io] or other
registries, `git` repositories, or subdirectories on your local file system.
You can also temporarily override the location of a dependency — for example,
to be able to test out a bug fix in the dependency that you are working on
locally. You can have different dependencies for different platforms, and
dependencies that are only used during development. Let's take a look at how
to do each of these.

It's possible to temporarily change the version or path of a dependency, this
can be useful for checking the new features or bug fixes after some major
release.

Dependencies can be specified for [crate features](features.md) and for
different [architectures and operating systems](#platform-specific-dependencies).

### Specifying dependencies from crates.io

Cargo is configured to look for dependencies on [crates.io] by default. Only
the name and a version string are required in this case. In [the cargo
guide](../guide/index.md), we specified a dependency on the `time` crate:
Here is an example of the most common method for specifying dependencies:

```toml
[dependencies]
time = "0.1.12"
```

Cargo looks for dependencies on [crates.io] by default. For this case, it only
requires the name and a version string.

The string `"0.1.12"` is a version requirement. Although it looks like a
specific *version* of the `time` crate, it actually specifies a *range* of
versions and allows [SemVer] compatible updates. An update is allowed if the new
version number does not modify the left-most non-zero digit in the major, minor,
patch grouping. In this case, if we ran `cargo update -p time`, cargo should
update us to version `0.1.13` if it is the latest `0.1.z` release, but would not
update us to `0.2.0`. If instead we had specified the version string as `1.0`,
cargo should update to `1.1` if it is the latest `1.y` release, but not `2.0`.
The version `0.0.x` is not considered compatible with any other version.
versions and allows [SemVer] compatible updates.

[SemVer]: https://semver.org
Since it does not contain any extra operators, it is interpreted as the caret
requirement `"^0.1.12"`, `cargo` will download a version of the crate `time`
that is compatible with `"0.1.12"` following the
[Caret requirement](#caret-requirements) rules.

Here are some more examples of version requirements and the versions that would
be allowed with them:
In this case, if we ran `cargo update -p time`, cargo could update the crate to
version `0.1.13` if it is the latest `0.1.z` release, but would not update us
to `0.2.0`.

```notrust
1.2.3 := >=1.2.3, <2.0.0
1.2 := >=1.2.0, <2.0.0
1 := >=1.0.0, <2.0.0
0.2.3 := >=0.2.3, <0.3.0
0.2 := >=0.2.0, <0.3.0
0.0.3 := >=0.0.3, <0.0.4
0.0 := >=0.0.0, <0.1.0
0 := >=0.0.0, <1.0.0
```
There are five types of version requirements:

This compatibility convention is different from SemVer in the way it treats
versions before 1.0.0. While SemVer says there is no compatibility before
1.0.0, Cargo considers `0.x.y` to be compatible with `0.x.z`, where `y ≥ z`
and `x > 0`.
| Type | Operators | Examples |
|----------------------------------------|-------------------|----------------------------------------|
| [Caret](#caret-requirements) | None or `^` | `"1.2.3"` and `"^1.2.3"` |
| [Tilde](#tilde-requirements) | `~` | `"~1.2.3"` |
| [Wildcard](#wildcard-requirements) | `*` | `"1.2.*"` |
| [Comparison](#comparison-requirements) | `>`, `<` and `>=` | `">1.2.3"`, `"<1.2.3"` and `">=1.2.3"` |
| [Strict](#strict-requirements) | `=` | `"= 1.2.3"` |

It is possible to further tweak the logic for selecting compatible versions
using special operators, though it shouldn't be necessary most of the time.
[SemVer]: https://doc.rust-lang.org/cargo/reference/resolver.html#semver-compatibility

### Caret requirements

**Caret requirements** are an alternative syntax for the default strategy,
`^1.2.3` is exactly equivalent to `1.2.3`.
**Caret requirements** allow SemVer compatible updates.

Updates are only allowed if the new version number does not modify the left-most
non-zero digit.

This compatibility convention is different from [SemVer] in the way it treats
versions before `"1.0.0"`. While SemVer says there is no compatibility before
1.0.0, Cargo considers `"0.x.y"` to be compatible with `"0.x.z"`, where `y ≥ z`
and `x` is not zero.

#### Examples:

If we specify the version string as `"1.4.8"`, compatible versions are:
- `"1.4.x"` with `x ≥ 8`.
- `"1.x.y"` with `x > 4`, `y` can be anything.

This table shows all possible ways to specify a caret requirements, and the
ranges that are considered compatible for each:

```notrust
^1 := >=1.0.0, <2.0.0
^1.2 := >=1.2.0, <2.0.0
^1.2.3 := >=1.2.3, <2.0.0
^0 := >=0.0.0, <1.0.0
^0.0 := >=0.0.0, <0.1.0
^0.0.3 := >=0.0.3, <0.0.4 (exact)
^0.2 := >=0.2.0, <0.3.0
^0.2.3 := >=0.2.3, <0.3.0
Comment on lines +72 to +79
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC #10158 tried not to mention much about the ^ syntax on requirement to reduce confusion. Do we want to follow the rule here and throughout this PR?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could I proceed here?

  1. Rename caret requirement to SemVer requirement.
  2. Inside of the caret requirements section, remove all carets, and add a note explaining that "1.4.8" == "^1.4.8".
  3. Try to move all caret requirements out of it's own section, and put it on the start of the file.

I tried approaching 3 like #10158 but I found it to be weird with the new table with all the operators.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... maybe keep calling it caret but only mention it as a alternative syntax at the end of the "Caret requirements" section? Such like

Note that Cargo favors specifying caret requirements without a real caret ^. You can still use the alternative syntax. For example, ^1.2.3 is exactly equivalent to 1.2.3.

Though it still seems a bit awkward...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like @weihanglo's idea here to not use ^ in this section where possible, and at the end there can be a small code-block that says that ^1.2.3 := 1.2.3 or similar

```

> **Note**: This is the only type of version requirement that has different
> rules for versions that start with `0`, and the version `"0.x.y"` is not
> compatible with any other versions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand this last clause about 0.x.y not being compatible with anything else, isn't 0.x.(y+1) compatible with that?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if x > 0.

Before the review this was stating that 0.0.x was not compatible with other versions, @ehuss said that 0.0.x was not a common version, so it wouldn't be as useful in this explanation, so I changed to 0.x.y without noticing that it is now incorrect.

I'm not sure how to proceed here, is this information even useful? I do often get confused about this, maybe I should just leave the definition.

Or remove completely the "and" part?

, and the version "0.x.y" is not compatible with any other versions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this note trying to convey? It's correct that 0.0.x is not that common but it's incorrect to say that 0.x.y is not compatible with any other versions.


### Tilde requirements

**Tilde requirements** specify a minimal version with some ability to update.
If you specify a major, minor, and patch version or only a major and minor
version, only patch-level changes are allowed. If you only specify a major
version, then minor- and patch-level changes are allowed.
If you specify a string with minor or patch version, only patch-level changes
are allowed. If you only specify a major version, then minor-level changes are
also allowed.

`~1.2.3` is an example of a tilde requirement.
#### Examples:

```notrust
~1.2.3 := >=1.2.3, <1.3.0
~1.2 := >=1.2.0, <1.3.0
~1 := >=1.0.0, <2.0.0
~1 := >=1.0.0, <2.0.0
~1.2 := >=1.2.0, <1.3.0
~1.2.3 := >=1.2.3, <1.3.0
```

### Wildcard requirements

**Wildcard requirements** allow for any version where the wildcard is
positioned.

`*`, `1.*` and `1.2.*` are examples of wildcard requirements.
#### Examples:

```notrust
* := >=0.0.0
1.* := >=1.0.0, <2.0.0
1.2.* := >=1.2.0, <1.3.0
* := >=0.0.0
1.* := >=1.0.0, <2.0.0
1.2.* := >=1.2.0, <1.3.0
```

> **Note**: [crates.io] does not allow bare `*` versions.
Expand All @@ -93,19 +118,71 @@ positioned.
**Comparison requirements** allow manually specifying a version range or an
exact version to depend on.

Here are some examples of comparison requirements:
Comparison requirements are recommended to be used with
[multiple requirements](#multiple-requirements).

#### Examples:

```notrust
>= 1.2.0
> 1
< 2
= 1.2.3
>1.2
<2
>=1.2.0
>=1.2.0, <1.3.0
>=1.2.2, <1.2.5
```

### Multiple requirements

As shown in the examples above, multiple version requirements can be
separated with a comma, e.g., `>= 1.2, < 1.5`.
As shown in the examples above, it is possible to combine any requirement to
restrict the versions even further.

The list of requirements should be separated by commas, spaces are optional.

A version is considered to be compatible with the list only if it is compatible
with all elements of the list.

#### Examples:

All of the lines below are equivalent:

```notrust
>=1.0.0, < 1.0.5
1.0.0, < 1.0.5
^1.0.0, < 1.0.5
~1.0.0, < 1.0.5
=1.0 , < 1.0.5
```

Example using the `time` crate:

```toml
[dependencies]
time = ">=0.2.7, <0.2.15"
```

> **Note**: It is possible to specify more than two requirements, but that's not
> necessary, any long list of requirements can be simplified to one with two
> [comparison requriements], using `>=` and `<`.

### Strict requirements

**Strict requirements** allow you to lock the numbers for major, minor
and patch versions. You can specify the exact version if the patch part is
given.

#### Examples:

```notrust
=0 := >=0.0.0, <1.0.0
=0.1 := >=0.1.0, <0.2.0
=0.1.2 := >=0.1.2, <0.1.2 (exact)
=1 := >=1.0.0, <2.0.0
=1.2 := >=1.2.0, <1.3.0
=1.2.3 := >=1.2.3, <1.2.4 (exact)
```

> **Note**: When using strict requirements with exact versions, no updates can
> be applied, including bugfixes and security updates.

### Specifying dependencies from other registries

Expand Down