Allow attributes in formal function parameters

This commit is contained in:
Caio 2019-06-09 07:58:40 -03:00
parent 5c45343f11
commit 1eaaf440d5
28 changed files with 1115 additions and 74 deletions

View File

@ -66,3 +66,9 @@ impl<T: HashStable<CTX>, CTX> HashStable<CTX> for ThinVec<T> {
(**self).hash_stable(hcx, hasher)
}
}
impl<T> Default for ThinVec<T> {
fn default() -> Self {
Self(None)
}
}

View File

@ -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) {

View File

@ -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<Attribute>,
pub ty: P<Ty>,
pub pat: P<Pat>,
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<Attribute>, 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),

View File

@ -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 {

View File

@ -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<ast::FnDecl>) {
self.configure_fn_decl(&mut fn_decl);
noop_visit_fn_decl(fn_decl, self);
}
}
fn is_cfg(attr: &ast::Attribute) -> bool {

View File

@ -963,9 +963,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn arg(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> 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,
}
}

View File

@ -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<ast::FnDecl>) {
self.cfg.configure_fn_decl(&mut fn_decl);
noop_visit_fn_decl(fn_decl, self);
}
}
pub struct ExpansionConfig<'feat> {

View File

@ -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,

View File

@ -568,8 +568,9 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
vis.visit_span(span);
}
pub fn noop_visit_arg<T: MutVisitor>(Arg { id, pat, ty }: &mut Arg, vis: &mut T) {
pub fn noop_visit_arg<T: MutVisitor>(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);
}

View File

@ -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<ast::Attribute>> {
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<ast::Attribute>> {
let mut attrs: Vec<ast::Attribute> = 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) => {

View File

@ -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();

View File

@ -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()),
}
}

View File

@ -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<FxHashMap<Span, Span>>,
pub param_attr_spans: Lock<Vec<Span>>
}
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()),
}
}

View File

@ -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<F>(
&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<FnDecl>> {
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<Arg>> {
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<Arg>> {
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)

View File

@ -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)
}

View File

@ -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));

View File

@ -444,6 +444,7 @@ symbols! {
panic_implementation,
panic_runtime,
partial_cmp,
param_attrs,
PartialOrd,
passes,
pat,

View File

@ -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

View File

@ -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 | fn foo(#[allow(dead_code)] id: i32) {}
| ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here
LL | /// Comment
| ^^^^^^^^^^^
|
= 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`.

View File

@ -0,0 +1,8 @@
// edition:2018
#![feature(param_attrs)]
trait Trait2015 { fn foo(#[allow(C)] i32); }
//~^ ERROR expected one of `:` or `@`, found `)`
fn main() {}

View File

@ -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

View File

@ -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<Self>
struct BoxSelfStruct {}
impl BoxSelfStruct {
fn foo(
#[allow(C)] self: Box<Self>,
#[cfg(something)] a: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] b: i32,
) {}
}
trait BoxSelfTrait {
fn foo(
#[forbid(C)] self: Box<Self>,
#[warn(C)] a: i32
) {}
}
impl BoxSelfTrait for BoxSelfStruct {
fn foo(
#[forbid(C)] self: Box<Self>,
#[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);
}

View File

@ -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
| {};
}

View File

@ -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`.

View File

@ -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);
}

View File

@ -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

View File

@ -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() {}

View File

@ -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`.