decouple "reporting in deps" from future incompatibility reason

This commit is contained in:
Waffle Lapkin
2025-06-03 01:29:36 +02:00
parent 52882f6522
commit 9b7da4deb2
4 changed files with 67 additions and 82 deletions

View File

@@ -126,7 +126,7 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> UnordSet<LintId> {
.filter(|lint| {
// Lints that show up in future-compat reports must always be run.
let has_future_breakage =
lint.future_incompatible.is_some_and(|fut| fut.reason.has_future_breakage());
lint.future_incompatible.is_some_and(|fut| fut.report_in_deps);
!has_future_breakage && !lint.eval_always
})
.filter(|lint| {

View File

@@ -178,8 +178,9 @@ declare_lint! {
Warn,
"applying forbid to lint-groups",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #81670 <https://github.com/rust-lang/rust/issues/81670>",
report_in_deps: true,
};
}
@@ -214,7 +215,7 @@ declare_lint! {
Deny,
"ill-formed attribute inputs that were previously accepted and used in practice",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
};
crate_level_only
@@ -251,8 +252,9 @@ declare_lint! {
Deny,
"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #68585 <https://github.com/rust-lang/rust/issues/68585>",
report_in_deps: true,
};
}
@@ -1240,8 +1242,9 @@ declare_lint! {
Deny,
"detect public re-exports of private extern crates",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #127909 <https://github.com/rust-lang/rust/issues/127909>",
report_in_deps: true,
};
}
@@ -1270,8 +1273,9 @@ declare_lint! {
Deny,
"type parameter default erroneously allowed in invalid location",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
report_in_deps: true,
};
}
@@ -1409,7 +1413,7 @@ declare_lint! {
Deny,
"patterns in functions without body were erroneously allowed",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
};
}
@@ -1453,8 +1457,9 @@ declare_lint! {
Deny,
"detects missing fragment specifiers in unused `macro_rules!` patterns",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
report_in_deps: true,
};
}
@@ -1495,7 +1500,7 @@ declare_lint! {
Warn,
"detects generic lifetime arguments in path segments with late bound lifetime parameters",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
};
}
@@ -2122,8 +2127,9 @@ declare_lint! {
Deny,
"detects proc macro derives using inaccessible names from parent modules",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #83583 <https://github.com/rust-lang/rust/issues/83583>",
report_in_deps: true,
};
}
@@ -2225,7 +2231,7 @@ declare_lint! {
"macro-expanded `macro_export` macros from the current crate \
cannot be referred to by absolute paths",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
};
crate_level_only
@@ -2346,7 +2352,7 @@ declare_lint! {
Deny,
"ambiguous associated items",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #57644 <https://github.com/rust-lang/rust/issues/57644>",
};
}
@@ -2362,8 +2368,9 @@ declare_lint! {
Deny,
"a feature gate that doesn't break dependent crates",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #64266 <https://github.com/rust-lang/rust/issues/64266>",
report_in_deps: true,
};
}
@@ -2674,7 +2681,7 @@ declare_lint! {
Warn,
"detects a generic constant is used in a type without a emitting a warning",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #76200 <https://github.com/rust-lang/rust/issues/76200>",
};
}
@@ -2733,7 +2740,7 @@ declare_lint! {
Warn,
"uninhabited static",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #74840 <https://github.com/rust-lang/rust/issues/74840>",
};
}
@@ -2866,7 +2873,7 @@ declare_lint! {
Warn,
"detect unsupported use of `Self` from outer item",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #124186 <https://github.com/rust-lang/rust/issues/124186>",
};
}
@@ -2912,8 +2919,9 @@ declare_lint! {
Warn,
"trailing semicolon in macro body used as expression",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #79813 <https://github.com/rust-lang/rust/issues/79813>",
report_in_deps: true,
};
}
@@ -2959,7 +2967,7 @@ declare_lint! {
Warn,
"detects derive helper attributes that are used before they are introduced",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #79202 <https://github.com/rust-lang/rust/issues/79202>",
};
}
@@ -3126,7 +3134,7 @@ declare_lint! {
Warn,
"transparent type contains an external ZST that is marked #[non_exhaustive] or contains private fields",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #78586 <https://github.com/rust-lang/rust/issues/78586>",
};
}
@@ -3177,7 +3185,7 @@ declare_lint! {
Warn,
"unstable syntax can change at any point in the future, causing a hard error!",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #65860 <https://github.com/rust-lang/rust/issues/65860>",
};
}
@@ -3685,8 +3693,9 @@ declare_lint! {
Warn,
"use of unsupported calling convention for function pointer",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #130260 <https://github.com/rust-lang/rust/issues/130260>",
report_in_deps: true,
};
}
@@ -4368,7 +4377,7 @@ declare_lint! {
Warn,
"detects certain glob imports that require reporting an ambiguity error",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #114095 <https://github.com/rust-lang/rust/issues/114095>",
};
}
@@ -4523,7 +4532,7 @@ declare_lint! {
Deny,
"elided lifetimes cannot be used in associated constants in impls",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #115010 <https://github.com/rust-lang/rust/issues/115010>",
};
}
@@ -4570,7 +4579,7 @@ declare_lint! {
Warn,
"detects certain macro bindings that should not be re-exported",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #120192 <https://github.com/rust-lang/rust/issues/120192>",
};
}
@@ -4635,7 +4644,7 @@ declare_lint! {
Warn,
"impl contains type parameters that are not covered",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #124559 <https://github.com/rust-lang/rust/issues/124559>",
};
}
@@ -4799,7 +4808,7 @@ declare_lint! {
Warn,
"detects out of scope calls to `macro_rules` in key-value attributes",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #124535 <https://github.com/rust-lang/rust/issues/124535>",
};
}
@@ -5040,8 +5049,9 @@ declare_lint! {
Warn,
"detects code relying on rustc's non-spec-compliant wasm C ABI",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #138762 <https://github.com/rust-lang/rust/issues/138762>",
report_in_deps: true,
};
}
@@ -5081,7 +5091,8 @@ declare_lint! {
Warn,
"detects code that could be affected by ABI issues on aarch64 softfloat targets",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #134375 <https://github.com/rust-lang/rust/issues/134375>",
report_in_deps: true,
};
}

View File

@@ -361,6 +361,18 @@ pub struct FutureIncompatibleInfo {
/// Set to false for lints that already include a more detailed
/// explanation.
pub explain_reason: bool,
/// If set to `true`, this will make future incompatibility warnings show up in cargo's
/// reports.
///
/// When a future incompatibility warning is first inroduced, set this to `false`
/// (or, rather, don't override the default). This allows crate developers an opportunity
/// to fix the warning before blasting all dependents with a warning they can't fix
/// (dependents have to wait for a new release of the affected crate to be published).
///
/// After a lint has been in this state for a while, consider setting this to true, so it
/// warns for everyone. It is a good signal that it is ready if you can determine that all
/// or most affected crates on crates.io have been updated.
pub report_in_deps: bool,
}
/// The reason for future incompatibility
@@ -380,46 +392,24 @@ pub struct FutureIncompatibleInfo {
pub enum FutureIncompatibilityReason {
/// This will be an error in a future release for all editions
///
/// This will *not* show up in cargo's future breakage report.
/// The warning will hence only be seen in local crates, not in dependencies.
///
/// Choose this variant when you are first introducing a "future
/// incompatible" warning that is intended to eventually be fixed in the
/// future. This allows crate developers an opportunity to fix the warning
/// before blasting all dependents with a warning they can't fix
/// (dependents have to wait for a new release of the affected crate to be
/// published).
/// future.
///
/// After a lint has been in this state for a while, consider graduating
/// it to [`FutureIncompatibilityReason::FutureReleaseErrorReportInDeps`].
FutureReleaseErrorDontReportInDeps,
/// This will be an error in a future release, and
/// Cargo should create a report even for dependencies
///
/// This is the *only* reason that will make future incompatibility warnings show up in cargo's
/// reports. All other future incompatibility warnings are not visible when they occur in a
/// dependency.
///
/// Choose this variant after the lint has been sitting in the
/// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`]
/// state for a while, and you feel like it is ready to graduate to
/// warning everyone. It is a good signal that it is ready if you can
/// determine that all or most affected crates on crates.io have been
/// updated.
/// After a lint has been in this state for a while and you feel like it is ready to graduate
/// to warning everyone, consider setting [`FutureIncompatibleInfo::report_in_deps`] to true.
/// (see it's documentation for more guidance)
///
/// After some period of time, lints with this variant can be turned into
/// hard errors (and the lint removed). Preferably when there is some
/// confidence that the number of impacted projects is very small (few
/// should have a broken dependency in their dependency tree).
///
/// [`EditionAndFutureReleaseError`]: FutureIncompatibilityReason::EditionAndFutureReleaseError
FutureReleaseErrorReportInDeps,
FutureReleaseError,
/// Code that changes meaning in some way in a
/// future release.
///
/// Choose this variant when the semantics of existing code is changing,
/// (as opposed to
/// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`],
/// (as opposed to [`FutureIncompatibilityReason::FutureReleaseError`],
/// which is for when code is going to be rejected in the future).
FutureReleaseSemanticsChange,
/// Previously accepted code that will become an
@@ -454,13 +444,12 @@ pub enum FutureIncompatibilityReason {
/// This will be an error in the provided edition *and* in a future
/// release.
///
/// This variant a combination of [`FutureReleaseErrorDontReportInDeps`]
/// and [`EditionError`]. This is useful in rare cases when we
/// want to have "preview" of a breaking change in an edition, but do a
/// breaking change later on all editions anyway.
/// This variant a combination of [`FutureReleaseError`] and [`EditionError`].
/// This is useful in rare cases when we want to have "preview" of a breaking
/// change in an edition, but do a breaking change later on all editions anyway.
///
/// [`EditionError`]: FutureIncompatibilityReason::EditionError
/// [`FutureReleaseErrorDontReportInDeps`]: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
/// [`FutureReleaseError`]: FutureIncompatibilityReason::FutureReleaseError
EditionAndFutureReleaseError(Edition),
/// This will change meaning in the provided edition *and* in a future
/// release.
@@ -478,7 +467,7 @@ pub enum FutureIncompatibilityReason {
/// Choose this variant if the built-in text of the diagnostic of the
/// other variants doesn't match your situation. This is behaviorally
/// equivalent to
/// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`].
/// [`FutureIncompatibilityReason::FutureReleaseError`].
Custom(&'static str),
}
@@ -490,34 +479,20 @@ impl FutureIncompatibilityReason {
| Self::EditionAndFutureReleaseError(e)
| Self::EditionAndFutureReleaseSemanticsChange(e) => Some(e),
FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
| FutureIncompatibilityReason::FutureReleaseErrorReportInDeps
FutureIncompatibilityReason::FutureReleaseError
| FutureIncompatibilityReason::FutureReleaseSemanticsChange
| FutureIncompatibilityReason::Custom(_) => None,
}
}
pub fn has_future_breakage(self) -> bool {
match self {
FutureIncompatibilityReason::FutureReleaseErrorReportInDeps => true,
FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
| FutureIncompatibilityReason::FutureReleaseSemanticsChange
| FutureIncompatibilityReason::EditionError(_)
| FutureIncompatibilityReason::EditionSemanticsChange(_)
| FutureIncompatibilityReason::EditionAndFutureReleaseError(_)
| FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(_)
| FutureIncompatibilityReason::Custom(_) => false,
}
}
}
impl FutureIncompatibleInfo {
pub const fn default_fields_for_macro() -> Self {
FutureIncompatibleInfo {
reference: "",
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reason: FutureIncompatibilityReason::FutureReleaseError,
explain_reason: true,
report_in_deps: false,
}
}
}

View File

@@ -299,7 +299,7 @@ pub fn lint_level(
let has_future_breakage = future_incompatible.map_or(
// Default allow lints trigger too often for testing.
sess.opts.unstable_opts.future_incompat_test && lint.default_level != Level::Allow,
|incompat| incompat.reason.has_future_breakage(),
|incompat| incompat.report_in_deps,
);
// Convert lint level to error level.
@@ -370,8 +370,7 @@ pub fn lint_level(
if let Some(future_incompatible) = future_incompatible {
let explanation = match future_incompatible.reason {
FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps
| FutureIncompatibilityReason::FutureReleaseErrorReportInDeps => {
FutureIncompatibilityReason::FutureReleaseError => {
"this was previously accepted by the compiler but is being phased out; \
it will become a hard error in a future release!"
.to_owned()