1414//! conflicts between multiple such attributes attached to the same
1515//! item.
1616
17+ use syntax_pos:: Span ;
1718use ty:: TyCtxt ;
1819
1920use hir;
@@ -27,6 +28,8 @@ enum Target {
2728 Enum ,
2829 Const ,
2930 ForeignMod ,
31+ Expression ,
32+ Statement ,
3033 Other ,
3134}
3235
@@ -62,7 +65,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
6265 let mut has_wasm_import_module = false ;
6366 for attr in & item. attrs {
6467 if attr. check_name ( "inline" ) {
65- self . check_inline ( attr, item, target)
68+ self . check_inline ( attr, & item. span , target)
6669 } else if attr. check_name ( "wasm_import_module" ) {
6770 has_wasm_import_module = true ;
6871 if attr. value_str ( ) . is_none ( ) {
@@ -99,13 +102,13 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
99102 }
100103
101104 /// Check if an `#[inline]` is applied to a function.
102- fn check_inline ( & self , attr : & hir:: Attribute , item : & hir :: Item , target : Target ) {
105+ fn check_inline ( & self , attr : & hir:: Attribute , span : & Span , target : Target ) {
103106 if target != Target :: Fn {
104107 struct_span_err ! ( self . tcx. sess,
105108 attr. span,
106109 E0518 ,
107110 "attribute should be applied to function" )
108- . span_label ( item . span , "not a function" )
111+ . span_label ( * span, "not a function" )
109112 . emit ( ) ;
110113 }
111114 }
@@ -196,10 +199,12 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
196199 }
197200 _ => continue ,
198201 } ;
199- struct_span_err ! ( self . tcx. sess, hint. span, E0517 ,
200- "attribute should be applied to {}" , allowed_targets)
201- . span_label ( item. span , format ! ( "not {} {}" , article, allowed_targets) )
202- . emit ( ) ;
202+ self . emit_repr_error (
203+ hint. span ,
204+ item. span ,
205+ & format ! ( "attribute should be applied to {}" , allowed_targets) ,
206+ & format ! ( "not {} {}" , article, allowed_targets) ,
207+ )
203208 }
204209
205210 // Just point at all repr hints if there are any incompatibilities.
@@ -221,17 +226,75 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
221226 "conflicting representation hints" ) ;
222227 }
223228 }
229+
230+ fn emit_repr_error (
231+ & self ,
232+ hint_span : Span ,
233+ label_span : Span ,
234+ hint_message : & str ,
235+ label_message : & str ,
236+ ) {
237+ struct_span_err ! ( self . tcx. sess, hint_span, E0517 , "{}" , hint_message)
238+ . span_label ( label_span, label_message)
239+ . emit ( ) ;
240+ }
241+
242+ fn check_stmt_attributes ( & self , stmt : & hir:: Stmt ) {
243+ // When checking statements ignore expressions, they will be checked later
244+ if let hir:: Stmt_ :: StmtDecl ( _, _) = stmt. node {
245+ for attr in stmt. node . attrs ( ) {
246+ if attr. check_name ( "inline" ) {
247+ self . check_inline ( attr, & stmt. span , Target :: Statement ) ;
248+ }
249+ if attr. check_name ( "repr" ) {
250+ self . emit_repr_error (
251+ attr. span ,
252+ stmt. span ,
253+ & format ! ( "attribute should not be applied to a statement" ) ,
254+ & format ! ( "not a struct, enum or union" ) ,
255+ ) ;
256+ }
257+ }
258+ }
259+ }
260+
261+ fn check_expr_attributes ( & self , expr : & hir:: Expr ) {
262+ for attr in expr. attrs . iter ( ) {
263+ if attr. check_name ( "inline" ) {
264+ self . check_inline ( attr, & expr. span , Target :: Expression ) ;
265+ }
266+ if attr. check_name ( "repr" ) {
267+ self . emit_repr_error (
268+ attr. span ,
269+ expr. span ,
270+ & format ! ( "attribute should not be applied to an expression" ) ,
271+ & format ! ( "not defining a struct, enum or union" ) ,
272+ ) ;
273+ }
274+ }
275+ }
224276}
225277
226278impl < ' a , ' tcx > Visitor < ' tcx > for CheckAttrVisitor < ' a , ' tcx > {
227279 fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
228- NestedVisitorMap :: None
280+ NestedVisitorMap :: OnlyBodies ( & self . tcx . hir )
229281 }
230282
231283 fn visit_item ( & mut self , item : & ' tcx hir:: Item ) {
232284 let target = Target :: from_item ( item) ;
233285 self . check_attributes ( item, target) ;
234- intravisit:: walk_item ( self , item) ;
286+ intravisit:: walk_item ( self , item)
287+ }
288+
289+
290+ fn visit_stmt ( & mut self , stmt : & ' tcx hir:: Stmt ) {
291+ self . check_stmt_attributes ( stmt) ;
292+ intravisit:: walk_stmt ( self , stmt)
293+ }
294+
295+ fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr ) {
296+ self . check_expr_attributes ( expr) ;
297+ intravisit:: walk_expr ( self , expr)
235298 }
236299}
237300
0 commit comments