diff --git a/src/cargo/util/lints.rs b/src/cargo/util/lints.rs index 3a0db21d8923..29cb3817b146 100644 --- a/src/cargo/util/lints.rs +++ b/src/cargo/util/lints.rs @@ -69,28 +69,36 @@ pub trait LevelTrait { pkg_lints: &TomlToolLints, ws_lints: &TomlToolLints, edition: Edition, - ) -> (LintLevel, i8) { - let unspecified_level = if let Some(level) = self + ) -> (LintLevel, LintLevelReason, i8) { + let (unspecified_level, reason) = if let Some(level) = self .edition_lint_opts() .filter(|(e, _)| edition >= *e) .map(|(_, l)| l) { - level + (level, LintLevelReason::Edition(edition)) } else { - self.default_level() + (self.default_level(), LintLevelReason::Default) }; // Don't allow the group to be overridden if the level is `Forbid` if unspecified_level == LintLevel::Forbid { - return (unspecified_level, 0); + return (unspecified_level, reason, 0); } if let Some(defined_level) = pkg_lints.get(self.name()) { - (defined_level.level().into(), defined_level.priority()) + ( + defined_level.level().into(), + LintLevelReason::Package, + defined_level.priority(), + ) } else if let Some(defined_level) = ws_lints.get(self.name()) { - (defined_level.level().into(), defined_level.priority()) + ( + defined_level.level().into(), + LintLevelReason::Workspace, + defined_level.priority(), + ) } else { - (unspecified_level, 0) + (unspecified_level, reason, 0) } } } @@ -153,7 +161,7 @@ impl Lint { lints: &TomlToolLints, ws_lints: &TomlToolLints, edition: Edition, - ) -> LintLevel { + ) -> (LintLevel, LintLevelReason) { self.groups .iter() .map(|g| (g.name, g.level_priority(lints, ws_lints, edition))) @@ -161,8 +169,8 @@ impl Lint { self.name, self.level_priority(lints, ws_lints, edition), ))) - .max_by_key(|(n, (l, p))| (l == &LintLevel::Forbid, *p, std::cmp::Reverse(*n))) - .map(|(_, (l, _))| l) + .max_by_key(|(n, (l, _, p))| (l == &LintLevel::Forbid, *p, std::cmp::Reverse(*n))) + .map(|(_, (l, r, _))| (l, r)) .unwrap() } } @@ -208,6 +216,25 @@ impl From for LintLevel { } } +#[derive(Copy, Clone, Debug)] +pub enum LintLevelReason { + Default, + Edition(Edition), + Package, + Workspace, +} + +impl Display for LintLevelReason { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + LintLevelReason::Default => write!(f, "by default"), + LintLevelReason::Edition(edition) => write!(f, "in edition {}", edition), + LintLevelReason::Package => write!(f, "in `[lints]`"), + LintLevelReason::Workspace => write!(f, "in `[workspace.lints]`"), + } + } +} + const IM_A_TEAPOT: Lint = Lint { name: "im_a_teapot", desc: "`im_a_teapot` is specified", @@ -225,7 +252,7 @@ pub fn check_im_a_teapot( gctx: &GlobalContext, ) -> CargoResult<()> { let manifest = pkg.manifest(); - let lint_level = IM_A_TEAPOT.level(pkg_lints, ws_lints, manifest.edition()); + let (lint_level, reason) = IM_A_TEAPOT.level(pkg_lints, ws_lints, manifest.edition()); if lint_level == LintLevel::Allow { return Ok(()); } @@ -240,7 +267,10 @@ pub fn check_im_a_teapot( } let level = lint_level.to_diagnostic_level(); let manifest_path = rel_cwd_manifest_path(path, gctx); - let emitted_reason = format!("`cargo::{}` is set to `{lint_level}`", IM_A_TEAPOT.name); + let emitted_reason = format!( + "`cargo::{}` is set to `{lint_level}` {reason}", + IM_A_TEAPOT.name + ); let key_span = get_span(manifest.document(), &["package", "im-a-teapot"], false).unwrap(); let value_span = get_span(manifest.document(), &["package", "im-a-teapot"], true).unwrap(); @@ -300,7 +330,7 @@ pub fn check_implicit_features( return Ok(()); } - let lint_level = IMPLICIT_FEATURES.level(pkg_lints, ws_lints, edition); + let (lint_level, reason) = IMPLICIT_FEATURES.level(pkg_lints, ws_lints, edition); if lint_level == LintLevel::Allow { return Ok(()); } @@ -345,7 +375,7 @@ pub fn check_implicit_features( ); if emitted_source.is_none() { emitted_source = Some(format!( - "`cargo::{}` is set to `{lint_level}`", + "`cargo::{}` is set to `{lint_level}` {reason}", IMPLICIT_FEATURES.name )); message = message.footer(Level::Note.title(emitted_source.as_ref().unwrap())); @@ -383,7 +413,7 @@ pub fn unused_dependencies( return Ok(()); } - let lint_level = UNUSED_OPTIONAL_DEPENDENCY.level(pkg_lints, ws_lints, edition); + let (lint_level, reason) = UNUSED_OPTIONAL_DEPENDENCY.level(pkg_lints, ws_lints, edition); if lint_level == LintLevel::Allow { return Ok(()); } @@ -449,7 +479,7 @@ pub fn unused_dependencies( ); if emitted_source.is_none() { emitted_source = Some(format!( - "`cargo::{}` is set to `{lint_level}`", + "`cargo::{}` is set to `{lint_level}` {reason}", UNUSED_OPTIONAL_DEPENDENCY.name )); message = diff --git a/tests/testsuite/lints/implicit_features/edition_2021_warn/stderr.term.svg b/tests/testsuite/lints/implicit_features/edition_2021_warn/stderr.term.svg index 75040932d829..11affcc2ee0c 100644 --- a/tests/testsuite/lints/implicit_features/edition_2021_warn/stderr.term.svg +++ b/tests/testsuite/lints/implicit_features/edition_2021_warn/stderr.term.svg @@ -33,7 +33,7 @@ | - = note: `cargo::implicit_features` is set to `warn` + = note: `cargo::implicit_features` is set to `warn` in `[lints]` warning: implicit features for optional dependencies is deprecated and will be unavailable in the 2024 edition diff --git a/tests/testsuite/lints/unused_optional_dependencies/edition_2024/stderr.term.svg b/tests/testsuite/lints/unused_optional_dependencies/edition_2024/stderr.term.svg index 1b93aa050e55..84eddf6de579 100644 --- a/tests/testsuite/lints/unused_optional_dependencies/edition_2024/stderr.term.svg +++ b/tests/testsuite/lints/unused_optional_dependencies/edition_2024/stderr.term.svg @@ -34,7 +34,7 @@ | - = note: `cargo::unused_optional_dependency` is set to `warn` + = note: `cargo::unused_optional_dependency` is set to `warn` by default = help: remove the dependency or activate it in a feature with `dep:bar` diff --git a/tests/testsuite/lints/unused_optional_dependencies/renamed_deps/stderr.term.svg b/tests/testsuite/lints/unused_optional_dependencies/renamed_deps/stderr.term.svg index 4d76be9bfbe6..2f1c99bec30e 100644 --- a/tests/testsuite/lints/unused_optional_dependencies/renamed_deps/stderr.term.svg +++ b/tests/testsuite/lints/unused_optional_dependencies/renamed_deps/stderr.term.svg @@ -34,7 +34,7 @@ | - = note: `cargo::unused_optional_dependency` is set to `warn` + = note: `cargo::unused_optional_dependency` is set to `warn` by default = help: remove the dependency or activate it in a feature with `dep:bar` diff --git a/tests/testsuite/lints_table.rs b/tests/testsuite/lints_table.rs index ad55849e4f23..75d0de4ee271 100644 --- a/tests/testsuite/lints_table.rs +++ b/tests/testsuite/lints_table.rs @@ -852,7 +852,7 @@ warning: `im_a_teapot` is specified 9 | im-a-teapot = true | ------------------ | - = note: `cargo::im_a_teapot` is set to `warn` + = note: `cargo::im_a_teapot` is set to `warn` in `[lints]` [CHECKING] foo v0.0.1 ([CWD]) [FINISHED] [..] ", @@ -892,7 +892,7 @@ warning: `im_a_teapot` is specified 9 | im-a-teapot = true | ------------------ | - = note: `cargo::im_a_teapot` is set to `warn` + = note: `cargo::im_a_teapot` is set to `warn` in `[lints]` [CHECKING] foo v0.0.1 ([CWD]) [FINISHED] [..] ", @@ -934,7 +934,7 @@ error: `im_a_teapot` is specified 9 | im-a-teapot = true | ^^^^^^^^^^^^^^^^^^ | - = note: `cargo::im_a_teapot` is set to `forbid` + = note: `cargo::im_a_teapot` is set to `forbid` in `[lints]` ", ) .run(); @@ -977,7 +977,7 @@ error: `im_a_teapot` is specified 13 | im-a-teapot = true | ^^^^^^^^^^^^^^^^^^ | - = note: `cargo::im_a_teapot` is set to `forbid` + = note: `cargo::im_a_teapot` is set to `forbid` in `[workspace.lints]` ", ) .run();