Skip to content

Commit abf0953

Browse files
committed
feat: Add -Zcargo-lints
1 parent 7ff7e34 commit abf0953

File tree

4 files changed

+180
-38
lines changed

4 files changed

+180
-38
lines changed

src/cargo/core/features.rs

+2
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,7 @@ unstable_cli_options!(
750750
#[serde(deserialize_with = "deserialize_build_std")]
751751
build_std: Option<Vec<String>> = ("Enable Cargo to compile the standard library itself as part of a crate graph compilation"),
752752
build_std_features: Option<Vec<String>> = ("Configure features enabled for the standard library itself when building the standard library"),
753+
cargo_lints: bool = ("Enable the `[lints.cargo]` table"),
753754
check_cfg: bool = ("Enable compile-time checking of `cfg` names/values/features"),
754755
codegen_backend: bool = ("Enable the `codegen-backend` option in profiles in .cargo/config.toml file"),
755756
config_include: bool = ("Enable the `include` key in config files"),
@@ -1117,6 +1118,7 @@ impl CliUnstable {
11171118
self.build_std = Some(crate::core::compiler::standard_lib::parse_unstable_flag(v))
11181119
}
11191120
"build-std-features" => self.build_std_features = Some(parse_features(v)),
1121+
"cargo-lints" => self.cargo_lints = parse_empty(k, v)?,
11201122
"check-cfg" => {
11211123
self.check_cfg = parse_empty(k, v)?;
11221124
}

src/cargo/util/toml/mod.rs

+46-5
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ pub fn to_real_manifest(
494494

495495
let workspace_config = match (original_toml.workspace.as_ref(), package.workspace.as_ref()) {
496496
(Some(toml_config), None) => {
497-
verify_lints(toml_config.lints.as_ref())?;
497+
verify_lints(toml_config.lints.as_ref(), gctx, &mut warnings)?;
498498
if let Some(ws_deps) = &toml_config.dependencies {
499499
for (name, dep) in ws_deps {
500500
unused_dep_keys(
@@ -828,7 +828,7 @@ pub fn to_real_manifest(
828828
.clone()
829829
.map(|mw| lints_inherit_with(mw, || inherit()?.lints()))
830830
.transpose()?;
831-
verify_lints(lints.as_ref())?;
831+
verify_lints(lints.as_ref(), gctx, manifest_ctx.warnings)?;
832832
let default = manifest::TomlLints::default();
833833
let rustflags = lints_to_rustflags(lints.as_ref().unwrap_or(&default));
834834

@@ -1322,7 +1322,7 @@ fn to_virtual_manifest(
13221322
.transpose()?;
13231323
let workspace_config = match original_toml.workspace {
13241324
Some(ref toml_config) => {
1325-
verify_lints(toml_config.lints.as_ref())?;
1325+
verify_lints(toml_config.lints.as_ref(), gctx, &mut warnings)?;
13261326
let ws_root_config = to_workspace_config(toml_config, root);
13271327
gctx.ws_roots
13281328
.borrow_mut()
@@ -1448,17 +1448,24 @@ struct ManifestContext<'a, 'b> {
14481448
features: &'a Features,
14491449
}
14501450

1451-
fn verify_lints(lints: Option<&manifest::TomlLints>) -> CargoResult<()> {
1451+
fn verify_lints(
1452+
lints: Option<&manifest::TomlLints>,
1453+
gctx: &GlobalContext,
1454+
warnings: &mut Vec<String>,
1455+
) -> CargoResult<()> {
14521456
let Some(lints) = lints else {
14531457
return Ok(());
14541458
};
14551459

14561460
for (tool, lints) in lints {
1457-
let supported = ["rust", "clippy", "rustdoc"];
1461+
let supported = ["cargo", "clippy", "rust", "rustdoc"];
14581462
if !supported.contains(&tool.as_str()) {
14591463
let supported = supported.join(", ");
14601464
anyhow::bail!("unsupported `{tool}` in `[lints]`, must be one of {supported}")
14611465
}
1466+
if tool == "cargo" && !gctx.cli_unstable().cargo_lints {
1467+
warn_for_cargo_lint_feature(gctx, warnings);
1468+
}
14621469
for name in lints.keys() {
14631470
if let Some((prefix, suffix)) = name.split_once("::") {
14641471
if tool == prefix {
@@ -1479,9 +1486,43 @@ fn verify_lints(lints: Option<&manifest::TomlLints>) -> CargoResult<()> {
14791486
Ok(())
14801487
}
14811488

1489+
fn warn_for_cargo_lint_feature(gctx: &GlobalContext, warnings: &mut Vec<String>) {
1490+
use std::fmt::Write as _;
1491+
1492+
let key_name = "lints.cargo";
1493+
let feature_name = "cargo-lints";
1494+
1495+
let mut message = String::new();
1496+
1497+
let _ = write!(
1498+
message,
1499+
"unused manifest key `{key_name}` (may be supported in a future version)"
1500+
);
1501+
if gctx.nightly_features_allowed {
1502+
let _ = write!(
1503+
message,
1504+
"
1505+
1506+
consider passing `-Z{feature_name}` to enable this feature."
1507+
);
1508+
} else {
1509+
let _ = write!(
1510+
message,
1511+
"
1512+
1513+
this Cargo does not support nightly features, but if you
1514+
switch to nightly channel you can pass
1515+
`-Z{feature_name}` to enable this feature.",
1516+
);
1517+
}
1518+
warnings.push(message);
1519+
}
1520+
14821521
fn lints_to_rustflags(lints: &manifest::TomlLints) -> Vec<String> {
14831522
let mut rustflags = lints
14841523
.iter()
1524+
// We don't want to pass any of the `cargo` lints to `rustc`
1525+
.filter(|(tool, _)| tool != &"cargo")
14851526
.flat_map(|(tool, lints)| {
14861527
lints.iter().map(move |(name, config)| {
14871528
let flag = match config.level() {

tests/testsuite/cargo/z_help/stdout.term.svg

+34-32
Loading

tests/testsuite/lints_table.rs

+98-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ fn fail_on_invalid_tool() {
111111
[..]
112112
113113
Caused by:
114-
unsupported `super-awesome-linter` in `[lints]`, must be one of rust, clippy, rustdoc
114+
unsupported `super-awesome-linter` in `[lints]`, must be one of cargo, clippy, rust, rustdoc
115115
",
116116
)
117117
.run();
@@ -749,3 +749,100 @@ pub const Ĕ: i32 = 2;
749749
)
750750
.run();
751751
}
752+
753+
#[cargo_test]
754+
fn cargo_lints_nightly_required() {
755+
let foo = project()
756+
.file(
757+
"Cargo.toml",
758+
r#"
759+
[package]
760+
name = "foo"
761+
version = "0.0.1"
762+
edition = "2015"
763+
authors = []
764+
765+
[lints.cargo]
766+
"unused-features" = "deny"
767+
"#,
768+
)
769+
.file("src/lib.rs", "")
770+
.build();
771+
772+
foo.cargo("check")
773+
.with_stderr(
774+
"\
775+
[WARNING] unused manifest key `lints.cargo` (may be supported in a future version)
776+
777+
this Cargo does not support nightly features, but if you
778+
switch to nightly channel you can pass
779+
`-Zcargo-lints` to enable this feature.
780+
[CHECKING] foo v0.0.1 ([CWD])
781+
[FINISHED] [..]
782+
",
783+
)
784+
.run();
785+
}
786+
787+
#[cargo_test]
788+
fn cargo_lints_no_z_flag() {
789+
let foo = project()
790+
.file(
791+
"Cargo.toml",
792+
r#"
793+
[package]
794+
name = "foo"
795+
version = "0.0.1"
796+
edition = "2015"
797+
authors = []
798+
799+
[lints.cargo]
800+
"unused-features" = "deny"
801+
"#,
802+
)
803+
.file("src/lib.rs", "")
804+
.build();
805+
806+
foo.cargo("check")
807+
.masquerade_as_nightly_cargo(&["-Zcargo-lints"])
808+
.with_stderr(
809+
"\
810+
[WARNING] unused manifest key `lints.cargo` (may be supported in a future version)
811+
812+
consider passing `-Zcargo-lints` to enable this feature.
813+
[CHECKING] foo v0.0.1 ([CWD])
814+
[FINISHED] [..]
815+
",
816+
)
817+
.run();
818+
}
819+
820+
#[cargo_test]
821+
fn cargo_lints_success() {
822+
let foo = project()
823+
.file(
824+
"Cargo.toml",
825+
r#"
826+
[package]
827+
name = "foo"
828+
version = "0.0.1"
829+
edition = "2015"
830+
authors = []
831+
832+
[lints.cargo]
833+
"unused-features" = "deny"
834+
"#,
835+
)
836+
.file("src/lib.rs", "")
837+
.build();
838+
839+
foo.cargo("check -Zcargo-lints")
840+
.masquerade_as_nightly_cargo(&["-Zcargo-lints"])
841+
.with_stderr(
842+
"\
843+
[CHECKING] foo v0.0.1 ([CWD])
844+
[FINISHED] [..]
845+
",
846+
)
847+
.run();
848+
}

0 commit comments

Comments
 (0)