@@ -94,7 +94,7 @@ impl CheckAttrVisitor<'tcx> {
9494 return ;
9595 }
9696
97- if matches ! ( target, Target :: Fn | Target :: Method ( _) | Target :: ForeignFn ) {
97+ if matches ! ( target, Target :: Closure | Target :: Fn | Target :: Method ( _) | Target :: ForeignFn ) {
9898 self . tcx . ensure ( ) . codegen_fn_attrs ( self . tcx . hir ( ) . local_def_id ( hir_id) ) ;
9999 }
100100
@@ -185,7 +185,7 @@ impl CheckAttrVisitor<'tcx> {
185185 /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
186186 fn check_non_exhaustive ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
187187 match target {
188- Target :: Struct | Target :: Enum => true ,
188+ Target :: Struct | Target :: Enum | Target :: Variant => true ,
189189 _ => {
190190 struct_span_err ! (
191191 self . tcx. sess,
@@ -470,6 +470,9 @@ impl CheckAttrVisitor<'tcx> {
470470
471471 for hint in & hints {
472472 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+ }
473476 name @ sym:: C | name @ sym:: align => {
474477 is_c |= name == sym:: C ;
475478 match target {
@@ -535,12 +538,16 @@ impl CheckAttrVisitor<'tcx> {
535538 }
536539 _ => continue ,
537540 } ;
538- self . emit_repr_error (
541+
542+ struct_span_err ! (
543+ self . tcx. sess,
539544 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)
543548 )
549+ . span_label ( * span, & format ! ( "not {} {}" , article, allowed_targets) )
550+ . emit ( ) ;
544551 }
545552
546553 // Just point at all repr hints if there are any incompatibilities.
@@ -579,56 +586,6 @@ impl CheckAttrVisitor<'tcx> {
579586 }
580587 }
581588
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-
632589 fn check_used ( & self , attrs : & ' hir [ Attribute ] , target : Target ) {
633590 for attr in attrs {
634591 if self . tcx . sess . check_name ( attr, sym:: used) && target != Target :: Static {
@@ -672,14 +629,32 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
672629 }
673630
674631 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+ }
676636 intravisit:: walk_stmt ( self , stmt)
677637 }
678638
679639 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 ) ;
681646 intravisit:: walk_expr ( self , expr)
682647 }
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+ }
683658}
684659
685660fn is_c_like_enum ( item : & Item < ' _ > ) -> bool {
0 commit comments