✨ Introduction

cargo-msrv is a program which can help you find, set, show or verify the MSRV for a Rust crate. You can also list the MSRV's of dependencies.

MSRV stands for 'Minimum Supported Rust Version', which is exactly what it says on the tin: the earliest Rust release which a given Rust crate promises to support. Most often support for earlier Rust versions is limited by newly introduced Rust language features, library functions or Rust editions.

For example, if you want to use const generics and be generic over integers, bool's or char's, you must use a Rust compiler which supports the const generics MVP. This feature was introduced in Rust 1.51. If you do not have any other code, or configuration, which requires an even newer Rust release, your MSRV would be '1.51'.

While the MSRV has been a well-known concept within the Rust community for a long time, it was also introduced to the Cargo build tool and package manager, as the rust-version in Cargo 1.56, which is part of the Rust 1.56 release distribution.

In the commands section for more.

đŸ”Ŧ How it works

Cargo-msrv will test your project by running various Rust toolchains against your project. The order in which the toolchains will be tested, and the amount of tests ran, depends on the search strategy, the set of available toolchains and of course the limiting factor of the project which will determine the MSRV. We usually call each test a cargo-msrv check. By default, the check command, the command used to test whether toolchain passes or fails a check, is cargo check.

There are currently two search strategies: bisect (default) and linear. When using the linear strategy, your crate will be checked against toolchains from most-recent to least-recent. When a check fails, the previous Rust (if any) version is returned as the MSRV (i.e. the highest toolchain for which a check command passes). The bisect strategy uses a binary search to find the MSRV. This can be significantly faster, so it's usually advisable to keep it enabled by default.

In addition to these two strategies, you can inspect the MSRV's set by the crate authors on which your project depends. This is achieved by resolving the dependency graph of your crate, and querying each crate for its author specified MSRV. Resolving the dependency graph is usually much quicker than running a toolchain command against your project, and may give you an indication of what your MSRV will be like. You can supply the highest listed version as the --min <version> option: cargo msrv --min <version>. This will reduce the possible search space, and speed up the search for the MSRV of your crate.

See cargo-msrv find and cargo-msrv list for more.

đŸĨ° Thanks

Thanks for using cargo-msrv! If you found an issue, or have an issue request, or any other question, feel free to open an issue at our GitHub repository.

A special thanks goes to everyone who took the time to report an issue, discuss new features and contributed to the documentation or the code! Thank you!

Getting started with cargo-msrv

🌞 Installation

Packages marked with 🔸 are maintained by community members (i.e. not the cargo-msrv authors). A big thank you to them!

Using Cargo:

You can install cargo-msrv from source by using Cargo, the Rust package manager and build tool (package).

How to install the latest stable release?

cargo install cargo-msrv

How to install the latest stable release more quickly?

Similar to the above, but allows for only the default channel to obtain a list of rustc releases. This compiles about 40% faster and produces binaries about half the size in the range of 4.5MB.

cargo install cargo-msrv --no-default-features

How to install the latest development release?

You may install cargo-msrv from GitHub:

cargo install cargo-msrv --git https://github.com/foresterre/cargo-msrv.git --branch main

Arch Linux 🔸

cargo-msrv is available from the Arch Linux extra repository.

How to install?

pacman -S cargo-msrv

Nix 🔸

cargo-msrv is available from the Nix package manager and in NixOS (package):

How to install (nixpkgs)?

nix-env -iA nixpkgs.cargo-msrv

How to install (NixOS)?

nix-env -iA nixos.cargo-msrv

NB: When installing with nix-shell --pure, ensure that rustup is available in the environment.

Other options

You may also build the program from source by cloning the repository and building a release from there.

How to build a release?

git clone git@github.com:foresterre/cargo-msrv.git
git checkout v0.16.0 # NB: Find the latest release tag here: https://github.com/foresterre/cargo-msrv/tags
cd cargo-msrv
cargo install cargo-msrv --path . # OR cargo build --release && mv ./target/cargo-msrv ./my/install/directory

How to build the latest development version from source?

git clone git@github.com:foresterre/cargo-msrv.git
cd cargo-msrv
cargo install cargo-msrv --path . # OR cargo build --release && mv ./target/cargo-msrv ./my/install/directory

You may find additional installation options in the README.

⏱ī¸ Quick start

If all you want to do is find the MSRV for your package, you can run:

cargo msrv find

This command will attempt to determine the MSRV by doing a binary search on acceptable Rust releases. If you require additional options, please refer to the cargo-msrv commands section, or run cargo msrv help to view the program's help output.

Migration Guide

0.16.0 - A few release highlights

A quick tour through some cargo msrv 0.16.0 highlights.

The noticeable one - cargo msrv find

The tagline of cargo-msrv is "Find the minimum supported Rust version (MSRV) for your project". Previously, one could achieve this by running cargo msrv. If you want to do the same in 0.16, you instead should run cargo msrv find. The top level cargo msrv action is no more.

There are two primary reasons to move this action to a subcommand instead of keeping it at the top level:

  1. Consistency: cargo msrv can do more than that tagline, and placing all actions on the subcommand level signals that they're equals.
  2. Unsupported CLI flags and options: When actions are placed on two layers, and one of these layers is below the other, then the bottom layer inherits its flags and options, even though they do not always overlap. For example, the set of CLI flags and options of cargo msrv find and cargo msrv list are not identical. cargo msrv find for example has an option called --release-source which should be present for cargo msrv find but not for cargo msrv list. If cargo msrv find would still be run as cargo msrv, you could also invoke this option for cargo msrv list, like so: cargo msrv --release-source rust-dist list. However, contextually, the --release-source option does not make sense for cargo msrv list, so previously it was ignored. By making cargo msrv find a subcommand like cargo msrv list, the flags and options which are not shared between all actions can be put solely below their own subcommand.

A consequence of (2) is that some unnecessary options and flags have been removed from the top level, and so this is a breaking change, not just for cargo msrv find but also for cargo msrv list.

Minor reasons for this change include that I can now talk about cargo msrv find as "cargo msrv find" instead of cargo msrv (find) or "the top level command". Plus, it addressed some difficulties around the code which does CLI parsing.

The UI part 1: output format options

The way the UI is rendered has been updated. Internally, it is now easier to add and maintain different output formats.

cargo-msrv now supports 3 output formats:

  • human (the default one, intended for the human eye)
  • json (intended for machine readability)
  • minimal (*new*, it was requested for environments where people only care about success/failure, such as CI)

The UI part 2: cargo msrv find and verify "human" output

As they say, "a picture is a thousand words":

Previously...

asciicast

New...

asciicast

I'll be iterating the UI further in the future. Constructive feedback is more than welcome!

cargo msrv find --write-msrv

This option will write the MSRV to your Cargo manifest:

asciicast

cargo msrv find --min and --max

The --min and --max options would previously only take three component semver versions like "1.2.3" or editions. It is common to specify the MSRV in a two component version like "1.2", so these are now also supported.

cargo msrv verify --rust-version

cargo msrv verify can be used to check whether your project is compatible with its MSRV. The MSRV is usually read from the Cargo manifest (Cargo.toml). Sometimes it can be useful to provide it manually instead. That's where this option comes in handy.

It should be noted that cargo-msrv does, at present, not unset any value you may have specified in the Cargo manifest. So if you have a Cargo manifest with rust-version = "1.56.0" and supply the --rust-version option with the value 1.55.0, the cargo project will (if the default options are used) fail to compile, and as a consequence cargo-msrv will report that your crate is not compatible with the specified MSRV.

Fetching the rust releases index

The rust releases index, the thing we use to figure out which Rust versions exist, are now only fetched when a subcommand needs it (currently cargo msrv find and cargo msrv verify).

The changelog

The complete changelog can be found here.

Thanks!

Thanks to all contributors, whether you submitted a PR or reported an issue. Some reported issues and PR's really made my day! 💛

Migration Guide: v0.15 to v0.16 with the JSON output format

Enabling json output

In v0.15, json lines output could be enabled by providing the --output-format json option as part of the top level cargo msrv (find) command. cargo msrv find --output-format json verify was a valid way to specify the output-format option, while cargo msrv verify --output-format json would not work (because --output-format was not defined for the subcommand, verify in this example).

This is no longer required; --output-format is now a global option, so in the above examples, both cases will now work.

NB: To determine the MSRV for a project, you should now run cargo msrv find instead of just cargo msrv. The top level command was moved to its own subcommand for consistency and more correct CLI argument parsing.

Message type tag

In v0.15, json messages were tagged using a field named reason. From v0.16 onwards, this field has been renamed to type instead. Please refer to the JSON output format page for a list of supported messages.

Message replacements

In this section, we will discuss the previously supported json messages, and provide suggestions of their replacements.

Mode

A json message with reason mode reported what command was running. Its direct replacement is the subcommand_init message. The v0.15 mode message also reported about the toolchain used, and which rustup run command was used to check for compatibility. These however are only relevant when running a command which checks for compatibility. Since we now also have command which do not check for compatibility, such as cargo msrv show and cargo msrv set, this was a good moment to move these fields out of this type of message. The new check_method message can tell you both about the toolchain used for compatibility checks, and about the compatibility check method via its method field. If this method has type rustup_run, then the args will contain the compatibility check arguments, previously known as the check_cmd.

The v0.15 mode message consisted of:

{
  "reason": "mode",
  // The mode in which cargo-msrv will operate
  "mode": "determine-msrv" /* OR */ "mode": "verify-msrv" /* OR */ "list-msrv" ,
   // The toolchain that will be used
  "toolchain":"x86_64-unknown-linux-gnu",
  // Command used to check a version. The key will be absent for mode 'list'
  "check_cmd":"cargo check"
}

Examples of messages which replace the information reported by the v0.15 mode message:

...
{
  "type": "subcommand_init",
  "subcommand_id": "find"
}
...
{
  "type": "check_method",
  "toolchain": {
    "version": "1.38.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "method": {
    "type": "rustup_run",
    "args": [
      "1.38.0-x86_64-pc-windows-msvc",
      "cargo",
      "check"
    ],
    "path": "..\\air3"
  }
}
...

Installing and Checking

The installing and checking messages reported respectively about locating or installing a specific Rust toolchain and checking that toolchain for compatibility. The former has been replaced by the setup_toolchain event, while the latter has been replaced by the check_toolchain event. Reporting about the progress has been replaced by the progress event.

Previously, you would receive the following event:

{
  "reason": "installing", /* OR */ "reason": "checking",
  // The current version being installed or checked
  "version": "1.25.0",
  // The number of versions checked before this
  "step": 0,
  // The total number of versions to be checked
  "total": 55,
  // The toolchain that is being used
  "toolchain": "x86_64-unknown-linux-gnu",
  // The command used to check each version. The key will be absent for mode 'list'
  "check_cmd": "cargo check"
}

And now, you instead receive these events:

...
{
  "type": "progress",
  "current": 25,
  "search_space_size": 34,
  "iteration": 2
}
...
{
  "type": "setup_toolchain",
  "toolchain": {
    "version": "1.38.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "scope": {
    "id": 2,
    "marker": "start"
  }
}
{
  "type": "setup_toolchain",
  "toolchain": {
    "version": "1.38.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "scope": {
    "id": 2,
    "marker": "end"
  }
}
...
{
  "type": "check_toolchain",
  "toolchain": {
    "version": "1.39.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "scope": {
    "id": 4,
    "marker": "start"
  }
}
{
  "type": "check_toolchain",
  "toolchain": {
    "version": "1.39.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "scope": {
    "id": 4,
    "marker": "end"
  }
}

Check complete

The check-complete message would be reported when a check, which determined whether the toolchain version under test is compatible, completed. It has been replaced by the check_result event. The result of the compatibility check is now reported via the is_compatible field, instead of the success field. The progress report can be followed via the progress event, and the check_cmd may be found by inspecting the check_method event, via the method.args field, assuming that the rustup_run method (method.type) is used.

Previously, you would receive the following event:

{
  "reason": "check-complete",
  // The version that was just checked
  "version": "1.25.0",
  // The number of versions checked before this
  "step": 0,
  // The total number of versions to be checked
  "total": 55,
  // true if this version is supported
  "success": false,
  // The toolchain that is being used
  "toolchain": "x86_64-unknown-linux-gnu",
  // The command used to check each version
  "check_cmd": "cargo check"
}

And now, you instead receive these events, if the toolchain is compatible:

...
{
  "type": "progress",
  "current": 26,
  "search_space_size": 34,
  "iteration": 27
}
...
{
  "type": "check_method",
  "toolchain": {
    "version": "1.38.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "method": {
    "type": "rustup_run",
    "args": [
      "1.38.0-x86_64-pc-windows-msvc",
      "cargo",
      "check"
    ],
    "path": "..\\air3"
  }
}
...
{
  "type": "check_result",
  "toolchain": {
    "version": "1.38.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "is_compatible": true
}

Or, if the toolchain is deemed incompatible:

{
  "type": "progress",
  "current": 27,
  "search_space_size": 34,
  "iteration": 28
}
...
{
  "type": "check_method",
  "toolchain": {
    "version": "1.37.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "method": {
    "type": "rustup_run",
    "args": [
      "1.37.0-x86_64-pc-windows-msvc",
      "cargo",
      "check"
    ],
    "path": "..\\air3"
  }
}
...
{
  "type": "check_result",
  "toolchain": {
    "version": "1.37.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "is_compatible": false,
  "error": "error: failed to parse lock file at: ..\\air3\\Cargo.lock\n\nCaused by:\n  invalid serialized PackageId for key `package.dependencies`\n"
}

MSRV completed

When the find msrv command or the verify command would be completed, they would report about their result. The success field would respectively be used to report whether an MSRV had been found, or whether the MSRV being verified was compatible or not. These messages, msrv-complete and verify-complete have been replaced by the subcommand_result event. Please refer to the subcommand_result event for the complete description of output per command.

The v0.15 output had the following format:

{
  "reason": "msrv-complete" /* OR */ "reason": "verify-complete",
  // true if a msrv was found
  "success": true,
  // the msrv if found. The key will be absent if msrv wasn't found
  "msrv": "1.42.0",
  // The toolchain that is being used
  "toolchain": "x86_64-unknown-linux-gnu",
  // The command used to check each version. The key will be absent for mode 'list'
  "check_cmd": "cargo check"
}

Below, you can find an example of the new output when finding the MSRV, where one is found:

{
  "type": "subcommand_result",
  "subcommand_id": "find",
  "result": {
    "version": "1.38.0",
    "success": true
  }
}

And another example for the output of the verify command, where the verification failed:

{
  "type": "subcommand_result",
  "subcommand_id": "verify",
  "result": {
    "toolchain": {
      "version": "1.60.0",
      "target": "x86_64-pc-windows-msvc"
    },
    "is_compatible": false,
    "error": "    Checking air v0.0.0 (..\\air)\nerror: expected one of `:`, `<`, `=`, `where`, or `{`, found `<eof>`\n  --> src\\lib.rs:24:11\n   |\n24 | pub trait DisplayEvent\n   |           ^^^^^^^^^^^^ expected one of `:`, `<`, `=`, `where`, or `{`\n\nerror: could not compile `air` due to previous error\n"
  }
}

List MSRV's specified by crate authors

This event contains the output of the list command, which reports the MSRV of dependencies of a crate. The exact output depends on which variant is used, either ordered-by-msrv (default) or direct-deps.

The output of the list command is almost the same as it was before. The event is no longer called list; instead the output is given via the subcommand_result event, where the value of subcommand_id is list. The output of the command (variant and list fields) can now be found as part of the result field. The success field has been removed.

{
  "reason": "list",
  // output variant
  "variant": "ordered-by-msrv" /* OR */ "direct-deps",
  // always success when returning a result
  "success": true,
  // The output of the list subcommand
  "list": [
    /* when variant = 'ordered-by-msrv */
    {
        "msrv": "<msrv>",
        "dependencies": ["<dependencies which have this msrv>", ...]
    }
    /* OR, when variant = direct-deps */
    {
        "dependency": "<dependency crate name>",
        "version": "<dependency crate version>",
        "msrv": "<dependency crate msrv>",
        "depends_on": ["<dependencies of direct dependency crate>", ...]
    }
  ],
}

An example of the ordered-by-msrv variant:

{
  "type": "subcommand_result",
  "subcommand_id": "list",
  "result": {
    "variant": "ordered-by-msrv",
    "list": [
      {
        "msrv": "1.38.0",
        "dependencies": [
          "storyteller"
        ]
      },
      {
        "msrv": "1.36.0",
        "dependencies": [
          "crossbeam-channel",
          "crossbeam-utils"
        ]
      },
      {
        "msrv": null,
        "dependencies": [
          "cfg-if",
          "lazy_static"
        ]
      }
    ]
  }
}

An example of the direct-deps variant:

{
  "type": "subcommand_result",
  "subcommand_id": "list",
  "result": {
    "variant": "direct-deps",
    "list": [
      {
        "name": "crossbeam-channel",
        "version": "0.5.4",
        "msrv": "1.36.0",
        "dependencies": [
          "cfg-if",
          "crossbeam-utils",
          "num_cpus",
          "rand",
          "signal-hook"
        ]
      }
    ]
  }
}

🚧 Section is work-in-progress.

🌱 Concepts

Rust Releases Index

Release Source

  • rust-changelog (default)
  • rust-dist

Resolver

  • run-toolchain resolver (default): resolver which runs actual toolchains against a crate
  • rust-version resolver: author defined resolver, used by cargo-msrv list

Output formats

In cargo-msrv we to status of the program is reported via events. These events are issued at several stages of the program execution. As a user of cargo-msrv, you may choose how these events are formatted into a human-readable or machine-readable representation. User output may also be disabled altogether.

The next section gives an overview of the supported representations. Thereafter, you may find an index to the chapters which detail each representation.

Choosing an output format

The first output format is the human output format. As the name suggests, its output is meant to be interpreted by humans, and consists of elaborate colouring and custom styling.

The second output format is the json output format. This is a detailed machine-readable format and also the format which most closely mimics the events as they are reported internally. Events are printed in a json-lines (jsonl) format to stderr.

The third output-format is the minimal output format. This format is intended to be used by shell scripts or programs which do not require detailed output. Its format does not require complex parsing, and only reports the final results of commands.

The fourth option is to not print any user output. This is uncommon, but may be used in conjunction with printing debug (i.e. developer) output only, so the debug output is not overwritten by the user output.

The output formats

Output format: human

This is the default output format. It can also be specified using the --output-format human option.

The output of the 'human' output format is intended to be interpreted by humans. It uses colour and custom printed layouts to convey its information to the user.

In the next section, examples are given for each subcommand and a specific use case. You may run cargo msrv help to review all flags and options available.

Output by subcommand

# cargo msrv (find)

I want to find the MSRV of my project

Use: cargo msrv

Screencast: find the MSRV

The output shows for each checked toolchain whether it is determined to be compatible or not. If a toolchain is not compatible, a reason is printed which may help you discover why it is not deemed compatible.

cargo-msrv will show a summary after the search completes. The summary consists of the search space considered, the search method used, the compiler target and of course the MSRV.

It is also possible that no MSRV could be found, for example if the program is not valid Rust code (i.e. would not compile).

I want to find the MSRV and write the result to the Cargo manifest

Use the --write-msrv flag: cargo msrv find --write-msrv

Screencast: find the MSRV and write the result to the Cargo manifest

The output is the same as for cargo msrv, plus an additional message which states that the MSRV has been written to the Cargo manifest.

Support for also writing to the clippy config is tracked in issue 529.

I want to find the MSRV and limit or increase the search space

Use the --min and/or --max options: cargo msrv find --min <Rust version or edition> --max <Rust version>

Sceencast: find the MSRV with a customized search space

By default, the search space is limited by the edition specified in the Cargo manifest. You may use the above options to override the limits of the search space. The output will be the same as otherwise running cargo msrv.

In the example we specified the minimal version by specifying a Rust edition. We also could've specified a Rust version instead, e.g. 1.10 or 1.20.0. It is not possible for the maximum considered version to specify an edition.

I want to find the MSRV, but use a linear search

Use the --linear flag: cargo msrv find --linear

Screencast: find the MSRV using a linear search

We use the bisection search method to speed up the search for the MSRV considerably, but sometimes a linear search can be useful, for example if the search space is very small. The output will be the same as otherwise running cargo msrv, except of course for the order in which the search is performed.

# cargo msrv list

I want to list the MSRV's of all dependencies

Use: cargo msrv list

Screencast: list MSRV's of dependencies

This example shows how to list the MSRV's of dependencies. The MSRV's are sourced from their Cargo manifests.

I want to list the MSRV's of my direct dependencies

Use the --variant option: cargo msrv list --variant direct-deps

Screencast: list MSRV's of direct dependencies

In this example, we instead list the MSRV's of the dependencies specified in the Cargo manifest.

# cargo msrv set

I want to set or update the MSRV of my project

Use: cargo msrv set <version>

asciicast

# cargo msrv show

# cargo msrv verify

Output format: json

The json output format is intended to be used as a machine-readable output, to be interpreted by tooling, although humans may also use it, as it provides the most detailed output of all supported output formats.

As described on the output-formats page, cargo-msrv reports the status of the program via events. A processor transforms these events into their output-format. In case of the json output format, events are almost 1-on-1 serialized to json (there are a few exceptions), and then printed to stderr. Each json serialized event ends with a newline. Each line thus represents a single serialized event.

To use the json output format, run cargo-msrv with the --output-format json option. For example, if you want to find the MSRV, you could run cargo msrv find --output-format json.

In the next section, you can find a description of the common fields of events. The section thereafter gives an overview of each of the supported events, with for each event its event specific fields.

Events and scope

Cargo MSRV currently reports two types of events: unscoped and scoped events. Unscoped events report about an action on a certain point in time, while scoped events report about an action which took place over a period of time.

In the context of the json output format, an unscoped event will print a single json-line to the stderr, while a scoped event will print two json-lines to the stderr (one prior to starting the action, and one after the action has been completed).

Common fields on events

nameoptionalvaluesdescription
typenoIdentifies a specific event.
scopeyesA pair of events which mark the start and end of an action. Together these two individual events are called a scoped event.
scope.idnoA unique id to match up the two events marking the begin and end of an action. The current incremental nature is an implementation detail and not guaranteed.
scope.markerno"start" or "end"Whether the event marks the beginning or the end of the action

The type field can be used to identify a specific event.

The scope field is only present for scoped events. The start value (on the marker subfield) marks the start of a scoped event, while end marks the end of a scoped event.

List of events

Event: Meta

type: meta

description: Reports metadata about the currently running cargo-msrv program instance.

fields:

namedescription
instanceName of the running cargo-msrv program as defined on compile time. This will usually be cargo-msrv.
versionVersion of the running cargo-msrv program as defined on compile time.
sha_shortShort SHA hash of the git commit used to compile and build cargo-msrv.
target_tripleTarget triple of toolchain used to compile and build cargo-msrv.
cargo_featuresFeatures which were enabled during the compilation of cargo-msrv.
rustcVersion of rustc used to compile cargo-msrv.

example:

{
  "type": "meta",
  "instance": "cargo-msrv",
  "version": "0.15.1",
  "sha_short": "79582b6",
  "target_triple": "x86_64-pc-windows-msvc",
  "cargo_features": "default,rust_releases_dist_source",
  "rustc": "1.62.0"
}

Event: FetchIndex

type: fetch_index

description: Prior to determining the MSRV of a crate, we have to figure out which Rust versions are available. We obtain those using the rust-releases library. The FetchIndex event reports that the index is being fetched, and details which source is used.

fields:

namedescription
sourcePlace from where the available Rust releases are obtained

example:

{
  "type": "fetch_index",
  "source": "rust_changelog",
  "scope": "start"
}
{
  "type": "fetch_index",
  "source": "rust_changelog",
  "scope": "end"
}

Event: CheckToolchain

type: check_toolchain

description: The primary way for cargo-msrv to determine whether a given Rust toolchain is compatible with your crate, is by installing a toolchain and using it to check a crate for compatibility with this toolchain. The CheckToolchain event is wrapped around this process and notifies you about the start and end of this process. This event is called as a scoped event, and within it's scope, you'll find the following events: setup_toolchain, check_method and check_result, which are described in more detail below.

fields:

namedescription
toolchainThe toolchain to be located or installed
toolchain.versionThe Rust version of the toolchain
toolchain.targetThe target-triple of the toolchain

example:

{
  "type": "check_toolchain",
  "toolchain": {
    "version": "1.35.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "scope": "start"
}
{
  "type": "check_toolchain",
  "toolchain": {
    "version": "1.35.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "scope": "end"
}

Event: SetupToolchain

type: setup_toolchain

description: The primary way for cargo-msrv to determine whether a given Rust toolchain is compatible with your crate, is by installing a toolchain and using it to check a crate for compatibility with this toolchain. The SetupToolchain event reports about the process of locating or installing a given toolchain.

fields:

namedescription
toolchainThe toolchain to be located or installed
toolchain.versionThe Rust version of the toolchain
toolchain.targetThe target-triple of the toolchain

example:

{
  "type": "setup_toolchain",
  "toolchain": {
    "version": "1.47.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "scope": "start"
}
{
  "type": "setup_toolchain",
  "toolchain": {
    "version": "1.47.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "scope": "end"
}

Event: CheckMethod

type: check_method

description: Reports which method has been used to check whether a toolchain is compatible with a crate.

fields:

nameoptionalconditiondescription
toolchainnoThe toolchain to be located or installed
toolchain.versionnoThe Rust version of the toolchain
toolchain.targetnoThe target-triple of the toolchain
methodnoThe method used to check for compatibility
method.typenoThe type of method
method.argsnomethod.type = rustup_runThe arguments provided to rustup
method.pathyesmethod.type = rustup_runThe path provided to rustup, if any

example:

{
  "type": "check_method",
  "toolchain": {
    "version": "1.37.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "method": {
    "rustup_run": {
      "args": [
        "1.37.0-x86_64-pc-windows-msvc",
        "cargo",
        "check"
      ],
      "path": "..\\air3\\"
    }
  }
}

Event: CheckResult

type: check_result

description: Reports the result of a cargo-msrv compatibility check.

fields:

nameoptionalconditiondescription
toolchainnoThe toolchain to be located or installed
toolchain.versionnoThe Rust version of the toolchain
toolchain.targetnoThe target-triple of the toolchain
is_compatiblenoBoolean value stating compatibility
erroryesis_compatible = falseError message of a failed compatibility check, if any

example:

{
  "type": "check_result",
  "toolchain": {
    "version": "1.38.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "is_compatible": true
}
{
  "type": "check_result",
  "toolchain": {
    "version": "1.37.0",
    "target": "x86_64-pc-windows-msvc"
  },
  "is_compatible": false,
  "error": "error: failed to parse lock file at: .\\air3\\Cargo.lock\n\nCaused by:\ninvalid serialized PackageId for key `package.dependencies`\n"
}

Event: AuxiliaryOutput

type: auxiliary_output

description: Reports about additional output written by cargo-msrv when applicable. For example, if the --write-msrv or --write-toolchain-file flag is provided, the MSRV will be written to the Cargo manifest or the Rust toolchain file respectively. The act of writing this (additional) output is reported by this event.

fields:

nameoptionalconditiondescription
destinationnoThe destination of the auxiliary output
destination.typenoType of destination, currently only "file"
destination.pathnoif destination.type = filePath of the written or amended file
itemnoWhat kind of output is written
item.typenoType of output item
item.kindnoif item.type = msrvTo which field the MSRV was written in the Cargo manifest, "rust-version" or "metadata_fallback"
item.kindnoif item.type = toolchain_fileWhich toolchain file kind was written, "legacy" or "toml"

example:

{
  "type": "auxiliary_output",
  "destination": {
    "type": "file",
    "path": "..\\air3\\Cargo.toml"
  },
  "item": {
    "type": "msrv",
    "kind": "rust_version"
  }
}

Event: Progress

type: progress

description: Reports on the progress of an ongoing MSRV search.

fields:

nameoptionalconditiondescription
currentnoIndex of the currently running check into the sorted search space. Starts at 0.
search_space_sizenoThe size of the search space.
iterationnoHow many iterations have been completed, plus one for the currently running iteration. Starts at 1.

Event: SubcommandInit

type: subcommand_init

description: Reports the start of a subcommand flow.

fields:

nameoptionalconditiondescription
subcommand_idnoA name identifying the subcommand

Event: SubcommandResult

type: subcommand_result

description: Reports the outcome of a subcommand flow.

fields:

nameoptionalconditiondescription
subcommand_idnoA name identifying the subcommand
resultnosubcommand_id = findResult of find command
result.successnosubcommand_id = findWhether the MSRV was found or not
result.versionnosubcommand_id = find and result.success = trueThe Minimum Supported Rust Version (MSRV)
resultnosubcommand_id = listResult of list command
result.variantnosubcommand_id = listType of list output. Either direct-deps or ordered-by-msrv.
result.listnosubcommand_id = list and result.variant = direct-depsList of direct dependencies of the selected crate
result.list.namenosubcommand_id = list and result.variant = direct-depsName of the crate
result.list.versionnosubcommand_id = list and result.variant = direct-depsVersion of the crate
result.list.msrvnosubcommand_id = list and result.variant = direct-depsMSRV of the crate if any, null if the MSRV is not set
result.list.dependenciesnosubcommand_id = list and result.variant = direct-depsDependencies of the given crate, relevant for the MSRV
result.listnosubcommand_id = list and result.variant = ordered-by-msrvList of all dependencies relevant for the MSRV, categorised by their MSRV
result.list.msrvnosubcommand_id = list and result.variant = ordered-by-msrvA value for the MSRV specified by at least one crate
result.list.dependenciesnosubcommand_id = list and result.variant = ordered-by-msrvList of dependencies which specified the same value for the MSRV
resultnosubcommand_id = setResult of set command
result.versionnosubcommand_id = setWhich version was set as MSRV
result.manifest_pathnosubcommand_id = setRelative path of file where the MSRV was written to
resultnosubcommand_id = showResult of show command
result.versionnosubcommand_id = showMSRV as set for the given crate
result.manifest_pathnosubcommand_id = showRelative path of file where the MSRV was read from
resultnosubcommand_id = verifyResult of verify command
result.toolchainnosubcommand_id = verifyThe toolchain to be located or installed
result.toolchain.versionnosubcommand_id = verifyThe Rust version of the verified toolchain
result.toolchain.targetnosubcommand_id = verifyThe target-triple of the verified toolchain
result.is_compatiblenosubcommand_id = verifyBoolean value stating compatibility
result.erroryessubcommand_id = verify and result.is_compatible = falseError message of a failed verify check, if any

example 1: find

{
  "type": "subcommand_result",
  "subcommand_id": "find",
  "result": {
    "version": "1.38.0",
    "success": true
  }
}

example 2: list with direct-deps

{
  "type": "subcommand_result",
  "subcommand_id": "list",
  "result": {
    "variant": "direct-deps",
    "list": [
      {
        "name": "crossbeam-channel",
        "version": "0.5.4",
        "msrv": "1.36.0",
        "dependencies": [
          "cfg-if",
          "crossbeam-utils",
          "num_cpus",
          "rand",
          "signal-hook"
        ]
      }
    ]
  }
}

Formatted:

{
  "type": "subcommand_result",
  "subcommand_id": "list",
  "result": {
    "variant": "direct-deps",
    "list": [
      {
        "name": "crossbeam-channel",
        "version": "0.5.4",
        "msrv": "1.36.0",
        "dependencies": [
          "cfg-if",
          "crossbeam-utils",
          "num_cpus",
          "rand",
          "signal-hook"
        ]
      }
    ]
  }
}

example 3: list with ordered-by-msrv

{
  "type": "subcommand_result",
  "subcommand_id": "list",
  "result": {
    "variant": "ordered-by-msrv",
    "list": [
      {
        "msrv": "1.38.0",
        "dependencies": [
          "storyteller"
        ]
      },
      {
        "msrv": "1.36.0",
        "dependencies": [
          "crossbeam-channel",
          "crossbeam-utils"
        ]
      },
      {
        "msrv": null,
        "dependencies": [
          "cfg-if",
          "lazy_static"
        ]
      }
    ]
  }
}

Formatted:

{
  "type": "subcommand_result",
  "subcommand_id": "list",
  "result": {
    "variant": "ordered-by-msrv",
    "list": [
      {
        "msrv": "1.38.0",
        "dependencies": [
          "storyteller"
        ]
      },
      {
        "msrv": "1.36.0",
        "dependencies": [
          "crossbeam-channel",
          "crossbeam-utils"
        ]
      },
      {
        "msrv": null,
        "dependencies": [
          "cfg-if",
          "lazy_static"
        ]
      }
    ]
  }
}

example 5: set:

{
  "type": "subcommand_result",
  "subcommand_id": "set",
  "result": {
    "version": "1.38.0",
    "manifest_path": "..\\air3\\Cargo.toml"
  }
}

example 6: show:

{
  "type": "subcommand_result",
  "subcommand_id": "show",
  "result": {
    "version": "1.38.0",
    "manifest_path": "..\\air3\\Cargo.toml"
  }
}

example 7: verify:

{
  "type": "subcommand_result",
  "subcommand_id": "verify",
  "result": {
    "toolchain": {
      "version": "1.38.0",
      "target": "x86_64-pc-windows-msvc"
    },
    "is_compatible": true
  }
}

Event: TerminateWithFailure

type: terminate_with_failure

description: Reports about failure which led to program termination with a non-zero exit code.

fields:

nameoptionaldescription
reasonnoReason of failure
reason.descriptionnoDescribes why cargo-msrv will terminate with a non-zero exit code

example:

{
  "type": "terminate_with_failure",
  "reason": {
    "description": "MSRV was not specified in Cargo manifest at '..\\air\\Cargo.toml'"
  }
}

Output format: minimal

The purpose of the minimal output format option is to provide just enough output for a machine (or shell script!) to be understandable, while not requiring elaborate parsers like the json output format. It may also be used as a minimal human-readable format.

This output format can be summarized by the following two statements:

  • If the command was successful, it prints the commands final result and exits with a zero exit code. Output is printed to stdout.
  • If the command was unsuccessful, it prints an error message, and exits with a non-zero exit code. Output is printed
    to stderr.

You may also refer to the 🚧 TODO 🚧 section to determine which kind of errors result in a non-zero exit code, and how different errors are categorised.

Output by subcommand

# cargo msrv (find)

If the MSRV was found, we report this minimal supported Rust version by writing it to stdout. If it could not be found, we report none instead, and write this value to stderr.

Example 1

If the MSRV is 1.60.0, the output will be just 1.60.0.

$ cargo msrv find --output-format minimal
# stdout
1.60.0

Example 2

If the MSRV can't be found, for example if your project requires a nightly compiler feature or has incorrect syntax, the output will be none.

$ cargo msrv find --output-format minimal
# stderr
none

# cargo msrv list

The list subcommand is not supported by the minimal output format, and "unsupported" will be printed. Support may be added in the future.

# cargo msrv set

The set subcommand prints the version set as MSRV.

Example 1

If we set our MSRV to be 1.31, the output will be 1.31.

cargo msrv find --output-format minimal set 1.31
# stdout
1.31

# cargo msrv show

The show subcommand prints the detected MSRV, if specified in the Cargo Manifest.

Example 1

Assuming our Cargo manifest contains a 1.60 MSRV, cargo-msrv will print 1.60.

Cargo.toml

[package]
rust-version = "1.60"

Shell

$ cargo msrv find --output-format minimal show
# stdout
1.60

Example 2

Assuming our Cargo manifest lists the MSRV in the package.metadata.msrv field, cargo-msrv will print 1.21.0. The package.rust-version field has precedence over the package.metadata.msrv. You may see the package.metadata.msrv key for crates which use a Cargo version which does not yet support the package.rust-version field. cargo-msrv supports both fields.

Cargo.toml

[package.metadata]
msrv = "1.21.0"

Shell

$ cargo msrv find --output-format minimal show
# stdout
1.21.0

# cargo msrv verify

The verify subcommand prints true (to stdout) with exit code zero if checking the toolchain for this platform which matches the MSRV succeeds. Else, it prints false (to stderr) with an exit code which is non-zero.

Example 1

Assuming our Cargo manifest contains an MSRV definition in the package.rust-version or package.metadata.msrv field, and the compatibility check succeeds:

[package.metadata]
msrv = "1.31"

Shell

$ cargo msrv find --output-format minimal verify
# stdout
true

Example 2

Assuming the given crate is incompatibility with the given MSRV:

Shell

$ cargo msrv find --output-format minimal verify --rust-version 1.31
# stderr
false

Output format: no-user-output

The 'no-user-output' is not really a "user output" variant. Choosing this option disables user output of events altogether. Disabling the user output may be achieved by providing the --no-user-output flag.

🚧 Section is work-in-progress.

🕹ī¸ cargo-msrv commands

  • cargo-msrv find: The find subcommand is used to find the MSRV for your crate.
  • cargo-msrv help: The help subcommand is used to learn more about the usage and the knobs and handles of the application.
  • cargo-msrv list: The list subcommand is used to list the known MSRV's of the dependencies of your crate.
  • cargo-msrv set: The set subcommand is used to quickly set the MSRV of a crate.
  • cargo-msrv show: The show subcommand is used to quickly show the MSRV of a crate.
  • cargo-msrv verify: The verify subcommand is used to check whether the pinned MSRV is acceptable.

Program wide options

See cargo msrv --help for a full list of program wide options.

cargo-msrv

COMMAND

  • Standalone: cargo-msrv find [options]
  • Through Cargo: cargo msrv find [options]

PREVIEW

asciicast

DESCRIPTION

Find the MSRV for your project.

This command will test your project by running various Rust toolchains against your project. The order in which these toolchains will be tested, and the amount of tests ran, depends on the search strategy, the amount of toolchains available and of course the limiting factor of the project which will determine the MSRV. We usually call each test a cargo-msrv check. By default, the check command, the command used to test whether toolchain passes or fails a check, is cargo check.

There are currently two search strategies: bisect (default) and linear. Linear tests projects against toolchains in a most-recent to least-recent order. When a check fails, the previous Rust (if any) version is returned as the MSRV (i.e. the highest still toolchain for which a check command passes). Bisect tests projects using a binary search. This can be significantly faster, so it's usually advisable to enable it by default.

Why run against complete toolchains?

Running against a complete toolchain may seem like a lot of wasted computing power. Why not run against just the AST, and (conditionally) tag each AST node with a supported from version (or query it, as library functions already have an ' available from' Rust version)?

Earlier we developed a prototype to do exactly this, and we may still add it as an optional strategy in the future, however we found that the selection of the MSRV of a toolchain is not just limited by the source code itself. External factors such as Rust editions or knobs in the Cargo manifest also impact the MSRV for a crate. As such, the running a complete toolchain helps us to be more precise1.

Future work

1. We want to eventually add a combination-of-strategies strategy which can combine result of other strategies to come to a possibly more precise definition.

2. If you come up with a strategy which will add value to cargo-msrv, feel free to contribute the idea, or even an implementation. If you don't know where to start, create a new issue, we're happy to help!

OPTIONS

--bisect

Use a binary search to find the MSRV. This is usually faster than using a linear search. The binary search strategy is the default since cargo-msrv v0.14.0.

--linear

Use a linear search to find the MSRV, by checking toolchains from latest to earliest. The linear search strategy was the default prior to cargo-msrv v0.14.0.

-h, --help

Prints help information

--include-all-patch-releases

Include all patch releases, instead of only the last. By default, after the list of Rust releases has been fetched, we
only keep the highest minor version for each Rust release. Say the list of Rust releases would be ["1.31.1", "1.31.0", "1.30.0], then we discard Rust 1.31.0, as you would usually not depend on the non-bugfixed compiler releases, and the patch version does not contain new features, thus no features to impact the MSRV. When you provide this flag however, these additional patch versions will be included in the search space.

--ignore-lockfile

Temporarily (re)moves the lockfile, so it will not interfere with the building process. This is important when testing against Rust versions prior to 1.38.0, for which Cargo does not recognize the new v2 lockfile (Cargo.lock), or some crates which use the even newer v3 lockfile.

--log-level level

Specify the severity of debug logs which the program will write to the log output. Possible values are: error, warn, info (default), debug and trace. Lower severities include messages of higher severities. When --no-log is present, this option will be ignored.

--log-target log_target

Specify where cargo-msrv should output its internal debug logs. Possible values are file (default) and stdout. The log output of stdout may interfere with user output. We would suggest to use --no-user-output in tandem with --log-target stdout. When --no-log is present, this option will be ignored.

--max version

Latest (most recent) version to take into account. The version must match a valid three component Rust toolchain version, and be semver compatible. An example of an acceptable versions is "1.35.0", while "1.35", "^1.35.0" and "1.35.0-beta" are not valid.

--min version

Earliest (least recent) version to take into account. The version must match a valid three component Rust toolchain version, and be semver compatible. Edition aliases may also be used. An example of an acceptable versions is "1.35.0", while "1.35", "^1.35.0" and "1.35.0-beta" are not valid. Editions map to the first version in which they were introduced, so for example "1.56.0" for edition "2021".

--no-check-feedback

If provided, the outcome of individual checks will not be printed. These prints provide feedback, about the order in which checks ran, and their results. This is especially useful if you want to know why a certain Rust version was deemed to be incompatible, for example, so you can identify Rust features which require a certain minimum Rust version.

--no-log

Do not write (internal) debug log output to the log target.

--no-user-output

Disables printing of diagnostic status messages. Useful when internal log output messages are printed to the stdout, using --log-target stdout, so no clipping between the user output prints and log message prints will take place. When present, the --output-format [value] option will be ignored.

--output-format format

Output diagnostic status messages in machine-readable format. Machine-readable status updates will be printed in the requested format to stdout. The only accepted format is currently "json", which will print diagnostic messages in a JSON format. When this option is absent, human-readable output will be printed. Diagnostic messages can be disabled entirely using the --no-user-output flag.

--release-source source

Select the rust-releases source to use as the release index. Available options are rust-changelog and rust-dist. The first will parse the Rust changelog file to determine which Rust releases have been made, while the second will index the Rust S3 distribution bucket.

--path directory-path

Path to the cargo project directory. This directory should contain a Cargo manifest (i.e. Cargo.toml) file. The given path should end in the Cargo manifest file. A valid path would be /home/user/project. A path like /home/user/project/Cargo.toml is incorrect.

--target target

Supply a custom target triplet to use as Rust distribution. If absent, the rustup default toolchain is used.

--write-toolchain-file

Output a rust-toolchain file with the determined MSRV as toolchain. The toolchain file will pin the Rust version for this crate. See here for more about the toolchain-file.

-V, --version

Prints cargo-msrv version information

-- ...cmd

When provided, the trailing command (cmd) will be used as the cargo-msrv check command, instead of the default cargo check. This cmd must be runnable by rustup through rustup run <toolchain> <cmd>.

EXAMPLES

  1. Try to determine the MSRV for the crate in your current working directory, using the binary search strategy.
cargo msrv find --bisect

or (from cargo-msrv v0.14.0, bisect is the default search method):

cargo msrv find
  1. Try to determine the MSRV for the crate in your current working directory, using the linear search strategy.
cargo msrv find --linear

NB: Prior to cargo-msrv v0.14.0, linear was the default search strategy, and no flag was available explicitly use this search strategy.

  1. Try to determine the MSRV for the crate in your current working directory, using a custom cargo-msrv check command: cargo test.
cargo msrv find -- cargo test
  1. Try to determine the MSRV for the crate in your current working directory, but use the JSON machine-readable output format.
cargo msrv find --output-format json

FOOTNOTES

1 Precision is of course a debatable concept. In this case we note that "a toolchain must be able to pass the cargo-msrv compatibility check command for a crate".

cargo-msrv help

COMMAND

  • Standalone: cargo-msrv help [subcommand]
  • Through Cargo: cargo msrv help [subcommand]

PREVIEW

asciicast

DESCRIPTION

Help users navigate the cargo-msrv CLI by printing a help message.

EXAMPLES

  1. Get help for cargo-msrv
cargo msrv help # OR cargo msrv --help
  1. Get help for a cargo-msrv subcommand, for example list:
cargo msrv help list # OR cargo msrv list --help

cargo-msrv list

COMMAND

  • Standalone: cargo-msrv list [options]
  • Through Cargo: cargo msrv list [options]

PREVIEW

asciicast

DESCRIPTION

List the author specified MSRV for each depended-upon package.

Authors may specify the MSRV for their crate by adding the package.rust-version key to the Cargo.toml manifest. See the Cargo book for more. This value is supported from Rust 1.56 onwards.

[package]
rust-version = "1.56"

For crates which have an MSRV prior to Rust 1.56, you can use the package.metadata.msrv key in the Cargo.toml manifest instead. The package.metadata table exists specifically for tools like cargo-msrv, and within this table, Cargo will not warn about keys it does not understand. Note that the use of this key is tailored to cargo-msrv and may not be supported by other tools.

[package.metadata]
msrv = "1.53.0"

Both package.rust-version and package.metadata.msrv require a two or three component version number, without semver operators or pre-release identifiers. For example, 1.56 and 1.56.0 are both valid, while ^1.56.0 and 1.56.0-beta are not.

OPTIONS

--variant variant

Type of table to print.

The variant must be one of: ordered-by-msrv (default) or direct-deps.

When the variant is ordered-by-msrv, the program will print a table which lists the MSRV for both direct and transitive dependencies. The table is sorted by MSRV. When a crate author did not specify an MSRV yet, the cell in the MSRV row will be empty.

When the variant is direct-deps, the program will print a table which lists the following properties for each direct-dependency of the given crate: the name of the dependency, the version of the dependency, the MSRV (empty if not specified), it's dependencies.

EXAMPLES

  1. List the MSRV's for both direct and transitive dependencies, grouped by MSRV.
cargo msrv list

Output for cargo-msrv commit c76b45a7ae39b52294e303eca6da56fda45b3feb:

Fetching index
┌────────â”Ŧ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ MSRV   ┆ Dependency                                                                                                                                │
╞════════â•Ē═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╡
│        ┆ typed-builder, tracing-subscriber, tracing-appender, tracing, toml_edit, petgraph, once_cell, json, indicatif, dirs, console,             │
│        ┆ comfy-table, clap, cargo_metadata, tracing-serde, tracing-log, tracing-core, thread_local, smallvec, sharded-slab, serde_json, serde,     │
│        ┆ ansi_term, time, crossbeam-channel, tracing-attributes, pin-project-lite, cfg-if, kstring, itertools, indexmap, combine,                  │
│        ┆ rust-releases-rust-dist, rust-releases-rust-changelog, rust-releases-core, fixedbitset, regex, number_prefix, lazy_static, dirs-sys,      │
│        ┆ winapi, unicode-width, terminal_size, libc, encode_unicode, strum_macros, strum, crossterm, vec_map, textwrap, strsim, bitflags, atty,    │
│        ┆ ansi_term, semver, cargo-platform, camino, unicode-xid, log, ryu, itoa, serde_derive, crossbeam-utils, either, hashbrown, autocfg,        │
│        ┆ memchr, bytes, tokio, rust-releases-io, rusoto_s3, rusoto_core, chrono, regex-syntax, aho-corasick, redox_users,                          │
│        ┆ winapi-x86_64-pc-windows-gnu, winapi-i686-pc-windows-gnu, heck, signal-hook-mio, signal-hook, parking_lot, mio, crossterm_winapi,         │
│        ┆ hermit-abi, tokio-macros, signal-hook-registry, num_cpus, directories-next, attohttpc, xml-rs, futures, async-trait, rustc_version,       │
│        ┆ rusoto_signature, rusoto_credential, hyper-tls, hyper, http, crc32fast, base64, time, num-traits, num-integer, redox_syscall, getrandom,  │
│        ┆ unicode-segmentation, parking_lot_core, lock_api, instant, ntapi, miow, dirs-sys-next, wildmatch, url, openssl, native-tls, flate2,       │
│        ┆ futures-util, futures-task, futures-sink, futures-io, futures-executor, futures-core, futures-channel, semver, time, sha2,                │
│        ┆ percent-encoding, md5, hmac, hex, zeroize, shlex, dirs-next, tokio-native-tls, want, tower-service, socket2, httpdate, httparse,          │
│        ┆ http-body, fnv, wasi, scopeguard, matches, idna, form_urlencoded, openssl-sys, foreign-types, tempfile, security-framework-sys,           │
│        ┆ security-framework, schannel, openssl-probe, miniz_oxide, slab, proc-macro-nested, proc-macro-hack, pin-utils, futures-macro,             │
│        ┆ semver-parser, version_check, time-macros, stdweb, standback, const_fn, opaque-debug, digest, cpufeatures, block-buffer, crypto-mac,      │
│        ┆ try-lock, unicode-normalization, unicode-bidi, vcpkg, pkg-config, cc, foreign-types-shared, remove_dir_all, rand, core-foundation-sys,    │
│        ┆ core-foundation, adler, time-macros-impl, wasm-bindgen, stdweb-internal-runtime, stdweb-internal-macros, stdweb-derive, discard,          │
│        ┆ generic-array, subtle, tinyvec, rand_hc, rand_core, rand_chacha, wasm-bindgen-macro, sha1, base-x, typenum, tinyvec_macros, ppv-lite86,   │
│        ┆ wasm-bindgen-macro-support, wasm-bindgen-shared, wasm-bindgen-backend, bumpalo                                                            │
├╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 1.31.0 ┆ syn, quote, proc-macro2, thiserror, thiserror-impl                                                                                        │
├╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 1.51.0 ┆ rust-releases                                                                                                                             │
├╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 1.53.0 ┆ cargo-msrv                                                                                                                                │
└────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

NB: The dependencies which are listed with an empty MSRV cell do not specify a MSRV yet. At the time of writing, most dependencies in the cargo-msrv dependency tree did not have an MSRV defined.

  1. List the MSRV's for your direct dependencies using
cargo msrv list --variant direct-deps

Output for cargo-msrv commit c76b45a7ae39b52294e303eca6da56fda45b3feb:

Fetching index
┌────────────────────â”Ŧ─────────â”Ŧ────────â”Ŧ──────────────────────────────────────────────────────────────────────────────┐
│ Dependency         ┆ Version ┆ MSRV   ┆ Depends on                                                                   │
╞════════════════════â•Ē═════════â•Ē════════â•Ē══════════════════════════════════════════════════════════════════════════════╡
│ typed-builder      ┆ 0.9.1   ┆        ┆ proc-macro2, quote, syn                                                      │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ tracing-subscriber ┆ 0.3.1   ┆        ┆ ansi_term, lazy_static, matchers, parking_lot, regex, serde, serde_json,     │
│                    ┆         ┆        ┆ sharded-slab, smallvec, thread_local, time, tracing, tracing-core,           │
│                    ┆         ┆        ┆ tracing-log, tracing-serde, criterion, log, regex, time, tokio, tracing,     │
│                    ┆         ┆        ┆ tracing-futures, tracing-log                                                 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ tracing-appender   ┆ 0.2.0   ┆        ┆ crossbeam-channel, time, tracing-subscriber, tempfile, time, tracing         │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ tracing            ┆ 0.1.29  ┆        ┆ cfg-if, log, pin-project-lite, tracing-attributes, tracing-core, criterion,  │
│                    ┆         ┆        ┆ futures, log, tokio, wasm-bindgen-test                                       │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ toml_edit          ┆ 0.8.0   ┆        ┆ combine, indexmap, itertools, kstring, serde, criterion, pretty_assertions,  │
│                    ┆         ┆        ┆ serde_json, toml, toml-test-harness                                          │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ rust-releases      ┆ 0.16.1  ┆ 1.51.0 ┆ rust-releases-channel-manifests, rust-releases-core, rust-releases-io,       │
│                    ┆         ┆        ┆ rust-releases-rust-changelog, rust-releases-rust-dist,                       │
│                    ┆         ┆        ┆ rust-releases-rust-dist-with-cli, yare                                       │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ petgraph           ┆ 0.6.0   ┆        ┆ fixedbitset, indexmap, quickcheck, serde, serde_derive, bincode, defmac,     │
│                    ┆         ┆        ┆ itertools, odds, rand                                                        │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ once_cell          ┆ 1.8.0   ┆        ┆ parking_lot, crossbeam-utils, lazy_static, regex                             │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ json               ┆ 0.12.4  ┆        ┆                                                                              │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ indicatif          ┆ 0.16.2  ┆        ┆ console, lazy_static, number_prefix, rayon, regex, unicode-segmentation,     │
│                    ┆         ┆        ┆ unicode-width, rand, tokio                                                   │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ dirs               ┆ 4.0.0   ┆        ┆ dirs-sys                                                                     │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ console            ┆ 0.15.0  ┆        ┆ libc, once_cell, regex, terminal_size, unicode-width, encode_unicode,        │
│                    ┆         ┆        ┆ winapi, winapi-util                                                          │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ comfy-table        ┆ 4.1.1   ┆        ┆ crossterm, strum, strum_macros, unicode-width, criterion, doc-comment,       │
│                    ┆         ┆        ┆ pretty_assertions, proptest                                                  │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ clap               ┆ 2.33.3  ┆        ┆ atty, bitflags, clippy, strsim, term_size, textwrap, unicode-width, vec_map, │
│                    ┆         ┆        ┆ yaml-rust, lazy_static, regex, version-sync, ansi_term                       │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌â”ŧ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ cargo_metadata     ┆ 0.14.1  ┆        ┆ camino, cargo-platform, derive_builder, semver, serde, serde_json            │
└────────────────────┴─────────┴────────┴──────────────────────────────────────────────────────────────────────────────┘

NB: The dependencies which are listed with an empty MSRV cell do not specify a MSRV yet. At the time of writing, most dependencies in the cargo-msrv dependency tree did not have an MSRV defined.

cargo-msrv set

COMMAND

  • Standalone: cargo-msrv set
  • Through Cargo: cargo msrv set

PREVIEW

asciicast

DESCRIPTION

Set the MSRV in the Cargo manifest.

This is either the package.rust-version field or the package.metadata.msrv field in the Cargo manifest ( Cargo.toml).

EXAMPLES

  1. Set an MSRV by providing a two component Rust version
cargo msrv set 1.56
  1. Set an MSRV by providing a three component Rust version
cargo msrv set 1.58.1

cargo-msrv show

COMMAND

  • Standalone: cargo-msrv show
  • Through Cargo: cargo msrv show

PREVIEW

asciicast

DESCRIPTION

Print the crate author specified MSRV.

This is either the package.rust-version field or the package.metadata.msrv field in the Cargo manifest ( Cargo.toml).

EXAMPLES

  1. Show the MSRV specified by a crate author
cargo msrv show

cargo-msrv verify

COMMAND

  • Standalone: cargo-msrv verify
  • Through Cargo: cargo msrv verify

PREVIEW

asciicast

DESCRIPTION

Verify whether the MSRV can be satisfied.

The MSRV can be specified in the Cargo manifest (Cargo.toml) using either the package.rust-version (Rust >=1.56, recommended), or the package.metadata.msrv field.

If the check fails, the program returns with a non-zero exit code.

OPTIONS

--rust-version version

Specify the Rust version of a Rust toolchain, against which the crate will be checked for compatibility.

EXAMPLES

  1. Verify whether the MSRV specified in the Cargo manifest is satisfiable (Good case).

Given a minimal rust crate with the following Cargo.toml manifest:

[package]
name = "example"
version = "0.1.0"
edition = "2021"
rust-version = "1.56.0"

and this minimal lib.rs file:

fn main() {
    println!("Hello world");
}

We check whether the MSRV's check command, in this case the default cargo check, can be satisfied. The crate author specified the MSRV in the Cargo.toml, using the package.rust-version key. Since the example crate used no features requiring a more recent version than Rust 1.56, the check will be satisfied, and the program returns a with exit code 0 (success).

cargo msrv verify # Will succeed, and return with exit code 0
  1. Verify whether the MSRV specified in the Cargo manifest is satisfiable (Bad case).

Given a minimal rust crate with the following Cargo.toml manifest:

[package]
name = "example"
version = "0.1.0"
edition = "2021"
rust-version = "1.56.0"

and this minimal lib.rs file:

fn main() {
    let cmd = Command::new("ls");
    assert_eq!(cmd.get_program(), "ls"); // will fail because Command::get_program was introduced in 1.57, which is greater than 1.56 (the MSRV)
}

We check whether the MSRV's check command, in this case the default cargo check, can be satisfied. The crate author specified the MSRV in the Cargo.toml, using the package.rust-version key. Since the example crate used a feature requiring a more recent version than Rust 1.56, the check cannot be satisfied, and the program returns a with a non-zero exit code (failure).

cargo msrv verify # Will fail, and return a non-zero exit code
  1. Run the 'verify' subcommand on a crate not in our current working directory.
cargo msrv --path path/to/my/crate verify

This example shows how to use arguments (in this case --path) shared between the default cargo-msrv command and verify. Note that shared arguments must be specified before the subcommand (here verify).

  1. Run the 'verify' subcommand using a self-determined Rust version.
cargo msrv verify --rust-version 1.56

Verification in CI

You can run cargo msrv verify in continuous integration services to check the MSRV with every contribution.

GitLab CI/CD

Use this snippet to have a dedicated job in the test stage of your pipeline:

msrv:
  stage: test
  image:
    name: foresterre/cargo-msrv:latest
    entrypoint: [""]
  before_script:
    - rustc --version
    - cargo --version
    - cargo msrv --version
  script:
    - cargo msrv --output-format minimal verify

Note: The empty entrypoint is necessary because the image has cargo-msrv as its entrypoint. Since we want to run other commands, like cargo --version, GitLab requires either an empty entrypoint or a shell.