From 1eaaf440d5173f090d6e937f4b4cffec6c038984 Mon Sep 17 00:00:00 2001 From: Caio Date: Sun, 9 Jun 2019 07:58:40 -0300 Subject: [PATCH] Allow attributes in formal function parameters --- src/librustc_data_structures/thin_vec.rs | 6 + src/librustc_passes/ast_validation.rs | 45 ++- src/libsyntax/ast.rs | 4 +- src/libsyntax/attr/mod.rs | 2 +- src/libsyntax/config.rs | 9 + src/libsyntax/ext/build.rs | 5 +- src/libsyntax/ext/expand.rs | 5 + src/libsyntax/feature_gate.rs | 15 + src/libsyntax/mut_visit.rs | 3 +- src/libsyntax/parse/attr.rs | 11 +- src/libsyntax/parse/diagnostics.rs | 8 +- src/libsyntax/parse/lexer/mod.rs | 1 + src/libsyntax/parse/mod.rs | 2 + src/libsyntax/parse/parser.rs | 80 +++-- src/libsyntax/visit.rs | 3 +- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- src/libsyntax_pos/symbol.rs | 1 + src/test/ui/parser/fn-arg-doc-comment.rs | 18 +- src/test/ui/parser/fn-arg-doc-comment.stderr | 46 +-- .../rfc-2565-param-attrs/param-attrs-2018.rs | 8 + .../param-attrs-2018.stderr | 18 + .../param-attrs-allowed.rs | 225 ++++++++++++ .../param-attrs-builtin-attrs.rs | 145 ++++++++ .../param-attrs-builtin-attrs.stderr | 339 ++++++++++++++++++ .../rfc-2565-param-attrs/param-attrs-cfg.rs | 79 ++++ .../param-attrs-cfg.stderr | 68 ++++ .../param-attrs-feature-gate.rs | 14 + .../param-attrs-feature-gate.stderr | 27 ++ 28 files changed, 1115 insertions(+), 74 deletions(-) create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs create mode 100644 src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr diff --git a/src/librustc_data_structures/thin_vec.rs b/src/librustc_data_structures/thin_vec.rs index 52f23f4893eeb..6692903cd4fe9 100644 --- a/src/librustc_data_structures/thin_vec.rs +++ b/src/librustc_data_structures/thin_vec.rs @@ -66,3 +66,9 @@ impl, CTX> HashStable for ThinVec { (**self).hash_stable(hcx, hasher) } } + +impl Default for ThinVec { + fn default() -> Self { + Self(None) + } +} diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 532cec2af159e..00b6db0ed9a12 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -14,6 +14,7 @@ use rustc::session::Session; use rustc_data_structures::fx::FxHashMap; use syntax::ast::*; use syntax::attr; +use syntax::feature_gate::is_builtin_attr; use syntax::source_map::Spanned; use syntax::symbol::{kw, sym}; use syntax::ptr::P; @@ -365,6 +366,29 @@ impl<'a> AstValidator<'a> { _ => None, } } + + fn check_fn_decl(&self, fn_decl: &FnDecl) { + fn_decl + .inputs + .iter() + .flat_map(|i| i.attrs.as_ref()) + .filter(|attr| { + let arr = [sym::allow, sym::cfg, sym::cfg_attr, sym::deny, sym::forbid, sym::warn]; + !arr.contains(&attr.name_or_empty()) && is_builtin_attr(attr) + }) + .for_each(|attr| if attr.is_sugared_doc { + let mut err = self.err_handler().struct_span_err( + attr.span, + "documentation comments cannot be applied to function parameters" + ); + err.span_label(attr.span, "doc comments are not allowed here"); + err.emit(); + } + else { + self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \ + forbid, and warn are the only allowed built-in attributes in function parameters") + }); + } } enum GenericPosition { @@ -470,6 +494,9 @@ fn validate_generics_order<'a>( impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_expr(&mut self, expr: &'a Expr) { match expr.node { + ExprKind::Closure(_, _, _, ref fn_decl, _, _) => { + self.check_fn_decl(fn_decl); + } ExprKind::IfLet(_, ref expr, _, _) | ExprKind::WhileLet(_, ref expr, _, _) => self.while_if_let_ambiguity(&expr), ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => { @@ -484,6 +511,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_ty(&mut self, ty: &'a Ty) { match ty.node { TyKind::BareFn(ref bfty) => { + self.check_fn_decl(&bfty.decl); self.check_decl_no_pat(&bfty.decl, |span, _| { struct_span_err!(self.session, span, E0561, "patterns aren't allowed in function pointer types").emit(); @@ -601,10 +629,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .note("only trait implementations may be annotated with default").emit(); } } - ItemKind::Fn(_, ref header, ref generics, _) => { + ItemKind::Fn(ref decl, ref header, ref generics, _) => { + self.visit_fn_header(header); + self.check_fn_decl(decl); // We currently do not permit const generics in `const fn`, as // this is tantamount to allowing compile-time dependent typing. - self.visit_fn_header(header); if header.constness.node == Constness::Const { // Look for const generics and error if we find any. for param in &generics.params { @@ -657,6 +686,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.no_questions_in_bounds(bounds, "supertraits", true); for trait_item in trait_items { if let TraitItemKind::Method(ref sig, ref block) = trait_item.node { + self.check_fn_decl(&sig.decl); self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node); self.check_trait_fn_not_const(sig.header.constness); if block.is_none() { @@ -711,6 +741,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { match fi.node { ForeignItemKind::Fn(ref decl, _) => { + self.check_fn_decl(decl); self.check_decl_no_pat(decl, |span, _| { struct_span_err!(self.session, span, E0130, "patterns aren't allowed in foreign function declarations") @@ -864,6 +895,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> { "`async fn` is not permitted in the 2015 edition").emit(); } } + + fn visit_impl_item(&mut self, ii: &'a ImplItem) { + match ii.node { + ImplItemKind::Method(ref sig, _) => { + self.check_fn_decl(&sig.decl); + } + _ => {} + } + visit::walk_impl_item(self, ii); + } } pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 02fbcb14fa599..68cb8c8574d8b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1770,6 +1770,7 @@ pub struct InlineAsm { /// E.g., `bar: usize` as in `fn foo(bar: usize)`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Arg { + pub attrs: ThinVec, pub ty: P, pub pat: P, pub id: NodeId, @@ -1817,7 +1818,7 @@ impl Arg { } } - pub fn from_self(eself: ExplicitSelf, eself_ident: Ident) -> Arg { + pub fn from_self(attrs: ThinVec, eself: ExplicitSelf, eself_ident: Ident) -> Arg { let span = eself.span.to(eself_ident.span); let infer_ty = P(Ty { id: DUMMY_NODE_ID, @@ -1825,6 +1826,7 @@ impl Arg { span, }); let arg = |mutbl, ty| Arg { + attrs, pat: P(Pat { id: DUMMY_NODE_ID, node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None), diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index b5d9b761773b4..f99397408ba26 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -724,7 +724,7 @@ macro_rules! derive_has_attrs { derive_has_attrs! { Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm, - ast::Field, ast::FieldPat, ast::Variant_ + ast::Field, ast::FieldPat, ast::Variant_, ast::Arg } pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate { diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 6123e95ccf821..1cc13ac7878be 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -298,6 +298,10 @@ impl<'a> StripUnconfigured<'a> { } } + pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) { + fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg)); + } + /// Denies `#[cfg]` on generic parameters until we decide what to do with it. /// See issue #51279. pub fn disallow_cfg_on_generic_param(&mut self, param: &ast::GenericParam) { @@ -364,6 +368,11 @@ impl<'a> MutVisitor for StripUnconfigured<'a> { self.configure_pat(pat); noop_visit_pat(pat, self) } + + fn visit_fn_decl(&mut self, mut fn_decl: &mut P) { + self.configure_fn_decl(&mut fn_decl); + noop_visit_fn_decl(fn_decl, self); + } } fn is_cfg(attr: &ast::Attribute) -> bool { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 2a03e49996b6c..9d4bf7d518d75 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -963,9 +963,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn arg(&self, span: Span, ident: ast::Ident, ty: P) -> ast::Arg { let arg_pat = self.pat_ident(span, ident); ast::Arg { - ty, + attrs: ThinVec::default(), + id: ast::DUMMY_NODE_ID, pat: arg_pat, - id: ast::DUMMY_NODE_ID + ty, } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 9960539555332..671c01c53bbbb 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1616,6 +1616,11 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { *id = self.cx.resolver.next_node_id() } } + + fn visit_fn_decl(&mut self, mut fn_decl: &mut P) { + self.cfg.configure_fn_decl(&mut fn_decl); + noop_visit_fn_decl(fn_decl, self); + } } pub struct ExpansionConfig<'feat> { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index b41b91c7631f5..93683074a570e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -560,6 +560,9 @@ declare_features! ( // Allows the user of associated type bounds. (active, associated_type_bounds, "1.34.0", Some(52662), None), + // Attributes on formal function params + (active, param_attrs, "1.36.0", Some(60406), None), + // Allows calling constructor functions in `const fn` // FIXME Create issue (active, const_constructor, "1.37.0", Some(61456), None), @@ -2508,6 +2511,18 @@ pub fn check_crate(krate: &ast::Crate, parse_sess: sess, plugin_attributes, }; + + sess + .param_attr_spans + .borrow() + .iter() + .for_each(|span| gate_feature!( + &ctx, + param_attrs, + *span, + "attributes on function parameters are unstable" + )); + let visitor = &mut PostExpansionVisitor { context: &ctx, builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 2889f8edfc64c..02e2c96868dd6 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -568,8 +568,9 @@ pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_arg(Arg { id, pat, ty }: &mut Arg, vis: &mut T) { +pub fn noop_visit_arg(Arg { attrs, id, pat, ty }: &mut Arg, vis: &mut T) { vis.visit_id(id); + visit_thin_attrs(attrs, vis); vis.visit_pat(pat); vis.visit_ty(ty); } diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 77a87e26e60d5..b28d48b9445fd 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -18,6 +18,14 @@ const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ permitted in this context"; impl<'a> Parser<'a> { + crate fn parse_arg_attributes(&mut self) -> PResult<'a, Vec> { + let attrs = self.parse_outer_attributes()?; + attrs.iter().for_each(|a| + self.sess.param_attr_spans.borrow_mut().push(a.span) + ); + Ok(attrs) + } + /// Parse attributes that appear before an item crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = Vec::new(); @@ -35,7 +43,8 @@ impl<'a> Parser<'a> { }; let inner_parse_policy = InnerAttributeParsePolicy::NotPermitted { reason: inner_error_reason }; - attrs.push(self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?); + let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?; + attrs.push(attr); just_parsed_doc_comment = false; } token::DocComment(s) => { diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index c4db9a9df45a9..472cbcd0f795e 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -28,7 +28,7 @@ crate fn dummy_arg(ident: Ident) -> Arg { span: ident.span, id: ast::DUMMY_NODE_ID }; - Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID } + Arg { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, ty: P(ty) } } pub enum Error { @@ -1074,11 +1074,11 @@ impl<'a> Parser<'a> { Err(err) } - crate fn eat_incorrect_doc_comment(&mut self, applied_to: &str) { + crate fn eat_incorrect_doc_comment_for_arg_type(&mut self) { if let token::DocComment(_) = self.token.kind { let mut err = self.diagnostic().struct_span_err( self.token.span, - &format!("documentation comments cannot be applied to {}", applied_to), + "documentation comments cannot be applied to a function parameter's type", ); err.span_label(self.token.span, "doc comments are not allowed here"); err.emit(); @@ -1095,7 +1095,7 @@ impl<'a> Parser<'a> { self.bump(); let mut err = self.diagnostic().struct_span_err( sp, - &format!("attributes cannot be applied to {}", applied_to), + "attributes cannot be applied to a function parameter's type", ); err.span_label(sp, "attributes are not allowed here"); err.emit(); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index e3d959c2c54c4..fca0bda2a3e6a 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1532,6 +1532,7 @@ mod tests { buffered_lints: Lock::new(vec![]), edition: Edition::from_session(), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), + param_attr_spans: Lock::new(Vec::new()), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 1d708d39a1379..c4da876a2e798 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -54,6 +54,7 @@ pub struct ParseSess { /// operation token that followed it, but that the parser cannot identify without further /// analysis. pub ambiguous_block_expr_parse: Lock>, + pub param_attr_spans: Lock> } impl ParseSess { @@ -79,6 +80,7 @@ impl ParseSess { buffered_lints: Lock::new(vec![]), edition: Edition::from_session(), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), + param_attr_spans: Lock::new(Vec::new()), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3acd708814560..7b99f7bd4e523 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1188,7 +1188,8 @@ impl<'a> Parser<'a> { // definition... // We don't allow argument names to be left off in edition 2018. - p.parse_arg_general(p.token.span.rust_2018(), true, false) + let is_name_required = p.token.span.rust_2018(); + p.parse_arg_general(true, false, |_| is_name_required) })?; generics.where_clause = self.parse_where_clause()?; @@ -1487,26 +1488,31 @@ impl<'a> Parser<'a> { /// Skips unexpected attributes and doc comments in this position and emits an appropriate /// error. /// This version of parse arg doesn't necessarily require identifier names. - fn parse_arg_general( + fn parse_arg_general( &mut self, - require_name: bool, is_trait_item: bool, allow_c_variadic: bool, - ) -> PResult<'a, Arg> { - if let Ok(Some(arg)) = self.parse_self_arg() { + is_name_required: F, + ) -> PResult<'a, Arg> + where + F: Fn(&token::Token) -> bool + { + let attrs = self.parse_arg_attributes()?; + if let Ok(Some(mut arg)) = self.parse_self_arg() { + arg.attrs = attrs.into(); return self.recover_bad_self_arg(arg, is_trait_item); } - let (pat, ty) = if require_name || self.is_named_argument() { - debug!("parse_arg_general parse_pat (require_name:{})", require_name); - self.eat_incorrect_doc_comment("method arguments"); - let pat = self.parse_pat(Some("argument name"))?; + let is_name_required = is_name_required(&self.token); + let (pat, ty) = if is_name_required || self.is_named_argument() { + debug!("parse_arg_general parse_pat (is_name_required:{})", is_name_required); + let pat = self.parse_pat(Some("argument name"))?; if let Err(mut err) = self.expect(&token::Colon) { if let Some(ident) = self.argument_without_type( &mut err, pat, - require_name, + is_name_required, is_trait_item, ) { err.emit(); @@ -1516,12 +1522,12 @@ impl<'a> Parser<'a> { } } - self.eat_incorrect_doc_comment("a method argument's type"); + self.eat_incorrect_doc_comment_for_arg_type(); (pat, self.parse_ty_common(true, true, allow_c_variadic)?) } else { debug!("parse_arg_general ident_to_pat"); let parser_snapshot_before_ty = self.clone(); - self.eat_incorrect_doc_comment("a method argument's type"); + self.eat_incorrect_doc_comment_for_arg_type(); let mut ty = self.parse_ty_common(true, true, allow_c_variadic); if ty.is_ok() && self.token != token::Comma && self.token != token::CloseDelim(token::Paren) { @@ -1554,11 +1560,12 @@ impl<'a> Parser<'a> { } }; - Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID }) + Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, ty }) } /// Parses an argument in a lambda header (e.g., `|arg, arg|`). fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { + let attrs = self.parse_arg_attributes()?; let pat = self.parse_pat(Some("argument name"))?; let t = if self.eat(&token::Colon) { self.parse_ty()? @@ -1570,6 +1577,7 @@ impl<'a> Parser<'a> { }) }; Ok(Arg { + attrs: attrs.into(), ty: t, pat, id: ast::DUMMY_NODE_ID @@ -5411,15 +5419,19 @@ impl<'a> Parser<'a> { &token::CloseDelim(token::Paren), SeqSep::trailing_allowed(token::Comma), |p| { - // If the argument is a C-variadic argument we should not - // enforce named arguments. - let enforce_named_args = if p.token == token::DotDotDot { - false - } else { - named_args - }; - match p.parse_arg_general(enforce_named_args, false, - allow_c_variadic) { + let do_not_enforce_named_arguments_for_c_variadic = + |token: &token::Token| -> bool { + if token == &token::DotDotDot { + false + } else { + named_args + } + }; + match p.parse_arg_general( + false, + allow_c_variadic, + do_not_enforce_named_arguments_for_c_variadic + ) { Ok(arg) => { if let TyKind::CVarArgs = arg.ty.node { c_variadic = true; @@ -5464,7 +5476,6 @@ impl<'a> Parser<'a> { /// Parses the argument list and result type of a function declaration. fn parse_fn_decl(&mut self, allow_c_variadic: bool) -> PResult<'a, P> { - let (args, c_variadic) = self.parse_fn_args(true, allow_c_variadic)?; let ret_ty = self.parse_ret_ty(true)?; @@ -5476,6 +5487,8 @@ impl<'a> Parser<'a> { } /// Returns the parsed optional self argument and whether a self shortcut was used. + /// + /// See `parse_self_arg_with_attrs` to collect attributes. fn parse_self_arg(&mut self) -> PResult<'a, Option> { let expect_ident = |this: &mut Self| match this.token.kind { // Preserve hygienic context. @@ -5581,7 +5594,18 @@ impl<'a> Parser<'a> { }; let eself = source_map::respan(eself_lo.to(eself_hi), eself); - Ok(Some(Arg::from_self(eself, eself_ident))) + Ok(Some(Arg::from_self(ThinVec::default(), eself, eself_ident))) + } + + /// Returns the parsed optional self argument with attributes and whether a self + /// shortcut was used. + fn parse_self_arg_with_attrs(&mut self) -> PResult<'a, Option> { + let attrs = self.parse_arg_attributes()?; + let arg_opt = self.parse_self_arg()?; + Ok(arg_opt.map(|mut arg| { + arg.attrs = attrs.into(); + arg + })) } /// Parses the parameter list and result type of a function that may have a `self` parameter. @@ -5591,7 +5615,7 @@ impl<'a> Parser<'a> { self.expect(&token::OpenDelim(token::Paren))?; // Parse optional self argument. - let self_arg = self.parse_self_arg()?; + let self_arg = self.parse_self_arg_with_attrs()?; // Parse the rest of the function parameter list. let sep = SeqSep::trailing_allowed(token::Comma); @@ -5865,7 +5889,7 @@ impl<'a> Parser<'a> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; let decl = self.parse_fn_decl_with_self(|p| { - p.parse_arg_general(true, true, false) + p.parse_arg_general(true, false, |_| true) })?; generics.where_clause = self.parse_where_clause()?; *at_end = true; @@ -7441,7 +7465,7 @@ impl<'a> Parser<'a> { } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { let ident = self.parse_ident().unwrap(); self.bump(); // `(` - let kw_name = if let Ok(Some(_)) = self.parse_self_arg() { + let kw_name = if let Ok(Some(_)) = self.parse_self_arg_with_attrs() { "method" } else { "function" @@ -7492,7 +7516,7 @@ impl<'a> Parser<'a> { self.eat_to_tokens(&[&token::Gt]); self.bump(); // `>` let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { - if let Ok(Some(_)) = self.parse_self_arg() { + if let Ok(Some(_)) = self.parse_self_arg_with_attrs() { ("fn", "method", false) } else { ("fn", "function", false) diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 24b0c37247191..8132024416a30 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -550,8 +550,9 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) { for argument in &function_declaration.inputs { + walk_list!(visitor, visit_attribute, argument.attrs.iter()); visitor.visit_pat(&argument.pat); - visitor.visit_ty(&argument.ty) + visitor.visit_ty(&argument.ty); } visitor.visit_fn_ret_ty(&function_declaration.output) } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index ffec667aba5d3..8b719b5477c65 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -928,7 +928,7 @@ impl<'a> MethodDef<'a> { let args = { let self_args = explicit_self.map(|explicit_self| { let ident = Ident::with_empty_ctxt(kw::SelfLower).with_span_pos(trait_.span); - ast::Arg::from_self(explicit_self, ident) + ast::Arg::from_self(ThinVec::default(), explicit_self, ident) }); let nonself_args = arg_types.into_iter() .map(|(name, ty)| cx.arg(trait_.span, name, ty)); diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 49123e4cc30c2..260bad6dc08b0 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -444,6 +444,7 @@ symbols! { panic_implementation, panic_runtime, partial_cmp, + param_attrs, PartialOrd, passes, pat, diff --git a/src/test/ui/parser/fn-arg-doc-comment.rs b/src/test/ui/parser/fn-arg-doc-comment.rs index 22af94b628452..4a4f959e21353 100644 --- a/src/test/ui/parser/fn-arg-doc-comment.rs +++ b/src/test/ui/parser/fn-arg-doc-comment.rs @@ -1,20 +1,20 @@ pub fn f( /// Comment - //~^ ERROR documentation comments cannot be applied to method arguments + //~^ ERROR documentation comments cannot be applied to function parameters //~| NOTE doc comments are not allowed here + //~| ERROR attributes on function parameters are unstable + //~| NOTE https://github.com/rust-lang/rust/issues/60406 id: u8, /// Other - //~^ ERROR documentation comments cannot be applied to method arguments + //~^ ERROR documentation comments cannot be applied to function parameters //~| NOTE doc comments are not allowed here + //~| ERROR attributes on function parameters are unstable + //~| NOTE https://github.com/rust-lang/rust/issues/60406 a: u8, ) {} -fn foo(#[allow(dead_code)] id: i32) {} -//~^ ERROR attributes cannot be applied to method arguments -//~| NOTE attributes are not allowed here - fn bar(id: #[allow(dead_code)] i32) {} -//~^ ERROR attributes cannot be applied to a method argument's type +//~^ ERROR attributes cannot be applied to a function parameter's type //~| NOTE attributes are not allowed here fn main() { @@ -26,10 +26,6 @@ fn main() { //~| ERROR mismatched types //~| NOTE expected u8, found reference //~| NOTE expected - foo(""); - //~^ ERROR mismatched types - //~| NOTE expected i32, found reference - //~| NOTE expected bar(""); //~^ ERROR mismatched types //~| NOTE expected i32, found reference diff --git a/src/test/ui/parser/fn-arg-doc-comment.stderr b/src/test/ui/parser/fn-arg-doc-comment.stderr index 73a24eebb3f12..9058e88d1d7b7 100644 --- a/src/test/ui/parser/fn-arg-doc-comment.stderr +++ b/src/test/ui/parser/fn-arg-doc-comment.stderr @@ -1,26 +1,38 @@ -error: documentation comments cannot be applied to method arguments +error: attributes cannot be applied to a function parameter's type + --> $DIR/fn-arg-doc-comment.rs:16:12 + | +LL | fn bar(id: #[allow(dead_code)] i32) {} + | ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here + +error: documentation comments cannot be applied to function parameters --> $DIR/fn-arg-doc-comment.rs:2:5 | LL | /// Comment | ^^^^^^^^^^^ doc comments are not allowed here -error: documentation comments cannot be applied to method arguments - --> $DIR/fn-arg-doc-comment.rs:6:5 +error: documentation comments cannot be applied to function parameters + --> $DIR/fn-arg-doc-comment.rs:8:5 | LL | /// Other | ^^^^^^^^^ doc comments are not allowed here -error: attributes cannot be applied to method arguments - --> $DIR/fn-arg-doc-comment.rs:12:8 +error[E0658]: attributes on function parameters are unstable + --> $DIR/fn-arg-doc-comment.rs:2:5 + | +LL | /// Comment + | ^^^^^^^^^^^ | -LL | fn foo(#[allow(dead_code)] id: i32) {} - | ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here + = note: for more information, see https://github.com/rust-lang/rust/issues/60406 + = help: add #![feature(param_attrs)] to the crate attributes to enable -error: attributes cannot be applied to a method argument's type - --> $DIR/fn-arg-doc-comment.rs:16:12 +error[E0658]: attributes on function parameters are unstable + --> $DIR/fn-arg-doc-comment.rs:8:5 | -LL | fn bar(id: #[allow(dead_code)] i32) {} - | ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here +LL | /// Other + | ^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/60406 + = help: add #![feature(param_attrs)] to the crate attributes to enable error[E0308]: mismatched types --> $DIR/fn-arg-doc-comment.rs:22:7 @@ -43,15 +55,6 @@ LL | f("", ""); error[E0308]: mismatched types --> $DIR/fn-arg-doc-comment.rs:29:9 | -LL | foo(""); - | ^^ expected i32, found reference - | - = note: expected type `i32` - found type `&'static str` - -error[E0308]: mismatched types - --> $DIR/fn-arg-doc-comment.rs:33:9 - | LL | bar(""); | ^^ expected i32, found reference | @@ -60,4 +63,5 @@ LL | bar(""); error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs new file mode 100644 index 0000000000000..e900ccab4fd83 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.rs @@ -0,0 +1,8 @@ +// edition:2018 + +#![feature(param_attrs)] + +trait Trait2015 { fn foo(#[allow(C)] i32); } +//~^ ERROR expected one of `:` or `@`, found `)` + +fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr new file mode 100644 index 0000000000000..d0ed65f288011 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr @@ -0,0 +1,18 @@ +error: expected one of `:` or `@`, found `)` + --> $DIR/param-attrs-2018.rs:5:41 + | +LL | trait Trait2015 { fn foo(#[allow(C)] i32); } + | ^ expected one of `:` or `@` here + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this was a parameter name, give it a type + | +LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); } + | ^^^^^^^^^^^^^ +help: if this is a type, explicitly ignore the parameter name + | +LL | trait Trait2015 { fn foo(#[allow(C)] _: i32); } + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs new file mode 100644 index 0000000000000..c521d04fda562 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs @@ -0,0 +1,225 @@ +// compile-flags: --cfg something +// compile-pass + +#![feature(param_attrs)] + +extern "C" { + fn ffi( + #[allow(C)] a: i32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] c: i32, + #[deny(C)] d: i32, + #[forbid(C)] #[warn(C)] ... + ); +} + +type FnType = fn( + #[allow(C)] a: i32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] c: i32, + #[deny(C)] d: i32, + #[forbid(C)] #[warn(C)] e: i32 +); + +pub fn foo( + #[allow(C)] a: i32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] c: i32, + #[deny(C)] d: i32, + #[forbid(C)] #[warn(C)] e: i32 +) {} + +// self, &self and &mut self + +struct SelfStruct {} +impl SelfStruct { + fn foo( + #[allow(C)] self, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] b: i32, + ) {} +} + +struct RefStruct {} +impl RefStruct { + fn foo( + #[allow(C)] &self, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] b: i32, + ) {} +} +trait RefTrait { + fn foo( + #[forbid(C)] &self, + #[warn(C)] a: i32 + ) {} +} +impl RefTrait for RefStruct { + fn foo( + #[forbid(C)] &self, + #[warn(C)] a: i32 + ) {} +} + +struct MutStruct {} +impl MutStruct { + fn foo( + #[allow(C)] &mut self, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] b: i32, + ) {} +} +trait MutTrait { + fn foo( + #[forbid(C)] &mut self, + #[warn(C)] a: i32 + ) {} +} +impl MutTrait for MutStruct { + fn foo( + #[forbid(C)] &mut self, + #[warn(C)] a: i32 + ) {} +} + +// self: Self, self: &Self and self: &mut Self + +struct NamedSelfSelfStruct {} +impl NamedSelfSelfStruct { + fn foo( + #[allow(C)] self: Self, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] b: i32, + ) {} +} + +struct NamedSelfRefStruct {} +impl NamedSelfRefStruct { + fn foo( + #[allow(C)] self: &Self, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] b: i32, + ) {} +} +trait NamedSelfRefTrait { + fn foo( + #[forbid(C)] self: &Self, + #[warn(C)] a: i32 + ) {} +} +impl NamedSelfRefTrait for NamedSelfRefStruct { + fn foo( + #[forbid(C)] self: &Self, + #[warn(C)] a: i32 + ) {} +} + +struct NamedSelfMutStruct {} +impl NamedSelfMutStruct { + fn foo( + #[allow(C)] self: &mut Self, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] b: i32, + ) {} +} +trait NamedSelfMutTrait { + fn foo( + #[forbid(C)] self: &mut Self, + #[warn(C)] a: i32 + ) {} +} +impl NamedSelfMutTrait for NamedSelfMutStruct { + fn foo( + #[forbid(C)] self: &mut Self, + #[warn(C)] a: i32 + ) {} +} + +// &'a self and &'a mut self + +struct NamedLifetimeRefStruct {} +impl NamedLifetimeRefStruct { + fn foo<'a>( + #[allow(C)] self: &'a Self, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] b: i32, + ) {} +} +trait NamedLifetimeRefTrait { + fn foo<'a>( + #[forbid(C)] &'a self, + #[warn(C)] a: i32 + ) {} +} +impl NamedLifetimeRefTrait for NamedLifetimeRefStruct { + fn foo<'a>( + #[forbid(C)] &'a self, + #[warn(C)] a: i32 + ) {} +} + +struct NamedLifetimeMutStruct {} +impl NamedLifetimeMutStruct { + fn foo<'a>( + #[allow(C)] self: &'a mut Self, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] b: i32, + ) {} +} +trait NamedLifetimeMutTrait { + fn foo<'a>( + #[forbid(C)] &'a mut self, + #[warn(C)] a: i32 + ) {} +} +impl NamedLifetimeMutTrait for NamedLifetimeMutStruct { + fn foo<'a>( + #[forbid(C)] &'a mut self, + #[warn(C)] a: i32 + ) {} +} + +// Box + +struct BoxSelfStruct {} +impl BoxSelfStruct { + fn foo( + #[allow(C)] self: Box, + #[cfg(something)] a: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] b: i32, + ) {} +} +trait BoxSelfTrait { + fn foo( + #[forbid(C)] self: Box, + #[warn(C)] a: i32 + ) {} +} +impl BoxSelfTrait for BoxSelfStruct { + fn foo( + #[forbid(C)] self: Box, + #[warn(C)] a: i32 + ) {} +} + +fn main() { + let _: unsafe extern "C" fn(_, _, _, ...) = ffi; + let _: fn(_, _, _, _) = foo; + let _: FnType = |_, _, _, _| {}; + let c = | + #[allow(C)] a: u32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] c: i32, + | {}; + let _ = c(1, 2); +} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs new file mode 100644 index 0000000000000..352375729bd45 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs @@ -0,0 +1,145 @@ +#![feature(param_attrs)] + +extern "C" { + fn ffi( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR The attribute `test` is currently unknown to the compiler and may have + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + ); +} + +type FnType = fn( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: u32, + //~^ ERROR The attribute `test` is currently unknown to the compiler and may have + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in +); + +pub fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: u32, + //~^ ERROR The attribute `test` is currently unknown to the compiler and may have + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in +) {} + +struct SelfStruct {} +impl SelfStruct { + fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + self, + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR The attribute `test` is currently unknown to the compiler and may have + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + ) {} +} + +struct RefStruct {} +impl RefStruct { + fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + &self, + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR The attribute `test` is currently unknown to the compiler and may have + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + ) {} +} +trait RefTrait { + fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + &self, + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR The attribute `test` is currently unknown to the compiler and may have + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + ) {} +} +impl RefTrait for RefStruct { + fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function + &self, + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[test] a: i32, + //~^ ERROR The attribute `test` is currently unknown to the compiler and may have + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + /// Qux + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32, + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + ) {} +} + +fn main() { + let _ = | + /// Foo + //~^ ERROR documentation comments cannot be applied to function + #[test] a: u32, + //~^ ERROR The attribute `test` is currently unknown to the compiler and may have + /// Bar + //~^ ERROR documentation comments cannot be applied to function + #[must_use] + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + /// Baz + //~^ ERROR documentation comments cannot be applied to function + #[no_mangle] b: i32 + //~^ ERROR allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in + | {}; +} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr new file mode 100644 index 0000000000000..e6f3efc04ce27 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr @@ -0,0 +1,339 @@ +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:5:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:9:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:11:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:13:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:15:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:21:5 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:25:5 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:27:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:29:5 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:31:5 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:36:5 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:40:5 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:42:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:44:5 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:46:5 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:53:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:56:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:60:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:62:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:64:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:66:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:74:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:77:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:81:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:83:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:85:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:87:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:93:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:96:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:100:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:102:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:104:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:106:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:112:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:115:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:119:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:121:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:123:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:125:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:132:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:136:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:138:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:140:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:142:9 + | +LL | #[no_mangle] b: i32 + | ^^^^^^^^^^^^ + +error[E0658]: The attribute `test` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/param-attrs-builtin-attrs.rs:7:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `test` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/param-attrs-builtin-attrs.rs:23:5 + | +LL | #[test] a: u32, + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `test` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/param-attrs-builtin-attrs.rs:38:5 + | +LL | #[test] a: u32, + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `test` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/param-attrs-builtin-attrs.rs:58:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `test` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/param-attrs-builtin-attrs.rs:79:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `test` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/param-attrs-builtin-attrs.rs:98:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `test` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/param-attrs-builtin-attrs.rs:117:9 + | +LL | #[test] a: i32, + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `test` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/param-attrs-builtin-attrs.rs:134:9 + | +LL | #[test] a: u32, + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 52 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs new file mode 100644 index 0000000000000..977b5d9ce3495 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs @@ -0,0 +1,79 @@ +// compile-flags: --cfg something + +#![feature(param_attrs)] +#![deny(unused_variables)] + +extern "C" { + fn ffi( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] c: i32, + #[cfg_attr(nothing, cfg(nothing))] ... + ); +} + +type FnType = fn( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + #[cfg_attr(nothing, cfg(nothing))] c: i32, + #[cfg_attr(something, cfg(nothing))] d: i32, +); + +fn foo( + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` [unused_variables] + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` [unused_variables] + #[cfg_attr(something, cfg(nothing))] d: i32, +) {} + +struct RefStruct {} +impl RefStruct { + fn bar( + &self, + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` [unused_variables] + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` [unused_variables] + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} +} +trait RefTrait { + fn bar( + &self, + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` [unused_variables] + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` [unused_variables] + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} +} +impl RefTrait for RefStruct { + fn bar( + &self, + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` [unused_variables] + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` [unused_variables] + #[cfg_attr(something, cfg(nothing))] d: i32, + ) {} +} + +fn main() { + let _: unsafe extern "C" fn(_, ...) = ffi; + let _: fn(_, _) = foo; + let _: FnType = |_, _| {}; + let c = | + #[cfg(nothing)] a: i32, + #[cfg(something)] b: i32, + //~^ ERROR unused variable: `b` [unused_variables] + #[cfg_attr(nothing, cfg(nothing))] c: i32, + //~^ ERROR unused variable: `c` [unused_variables] + #[cfg_attr(something, cfg(nothing))] d: i32, + | {}; + let _ = c(1, 2); +} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr new file mode 100644 index 0000000000000..c97190324e5a2 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr @@ -0,0 +1,68 @@ +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:24:23 + | +LL | #[cfg(something)] b: i32, + | ^ help: consider prefixing with an underscore: `_b` + | +note: lint level defined here + --> $DIR/param-attrs-cfg.rs:4:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:26:40 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: consider prefixing with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:72:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: consider prefixing with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:74:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: consider prefixing with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:47:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: consider prefixing with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:49:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: consider prefixing with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:36:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: consider prefixing with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:38:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: consider prefixing with an underscore: `_c` + +error: unused variable: `b` + --> $DIR/param-attrs-cfg.rs:58:27 + | +LL | #[cfg(something)] b: i32, + | ^ help: consider prefixing with an underscore: `_b` + +error: unused variable: `c` + --> $DIR/param-attrs-cfg.rs:60:44 + | +LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, + | ^ help: consider prefixing with an underscore: `_c` + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs new file mode 100644 index 0000000000000..c5a6514efb0f0 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs @@ -0,0 +1,14 @@ +// gate-test-param_attrs + +fn foo( + /// Foo + //~^ ERROR documentation comments cannot be applied to function parameters + //~| NOTE doc comments are not allowed here + //~| ERROR attributes on function parameters are unstable + //~| NOTE https://github.com/rust-lang/rust/issues/60406 + #[allow(C)] a: u8 + //~^ ERROR attributes on function parameters are unstable + //~| NOTE https://github.com/rust-lang/rust/issues/60406 +) {} + +fn main() {} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr new file mode 100644 index 0000000000000..82f21e7fdbcb4 --- /dev/null +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr @@ -0,0 +1,27 @@ +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-feature-gate.rs:4:5 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error[E0658]: attributes on function parameters are unstable + --> $DIR/param-attrs-feature-gate.rs:4:5 + | +LL | /// Foo + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/60406 + = help: add #![feature(param_attrs)] to the crate attributes to enable + +error[E0658]: attributes on function parameters are unstable + --> $DIR/param-attrs-feature-gate.rs:9:5 + | +LL | #[allow(C)] a: u8 + | ^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/60406 + = help: add #![feature(param_attrs)] to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`.