Skip to content

Commit

Permalink
feat: Add -Zcargo-lints
Browse files Browse the repository at this point in the history
  • Loading branch information
Muscraft committed Mar 23, 2024
1 parent 7ff7e34 commit abf0953
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 38 deletions.
2 changes: 2 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,7 @@ unstable_cli_options!(
#[serde(deserialize_with = "deserialize_build_std")]
build_std: Option<Vec<String>> = ("Enable Cargo to compile the standard library itself as part of a crate graph compilation"),
build_std_features: Option<Vec<String>> = ("Configure features enabled for the standard library itself when building the standard library"),
cargo_lints: bool = ("Enable the `[lints.cargo]` table"),
check_cfg: bool = ("Enable compile-time checking of `cfg` names/values/features"),
codegen_backend: bool = ("Enable the `codegen-backend` option in profiles in .cargo/config.toml file"),
config_include: bool = ("Enable the `include` key in config files"),
Expand Down Expand Up @@ -1117,6 +1118,7 @@ impl CliUnstable {
self.build_std = Some(crate::core::compiler::standard_lib::parse_unstable_flag(v))
}
"build-std-features" => self.build_std_features = Some(parse_features(v)),
"cargo-lints" => self.cargo_lints = parse_empty(k, v)?,
"check-cfg" => {
self.check_cfg = parse_empty(k, v)?;
}
Expand Down
51 changes: 46 additions & 5 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ pub fn to_real_manifest(

let workspace_config = match (original_toml.workspace.as_ref(), package.workspace.as_ref()) {
(Some(toml_config), None) => {
verify_lints(toml_config.lints.as_ref())?;
verify_lints(toml_config.lints.as_ref(), gctx, &mut warnings)?;
if let Some(ws_deps) = &toml_config.dependencies {
for (name, dep) in ws_deps {
unused_dep_keys(
Expand Down Expand Up @@ -828,7 +828,7 @@ pub fn to_real_manifest(
.clone()
.map(|mw| lints_inherit_with(mw, || inherit()?.lints()))
.transpose()?;
verify_lints(lints.as_ref())?;
verify_lints(lints.as_ref(), gctx, manifest_ctx.warnings)?;
let default = manifest::TomlLints::default();
let rustflags = lints_to_rustflags(lints.as_ref().unwrap_or(&default));

Expand Down Expand Up @@ -1322,7 +1322,7 @@ fn to_virtual_manifest(
.transpose()?;
let workspace_config = match original_toml.workspace {
Some(ref toml_config) => {
verify_lints(toml_config.lints.as_ref())?;
verify_lints(toml_config.lints.as_ref(), gctx, &mut warnings)?;
let ws_root_config = to_workspace_config(toml_config, root);
gctx.ws_roots
.borrow_mut()
Expand Down Expand Up @@ -1448,17 +1448,24 @@ struct ManifestContext<'a, 'b> {
features: &'a Features,
}

fn verify_lints(lints: Option<&manifest::TomlLints>) -> CargoResult<()> {
fn verify_lints(
lints: Option<&manifest::TomlLints>,
gctx: &GlobalContext,
warnings: &mut Vec<String>,
) -> CargoResult<()> {
let Some(lints) = lints else {
return Ok(());
};

for (tool, lints) in lints {
let supported = ["rust", "clippy", "rustdoc"];
let supported = ["cargo", "clippy", "rust", "rustdoc"];
if !supported.contains(&tool.as_str()) {
let supported = supported.join(", ");
anyhow::bail!("unsupported `{tool}` in `[lints]`, must be one of {supported}")
}
if tool == "cargo" && !gctx.cli_unstable().cargo_lints {
warn_for_cargo_lint_feature(gctx, warnings);
}
for name in lints.keys() {
if let Some((prefix, suffix)) = name.split_once("::") {
if tool == prefix {
Expand All @@ -1479,9 +1486,43 @@ fn verify_lints(lints: Option<&manifest::TomlLints>) -> CargoResult<()> {
Ok(())
}

fn warn_for_cargo_lint_feature(gctx: &GlobalContext, warnings: &mut Vec<String>) {
use std::fmt::Write as _;

let key_name = "lints.cargo";
let feature_name = "cargo-lints";

let mut message = String::new();

let _ = write!(
message,
"unused manifest key `{key_name}` (may be supported in a future version)"
);
if gctx.nightly_features_allowed {
let _ = write!(
message,
"
consider passing `-Z{feature_name}` to enable this feature."
);
} else {
let _ = write!(
message,
"
this Cargo does not support nightly features, but if you
switch to nightly channel you can pass
`-Z{feature_name}` to enable this feature.",
);
}
warnings.push(message);
}

fn lints_to_rustflags(lints: &manifest::TomlLints) -> Vec<String> {
let mut rustflags = lints
.iter()
// We don't want to pass any of the `cargo` lints to `rustc`
.filter(|(tool, _)| tool != &"cargo")
.flat_map(|(tool, lints)| {
lints.iter().map(move |(name, config)| {
let flag = match config.level() {
Expand Down
66 changes: 34 additions & 32 deletions tests/testsuite/cargo/z_help/stdout.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
99 changes: 98 additions & 1 deletion tests/testsuite/lints_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn fail_on_invalid_tool() {
[..]
Caused by:
unsupported `super-awesome-linter` in `[lints]`, must be one of rust, clippy, rustdoc
unsupported `super-awesome-linter` in `[lints]`, must be one of cargo, clippy, rust, rustdoc
",
)
.run();
Expand Down Expand Up @@ -749,3 +749,100 @@ pub const Ĕ: i32 = 2;
)
.run();
}

#[cargo_test]
fn cargo_lints_nightly_required() {
let foo = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[lints.cargo]
"unused-features" = "deny"
"#,
)
.file("src/lib.rs", "")
.build();

foo.cargo("check")
.with_stderr(
"\
[WARNING] unused manifest key `lints.cargo` (may be supported in a future version)
this Cargo does not support nightly features, but if you
switch to nightly channel you can pass
`-Zcargo-lints` to enable this feature.
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] [..]
",
)
.run();
}

#[cargo_test]
fn cargo_lints_no_z_flag() {
let foo = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[lints.cargo]
"unused-features" = "deny"
"#,
)
.file("src/lib.rs", "")
.build();

foo.cargo("check")
.masquerade_as_nightly_cargo(&["-Zcargo-lints"])
.with_stderr(
"\
[WARNING] unused manifest key `lints.cargo` (may be supported in a future version)
consider passing `-Zcargo-lints` to enable this feature.
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] [..]
",
)
.run();
}

#[cargo_test]
fn cargo_lints_success() {
let foo = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"
authors = []
[lints.cargo]
"unused-features" = "deny"
"#,
)
.file("src/lib.rs", "")
.build();

foo.cargo("check -Zcargo-lints")
.masquerade_as_nightly_cargo(&["-Zcargo-lints"])
.with_stderr(
"\
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] [..]
",
)
.run();
}

0 comments on commit abf0953

Please sign in to comment.