@@ -5,7 +5,9 @@ extern crate rustc_macros;
5
5
6
6
pub use self :: Level :: * ;
7
7
use rustc_ast:: node_id:: { NodeId , NodeMap } ;
8
+ use rustc_ast:: AttrId ;
8
9
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher , ToStableHashKey } ;
10
+ use rustc_hir:: HirId ;
9
11
use rustc_serialize:: json:: Json ;
10
12
use rustc_span:: edition:: Edition ;
11
13
use rustc_span:: { sym, symbol:: Ident , MultiSpan , Span , Symbol } ;
@@ -48,29 +50,70 @@ pub enum Applicability {
48
50
Unspecified ,
49
51
}
50
52
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
+ }
63
84
}
64
85
}
65
86
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
+ }
67
103
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 ) ;
70
106
71
107
#[ inline]
72
108
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
+ }
74
117
}
75
118
}
76
119
@@ -133,10 +176,13 @@ impl Level {
133
176
}
134
177
135
178
/// 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
+ {
137
183
match x {
138
184
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 ( ) ) ) ,
140
186
sym:: warn => Some ( Level :: Warn ) ,
141
187
sym:: deny => Some ( Level :: Deny ) ,
142
188
sym:: forbid => Some ( Level :: Forbid ) ,
0 commit comments