@@ -94,7 +94,7 @@ impl CheckAttrVisitor<'tcx> {
94
94
return ;
95
95
}
96
96
97
- if matches ! ( target, Target :: Fn | Target :: Method ( _) | Target :: ForeignFn ) {
97
+ if matches ! ( target, Target :: Closure | Target :: Fn | Target :: Method ( _) | Target :: ForeignFn ) {
98
98
self . tcx . ensure ( ) . codegen_fn_attrs ( self . tcx . hir ( ) . local_def_id ( hir_id) ) ;
99
99
}
100
100
@@ -185,7 +185,7 @@ impl CheckAttrVisitor<'tcx> {
185
185
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
186
186
fn check_non_exhaustive ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
187
187
match target {
188
- Target :: Struct | Target :: Enum => true ,
188
+ Target :: Struct | Target :: Enum | Target :: Variant => true ,
189
189
_ => {
190
190
struct_span_err ! (
191
191
self . tcx. sess,
@@ -470,6 +470,9 @@ impl CheckAttrVisitor<'tcx> {
470
470
471
471
for hint in & hints {
472
472
let ( article, allowed_targets) = match hint. name_or_empty ( ) {
473
+ _ if !matches ! ( target, Target :: Struct | Target :: Enum | Target :: Union ) => {
474
+ ( "a" , "struct, enum, or union" )
475
+ }
473
476
name @ sym:: C | name @ sym:: align => {
474
477
is_c |= name == sym:: C ;
475
478
match target {
@@ -535,12 +538,16 @@ impl CheckAttrVisitor<'tcx> {
535
538
}
536
539
_ => continue ,
537
540
} ;
538
- self . emit_repr_error (
541
+
542
+ struct_span_err ! (
543
+ self . tcx. sess,
539
544
hint. span( ) ,
540
- * span ,
541
- & format ! ( "attribute should be applied to {}", allowed_targets ) ,
542
- & format ! ( "not {} {}" , article, allowed_targets) ,
545
+ E0517 ,
546
+ " {}",
547
+ & format!( "attribute should be applied to {} {}" , article, allowed_targets)
543
548
)
549
+ . span_label ( * span, & format ! ( "not {} {}" , article, allowed_targets) )
550
+ . emit ( ) ;
544
551
}
545
552
546
553
// Just point at all repr hints if there are any incompatibilities.
@@ -579,56 +586,6 @@ impl CheckAttrVisitor<'tcx> {
579
586
}
580
587
}
581
588
582
- fn emit_repr_error (
583
- & self ,
584
- hint_span : Span ,
585
- label_span : Span ,
586
- hint_message : & str ,
587
- label_message : & str ,
588
- ) {
589
- struct_span_err ! ( self . tcx. sess, hint_span, E0517 , "{}" , hint_message)
590
- . span_label ( label_span, label_message)
591
- . emit ( ) ;
592
- }
593
-
594
- fn check_stmt_attributes ( & self , stmt : & hir:: Stmt < ' _ > ) {
595
- // When checking statements ignore expressions, they will be checked later
596
- if let hir:: StmtKind :: Local ( ref l) = stmt. kind {
597
- self . check_attributes ( l. hir_id , & l. attrs , & stmt. span , Target :: Statement , None ) ;
598
- for attr in l. attrs . iter ( ) {
599
- if self . tcx . sess . check_name ( attr, sym:: repr) {
600
- self . emit_repr_error (
601
- attr. span ,
602
- stmt. span ,
603
- "attribute should not be applied to a statement" ,
604
- "not a struct, enum, or union" ,
605
- ) ;
606
- }
607
- }
608
- }
609
- }
610
-
611
- fn check_expr_attributes ( & self , expr : & hir:: Expr < ' _ > ) {
612
- let target = match expr. kind {
613
- hir:: ExprKind :: Closure ( ..) => Target :: Closure ,
614
- _ => Target :: Expression ,
615
- } ;
616
- self . check_attributes ( expr. hir_id , & expr. attrs , & expr. span , target, None ) ;
617
- for attr in expr. attrs . iter ( ) {
618
- if self . tcx . sess . check_name ( attr, sym:: repr) {
619
- self . emit_repr_error (
620
- attr. span ,
621
- expr. span ,
622
- "attribute should not be applied to an expression" ,
623
- "not defining a struct, enum, or union" ,
624
- ) ;
625
- }
626
- }
627
- if target == Target :: Closure {
628
- self . tcx . ensure ( ) . codegen_fn_attrs ( self . tcx . hir ( ) . local_def_id ( expr. hir_id ) ) ;
629
- }
630
- }
631
-
632
589
fn check_used ( & self , attrs : & ' hir [ Attribute ] , target : Target ) {
633
590
for attr in attrs {
634
591
if self . tcx . sess . check_name ( attr, sym:: used) && target != Target :: Static {
@@ -672,14 +629,32 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
672
629
}
673
630
674
631
fn visit_stmt ( & mut self , stmt : & ' tcx hir:: Stmt < ' tcx > ) {
675
- self . check_stmt_attributes ( stmt) ;
632
+ // When checking statements ignore expressions, they will be checked later.
633
+ if let hir:: StmtKind :: Local ( ref l) = stmt. kind {
634
+ self . check_attributes ( l. hir_id , & l. attrs , & stmt. span , Target :: Statement , None ) ;
635
+ }
676
636
intravisit:: walk_stmt ( self , stmt)
677
637
}
678
638
679
639
fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
680
- self . check_expr_attributes ( expr) ;
640
+ let target = match expr. kind {
641
+ hir:: ExprKind :: Closure ( ..) => Target :: Closure ,
642
+ _ => Target :: Expression ,
643
+ } ;
644
+
645
+ self . check_attributes ( expr. hir_id , & expr. attrs , & expr. span , target, None ) ;
681
646
intravisit:: walk_expr ( self , expr)
682
647
}
648
+
649
+ fn visit_variant (
650
+ & mut self ,
651
+ variant : & ' tcx hir:: Variant < ' tcx > ,
652
+ generics : & ' tcx hir:: Generics < ' tcx > ,
653
+ item_id : HirId ,
654
+ ) {
655
+ self . check_attributes ( variant. id , variant. attrs , & variant. span , Target :: Variant , None ) ;
656
+ intravisit:: walk_variant ( self , variant, generics, item_id)
657
+ }
683
658
}
684
659
685
660
fn is_c_like_enum ( item : & Item < ' _ > ) -> bool {
0 commit comments