@@ -104,7 +104,7 @@ impl CheckAttrVisitor<'tcx> {
104104 return ;
105105 }
106106
107- if matches ! ( target, Target :: Fn | Target :: Method ( _) | Target :: ForeignFn ) {
107+ if matches ! ( target, Target :: Closure | Target :: Fn | Target :: Method ( _) | Target :: ForeignFn ) {
108108 self . tcx . ensure ( ) . codegen_fn_attrs ( self . tcx . hir ( ) . local_def_id ( hir_id) ) ;
109109 }
110110
@@ -195,7 +195,7 @@ impl CheckAttrVisitor<'tcx> {
195195 /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
196196 fn check_non_exhaustive ( & self , attr : & Attribute , span : & Span , target : Target ) -> bool {
197197 match target {
198- Target :: Struct | Target :: Enum => true ,
198+ Target :: Struct | Target :: Enum | Target :: Variant => true ,
199199 _ => {
200200 struct_span_err ! (
201201 self . tcx. sess,
@@ -587,6 +587,9 @@ impl CheckAttrVisitor<'tcx> {
587587
588588 for hint in & hints {
589589 let ( article, allowed_targets) = match hint. name_or_empty ( ) {
590+ _ if !matches ! ( target, Target :: Struct | Target :: Enum | Target :: Union ) => {
591+ ( "a" , "struct, enum, or union" )
592+ }
590593 name @ sym:: C | name @ sym:: align => {
591594 is_c |= name == sym:: C ;
592595 match target {
@@ -652,12 +655,16 @@ impl CheckAttrVisitor<'tcx> {
652655 }
653656 _ => continue ,
654657 } ;
655- self . emit_repr_error (
658+
659+ struct_span_err ! (
660+ self . tcx. sess,
656661 hint. span( ) ,
657- * span ,
658- & format ! ( "attribute should be applied to {}", allowed_targets ) ,
659- & format ! ( "not {} {}" , article, allowed_targets) ,
662+ E0517 ,
663+ " {}",
664+ & format!( "attribute should be applied to {} {}" , article, allowed_targets)
660665 )
666+ . span_label ( * span, & format ! ( "not {} {}" , article, allowed_targets) )
667+ . emit ( ) ;
661668 }
662669
663670 // Just point at all repr hints if there are any incompatibilities.
@@ -703,56 +710,6 @@ impl CheckAttrVisitor<'tcx> {
703710 }
704711 }
705712
706- fn emit_repr_error (
707- & self ,
708- hint_span : Span ,
709- label_span : Span ,
710- hint_message : & str ,
711- label_message : & str ,
712- ) {
713- struct_span_err ! ( self . tcx. sess, hint_span, E0517 , "{}" , hint_message)
714- . span_label ( label_span, label_message)
715- . emit ( ) ;
716- }
717-
718- fn check_stmt_attributes ( & self , stmt : & hir:: Stmt < ' _ > ) {
719- // When checking statements ignore expressions, they will be checked later
720- if let hir:: StmtKind :: Local ( ref l) = stmt. kind {
721- self . check_attributes ( l. hir_id , & l. attrs , & stmt. span , Target :: Statement , None ) ;
722- for attr in l. attrs . iter ( ) {
723- if self . tcx . sess . check_name ( attr, sym:: repr) {
724- self . emit_repr_error (
725- attr. span ,
726- stmt. span ,
727- "attribute should not be applied to a statement" ,
728- "not a struct, enum, or union" ,
729- ) ;
730- }
731- }
732- }
733- }
734-
735- fn check_expr_attributes ( & self , expr : & hir:: Expr < ' _ > ) {
736- let target = match expr. kind {
737- hir:: ExprKind :: Closure ( ..) => Target :: Closure ,
738- _ => Target :: Expression ,
739- } ;
740- self . check_attributes ( expr. hir_id , & expr. attrs , & expr. span , target, None ) ;
741- for attr in expr. attrs . iter ( ) {
742- if self . tcx . sess . check_name ( attr, sym:: repr) {
743- self . emit_repr_error (
744- attr. span ,
745- expr. span ,
746- "attribute should not be applied to an expression" ,
747- "not defining a struct, enum, or union" ,
748- ) ;
749- }
750- }
751- if target == Target :: Closure {
752- self . tcx . ensure ( ) . codegen_fn_attrs ( self . tcx . hir ( ) . local_def_id ( expr. hir_id ) ) ;
753- }
754- }
755-
756713 fn check_used ( & self , attrs : & ' hir [ Attribute ] , target : Target ) {
757714 for attr in attrs {
758715 if self . tcx . sess . check_name ( attr, sym:: used) && target != Target :: Static {
@@ -808,14 +765,32 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
808765 }
809766
810767 fn visit_stmt ( & mut self , stmt : & ' tcx hir:: Stmt < ' tcx > ) {
811- self . check_stmt_attributes ( stmt) ;
768+ // When checking statements ignore expressions, they will be checked later.
769+ if let hir:: StmtKind :: Local ( ref l) = stmt. kind {
770+ self . check_attributes ( l. hir_id , & l. attrs , & stmt. span , Target :: Statement , None ) ;
771+ }
812772 intravisit:: walk_stmt ( self , stmt)
813773 }
814774
815775 fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
816- self . check_expr_attributes ( expr) ;
776+ let target = match expr. kind {
777+ hir:: ExprKind :: Closure ( ..) => Target :: Closure ,
778+ _ => Target :: Expression ,
779+ } ;
780+
781+ self . check_attributes ( expr. hir_id , & expr. attrs , & expr. span , target, None ) ;
817782 intravisit:: walk_expr ( self , expr)
818783 }
784+
785+ fn visit_variant (
786+ & mut self ,
787+ variant : & ' tcx hir:: Variant < ' tcx > ,
788+ generics : & ' tcx hir:: Generics < ' tcx > ,
789+ item_id : HirId ,
790+ ) {
791+ self . check_attributes ( variant. id , variant. attrs , & variant. span , Target :: Variant , None ) ;
792+ intravisit:: walk_variant ( self , variant, generics, item_id)
793+ }
819794}
820795
821796fn is_c_like_enum ( item : & Item < ' _ > ) -> bool {
0 commit comments