Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions crates/xtask-lint-docs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,16 @@ fn lint_groups(buf: &mut String) -> anyhow::Result<()> {
continue;
}
let group_name = format!("`cargo::{}`", group.name);
// HACK: `default` is a secondary group without its own level
let group_level = if group.name == "default" {
"warn/deny".to_owned()
} else {
group.default_level.to_string()
};
writeln!(
buf,
"| {:<max_name_len$} | {:<max_desc_len$} | {:<default_level_len$} |",
group_name,
group.desc,
group.default_level.to_string(),
group_name, group.desc, group_level,
)?;
}
writeln!(buf, "\n")?;
Expand Down
145 changes: 134 additions & 11 deletions src/cargo/diagnostics/lint.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::cmp::{Reverse, max_by_key};
use std::cmp::Reverse;
use std::fmt::Display;

use cargo_util_schemas::manifest;
Expand Down Expand Up @@ -60,18 +60,29 @@ impl Lint {
pkg_lints,
);

let (_, (level, source, _)) = max_by_key(
let default_group = if LintLevel::Warn <= self.primary_group.default_level {
let lint_level_priority =
level_priority("default", self.primary_group.default_level, pkg_lints);
Some(("default", lint_level_priority))
} else {
None
};

let (_, (level, source, _)) = [
(self.name, lint_level_priority),
(self.primary_group.name, group_level_priority),
|(n, (l, s, p))| {
(
l == &LintLevel::Forbid,
*s != LintLevelSource::Default,
*p,
Reverse(*n),
)
},
);
]
.into_iter()
.chain(default_group)
.max_by_key(|(n, (l, s, p))| {
(
l == &LintLevel::Forbid,
*s != LintLevelSource::Default,
*p,
Reverse(*n),
)
})
.unwrap();
LintLevelProduct { level, source }
}

Expand Down Expand Up @@ -246,4 +257,116 @@ mod tests {
assert_eq!(level, LintLevel::Deny);
assert_eq!(source, LintLevelSource::Package);
}

#[test]
fn default_group_overrides_default() {
let lint = test_lint("non_kebab_case_bins", &STYLE);

let mut pkg_lints = manifest::TomlToolLints::new();
pkg_lints.insert(
"default".to_string(),
manifest::TomlLint::Level(manifest::TomlLintLevel::Deny),
);
let features = Features::default();

let LintLevelProduct { level, source } = lint.level(&pkg_lints, None, &features);
assert_eq!(level, LintLevel::Deny);
assert_eq!(source, LintLevelSource::Package);
}

#[test]
fn default_before_primary() {
let lint = test_lint("non_kebab_case_bins", &STYLE);

let mut pkg_lints = manifest::TomlToolLints::new();
pkg_lints.insert(
"default".to_string(),
manifest::TomlLint::Level(manifest::TomlLintLevel::Deny),
);
pkg_lints.insert(
"style".to_string(),
manifest::TomlLint::Level(manifest::TomlLintLevel::Allow),
);
let features = Features::default();

let LintLevelProduct { level, source } = lint.level(&pkg_lints, None, &features);
assert_eq!(level, LintLevel::Deny);
assert_eq!(source, LintLevelSource::Package);
}

#[test]
fn default_after_primary() {
let lint = test_lint("non_kebab_case_bins", &STYLE);

let mut pkg_lints = manifest::TomlToolLints::new();
pkg_lints.insert(
"style".to_string(),
manifest::TomlLint::Level(manifest::TomlLintLevel::Allow),
);
pkg_lints.insert(
"default".to_string(),
manifest::TomlLint::Level(manifest::TomlLintLevel::Deny),
);
let features = Features::default();

let LintLevelProduct { level, source } = lint.level(&pkg_lints, None, &features);
assert_eq!(level, LintLevel::Deny);
assert_eq!(source, LintLevelSource::Package);
}

#[test]
fn default_higher_than_primary() {
let lint = test_lint("non_kebab_case_bins", &STYLE);

let mut pkg_lints = manifest::TomlToolLints::new();
pkg_lints.insert(
"default".to_string(),
manifest::TomlLint::Config(manifest::TomlLintConfig {
level: manifest::TomlLintLevel::Deny,
priority: 1,
config: Default::default(),
}),
);
pkg_lints.insert(
"style".to_string(),
manifest::TomlLint::Config(manifest::TomlLintConfig {
level: manifest::TomlLintLevel::Allow,
priority: -1,
config: Default::default(),
}),
);
let features = Features::default();

let LintLevelProduct { level, source } = lint.level(&pkg_lints, None, &features);
assert_eq!(level, LintLevel::Deny);
assert_eq!(source, LintLevelSource::Package);
}

#[test]
fn default_lower_than_primary() {
let lint = test_lint("non_kebab_case_bins", &STYLE);

let mut pkg_lints = manifest::TomlToolLints::new();
pkg_lints.insert(
"default".to_string(),
manifest::TomlLint::Config(manifest::TomlLintConfig {
level: manifest::TomlLintLevel::Deny,
priority: -1,
config: Default::default(),
}),
);
pkg_lints.insert(
"style".to_string(),
manifest::TomlLint::Config(manifest::TomlLintConfig {
level: manifest::TomlLintLevel::Allow,
priority: 1,
config: Default::default(),
}),
);
let features = Features::default();

let LintLevelProduct { level, source } = lint.level(&pkg_lints, None, &features);
assert_eq!(level, LintLevel::Allow);
assert_eq!(source, LintLevelSource::Package);
}
}
26 changes: 21 additions & 5 deletions src/cargo/diagnostics/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,17 +134,26 @@ static CARGO_LINTS_MSRV: cargo_util_schemas::manifest::RustVersion =
cargo_util_schemas::manifest::RustVersion::new(1, 79, 0);

pub static LINT_GROUPS: &[LintGroup] = &[
COMPLEXITY,
DEFAULT,
CORRECTNESS,
NURSERY,
PEDANTIC,
COMPLEXITY,
PERF,
RESTRICTION,
STYLE,
SUSPICIOUS,
NURSERY,
PEDANTIC,
RESTRICTION,
TEST_DUMMY_UNSTABLE,
];

const DEFAULT: LintGroup = LintGroup {
name: "default",
desc: "all lints that are on by default (correctness, suspicious, style, complexity, perf)",
default_level: LintLevel::Warn,
feature_gate: None,
hidden: false,
};

const COMPLEXITY: LintGroup = LintGroup {
name: "complexity",
desc: "code that does something simple but in a complex way",
Expand Down Expand Up @@ -238,6 +247,7 @@ fn find_lint_or_group<'a>(
mod tests {
use itertools::Itertools;
use snapbox::ToDebug;
use std::cmp::Reverse;
use std::collections::HashSet;

use super::*;
Expand Down Expand Up @@ -283,7 +293,13 @@ mod tests {
);
let actual = LINT_GROUPS
.iter()
.map(|l| l.name.to_uppercase())
.map(|l| {
(
l.name != "default",
Reverse(l.default_level),
l.name.to_uppercase(),
)
})
.collect::<Vec<_>>();

let mut expected = actual.clone();
Expand Down
21 changes: 11 additions & 10 deletions src/doc/src/reference/lints.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ Note: [Cargo's linting system is unstable](unstable.md#lintscargo) and can only



| Group | Description | Default level |
|----------------------|------------------------------------------------------------------|---------------|
| `cargo::complexity` | code that does something simple but in a complex way | warn |
| `cargo::correctness` | code that is outright wrong or useless | deny |
| `cargo::nursery` | new lints that are still under development | allow |
| `cargo::pedantic` | lints which are rather strict or have occasional false positives | allow |
| `cargo::perf` | code that can be written to run faster | warn |
| `cargo::restriction` | lints which prevent the use of Cargo features | allow |
| `cargo::style` | code that should be written in a more idiomatic way | warn |
| `cargo::suspicious` | code that is most likely wrong or useless | warn |
| Group | Description | Default level |
|----------------------|-------------------------------------------------------------------------------------|---------------|
| `cargo::default` | all lints that are on by default (correctness, suspicious, style, complexity, perf) | warn/deny |
| `cargo::correctness` | code that is outright wrong or useless | deny |
| `cargo::complexity` | code that does something simple but in a complex way | warn |
| `cargo::perf` | code that can be written to run faster | warn |
| `cargo::style` | code that should be written in a more idiomatic way | warn |
| `cargo::suspicious` | code that is most likely wrong or useless | warn |
| `cargo::nursery` | new lints that are still under development | allow |
| `cargo::pedantic` | lints which are rather strict or have occasional false positives | allow |
| `cargo::restriction` | lints which prevent the use of Cargo features | allow |


## Allowed-by-default
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/lints/blanket_hint_mostly_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ edition = "2015"
hint-mostly-unused = true

[lints.cargo]
default = { level = "allow", priority = -1 }
blanket_hint_mostly_unused = "deny"
"#,
)
Expand Down
Loading
Loading