Skip to content
Merged
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
4 changes: 4 additions & 0 deletions crates/xtask-lint-docs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ fn add_lint(lint: &Lint, buf: &mut String) -> std::fmt::Result {
writeln!(buf, "Group: `{}`", lint.primary_group.name)?;
writeln!(buf)?;
writeln!(buf, "Level: `{}`", lint.primary_group.default_level)?;
if let Some(msrv) = &lint.msrv {
writeln!(buf)?;
writeln!(buf, "MSRV: `{msrv}`")?;
}
writeln!(buf, "{}\n", lint.docs.as_ref().unwrap())
}

Expand Down
4 changes: 3 additions & 1 deletion src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1431,7 +1431,7 @@ impl<'gctx> Workspace<'gctx> {
let mut verify_error_count = 0;

analyze_cargo_lints_table(
self.root_maybe().into(),
(self, self.root_maybe()).into(),
self.root_manifest(),
&cargo_lints,
&mut verify_error_count,
Expand Down Expand Up @@ -1460,6 +1460,7 @@ impl<'gctx> Workspace<'gctx> {
self.gctx,
)?;
implicit_minimum_version_req_ws(
self,
self.root_maybe(),
self.root_manifest(),
&cargo_lints,
Expand All @@ -1473,6 +1474,7 @@ impl<'gctx> Workspace<'gctx> {
// improve the testing experience while we are collecting feedback
if self.gctx.cli_unstable().profile_hint_mostly_unused {
blanket_hint_mostly_unused(
self,
self.root_maybe(),
self.root_manifest(),
&cargo_lints,
Expand Down
51 changes: 41 additions & 10 deletions src/cargo/lints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ use annotate_snippets::AnnotationKind;
use annotate_snippets::Group;
use annotate_snippets::Level;
use annotate_snippets::Snippet;
use cargo_util_schemas::manifest::RustVersion;
use cargo_util_schemas::manifest::TomlLintLevel;
use cargo_util_schemas::manifest::TomlToolLints;
use pathdiff::diff_paths;

use crate::core::Workspace;
use crate::core::{Edition, Feature, Features, MaybePackage, Package};
use crate::{CargoResult, GlobalContext};

Expand All @@ -35,39 +37,54 @@ pub enum ManifestFor<'a> {
/// Lint runs for a specific package.
Package(&'a Package),
/// Lint runs for workspace-level config.
Workspace(&'a MaybePackage),
Workspace {
ws: &'a Workspace<'a>,
maybe_pkg: &'a MaybePackage,
},
}

impl ManifestFor<'_> {
fn lint_level(&self, pkg_lints: &TomlToolLints, lint: &Lint) -> (LintLevel, LintLevelReason) {
lint.level(pkg_lints, self.edition(), self.unstable_features())
lint.level(
pkg_lints,
self.rust_version(),
self.edition(),
self.unstable_features(),
)
}

pub fn rust_version(&self) -> Option<&RustVersion> {
match self {
ManifestFor::Package(p) => p.rust_version(),
ManifestFor::Workspace { ws, maybe_pkg: _ } => ws.lowest_rust_version(),
}
}

pub fn contents(&self) -> Option<&str> {
match self {
ManifestFor::Package(p) => p.manifest().contents(),
ManifestFor::Workspace(p) => p.contents(),
ManifestFor::Workspace { ws: _, maybe_pkg } => maybe_pkg.contents(),
}
}

pub fn document(&self) -> Option<&toml::Spanned<toml::de::DeTable<'static>>> {
match self {
ManifestFor::Package(p) => p.manifest().document(),
ManifestFor::Workspace(p) => p.document(),
ManifestFor::Workspace { ws: _, maybe_pkg } => maybe_pkg.document(),
}
}

pub fn edition(&self) -> Edition {
match self {
ManifestFor::Package(p) => p.manifest().edition(),
ManifestFor::Workspace(p) => p.edition(),
ManifestFor::Workspace { ws: _, maybe_pkg } => maybe_pkg.edition(),
}
}

pub fn unstable_features(&self) -> &Features {
match self {
ManifestFor::Package(p) => p.manifest().unstable_features(),
ManifestFor::Workspace(p) => p.unstable_features(),
ManifestFor::Workspace { ws: _, maybe_pkg } => maybe_pkg.unstable_features(),
}
}
}
Expand All @@ -78,9 +95,9 @@ impl<'a> From<&'a Package> for ManifestFor<'a> {
}
}

impl<'a> From<&'a MaybePackage> for ManifestFor<'a> {
fn from(value: &'a MaybePackage) -> ManifestFor<'a> {
ManifestFor::Workspace(value)
impl<'a> From<(&'a Workspace<'a>, &'a MaybePackage)> for ManifestFor<'a> {
fn from((ws, maybe_pkg): (&'a Workspace<'a>, &'a MaybePackage)) -> ManifestFor<'a> {
ManifestFor::Workspace { ws, maybe_pkg }
}
}

Expand Down Expand Up @@ -184,7 +201,7 @@ fn report_feature_not_enabled(

let key_path = match manifest {
ManifestFor::Package(_) => &["lints", "cargo", lint_name][..],
ManifestFor::Workspace(_) => &["workspace", "lints", "cargo", lint_name][..],
ManifestFor::Workspace { .. } => &["workspace", "lints", "cargo", lint_name][..],
};

let mut error = Group::with_title(Level::ERROR.primary_title(title));
Expand Down Expand Up @@ -400,6 +417,12 @@ pub struct Lint {
pub name: &'static str,
pub desc: &'static str,
pub primary_group: &'static LintGroup,
/// The minimum supported Rust version for applying this lint
///
/// Note: If the lint is on by default and did not qualify as a hard-warning before the
/// linting system, then at earliest an MSRV of 1.78 is required as `[lints.cargo]` was a hard
/// error before then.
pub msrv: Option<RustVersion>,
pub edition_lint_opts: Option<(Edition, LintLevel)>,
pub feature_gate: Option<&'static Feature>,
/// This is a markdown formatted string that will be used when generating
Expand All @@ -412,6 +435,7 @@ impl Lint {
pub fn level(
&self,
pkg_lints: &TomlToolLints,
pkg_rust_version: Option<&RustVersion>,
edition: Edition,
unstable_features: &Features,
) -> (LintLevel, LintLevelReason) {
Expand All @@ -424,6 +448,13 @@ impl Lint {
return (LintLevel::Allow, LintLevelReason::Default);
}

if let (Some(msrv), Some(pkg_rust_version)) = (&self.msrv, pkg_rust_version) {
let pkg_rust_version = pkg_rust_version.to_partial();
if !msrv.is_compatible_with(&pkg_rust_version) {
return (LintLevel::Allow, LintLevelReason::Default);
}
}

let lint_level_priority = level_priority(
self.name,
self.primary_group.default_level,
Expand Down
4 changes: 4 additions & 0 deletions src/cargo/lints/rules/blanket_hint_mostly_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use cargo_util_schemas::manifest::TomlToolLints;
use crate::CargoResult;
use crate::GlobalContext;
use crate::core::MaybePackage;
use crate::core::Workspace;
use crate::lints::Lint;
use crate::lints::LintLevel;
use crate::lints::SUSPICIOUS;
Expand All @@ -22,6 +23,7 @@ pub static LINT: &Lint = &Lint {
name: "blanket_hint_mostly_unused",
desc: "blanket_hint_mostly_unused lint",
primary_group: &SUSPICIOUS,
msrv: Some(super::CARGO_LINTS_MSRV),
edition_lint_opts: None,
feature_gate: None,
docs: Some(
Expand Down Expand Up @@ -54,6 +56,7 @@ hint-mostly-unused = true
};

pub fn blanket_hint_mostly_unused(
ws: &Workspace<'_>,
maybe_pkg: &MaybePackage,
path: &Path,
pkg_lints: &TomlToolLints,
Expand All @@ -62,6 +65,7 @@ pub fn blanket_hint_mostly_unused(
) -> CargoResult<()> {
let (lint_level, reason) = LINT.level(
pkg_lints,
ws.lowest_rust_version(),
maybe_pkg.edition(),
maybe_pkg.unstable_features(),
);
Expand Down
9 changes: 7 additions & 2 deletions src/cargo/lints/rules/im_a_teapot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub static LINT: &Lint = &Lint {
name: "im_a_teapot",
desc: "`im_a_teapot` is specified",
primary_group: &TEST_DUMMY_UNSTABLE,
msrv: None,
edition_lint_opts: None,
feature_gate: Some(Feature::test_dummy_unstable()),
docs: None,
Expand All @@ -35,8 +36,12 @@ pub fn check_im_a_teapot(
gctx: &GlobalContext,
) -> CargoResult<()> {
let manifest = pkg.manifest();
let (lint_level, reason) =
LINT.level(pkg_lints, manifest.edition(), manifest.unstable_features());
let (lint_level, reason) = LINT.level(
pkg_lints,
pkg.rust_version(),
manifest.edition(),
manifest.unstable_features(),
);

if lint_level == LintLevel::Allow {
return Ok(());
Expand Down
5 changes: 5 additions & 0 deletions src/cargo/lints/rules/implicit_minimum_version_req.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::GlobalContext;
use crate::core::Manifest;
use crate::core::MaybePackage;
use crate::core::Package;
use crate::core::Workspace;
use crate::lints::Lint;
use crate::lints::LintLevel;
use crate::lints::LintLevelReason;
Expand All @@ -29,6 +30,7 @@ pub static LINT: &Lint = &Lint {
name: "implicit_minimum_version_req",
desc: "dependency version requirement without an explicit minimum version",
primary_group: &PEDANTIC,
msrv: None,
edition_lint_opts: None,
feature_gate: None,
docs: Some(
Expand Down Expand Up @@ -90,6 +92,7 @@ pub fn implicit_minimum_version_req_pkg(
) -> CargoResult<()> {
let (lint_level, reason) = LINT.level(
cargo_lints,
pkg.rust_version(),
pkg.manifest().edition(),
pkg.manifest().unstable_features(),
);
Expand Down Expand Up @@ -148,6 +151,7 @@ pub fn implicit_minimum_version_req_pkg(
}

pub fn implicit_minimum_version_req_ws(
ws: &Workspace<'_>,
maybe_pkg: &MaybePackage,
manifest_path: &Path,
cargo_lints: &TomlToolLints,
Expand All @@ -156,6 +160,7 @@ pub fn implicit_minimum_version_req_ws(
) -> CargoResult<()> {
let (lint_level, reason) = LINT.level(
cargo_lints,
ws.lowest_rust_version(),
maybe_pkg.edition(),
maybe_pkg.unstable_features(),
);
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/lints/rules/missing_lints_inheritance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub static LINT: &Lint = &Lint {
name: "missing_lints_inheritance",
desc: "missing `[lints]` to inherit `[workspace.lints]`",
primary_group: &SUSPICIOUS,
msrv: Some(super::CARGO_LINTS_MSRV),
edition_lint_opts: None,
feature_gate: None,
docs: Some(
Expand Down Expand Up @@ -62,6 +63,7 @@ pub fn missing_lints_inheritance(
) -> CargoResult<()> {
let (lint_level, reason) = LINT.level(
cargo_lints,
pkg.rust_version(),
pkg.manifest().edition(),
pkg.manifest().unstable_features(),
);
Expand Down
7 changes: 7 additions & 0 deletions src/cargo/lints/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,10 @@ pub static LINTS: &[&crate::lints::Lint] = &[
unused_workspace_dependencies::LINT,
unused_workspace_package_fields::LINT,
];

/// Version required for specifying `[lints.cargo]`
///
/// Before this, it was an error. No on-by-default lint should fire before this time without
/// another way of disabling it.
static CARGO_LINTS_MSRV: cargo_util_schemas::manifest::RustVersion =
cargo_util_schemas::manifest::RustVersion::new(1, 79, 0);
2 changes: 2 additions & 0 deletions src/cargo/lints/rules/non_kebab_case_bins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub static LINT: &Lint = &Lint {
name: "non_kebab_case_bins",
desc: "binaries should have a kebab-case name",
primary_group: &STYLE,
msrv: Some(super::CARGO_LINTS_MSRV),
edition_lint_opts: None,
feature_gate: None,
docs: Some(
Expand Down Expand Up @@ -71,6 +72,7 @@ pub fn non_kebab_case_bins(
) -> CargoResult<()> {
let (lint_level, reason) = LINT.level(
cargo_lints,
pkg.rust_version(),
pkg.manifest().edition(),
pkg.manifest().unstable_features(),
);
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/lints/rules/non_kebab_case_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub static LINT: &Lint = &Lint {
name: "non_kebab_case_features",
desc: "features should have a kebab-case name",
primary_group: &RESTRICTION,
msrv: None,
edition_lint_opts: None,
feature_gate: None,
docs: Some(
Expand Down Expand Up @@ -64,6 +65,7 @@ pub fn non_kebab_case_features(
) -> CargoResult<()> {
let (lint_level, reason) = LINT.level(
cargo_lints,
pkg.rust_version(),
pkg.manifest().edition(),
pkg.manifest().unstable_features(),
);
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/lints/rules/non_kebab_case_packages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub static LINT: &Lint = &Lint {
name: "non_kebab_case_packages",
desc: "packages should have a kebab-case name",
primary_group: &RESTRICTION,
msrv: None,
edition_lint_opts: None,
feature_gate: None,
docs: Some(
Expand Down Expand Up @@ -64,6 +65,7 @@ pub fn non_kebab_case_packages(
) -> CargoResult<()> {
let (lint_level, reason) = LINT.level(
cargo_lints,
pkg.rust_version(),
pkg.manifest().edition(),
pkg.manifest().unstable_features(),
);
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/lints/rules/non_snake_case_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub static LINT: &Lint = &Lint {
name: "non_snake_case_features",
desc: "features should have a snake-case name",
primary_group: &RESTRICTION,
msrv: None,
edition_lint_opts: None,
feature_gate: None,
docs: Some(
Expand Down Expand Up @@ -64,6 +65,7 @@ pub fn non_snake_case_features(
) -> CargoResult<()> {
let (lint_level, reason) = LINT.level(
cargo_lints,
pkg.rust_version(),
pkg.manifest().edition(),
pkg.manifest().unstable_features(),
);
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/lints/rules/non_snake_case_packages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub static LINT: &Lint = &Lint {
name: "non_snake_case_packages",
desc: "packages should have a snake-case name",
primary_group: &RESTRICTION,
msrv: None,
edition_lint_opts: None,
feature_gate: None,
docs: Some(
Expand Down Expand Up @@ -64,6 +65,7 @@ pub fn non_snake_case_packages(
) -> CargoResult<()> {
let (lint_level, reason) = LINT.level(
cargo_lints,
pkg.rust_version(),
pkg.manifest().edition(),
pkg.manifest().unstable_features(),
);
Expand Down
2 changes: 2 additions & 0 deletions src/cargo/lints/rules/redundant_homepage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub static LINT: &Lint = &Lint {
name: "redundant_homepage",
desc: "`package.homepage` is redundant with another manifest field",
primary_group: &STYLE,
msrv: Some(super::CARGO_LINTS_MSRV),
edition_lint_opts: None,
feature_gate: None,
docs: Some(
Expand Down Expand Up @@ -68,6 +69,7 @@ pub fn redundant_homepage(
) -> CargoResult<()> {
let (lint_level, reason) = LINT.level(
cargo_lints,
pkg.rust_version(),
pkg.manifest().edition(),
pkg.manifest().unstable_features(),
);
Expand Down
Loading