From fb08c99bdf53bfff3333c40ff51a1e5447545692 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 20 Jan 2026 18:50:18 -0700 Subject: [PATCH 1/3] test: Make a implicit_minimum_version_req test ordered --- .../lints/implicit_minimum_version_req.rs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/tests/testsuite/lints/implicit_minimum_version_req.rs b/tests/testsuite/lints/implicit_minimum_version_req.rs index 80044e20f31..cdfcd5ba121 100644 --- a/tests/testsuite/lints/implicit_minimum_version_req.rs +++ b/tests/testsuite/lints/implicit_minimum_version_req.rs @@ -948,10 +948,9 @@ implicit_minimum_version_req = "warn" .file("src/lib.rs", "") .build(); - p.cargo("check -Zcargo-lints") + p.cargo("check -Zcargo-lints --quiet") .masquerade_as_nightly_cargo(&["cargo-lints"]) - .with_stderr_data( - str![[r#" + .with_stderr_data(str![[r#" [WARNING] dependency version requirement without an explicit minimum version --> Cargo.toml:7:7 | @@ -974,19 +973,8 @@ implicit_minimum_version_req = "warn" 8 | regex = "1.0.0" | ++ = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` -[UPDATING] `dummy-registry` index -[LOCKING] 2 packages to latest compatible versions -[DOWNLOADING] crates ... -[DOWNLOADED] regex v1.0.0 (registry `dummy-registry`) -[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`) -[CHECKING] dep v1.0.0 -[CHECKING] regex v1.0.0 -[CHECKING] foo v0.0.0 ([ROOT]/foo) -[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s -"#]] - .unordered(), - ) +"#]]) .run(); } From 768308307b69fe966da15fa62131e41ee2052369 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 20 Jan 2026 18:50:18 -0700 Subject: [PATCH 2/3] fix: Move implicit_minimum_version_req emitted source to primary group --- .../rules/implicit_minimum_version_req.rs | 19 +++++----- .../lints/implicit_minimum_version_req.rs | 36 +++++++++---------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/cargo/lints/rules/implicit_minimum_version_req.rs b/src/cargo/lints/rules/implicit_minimum_version_req.rs index 6de25b24021..c4b883245cc 100644 --- a/src/cargo/lints/rules/implicit_minimum_version_req.rs +++ b/src/cargo/lints/rules/implicit_minimum_version_req.rs @@ -272,17 +272,18 @@ fn report<'a>( let Some(span) = span_of_version_req(document, key_path) else { return None; }; - desc = desc.element( - Snippet::source(contents) - .path(manifest_path.to_owned()) - .annotation(AnnotationKind::Primary.span(span.clone()).label(label)), - ); - help = help - .element(Snippet::source(contents).patch(Patch::new(span.clone(), replacement))) + desc = desc + .element( + Snippet::source(contents) + .path(manifest_path.to_owned()) + .annotation(AnnotationKind::Primary.span(span.clone()).label(label)), + ) .element(Level::NOTE.message(emitted_source)); + help = help.element(Snippet::source(contents).patch(Patch::new(span.clone(), replacement))); } else { - desc = desc.element(Origin::path(manifest_path.to_owned())); - help = help.element(Level::NOTE.message(emitted_source)); + desc = desc + .element(Origin::path(manifest_path.to_owned())) + .element(Level::NOTE.message(emitted_source)); } Some([desc, help]) diff --git a/tests/testsuite/lints/implicit_minimum_version_req.rs b/tests/testsuite/lints/implicit_minimum_version_req.rs index cdfcd5ba121..fa41da2c50e 100644 --- a/tests/testsuite/lints/implicit_minimum_version_req.rs +++ b/tests/testsuite/lints/implicit_minimum_version_req.rs @@ -39,11 +39,11 @@ implicit_minimum_version_req = "warn" 7 | dep = "1" | ^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = "1.0.0" | ++++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [DOWNLOADING] crates ... @@ -87,11 +87,11 @@ implicit_minimum_version_req = "warn" 7 | dep = "1.0" | ^^^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = "1.0.0" | ++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [DOWNLOADING] crates ... @@ -172,11 +172,11 @@ implicit_minimum_version_req = "warn" 7 | dep = { version = "1" } | ^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = { version = "1.0.0" } | ++++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [DOWNLOADING] crates ... @@ -220,11 +220,11 @@ implicit_minimum_version_req = "warn" 7 | dep = ">=1.0" | ^^^^^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = ">=1.0.0" | ++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [DOWNLOADING] crates ... @@ -453,11 +453,11 @@ implicit_minimum_version_req = "warn" 7 | dep = ">=1.0, <2.0" | ^^^^^^^^^^^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = ">=1.0.0, <2.0" | ++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [DOWNLOADING] crates ... @@ -626,11 +626,11 @@ edition = "2021" 7 | bar = { path = "bar", version = "0.1" } | ^^^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | bar = { path = "bar", version = "0.1.0" } | ++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [LOCKING] 1 package to latest compatible version [CHECKING] bar v0.1.0 ([ROOT]/foo/bar) [CHECKING] foo v0.0.0 ([ROOT]/foo) @@ -720,11 +720,11 @@ implicit_minimum_version_req = "warn" 7 | bar = { git = '[ROOTURL]/bar', version = "0.1" } | [..]^^^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | bar = { git = '[ROOTURL]/bar', version = "0.1.0" } | [..]++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] git repository `[ROOTURL]/bar` [LOCKING] 1 package to latest compatible version [CHECKING] bar v0.1.0 ([ROOTURL]/bar#[..]) @@ -766,11 +766,11 @@ implicit_minimum_version_req = "warn" 7 | dep = "1" | ^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = "1.0.0" | ++++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [CHECKING] foo v0.0.0 ([ROOT]/foo) @@ -812,11 +812,11 @@ implicit_minimum_version_req = "warn" 7 | dep = "1.0" | ^^^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = "1.0.0" | ++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [DOWNLOADING] crates ... @@ -861,11 +861,11 @@ implicit_minimum_version_req = "warn" 8 | dep = "1" | ^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 8 | dep = "1.0.0" | ++++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [DOWNLOADING] crates ... @@ -910,11 +910,11 @@ implicit_minimum_version_req = "warn" 8 | dep = "1" | ^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 8 | dep = "1.0.0" | ++++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [CHECKING] foo v0.0.0 ([ROOT]/foo) @@ -957,22 +957,22 @@ implicit_minimum_version_req = "warn" 7 | dep = "1" | ^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = "1.0.0" | ++++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [WARNING] dependency version requirement without an explicit minimum version --> Cargo.toml:8:9 | 8 | regex = "1.0" | ^^^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 8 | regex = "1.0.0" | ++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` "#]]) .run(); @@ -1023,11 +1023,11 @@ workspace = true 7 | dep = "1" | ^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = "1.0.0" | ++++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [DOWNLOADING] crates ... @@ -1080,11 +1080,11 @@ edition = "2021" 7 | dep = "1" | ^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = "1.0.0" | ++++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [CHECKING] member v0.0.0 ([ROOT]/foo/member) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s @@ -1138,22 +1138,22 @@ workspace = true 7 | dep = "1" | ^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = "1.0.0" | ++++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [WARNING] dependency version requirement without an explicit minimum version --> member/Cargo.toml:7:7 | 7 | dep = "1.0" | ^^^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = "1.0.0" | ++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [UPDATING] `dummy-registry` index [LOCKING] 1 package to latest compatible version [DOWNLOADING] crates ... @@ -1198,11 +1198,11 @@ implicit_minimum_version_req = "deny" 7 | dep = "1" | ^^^ missing full version components | + = [NOTE] `cargo::implicit_minimum_version_req` is set to `deny` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 7 | dep = "1.0.0" | ++++ - = [NOTE] `cargo::implicit_minimum_version_req` is set to `deny` in `[lints]` [ERROR] encountered 1 error while running lints "#]]) From 0f6e2325183680ab5e77595c08a7b7847afc79a3 Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Tue, 20 Jan 2026 18:50:18 -0700 Subject: [PATCH 3/3] fix: show implicit_minimum_version_req emitted source once per package --- .../rules/implicit_minimum_version_req.rs | 34 +++++++++++++------ .../lints/implicit_minimum_version_req.rs | 1 - 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/cargo/lints/rules/implicit_minimum_version_req.rs b/src/cargo/lints/rules/implicit_minimum_version_req.rs index c4b883245cc..f3f0ccdc695 100644 --- a/src/cargo/lints/rules/implicit_minimum_version_req.rs +++ b/src/cargo/lints/rules/implicit_minimum_version_req.rs @@ -126,6 +126,7 @@ pub fn lint_package( let contents = manifest.contents(); let target_key_for_platform = target_key_for_platform(&manifest); + let mut emit_source = true; for dep in manifest.dependencies().iter() { let version_req = dep.version_req(); let Some(suggested_req) = get_suggested_version_req(&version_req) else { @@ -148,10 +149,15 @@ pub fn lint_package( key_path, &manifest_path, &suggested_req, + emit_source, ) else { continue; }; + if emit_source { + emit_source = false; + } + if lint_level.is_error() { *error_count += 1; } @@ -198,6 +204,7 @@ pub fn lint_workspace( (name, req) }); + let mut emit_source = true; for (name_in_toml, version_req) in dep_iter { let Some(suggested_req) = get_suggested_version_req(&version_req) else { continue; @@ -213,10 +220,15 @@ pub fn lint_workspace( &key_path, &manifest_path, &suggested_req, + emit_source, ) else { continue; }; + if emit_source { + emit_source = false; + } + if lint_level.is_error() { *error_count += 1; } @@ -256,6 +268,7 @@ fn report<'a>( key_path: &[&str], manifest_path: &str, suggested_req: &str, + emit_source: bool, ) -> Option<[Group<'a>; 2]> { let level = lint_level.to_diagnostic_level(); let emitted_source = LINT.emitted_source(lint_level, reason); @@ -272,18 +285,19 @@ fn report<'a>( let Some(span) = span_of_version_req(document, key_path) else { return None; }; - desc = desc - .element( - Snippet::source(contents) - .path(manifest_path.to_owned()) - .annotation(AnnotationKind::Primary.span(span.clone()).label(label)), - ) - .element(Level::NOTE.message(emitted_source)); + desc = desc.element( + Snippet::source(contents) + .path(manifest_path.to_owned()) + .annotation(AnnotationKind::Primary.span(span.clone()).label(label)), + ); + help = help.element(Snippet::source(contents).patch(Patch::new(span.clone(), replacement))); } else { - desc = desc - .element(Origin::path(manifest_path.to_owned())) - .element(Level::NOTE.message(emitted_source)); + desc = desc.element(Origin::path(manifest_path.to_owned())); + } + + if emit_source { + desc = desc.element(Level::NOTE.message(emitted_source)); } Some([desc, help]) diff --git a/tests/testsuite/lints/implicit_minimum_version_req.rs b/tests/testsuite/lints/implicit_minimum_version_req.rs index fa41da2c50e..a88fb315e05 100644 --- a/tests/testsuite/lints/implicit_minimum_version_req.rs +++ b/tests/testsuite/lints/implicit_minimum_version_req.rs @@ -968,7 +968,6 @@ implicit_minimum_version_req = "warn" 8 | regex = "1.0" | ^^^^^ missing full version components | - = [NOTE] `cargo::implicit_minimum_version_req` is set to `warn` in `[lints]` [HELP] consider specifying full `major.minor.patch` version components | 8 | regex = "1.0.0"