@@ -14,6 +14,7 @@ use rustc::session::Session;
1414use rustc_data_structures:: fx:: FxHashMap ;
1515use syntax:: ast:: * ;
1616use syntax:: attr;
17+ use syntax:: feature_gate:: is_builtin_attr;
1718use syntax:: source_map:: Spanned ;
1819use syntax:: symbol:: { kw, sym} ;
1920use syntax:: ptr:: P ;
@@ -365,6 +366,29 @@ impl<'a> AstValidator<'a> {
365366 _ => None ,
366367 }
367368 }
369+
370+ fn check_fn_decl ( & self , fn_decl : & FnDecl ) {
371+ fn_decl
372+ . inputs
373+ . iter ( )
374+ . flat_map ( |i| i. attrs . as_ref ( ) )
375+ . filter ( |attr| {
376+ let arr = [ sym:: allow, sym:: cfg, sym:: cfg_attr, sym:: deny, sym:: forbid, sym:: warn] ;
377+ !arr. contains ( & attr. name_or_empty ( ) ) && is_builtin_attr ( attr)
378+ } )
379+ . for_each ( |attr| if attr. is_sugared_doc {
380+ let mut err = self . err_handler ( ) . struct_span_err (
381+ attr. span ,
382+ "documentation comments cannot be applied to function parameters"
383+ ) ;
384+ err. span_label ( attr. span , "doc comments are not allowed here" ) ;
385+ err. emit ( ) ;
386+ }
387+ else {
388+ self . err_handler ( ) . span_err ( attr. span , "allow, cfg, cfg_attr, deny, \
389+ forbid, and warn are the only allowed built-in attributes in function parameters")
390+ } ) ;
391+ }
368392}
369393
370394enum GenericPosition {
@@ -470,6 +494,9 @@ fn validate_generics_order<'a>(
470494impl < ' a > Visitor < ' a > for AstValidator < ' a > {
471495 fn visit_expr ( & mut self , expr : & ' a Expr ) {
472496 match expr. node {
497+ ExprKind :: Closure ( _, _, _, ref fn_decl, _, _) => {
498+ self . check_fn_decl ( fn_decl) ;
499+ }
473500 ExprKind :: IfLet ( _, ref expr, _, _) | ExprKind :: WhileLet ( _, ref expr, _, _) =>
474501 self . while_if_let_ambiguity ( & expr) ,
475502 ExprKind :: InlineAsm ( ..) if !self . session . target . target . options . allow_asm => {
@@ -484,6 +511,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
484511 fn visit_ty ( & mut self , ty : & ' a Ty ) {
485512 match ty. node {
486513 TyKind :: BareFn ( ref bfty) => {
514+ self . check_fn_decl ( & bfty. decl ) ;
487515 self . check_decl_no_pat ( & bfty. decl , |span, _| {
488516 struct_span_err ! ( self . session, span, E0561 ,
489517 "patterns aren't allowed in function pointer types" ) . emit ( ) ;
@@ -601,10 +629,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
601629 . note ( "only trait implementations may be annotated with default" ) . emit ( ) ;
602630 }
603631 }
604- ItemKind :: Fn ( _, ref header, ref generics, _) => {
632+ ItemKind :: Fn ( ref decl, ref header, ref generics, _) => {
633+ self . visit_fn_header ( header) ;
634+ self . check_fn_decl ( decl) ;
605635 // We currently do not permit const generics in `const fn`, as
606636 // this is tantamount to allowing compile-time dependent typing.
607- self . visit_fn_header ( header) ;
608637 if header. constness . node == Constness :: Const {
609638 // Look for const generics and error if we find any.
610639 for param in & generics. params {
@@ -657,6 +686,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
657686 self . no_questions_in_bounds ( bounds, "supertraits" , true ) ;
658687 for trait_item in trait_items {
659688 if let TraitItemKind :: Method ( ref sig, ref block) = trait_item. node {
689+ self . check_fn_decl ( & sig. decl ) ;
660690 self . check_trait_fn_not_async ( trait_item. span , sig. header . asyncness . node ) ;
661691 self . check_trait_fn_not_const ( sig. header . constness ) ;
662692 if block. is_none ( ) {
@@ -711,6 +741,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
711741 fn visit_foreign_item ( & mut self , fi : & ' a ForeignItem ) {
712742 match fi. node {
713743 ForeignItemKind :: Fn ( ref decl, _) => {
744+ self . check_fn_decl ( decl) ;
714745 self . check_decl_no_pat ( decl, |span, _| {
715746 struct_span_err ! ( self . session, span, E0130 ,
716747 "patterns aren't allowed in foreign function declarations" )
@@ -864,6 +895,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
864895 "`async fn` is not permitted in the 2015 edition" ) . emit ( ) ;
865896 }
866897 }
898+
899+ fn visit_impl_item ( & mut self , ii : & ' a ImplItem ) {
900+ match ii. node {
901+ ImplItemKind :: Method ( ref sig, _) => {
902+ self . check_fn_decl ( & sig. decl ) ;
903+ }
904+ _ => { }
905+ }
906+ visit:: walk_impl_item ( self , ii) ;
907+ }
867908}
868909
869910pub fn check_crate ( session : & Session , krate : & Crate ) -> ( bool , bool ) {
0 commit comments