@@ -5,7 +5,9 @@ extern crate rustc_macros;
55
66pub use self :: Level :: * ;
77use rustc_ast:: node_id:: { NodeId , NodeMap } ;
8+ use rustc_ast:: AttrId ;
89use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher , ToStableHashKey } ;
10+ use rustc_hir:: HirId ;
911use rustc_serialize:: json:: Json ;
1012use rustc_span:: edition:: Edition ;
1113use rustc_span:: { sym, symbol:: Ident , MultiSpan , Span , Symbol } ;
@@ -48,29 +50,70 @@ pub enum Applicability {
4850 Unspecified ,
4951}
5052
51- rustc_index:: newtype_index! {
52- /// FIXME: The lint expectation ID is currently a simple copy of the `AttrId`
53- /// that the expectation originated from. In the future it should be generated
54- /// by other means. This is for one to keep the IDs independent of each other
55- /// and also to ensure that it is actually stable between compilation sessions.
56- /// (The `AttrId` for instance, is not stable).
57- ///
58- /// Additionally, it would be nice if this generation could be moved into
59- /// [`Level::from_symbol`] to have it all contained in one module and to
60- /// make it simpler to use.
61- pub struct LintExpectationId {
62- DEBUG_FORMAT = "LintExpectationId({})"
53+ /// Each lint expectation has a `LintExpectationId` assigned by the
54+ /// [`LintLevelsBuilder`][`rustc_lint::levels::LintLevelsBuilder`]. Expected
55+ /// [`Diagnostic`][`rustc_errors::Diagnostic`]s get the lint level `Expect` which
56+ /// stores the `LintExpectationId` to match it with the actual expectation later on.
57+ ///
58+ /// The `LintExpectationId` has to be has stable between compilations, as diagnostic
59+ /// instances might be loaded from cache. Lint messages can be emitted during an
60+ /// `EarlyLintPass` operating on the AST and during a `LateLintPass` traversing the
61+ /// HIR tree. The AST doesn't have enough information to create a stable id. The
62+ /// `LintExpectationId` will instead store the [`AttrId`] defining the expectation.
63+ /// These `LintExpectationId` will be updated to use the stable [`HirId`] once the
64+ /// AST has been lowered. The transformation is done by the
65+ /// [`LintLevelsBuilder`][`rustc_lint::levels::LintLevelsBuilder`]
66+ #[ derive( Clone , Copy , PartialEq , PartialOrd , Eq , Ord , Debug , Hash , Encodable , Decodable ) ]
67+ pub enum LintExpectationId {
68+ /// Used for lints emitted during the `EarlyLintPass`. This id is not
69+ /// has stable and should not be cached.
70+ Unstable ( AttrId ) ,
71+ /// The [`HirId`] that the lint expectation is attached to. This id is
72+ /// stable and can be cached. The additional index ensures that nodes with
73+ /// several expectations can correctly match diagnostics to the individual
74+ /// expectation.
75+ Stable { hir_id : HirId , attr_index : usize } ,
76+ }
77+
78+ impl LintExpectationId {
79+ pub fn is_stable ( & self ) -> bool {
80+ match self {
81+ LintExpectationId :: Unstable ( _) => false ,
82+ LintExpectationId :: Stable { .. } => true ,
83+ }
6384 }
6485}
6586
66- rustc_data_structures:: impl_stable_hash_via_hash!( LintExpectationId ) ;
87+ impl < HCX : rustc_hir:: HashStableContext > HashStable < HCX > for LintExpectationId {
88+ #[ inline]
89+ fn hash_stable ( & self , hcx : & mut HCX , hasher : & mut StableHasher ) {
90+ match self {
91+ LintExpectationId :: Unstable ( _) => {
92+ unreachable ! (
93+ "HashStable should never be called for an unstable `LintExpectationId`"
94+ )
95+ }
96+ LintExpectationId :: Stable { hir_id, attr_index } => {
97+ hir_id. hash_stable ( hcx, hasher) ;
98+ attr_index. hash_stable ( hcx, hasher) ;
99+ }
100+ }
101+ }
102+ }
67103
68- impl < HCX > ToStableHashKey < HCX > for LintExpectationId {
69- type KeyType = u32 ;
104+ impl < HCX : rustc_hir :: HashStableContext > ToStableHashKey < HCX > for LintExpectationId {
105+ type KeyType = ( HirId , usize ) ;
70106
71107 #[ inline]
72108 fn to_stable_hash_key ( & self , _: & HCX ) -> Self :: KeyType {
73- self . as_u32 ( )
109+ match self {
110+ LintExpectationId :: Unstable ( _) => {
111+ unreachable ! (
112+ "HashStable should never be called for an unstable `LintExpectationId`"
113+ )
114+ }
115+ LintExpectationId :: Stable { hir_id, attr_index } => ( * hir_id, * attr_index) ,
116+ }
74117 }
75118}
76119
@@ -133,10 +176,13 @@ impl Level {
133176 }
134177
135178 /// Converts a symbol to a level.
136- pub fn from_symbol ( x : Symbol , possible_lint_expect_id : u32 ) -> Option < Level > {
179+ pub fn from_symbol < F > ( x : Symbol , create_expectation_id : F ) -> Option < Level >
180+ where
181+ F : FnOnce ( ) -> LintExpectationId ,
182+ {
137183 match x {
138184 sym:: allow => Some ( Level :: Allow ) ,
139- sym:: expect => Some ( Level :: Expect ( LintExpectationId :: from ( possible_lint_expect_id ) ) ) ,
185+ sym:: expect => Some ( Level :: Expect ( create_expectation_id ( ) ) ) ,
140186 sym:: warn => Some ( Level :: Warn ) ,
141187 sym:: deny => Some ( Level :: Deny ) ,
142188 sym:: forbid => Some ( Level :: Forbid ) ,
0 commit comments