@@ -2,6 +2,7 @@ use crate::context::{CheckLintNameResult, LintStore};
2
2
use crate :: late:: unerased_lint_store;
3
3
use rustc_ast as ast;
4
4
use rustc_ast:: unwrap_or;
5
+ use rustc_ast:: NestedMetaItem ;
5
6
use rustc_ast_pretty:: pprust;
6
7
use rustc_data_structures:: fx:: FxHashMap ;
7
8
use rustc_errors:: { struct_span_err, Applicability , DiagnosticBuilder } ;
@@ -247,44 +248,18 @@ impl<'s> LintLevelsBuilder<'s> {
247
248
248
249
// Before processing the lint names, look for a reason (RFC 2383)
249
250
// at the end.
250
- let mut reason = None ;
251
251
let tail_li = & metas[ metas. len ( ) - 1 ] ;
252
- if let Some ( item) = tail_li. meta_item ( ) {
253
- match item. kind {
254
- ast:: MetaItemKind :: Word => { } // actual lint names handled later
255
- ast:: MetaItemKind :: NameValue ( ref name_value) => {
256
- if item. path == sym:: reason {
257
- // FIXME (#55112): issue unused-attributes lint if we thereby
258
- // don't have any lint names (`#[level(reason = "foo")]`)
259
- if let ast:: LitKind :: Str ( rationale, _) = name_value. kind {
260
- if !self . sess . features_untracked ( ) . lint_reasons {
261
- feature_err (
262
- & self . sess . parse_sess ,
263
- sym:: lint_reasons,
264
- item. span ,
265
- "lint reasons are experimental" ,
266
- )
267
- . emit ( ) ;
268
- }
269
- reason = Some ( rationale) ;
270
- } else {
271
- bad_attr ( name_value. span )
272
- . span_label ( name_value. span , "reason must be a string literal" )
273
- . emit ( ) ;
274
- }
275
- // found reason, reslice meta list to exclude it
276
- metas. pop ( ) . unwrap ( ) ;
277
- } else {
278
- bad_attr ( item. span )
279
- . span_label ( item. span , "bad attribute argument" )
280
- . emit ( ) ;
281
- }
282
- }
283
- ast:: MetaItemKind :: List ( _) => {
284
- bad_attr ( item. span ) . span_label ( item. span , "bad attribute argument" ) . emit ( ) ;
285
- }
252
+ let reason = match try_parse_reason_metadata ( tail_li, self . sess ) {
253
+ ParseLintReasonResult :: Ok ( reason) => {
254
+ metas. pop ( ) . unwrap ( ) ;
255
+ Some ( reason)
286
256
}
287
- }
257
+ ParseLintReasonResult :: MalformedReason => {
258
+ metas. pop ( ) . unwrap ( ) ;
259
+ None
260
+ }
261
+ ParseLintReasonResult :: NotFound => None ,
262
+ } ;
288
263
289
264
for li in metas {
290
265
let sp = li. span ( ) ;
@@ -568,6 +543,57 @@ impl<'s> LintLevelsBuilder<'s> {
568
543
}
569
544
}
570
545
546
+ pub ( crate ) enum ParseLintReasonResult {
547
+ /// The reason was found and is returned as part of this value.
548
+ Ok ( Symbol ) ,
549
+ /// Indicates that the reason field was found but was malformed.
550
+ MalformedReason ,
551
+ /// The checked item is not a reason field.
552
+ NotFound ,
553
+ }
554
+
555
+ pub ( crate ) fn try_parse_reason_metadata (
556
+ item : & NestedMetaItem ,
557
+ sess : & Session ,
558
+ ) -> ParseLintReasonResult {
559
+ let bad_attr = |span| struct_span_err ! ( sess, span, E0452 , "malformed lint attribute input" ) ;
560
+ if let Some ( item) = item. meta_item ( ) {
561
+ match item. kind {
562
+ ast:: MetaItemKind :: Word => { } // actual lint names handled later
563
+ ast:: MetaItemKind :: NameValue ( ref name_value) => {
564
+ if item. path == sym:: reason {
565
+ // FIXME (#55112): issue unused-attributes lint if we thereby
566
+ // don't have any lint names (`#[level(reason = "foo")]`)
567
+ if let ast:: LitKind :: Str ( rationale, _) = name_value. kind {
568
+ if !sess. features_untracked ( ) . lint_reasons {
569
+ feature_err (
570
+ & sess. parse_sess ,
571
+ sym:: lint_reasons,
572
+ item. span ,
573
+ "lint reasons are experimental" ,
574
+ )
575
+ . emit ( ) ;
576
+ }
577
+ return ParseLintReasonResult :: Ok ( rationale) ;
578
+ } else {
579
+ bad_attr ( name_value. span )
580
+ . span_label ( name_value. span , "reason must be a string literal" )
581
+ . emit ( ) ;
582
+ return ParseLintReasonResult :: MalformedReason ;
583
+ }
584
+ } else {
585
+ bad_attr ( item. span ) . span_label ( item. span , "bad attribute argument" ) . emit ( ) ;
586
+ }
587
+ }
588
+ ast:: MetaItemKind :: List ( _) => {
589
+ bad_attr ( item. span ) . span_label ( item. span , "bad attribute argument" ) . emit ( ) ;
590
+ }
591
+ }
592
+ }
593
+
594
+ ParseLintReasonResult :: NotFound
595
+ }
596
+
571
597
pub fn is_known_lint_tool ( m_item : Symbol , sess : & Session , attrs : & [ ast:: Attribute ] ) -> bool {
572
598
if [ sym:: clippy, sym:: rustc, sym:: rustdoc] . contains ( & m_item) {
573
599
return true ;
0 commit comments