diff --git a/compiler/rustc_attr_parsing/src/attributes/lint.rs b/compiler/rustc_attr_parsing/src/attributes/lint.rs index f9c8ff6e68749..3cd364add9513 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint.rs @@ -1,5 +1,4 @@ use rustc_ast::LitKind; -use rustc_hir::HashIgnoredAttrId; use rustc_hir::attrs::{LintAttribute, LintAttributeKind, LintInstance}; use rustc_hir::lints::AttributeLintKind; use rustc_hir::target::GenericParamKind; @@ -251,7 +250,7 @@ fn validate_lint_attr( lint_instances, attr_span: cx.attr_span, attr_style: cx.attr_style, - attr_id: HashIgnoredAttrId { attr_id: cx.attr_id }, + target_span: cx.target_span, kind: T::KIND, }) } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index b87a71bcbd92b..220f69143ddda 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -15,7 +15,7 @@ use rustc_hir::{AttrPath, HirId}; use rustc_parse::parser::Recovery; use rustc_session::Session; use rustc_session::lint::{Lint, LintId}; -use rustc_span::{AttrId, ErrorGuaranteed, Span, Symbol}; +use rustc_span::{ErrorGuaranteed, Span, Symbol}; use crate::AttributeParser; // Glob imports to avoid big, bitrotty import lists @@ -447,8 +447,6 @@ pub struct AcceptContext<'f, 'sess, S: Stage> { /// The name of the attribute we're currently accepting. pub(crate) attr_path: AttrPath, - - pub(crate) attr_id: AttrId, } impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 06738b9c73375..c239a7cd191d7 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -240,7 +240,6 @@ impl<'sess> AttributeParser<'sess, Early> { if let Some(safety) = attr_safety { parser.check_attribute_safety(&attr_path, inner_span, safety, &mut emit_lint) } - let attr_id = sess.psess.attr_id_generator.mk_attr_id(); let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext { shared: SharedContext { cx: &mut parser, @@ -254,7 +253,6 @@ impl<'sess> AttributeParser<'sess, Early> { parsed_description, template, attr_path, - attr_id, }; parse_fn(&mut cx, args) } @@ -420,7 +418,6 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { parsed_description: ParsedDescription::Attribute, template: &accept.template, attr_path: attr_path.clone(), - attr_id: attr.id, }; (accept.accept_fn)(&mut cx, &args); diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index ce3d781712515..71ccecf592ac0 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -311,6 +311,38 @@ impl StableOrd for ( const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); } +impl HashStable for (T1, T2, T3, T4, T5) +where + T1: HashStable, + T2: HashStable, + T3: HashStable, + T4: HashStable, + T5: HashStable, +{ + fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { + let (ref _0, ref _1, ref _2, ref _3, ref _4) = *self; + _0.hash_stable(hcx, hasher); + _1.hash_stable(hcx, hasher); + _2.hash_stable(hcx, hasher); + _3.hash_stable(hcx, hasher); + _4.hash_stable(hcx, hasher); + } +} + +impl StableOrd + for (T1, T2, T3, T4, T5) +{ + const CAN_USE_UNSTABLE_SORT: bool = T1::CAN_USE_UNSTABLE_SORT + && T2::CAN_USE_UNSTABLE_SORT + && T3::CAN_USE_UNSTABLE_SORT + && T4::CAN_USE_UNSTABLE_SORT + && T5::CAN_USE_UNSTABLE_SORT; + + // Ordering of tuples is a pure function of their elements' ordering, and since + // the ordering of each element is stable so must be the ordering of the tuple. + const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = (); +} + impl, Hcx> HashStable for [T] { default fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { self.len().hash_stable(hcx, hasher); diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index f18d5a1f190a2..c421792d47e52 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -22,9 +22,7 @@ use thin_vec::ThinVec; use crate::attrs::diagnostic::*; use crate::attrs::pretty_printing::PrintAttribute; use crate::limit::Limit; -use crate::{ - DefaultBodyStability, HashIgnoredAttrId, PartialConstStability, RustcVersion, Stability, -}; +use crate::{DefaultBodyStability, PartialConstStability, RustcVersion, Stability}; #[derive(Copy, Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)] pub enum EiiImplResolution { @@ -903,8 +901,7 @@ pub struct LintAttribute { pub kind: LintAttributeKind, pub attr_style: AttrStyle, pub attr_span: Span, - /// Needed by `LintExpectationId` to track fulfilled expectations - pub attr_id: HashIgnoredAttrId, + pub target_span: Span, pub lint_instances: ThinVec, } diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 12e23eea720fe..bb24b25198c75 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -4,7 +4,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::LintExpectationId; use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS; -use rustc_span::Symbol; +use rustc_span::{Span, Symbol}; use crate::lints::{Expectation, ExpectationNote}; @@ -33,10 +33,12 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp expectations } -fn canonicalize_id(expect_id: &LintExpectationId) -> (rustc_span::AttrId, u16) { +fn canonicalize_id(expect_id: &LintExpectationId) -> (Span, u16, u16) { match *expect_id { - LintExpectationId::Unstable { attr_id, lint_index, .. } => (attr_id, lint_index), - LintExpectationId::Stable { attr_id, lint_index, .. } => (attr_id, lint_index), + LintExpectationId::Unstable { target_span, lint_index, attr_index } + | LintExpectationId::Stable { target_span, lint_index, attr_index, .. } => { + (target_span, lint_index, attr_index) + } } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 12c5748d5ecdf..bacc963c7c203 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -723,10 +723,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { return; }; - for (attr_index, LintAttribute { reason, lint_instances, attr_id, kind, .. }) in + for (attr_index, LintAttribute { reason, lint_instances, kind, target_span, .. }) in attrs.enumerate() { - let attr_id = attr_id.attr_id; let level = match kind { LintAttributeKind::Allow => Level::Allow, LintAttributeKind::Deny => Level::Deny, @@ -737,12 +736,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let lint_index = lint.lint_index().try_into().unwrap(); let attr_index = attr_index.try_into().unwrap(); let expectation_id = match source_hir_id { - None => LintExpectationId::Unstable { attr_id, lint_index }, + None => LintExpectationId::Unstable { + target_span: *target_span, + lint_index, + attr_index, + }, Some(hir_id) => LintExpectationId::Stable { hir_id, - attr_id, lint_index, attr_index, + target_span: *target_span, }, }; diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 2ebbe633ecd1a..ab07fb9bbb54e 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::fmt::Display; +use std::hash::Hash; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::stable_hasher::{ @@ -10,7 +11,7 @@ use rustc_hir_id::{HirId, ItemLocalId}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::DefPathHash; pub use rustc_span::edition::Edition; -use rustc_span::{AttrId, HashStableContext, Ident, Span, Symbol, sym}; +use rustc_span::{HashStableContext, Ident, Span, Symbol, sym}; use serde::{Deserialize, Serialize}; pub use self::Level::*; @@ -91,7 +92,7 @@ pub enum Applicability { /// instances might be loaded from cache. Lint messages can be emitted during an /// `EarlyLintPass` operating on the AST and during a `LateLintPass` traversing the /// HIR tree. The AST doesn't have enough information to create a stable id. The -/// `LintExpectationId` will instead store the [`AttrId`] defining the expectation. +/// `LintExpectationId` will instead store the `target_span` defining the expectation. /// These `LintExpectationId` will be updated to use the stable [`HirId`] once the /// AST has been lowered. The transformation is done by the `LintLevelsBuilder` /// @@ -105,12 +106,12 @@ pub enum Applicability { pub enum LintExpectationId { /// Used for lints emitted during the `EarlyLintPass`. This id is not /// hash stable and should not be cached. - Unstable { attr_id: AttrId, lint_index: u16 }, + Unstable { target_span: Span, lint_index: u16, attr_index: u16 }, /// The [`HirId`] that the lint expectation is attached to. This id is /// stable and can be cached. The additional index ensures that nodes with /// several expectations can correctly match diagnostics to the individual /// expectation. - Stable { hir_id: HirId, attr_id: AttrId, attr_index: u16, lint_index: u16 }, + Stable { hir_id: HirId, attr_index: u16, lint_index: u16, target_span: Span }, } impl LintExpectationId { @@ -140,12 +141,13 @@ impl HashStable for LintExpectationId { #[inline] fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { match self { - LintExpectationId::Stable { hir_id, attr_index, lint_index, .. } => { + LintExpectationId::Stable { hir_id, target_span, attr_index, lint_index, .. } => { hir_id.hash_stable(hcx, hasher); + target_span.hash_stable(hcx, hasher); attr_index.hash_stable(hcx, hasher); lint_index.hash_stable(hcx, hasher); } - _ => { + LintExpectationId::Unstable { .. } => { unreachable!( "HashStable should only be called for filled and stable `LintExpectationId`" ) @@ -155,16 +157,16 @@ impl HashStable for LintExpectationId { } impl ToStableHashKey for LintExpectationId { - type KeyType = (DefPathHash, ItemLocalId, u16, u16); + type KeyType = (DefPathHash, ItemLocalId, Span, u16, u16); #[inline] fn to_stable_hash_key(&self, hcx: &mut Hcx) -> Self::KeyType { match self { - LintExpectationId::Stable { hir_id, attr_index, lint_index, .. } => { + LintExpectationId::Stable { hir_id, attr_index, lint_index, target_span, .. } => { let (def_path_hash, lint_idx) = hir_id.to_stable_hash_key(hcx); - (def_path_hash, lint_idx, *attr_index, *lint_index) + (def_path_hash, lint_idx, *target_span, *attr_index, *lint_index) } - _ => { + LintExpectationId::Unstable { .. } => { unreachable!("HashStable should only be called for a filled `LintExpectationId`") } } diff --git a/tests/incremental/cache-lint-expectation.rs b/tests/incremental/cache-lint-expectation.rs new file mode 100644 index 0000000000000..3c82225a95a29 --- /dev/null +++ b/tests/incremental/cache-lint-expectation.rs @@ -0,0 +1,8 @@ +// Regression test for #154878 +//@ revisions: cpass1 cpass2 + +pub fn main() { + let x = 42.0; + #[expect(invalid_nan_comparisons)] + let _b = x == f32::NAN; +}