diff --git a/src/bin/cargo/commands/add.rs b/src/bin/cargo/commands/add.rs
index 39f0e189e3d..90c4f4dd5df 100644
--- a/src/bin/cargo/commands/add.rs
+++ b/src/bin/cargo/commands/add.rs
@@ -72,6 +72,10 @@ The package will be removed from your features.")
Example uses:
- Depending on multiple versions of a crate
- Depend on crates with the same name from different registries"),
+ flag(
+ "ignore-rust-version",
+ "Ignore `rust-version` specification in packages (unstable)"
+ ),
])
.arg_manifest_path()
.arg_package("Package to modify")
@@ -188,12 +192,24 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let dependencies = parse_dependencies(config, args)?;
+ let ignore_rust_version = args.flag("ignore-rust-version");
+ if ignore_rust_version && !config.cli_unstable().msrv_policy {
+ return Err(CliError::new(
+ anyhow::format_err!(
+ "`--ignore-rust-version` is unstable; pass `-Zmsrv-policy` to enable support for it"
+ ),
+ 101,
+ ));
+ }
+ let honor_rust_version = !ignore_rust_version;
+
let options = AddOptions {
config,
spec,
dependencies,
section,
dry_run,
+ honor_rust_version,
};
add(&ws, &options)?;
diff --git a/src/cargo/ops/cargo_add/mod.rs b/src/cargo/ops/cargo_add/mod.rs
index 5c519ac09f0..11ca282ee42 100644
--- a/src/cargo/ops/cargo_add/mod.rs
+++ b/src/cargo/ops/cargo_add/mod.rs
@@ -51,6 +51,8 @@ pub struct AddOptions<'a> {
pub section: DepTable,
/// Act as if dependencies will be added
pub dry_run: bool,
+ /// Whether the minimum supported Rust version should be considered during resolution
+ pub honor_rust_version: bool,
}
/// Add dependencies to a manifest
@@ -86,7 +88,9 @@ pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<(
&manifest,
raw,
workspace,
+ &options.spec,
&options.section,
+ options.honor_rust_version,
options.config,
&mut registry,
)
@@ -256,7 +260,9 @@ fn resolve_dependency(
manifest: &LocalManifest,
arg: &DepOp,
ws: &Workspace<'_>,
+ spec: &Package,
section: &DepTable,
+ honor_rust_version: bool,
config: &Config,
registry: &mut PackageRegistry<'_>,
) -> CargoResult {
@@ -368,7 +374,14 @@ fn resolve_dependency(
}
dependency = dependency.set_source(src);
} else {
- let latest = get_latest_dependency(&dependency, false, config, registry)?;
+ let latest = get_latest_dependency(
+ spec,
+ &dependency,
+ false,
+ honor_rust_version,
+ config,
+ registry,
+ )?;
if dependency.name != latest.name {
config.shell().warn(format!(
@@ -518,8 +531,10 @@ fn get_existing_dependency(
}
fn get_latest_dependency(
+ spec: &Package,
dependency: &Dependency,
_flag_allow_prerelease: bool,
+ honor_rust_version: bool,
config: &Config,
registry: &mut PackageRegistry<'_>,
) -> CargoResult {
@@ -529,7 +544,7 @@ fn get_latest_dependency(
unreachable!("registry dependencies required, found a workspace dependency");
}
MaybeWorkspace::Other(query) => {
- let possibilities = loop {
+ let mut possibilities = loop {
match registry.query_vec(&query, QueryKind::Fuzzy) {
std::task::Poll::Ready(res) => {
break res?;
@@ -537,19 +552,79 @@ fn get_latest_dependency(
std::task::Poll::Pending => registry.block_until_ready()?,
}
};
- let latest = possibilities
- .iter()
- .max_by_key(|s| {
- // Fallback to a pre-release if no official release is available by sorting them as
- // less.
- let stable = s.version().pre.is_empty();
- (stable, s.version())
- })
- .ok_or_else(|| {
- anyhow::format_err!(
- "the crate `{dependency}` could not be found in registry index."
- )
- })?;
+
+ possibilities.sort_by_key(|s| {
+ // Fallback to a pre-release if no official release is available by sorting them as
+ // less.
+ let stable = s.version().pre.is_empty();
+ (stable, s.version().clone())
+ });
+
+ let mut latest = possibilities.last().ok_or_else(|| {
+ anyhow::format_err!(
+ "the crate `{dependency}` could not be found in registry index."
+ )
+ })?;
+
+ if config.cli_unstable().msrv_policy && honor_rust_version {
+ fn parse_msrv(rust_version: impl AsRef) -> (u64, u64, u64) {
+ // HACK: `rust-version` is a subset of the `VersionReq` syntax that only ever
+ // has one comparator with a required minor and optional patch, and uses no
+ // other features. If in the future this syntax is expanded, this code will need
+ // to be updated.
+ let version_req = semver::VersionReq::parse(rust_version.as_ref()).unwrap();
+ assert!(version_req.comparators.len() == 1);
+ let comp = &version_req.comparators[0];
+ assert_eq!(comp.op, semver::Op::Caret);
+ assert_eq!(comp.pre, semver::Prerelease::EMPTY);
+ (comp.major, comp.minor.unwrap_or(0), comp.patch.unwrap_or(0))
+ }
+
+ if let Some(req_msrv) = spec.rust_version().map(parse_msrv) {
+ let msrvs = possibilities
+ .iter()
+ .map(|s| (s, s.rust_version().map(parse_msrv)))
+ .collect::>();
+
+ // Find the latest version of the dep which has a compatible rust-version. To
+ // determine whether or not one rust-version is compatible with another, we
+ // compare the lowest possible versions they could represent, and treat
+ // candidates without a rust-version as compatible by default.
+ let (latest_msrv, _) = msrvs
+ .iter()
+ .filter(|(_, v)| v.map(|msrv| req_msrv >= msrv).unwrap_or(true))
+ .last()
+ .ok_or_else(|| {
+ // Failing that, try to find the highest version with the lowest
+ // rust-version to report to the user.
+ let lowest_candidate = msrvs
+ .iter()
+ .min_set_by_key(|(_, v)| v)
+ .iter()
+ .map(|(s, _)| s)
+ .max_by_key(|s| s.version());
+ rust_version_incompat_error(
+ &dependency.name,
+ spec.rust_version().unwrap(),
+ lowest_candidate.copied(),
+ )
+ })?;
+
+ if latest_msrv.version() < latest.version() {
+ config.shell().warn(format_args!(
+ "ignoring `{dependency}@{latest_version}` (which has a rust-version of \
+ {latest_rust_version}) to satisfy this package's rust-version of \
+ {rust_version} (use `--ignore-rust-version` to override)",
+ latest_version = latest.version(),
+ latest_rust_version = latest.rust_version().unwrap(),
+ rust_version = spec.rust_version().unwrap(),
+ ))?;
+
+ latest = latest_msrv;
+ }
+ }
+ }
+
let mut dep = Dependency::from(latest);
if let Some(reg_name) = dependency.registry.as_deref() {
dep = dep.set_registry(reg_name);
@@ -559,6 +634,31 @@ fn get_latest_dependency(
}
}
+fn rust_version_incompat_error(
+ dep: &str,
+ rust_version: &str,
+ lowest_rust_version: Option<&Summary>,
+) -> anyhow::Error {
+ let mut error_msg = format!(
+ "could not find version of crate `{dep}` that satisfies this package's rust-version of \
+ {rust_version}\n\
+ help: use `--ignore-rust-version` to override this behavior"
+ );
+
+ if let Some(lowest) = lowest_rust_version {
+ // rust-version must be present for this candidate since it would have been selected as
+ // compatible previously if it weren't.
+ let version = lowest.version();
+ let rust_version = lowest.rust_version().unwrap();
+ error_msg.push_str(&format!(
+ "\nnote: the lowest rust-version available for `{dep}` is {rust_version}, used in \
+ version {version}"
+ ));
+ }
+
+ anyhow::format_err!(error_msg)
+}
+
fn select_package(
dependency: &Dependency,
config: &Config,
diff --git a/src/doc/man/cargo-add.md b/src/doc/man/cargo-add.md
index c441a82b2ff..3c15fc9d5db 100644
--- a/src/doc/man/cargo-add.md
+++ b/src/doc/man/cargo-add.md
@@ -123,6 +123,15 @@ crates, the features for a specific crate may be enabled with
which enables all specified features.
{{/option}}
+{{#option "`--ignore-rust-version`" }}
+Ignore `rust-version` specification in packages.
+
+This option is unstable and available only on the
+[nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html)
+and requires the `-Z unstable-options` flag to enable.
+See for more information.
+{{/option}}
+
{{/options}}
diff --git a/src/doc/man/generated_txt/cargo-add.txt b/src/doc/man/generated_txt/cargo-add.txt
index ac332a44e72..6447499dc04 100644
--- a/src/doc/man/generated_txt/cargo-add.txt
+++ b/src/doc/man/generated_txt/cargo-add.txt
@@ -111,6 +111,15 @@ OPTIONS
be enabled with package-name/feature-name syntax. This flag may be
specified multiple times, which enables all specified features.
+ --ignore-rust-version
+ Ignore rust-version specification in packages.
+
+ This option is unstable and available only on the nightly channel
+ and
+ requires the -Z unstable-options flag to enable. See
+ for more
+ information.
+
Display Options
-v, --verbose
Use verbose output. May be specified twice for “very verbose”
diff --git a/src/doc/src/commands/cargo-add.md b/src/doc/src/commands/cargo-add.md
index 89c1cc6f1ea..132c093264d 100644
--- a/src/doc/src/commands/cargo-add.md
+++ b/src/doc/src/commands/cargo-add.md
@@ -129,6 +129,14 @@ crates, the features for a specific crate may be enabled with
which enables all specified features.
+--ignore-rust-version
+Ignore rust-version
specification in packages.
+This option is unstable and available only on the
+nightly channel
+and requires the -Z unstable-options
flag to enable.
+See https://github.com/rust-lang/cargo/issues/5579 for more information.
+
+
diff --git a/src/etc/man/cargo-add.1 b/src/etc/man/cargo-add.1
index 086a561fd65..f69e6d0db2f 100644
--- a/src/etc/man/cargo-add.1
+++ b/src/etc/man/cargo-add.1
@@ -140,6 +140,16 @@ crates, the features for a specific crate may be enabled with
\fBpackage\-name/feature\-name\fR syntax. This flag may be specified multiple times,
which enables all specified features.
.RE
+.sp
+\fB\-\-ignore\-rust\-version\fR
+.RS 4
+Ignore \fBrust\-version\fR specification in packages.
+.sp
+This option is unstable and available only on the
+\fInightly channel\fR
+and requires the \fB\-Z unstable\-options\fR flag to enable.
+See for more information.
+.RE
.SS "Display Options"
.sp
\fB\-v\fR,
diff --git a/tests/testsuite/cargo_add/mod.rs b/tests/testsuite/cargo_add/mod.rs
index 26a11dd8a49..cd7e94e0995 100644
--- a/tests/testsuite/cargo_add/mod.rs
+++ b/tests/testsuite/cargo_add/mod.rs
@@ -102,6 +102,10 @@ mod quiet;
mod registry;
mod rename;
mod require_weak;
+mod rust_version_ignore;
+mod rust_version_incompatible;
+mod rust_version_latest;
+mod rust_version_older;
mod sorted_table_with_dotted_item;
mod target;
mod target_cfg;
diff --git a/tests/testsuite/cargo_add/rust_version_ignore/in/Cargo.toml b/tests/testsuite/cargo_add/rust_version_ignore/in/Cargo.toml
new file mode 100644
index 00000000000..b24cd9deb20
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_ignore/in/Cargo.toml
@@ -0,0 +1,6 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.68"
diff --git a/tests/testsuite/cargo_add/rust_version_ignore/in/src/lib.rs b/tests/testsuite/cargo_add/rust_version_ignore/in/src/lib.rs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_ignore/mod.rs b/tests/testsuite/cargo_add/rust_version_ignore/mod.rs
new file mode 100644
index 00000000000..9aa11eaac95
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_ignore/mod.rs
@@ -0,0 +1,36 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use crate::cargo_add::init_registry;
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ init_registry();
+
+ cargo_test_support::registry::Package::new("rust-version-user", "0.1.0")
+ .rust_version("1.66")
+ .publish();
+ cargo_test_support::registry::Package::new("rust-version-user", "0.2.1")
+ .rust_version("1.72")
+ .publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("-Zmsrv-policy")
+ .arg("add")
+ .arg("--ignore-rust-version")
+ .arg_line("rust-version-user")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/tests/testsuite/cargo_add/rust_version_ignore/out/Cargo.toml b/tests/testsuite/cargo_add/rust_version_ignore/out/Cargo.toml
new file mode 100644
index 00000000000..62164a3445a
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_ignore/out/Cargo.toml
@@ -0,0 +1,9 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.68"
+
+[dependencies]
+rust-version-user = "0.2.1"
diff --git a/tests/testsuite/cargo_add/rust_version_ignore/out/src/lib.rs b/tests/testsuite/cargo_add/rust_version_ignore/out/src/lib.rs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_ignore/stderr.log b/tests/testsuite/cargo_add/rust_version_ignore/stderr.log
new file mode 100644
index 00000000000..430abe31b47
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_ignore/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding rust-version-user v0.2.1 to dependencies.
diff --git a/tests/testsuite/cargo_add/rust_version_ignore/stdout.log b/tests/testsuite/cargo_add/rust_version_ignore/stdout.log
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_incompatible/in/Cargo.toml b/tests/testsuite/cargo_add/rust_version_incompatible/in/Cargo.toml
new file mode 100644
index 00000000000..ef6fce441ff
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_incompatible/in/Cargo.toml
@@ -0,0 +1,6 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.56"
diff --git a/tests/testsuite/cargo_add/rust_version_incompatible/in/src/lib.rs b/tests/testsuite/cargo_add/rust_version_incompatible/in/src/lib.rs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs b/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs
new file mode 100644
index 00000000000..6baad0e05b1
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs
@@ -0,0 +1,38 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use crate::cargo_add::init_registry;
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ init_registry();
+
+ cargo_test_support::registry::Package::new("rust-version-user", "0.1.0")
+ .rust_version("1.66")
+ .publish();
+ cargo_test_support::registry::Package::new("rust-version-user", "0.1.1")
+ .rust_version("1.66")
+ .publish();
+ cargo_test_support::registry::Package::new("rust-version-user", "0.2.1")
+ .rust_version("1.72")
+ .publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("-Zmsrv-policy")
+ .arg("add")
+ .arg_line("rust-version-user")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .assert()
+ .failure()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/tests/testsuite/cargo_add/rust_version_incompatible/out/Cargo.toml b/tests/testsuite/cargo_add/rust_version_incompatible/out/Cargo.toml
new file mode 100644
index 00000000000..ef6fce441ff
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_incompatible/out/Cargo.toml
@@ -0,0 +1,6 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.56"
diff --git a/tests/testsuite/cargo_add/rust_version_incompatible/out/src/lib.rs b/tests/testsuite/cargo_add/rust_version_incompatible/out/src/lib.rs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_incompatible/stderr.log b/tests/testsuite/cargo_add/rust_version_incompatible/stderr.log
new file mode 100644
index 00000000000..babed5b23ca
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_incompatible/stderr.log
@@ -0,0 +1,4 @@
+ Updating `dummy-registry` index
+error: could not find version of crate `rust-version-user` that satisfies this package's rust-version of 1.56
+help: use `--ignore-rust-version` to override this behavior
+note: the lowest rust-version available for `rust-version-user` is 1.66, used in version 0.1.1
diff --git a/tests/testsuite/cargo_add/rust_version_incompatible/stdout.log b/tests/testsuite/cargo_add/rust_version_incompatible/stdout.log
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_latest/in/Cargo.toml b/tests/testsuite/cargo_add/rust_version_latest/in/Cargo.toml
new file mode 100644
index 00000000000..d9358a5de5e
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_latest/in/Cargo.toml
@@ -0,0 +1,6 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.72"
diff --git a/tests/testsuite/cargo_add/rust_version_latest/in/src/lib.rs b/tests/testsuite/cargo_add/rust_version_latest/in/src/lib.rs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_latest/mod.rs b/tests/testsuite/cargo_add/rust_version_latest/mod.rs
new file mode 100644
index 00000000000..60e38960fa4
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_latest/mod.rs
@@ -0,0 +1,35 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use crate::cargo_add::init_registry;
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ init_registry();
+
+ cargo_test_support::registry::Package::new("rust-version-user", "0.1.0")
+ .rust_version("1.66")
+ .publish();
+ cargo_test_support::registry::Package::new("rust-version-user", "0.2.1")
+ .rust_version("1.72")
+ .publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("-Zmsrv-policy")
+ .arg("add")
+ .arg_line("rust-version-user")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/tests/testsuite/cargo_add/rust_version_latest/out/Cargo.toml b/tests/testsuite/cargo_add/rust_version_latest/out/Cargo.toml
new file mode 100644
index 00000000000..f824b41c3d0
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_latest/out/Cargo.toml
@@ -0,0 +1,9 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.72"
+
+[dependencies]
+rust-version-user = "0.2.1"
diff --git a/tests/testsuite/cargo_add/rust_version_latest/out/src/lib.rs b/tests/testsuite/cargo_add/rust_version_latest/out/src/lib.rs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_latest/stderr.log b/tests/testsuite/cargo_add/rust_version_latest/stderr.log
new file mode 100644
index 00000000000..430abe31b47
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_latest/stderr.log
@@ -0,0 +1,2 @@
+ Updating `dummy-registry` index
+ Adding rust-version-user v0.2.1 to dependencies.
diff --git a/tests/testsuite/cargo_add/rust_version_latest/stdout.log b/tests/testsuite/cargo_add/rust_version_latest/stdout.log
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_older/in/Cargo.toml b/tests/testsuite/cargo_add/rust_version_older/in/Cargo.toml
new file mode 100644
index 00000000000..6fd6f12324f
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_older/in/Cargo.toml
@@ -0,0 +1,6 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.70"
diff --git a/tests/testsuite/cargo_add/rust_version_older/in/src/lib.rs b/tests/testsuite/cargo_add/rust_version_older/in/src/lib.rs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_older/mod.rs b/tests/testsuite/cargo_add/rust_version_older/mod.rs
new file mode 100644
index 00000000000..60e38960fa4
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_older/mod.rs
@@ -0,0 +1,35 @@
+use cargo_test_support::compare::assert_ui;
+use cargo_test_support::prelude::*;
+use cargo_test_support::Project;
+
+use crate::cargo_add::init_registry;
+use cargo_test_support::curr_dir;
+
+#[cargo_test]
+fn case() {
+ init_registry();
+
+ cargo_test_support::registry::Package::new("rust-version-user", "0.1.0")
+ .rust_version("1.66")
+ .publish();
+ cargo_test_support::registry::Package::new("rust-version-user", "0.2.1")
+ .rust_version("1.72")
+ .publish();
+
+ let project = Project::from_template(curr_dir!().join("in"));
+ let project_root = project.root();
+ let cwd = &project_root;
+
+ snapbox::cmd::Command::cargo_ui()
+ .arg("-Zmsrv-policy")
+ .arg("add")
+ .arg_line("rust-version-user")
+ .current_dir(cwd)
+ .masquerade_as_nightly_cargo(&["msrv-policy"])
+ .assert()
+ .success()
+ .stdout_matches_path(curr_dir!().join("stdout.log"))
+ .stderr_matches_path(curr_dir!().join("stderr.log"));
+
+ assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
+}
diff --git a/tests/testsuite/cargo_add/rust_version_older/out/Cargo.toml b/tests/testsuite/cargo_add/rust_version_older/out/Cargo.toml
new file mode 100644
index 00000000000..14737e3288d
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_older/out/Cargo.toml
@@ -0,0 +1,9 @@
+[workspace]
+
+[package]
+name = "cargo-list-test-fixture"
+version = "0.0.0"
+rust-version = "1.70"
+
+[dependencies]
+rust-version-user = "0.1.0"
diff --git a/tests/testsuite/cargo_add/rust_version_older/out/src/lib.rs b/tests/testsuite/cargo_add/rust_version_older/out/src/lib.rs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/testsuite/cargo_add/rust_version_older/stderr.log b/tests/testsuite/cargo_add/rust_version_older/stderr.log
new file mode 100644
index 00000000000..4c5988d0bb0
--- /dev/null
+++ b/tests/testsuite/cargo_add/rust_version_older/stderr.log
@@ -0,0 +1,3 @@
+ Updating `dummy-registry` index
+warning: ignoring `rust-version-user@0.2.1` (which has a rust-version of 1.72) to satisfy this package's rust-version of 1.70 (use `--ignore-rust-version` to override)
+ Adding rust-version-user v0.1.0 to dependencies.
diff --git a/tests/testsuite/cargo_add/rust_version_older/stdout.log b/tests/testsuite/cargo_add/rust_version_older/stdout.log
new file mode 100644
index 00000000000..e69de29bb2d