11use std:: marker:: PhantomData ;
22
3- use rustc_ast:: AttrStyle ;
43use rustc_hir:: HashIgnoredAttrId ;
5- use rustc_hir:: attrs:: { LintAttrIdsInformation , LintAttributeKind } ;
4+ use rustc_hir:: attrs:: { LintAttrIdsInformation , LintAttrInfo , LintAttributeKind } ;
65use rustc_hir:: lints:: { AttributeLintKind , RenamedLintSuggestion } ;
76use rustc_middle:: bug;
87use rustc_session:: lint:: CheckLintNameResult ;
@@ -54,59 +53,38 @@ const ALLOWED_TARGETS: &'static [Policy] = {
5453 Allow ( Target :: Delegation { mac : false } ) ,
5554 Allow ( Target :: Delegation { mac : true } ) ,
5655 Warn ( Target :: MacroCall ) ,
57- ] }
58- ;
59-
56+ ]
57+ } ;
6058
6159pub ( crate ) trait Lint {
62- fn lint_level < S : Stage > ( cx : & FinalizeContext < ' _ , ' _ , S > , ) -> LintAttributeKind ;
60+ const KIND : LintAttributeKind ;
6361 const ATTR_SYMBOL : Symbol ;
6462}
6563
6664#[ derive( Default ) ]
6765pub ( crate ) struct LintParser < T : Lint > {
68- lint_ids : ThinVec < LintAttrIdsInformation > ,
69- reason : Option < Symbol > ,
70- errored : bool ,
71- attr_span : Option < Span > ,
72- attr_style : Option < AttrStyle > ,
66+ lint_attrs : ThinVec < LintAttrInfo > ,
67+ lint_index : usize ,
7368 phantom : PhantomData < T > ,
7469}
7570
76- impl < S : Stage , T : Lint + ' static + Default > AttributeParser < S > for LintParser < T > {
71+ impl < S : Stage , T : Lint + ' static + Default > AttributeParser < S > for LintParser < T > {
7772 const ATTRIBUTES : AcceptMapping < Self , S > = & [ (
7873 & [ T :: ATTR_SYMBOL ] ,
7974 template ! (
8075 List : & [ "lint1" , "lint1, lint2, ..." , r#"lint1, lint2, lint3, reason = "...""# ] ,
8176 "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
8277 ) ,
8378 |this, cx, args| {
84- * this = Self :: default ( ) ;
85- this. attr_span = Some ( cx. attr_span ) ;
86- this. attr_style = Some ( cx. attr_style ) ;
87- validate_lint_attr (
88- cx,
89- args,
90- & mut this. lint_ids ,
91- & mut this. errored ,
92- & mut this. reason ,
93- T :: ATTR_SYMBOL ,
94- ) ;
79+ if let Some ( lint_attr) = validate_lint_attr ( cx, args, T :: ATTR_SYMBOL , & mut this. lint_index ) {
80+ this. lint_attrs . push ( lint_attr) ;
81+ }
9582 } ,
9683 ) ] ;
9784
98- fn finalize ( self , cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
99- let ( Some ( attr_span) , Some ( attr_style) ) = ( self . attr_span , self . attr_style ) else {
100- return None ;
101- } ;
102- if !self . errored {
103- Some ( AttributeKind :: LintAttribute {
104- lint_groups : self . lint_ids ,
105- reason : self . reason ,
106- kind : T :: lint_level ( cx) ,
107- attr_span,
108- attr_style,
109- } )
85+ fn finalize ( self , _cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
86+ if !self . lint_attrs . is_empty ( ) {
87+ Some ( AttributeKind :: LintAttribute { sub_attrs : self . lint_attrs , kind : T :: KIND } )
11088 } else {
11189 None
11290 }
@@ -120,105 +98,95 @@ pub(crate) struct Expect;
12098pub ( crate ) type ExpectParser = LintParser < Expect > ;
12199
122100impl Lint for Expect {
123- fn lint_level < S : Stage > ( cx : & FinalizeContext < ' _ , ' _ , S > ) -> LintAttributeKind {
124- LintAttributeKind :: Expect ( HashIgnoredAttrId { attr_id : cx. attr_id } )
125- }
101+ const KIND : LintAttributeKind = LintAttributeKind :: Expect ;
126102 const ATTR_SYMBOL : Symbol = sym:: expect;
127- }
103+ }
128104
129105#[ derive( Default ) ]
130106pub ( crate ) struct Allow ;
131107pub ( crate ) type AllowParser = LintParser < Allow > ;
132108
133109impl Lint for Allow {
134- fn lint_level < S : Stage > ( _cx : & FinalizeContext < ' _ , ' _ , S > ) -> LintAttributeKind {
135- LintAttributeKind :: Allow
136- }
110+ const KIND : LintAttributeKind = LintAttributeKind :: Allow ;
137111 const ATTR_SYMBOL : Symbol = sym:: allow;
138- }
112+ }
139113#[ derive( Default ) ]
140114pub ( crate ) struct Warn ;
141115pub ( crate ) type WarnParser = LintParser < Warn > ;
142116
143117impl Lint for Warn {
144- fn lint_level < S : Stage > ( _cx : & FinalizeContext < ' _ , ' _ , S > ) -> LintAttributeKind {
145- LintAttributeKind :: Warn
146- }
118+ const KIND : LintAttributeKind = LintAttributeKind :: Warn ;
119+
147120 const ATTR_SYMBOL : Symbol = sym:: warn;
148- }
121+ }
149122
150123#[ derive( Default ) ]
151124pub ( crate ) struct Deny ;
152125pub ( crate ) type DenyParser = LintParser < Deny > ;
153126
154127impl Lint for Deny {
155- fn lint_level < S : Stage > ( _cx : & FinalizeContext < ' _ , ' _ , S > ) -> LintAttributeKind {
156- LintAttributeKind :: Deny
157- }
128+ const KIND : LintAttributeKind = LintAttributeKind :: Deny ;
129+
158130 const ATTR_SYMBOL : Symbol = sym:: deny;
159- }
131+ }
160132
161133#[ derive( Default ) ]
162134pub ( crate ) struct Forbid ;
163135pub ( crate ) type ForbidParser = LintParser < Forbid > ;
164136
165137impl Lint for Forbid {
166- fn lint_level < S : Stage > ( _cx : & FinalizeContext < ' _ , ' _ , S > ) -> LintAttributeKind {
167- LintAttributeKind :: Forbid
168- }
169- const ATTR_SYMBOL : Symbol = sym:: forbid;
170- }
171-
172-
138+ const KIND : LintAttributeKind = LintAttributeKind :: Forbid ;
173139
140+ const ATTR_SYMBOL : Symbol = sym:: forbid;
141+ }
174142
175143#[ inline( always) ]
176144fn validate_lint_attr < S : Stage > (
177145 cx : & mut AcceptContext < ' _ , ' _ , S > ,
178146 args : & ArgParser ,
179- lint_ids : & mut ThinVec < LintAttrIdsInformation > ,
180- errored : & mut bool ,
181- reason : & mut Option < Symbol > ,
182147 attr_name : Symbol ,
183- ) {
184-
148+ lint_index : & mut usize
149+ ) -> Option < LintAttrInfo > {
185150 let Some ( list) = args. list ( ) else {
186151 cx. expected_list ( cx. inner_span , args) ;
187- return ;
152+ return None ;
188153 } ;
189154 let mut list = list. mixed ( ) . peekable ( ) ;
190155
191- let mut lint_index = 0 ;
192156 let mut skip_reason_check = false ;
157+ let mut errored = false ;
158+ let mut reason = None ;
159+ let mut lint_ids = ThinVec :: new ( ) ;
160+
193161 while let Some ( item) = list. next ( ) {
194162 let Some ( meta_item) = item. meta_item ( ) else {
195163 cx. expected_identifier ( item. span ( ) ) ;
196- * errored = true ;
164+ errored = true ;
197165 continue ;
198166 } ;
199167
200168 if let Some ( args) = meta_item. word_is ( sym:: reason) {
201169 if reason. is_some ( ) {
202170 // TODO check if this check is already present
203171 cx. duplicate_key ( meta_item. span ( ) , sym:: reason) ;
204- * errored = true ;
172+ errored = true ;
205173 }
206174 let ArgParser :: NameValue ( nv) = args else {
207175 cx. expected_name_value ( meta_item. span ( ) , Some ( sym:: reason) ) ;
208- * errored = true ;
176+ errored = true ;
209177 continue ;
210178 } ;
211179 if list. peek ( ) . is_some ( ) {
212180 cx. expected_nv_as_last_argument ( nv. args_span ( ) , attr_name, sym:: reason) ;
213- * errored = true ;
181+ errored = true ;
214182 continue ;
215183 }
216184 let Some ( s) = nv. value_as_str ( ) else {
217185 cx. expected_string_literal ( nv. value_span , Some ( nv. value_as_lit ( ) ) ) ;
218- * errored = true ;
186+ errored = true ;
219187 continue ;
220188 } ;
221- * reason = Some ( s) ;
189+ reason = Some ( s) ;
222190 } else {
223191 let mut segments = meta_item. path ( ) . segments ( ) ;
224192
@@ -241,19 +209,33 @@ fn validate_lint_attr<S: Stage>(
241209 & tool_name. map ( |tool| format ! ( "{tool}::{}" , & name) ) . unwrap_or ( name. clone ( ) ) ,
242210 ) ;
243211
244- if let Some ( ids) =
245- check_lint ( cx, original_name, & name, tool_name, tool_span, meta_item. span ( ) , lint_index )
246- {
212+ if let Some ( ids) = check_lint (
213+ cx,
214+ original_name,
215+ & name,
216+ tool_name,
217+ tool_span,
218+ meta_item. span ( ) ,
219+ * lint_index,
220+ ) {
247221 lint_ids. extend ( ids) ;
248222 } else {
249223 skip_reason_check = true
250224 }
251- lint_index += 1 ;
225+ * lint_index += 1 ;
252226 }
253227 }
254228 if !skip_reason_check && lint_ids. is_empty ( ) {
255229 cx. warn_empty_attribute ( cx. attr_span ) ;
256230 }
231+
232+ ( !errored) . then_some ( LintAttrInfo {
233+ reason,
234+ lint_groups : lint_ids,
235+ attr_span : cx. attr_span ,
236+ attr_style : cx. attr_style ,
237+ attr_id : HashIgnoredAttrId { attr_id : cx. attr_id } ,
238+ } )
257239}
258240
259241fn check_lint < S : Stage > (
@@ -263,7 +245,7 @@ fn check_lint<S: Stage>(
263245 tool_name : Option < Symbol > ,
264246 tool_span : Option < Span > ,
265247 span : Span ,
266- lint_index : usize
248+ lint_index : usize ,
267249) -> Option < Vec < LintAttrIdsInformation > > {
268250 let Some ( lint_store) = & cx. sess . lint_store else {
269251 bug ! ( "lint_store required while parsing attributes" ) ;
@@ -304,7 +286,7 @@ fn check_lint<S: Stage>(
304286 original_name,
305287 span,
306288 tool_name,
307- lint_index
289+ lint_index,
308290 } ) ;
309291 }
310292 }
@@ -351,7 +333,13 @@ fn check_lint<S: Stage>(
351333
352334 for id in ids {
353335 let name = Symbol :: intern ( & id. to_string ( ) ) ;
354- lint_ids. push ( LintAttrIdsInformation { name, original_name, span, tool_name, lint_index} ) ;
336+ lint_ids. push ( LintAttrIdsInformation {
337+ name,
338+ original_name,
339+ span,
340+ tool_name,
341+ lint_index,
342+ } ) ;
355343 }
356344 }
357345
0 commit comments