From 8674efdb7c9d263caef8d282086a4243eae8df20 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 29 Jan 2020 01:30:01 +0100 Subject: [PATCH 1/2] parser: move restrictions re. `self` to `ast_validation`. --- src/librustc_ast_passes/ast_validation.rs | 44 +++- src/librustc_parse/parser/diagnostics.rs | 12 +- src/librustc_parse/parser/item.rs | 60 +++-- src/librustc_parse/parser/ty.rs | 4 +- .../ui/invalid-self-argument/bare-fn-start.rs | 6 +- .../bare-fn-start.stderr | 6 +- .../ui/parser/self-param-semantic-fail.rs | 64 +++++ .../ui/parser/self-param-semantic-fail.stderr | 220 ++++++++++++++++++ .../ui/parser/self-param-syntactic-pass.rs | 66 ++++++ 9 files changed, 426 insertions(+), 56 deletions(-) create mode 100644 src/test/ui/parser/self-param-semantic-fail.rs create mode 100644 src/test/ui/parser/self-param-semantic-fail.stderr create mode 100644 src/test/ui/parser/self-param-syntactic-pass.rs diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 152086bfce0ea..f37f93c0254bd 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -23,6 +23,12 @@ use syntax::print::pprust; use syntax::visit::{self, Visitor}; use syntax::walk_list; +/// Is `self` allowed semantically as the first parameter in an `FnDecl`? +enum SelfSemantic { + Yes, + No, +} + /// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`). #[derive(Clone, Copy)] enum BoundContext { @@ -302,7 +308,13 @@ impl<'a> AstValidator<'a> { } } - fn check_fn_decl(&self, fn_decl: &FnDecl) { + fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) { + self.check_decl_cvaradic_pos(fn_decl); + self.check_decl_attrs(fn_decl); + self.check_decl_self_param(fn_decl, self_semantic); + } + + fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) { match &*fn_decl.inputs { [Param { ty, span, .. }] => { if let TyKind::CVarArgs = ty.kind { @@ -324,7 +336,9 @@ impl<'a> AstValidator<'a> { } _ => {} } + } + fn check_decl_attrs(&self, fn_decl: &FnDecl) { fn_decl .inputs .iter() @@ -352,6 +366,21 @@ impl<'a> AstValidator<'a> { }); } + fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) { + if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) { + if param.is_self() { + self.err_handler() + .struct_span_err( + param.span, + "`self` parameter only allowed in associated `fn`s", + ) + .span_label(param.span, "not semantically valid as function parameter") + .note("associated `fn`s are those in `impl` or `trait` definitions") + .emit(); + } + } + } + fn check_defaultness(&self, span: Span, defaultness: Defaultness) { if let Defaultness::Default = defaultness { self.err_handler() @@ -504,7 +533,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_expr(&mut self, expr: &'a Expr) { match &expr.kind { ExprKind::Closure(_, _, _, fn_decl, _, _) => { - self.check_fn_decl(fn_decl); + self.check_fn_decl(fn_decl, SelfSemantic::No); } ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => { struct_span_err!( @@ -524,7 +553,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_ty(&mut self, ty: &'a Ty) { match ty.kind { TyKind::BareFn(ref bfty) => { - self.check_fn_decl(&bfty.decl); + self.check_fn_decl(&bfty.decl, SelfSemantic::No); Self::check_decl_no_pat(&bfty.decl, |span, _| { struct_span_err!( self.session, @@ -685,7 +714,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Fn(ref sig, ref generics, _) => { self.visit_fn_header(&sig.header); - self.check_fn_decl(&sig.decl); + self.check_fn_decl(&sig.decl, SelfSemantic::No); // We currently do not permit const generics in `const fn`, as // this is tantamount to allowing compile-time dependent typing. if sig.header.constness.node == Constness::Const { @@ -793,7 +822,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { match fi.kind { ForeignItemKind::Fn(ref decl, _) => { - self.check_fn_decl(decl); + self.check_fn_decl(decl, SelfSemantic::No); Self::check_decl_no_pat(decl, |span, _| { struct_span_err!( self.session, @@ -987,9 +1016,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { AssocItemKind::Const(_, body) => { self.check_impl_item_provided(ii.span, body, "constant", " = ;"); } - AssocItemKind::Fn(sig, body) => { + AssocItemKind::Fn(_, body) => { self.check_impl_item_provided(ii.span, body, "function", " { }"); - self.check_fn_decl(&sig.decl); } AssocItemKind::TyAlias(bounds, body) => { self.check_impl_item_provided(ii.span, body, "type", " = ;"); @@ -1005,7 +1033,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_defaultness(ti.span, ti.defaultness); if let AssocItemKind::Fn(sig, block) = &ti.kind { - self.check_fn_decl(&sig.decl); self.check_trait_fn_not_async(ti.span, sig.header.asyncness.node); self.check_trait_fn_not_const(sig.header.constness); if block.is_none() { @@ -1035,6 +1062,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_assoc_item(&mut self, item: &'a AssocItem) { if let AssocItemKind::Fn(sig, _) = &item.kind { + self.check_fn_decl(&sig.decl, SelfSemantic::Yes); self.check_c_varadic_type(&sig.decl); } visit::walk_assoc_item(self, item); diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 80bc5c158a64f..09f393a81abad 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -1336,8 +1336,8 @@ impl<'a> Parser<'a> { err: &mut DiagnosticBuilder<'_>, pat: P, require_name: bool, - is_self_allowed: bool, - is_trait_item: bool, + is_self_semantic: bool, + in_assoc_item: bool, ) -> Option { // If we find a pattern followed by an identifier, it could be an (incorrect) // C-style parameter declaration. @@ -1357,13 +1357,13 @@ impl<'a> Parser<'a> { return Some(ident); } else if let PatKind::Ident(_, ident, _) = pat.kind { if require_name - && (is_trait_item + && (in_assoc_item || self.token == token::Comma || self.token == token::Lt || self.token == token::CloseDelim(token::Paren)) { // `fn foo(a, b) {}`, `fn foo(a, b) {}` or `fn foo(usize, usize) {}` - if is_self_allowed { + if is_self_semantic { err.span_suggestion( pat.span, "if this is a `self` type, give it a parameter name", @@ -1423,12 +1423,12 @@ impl<'a> Parser<'a> { pub(super) fn recover_bad_self_param( &mut self, mut param: ast::Param, - is_trait_item: bool, + in_assoc_item: bool, ) -> PResult<'a, ast::Param> { let sp = param.pat.span; param.ty.kind = TyKind::Err; let mut err = self.struct_span_err(sp, "unexpected `self` parameter in function"); - if is_trait_item { + if in_assoc_item { err.span_label(sp, "must be the first associated function parameter"); } else { err.span_label(sp, "not valid as function parameter"); diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 6611661132306..0ff595f444413 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1715,8 +1715,9 @@ impl<'a> Parser<'a> { /// The parsing configuration used to parse a parameter list (see `parse_fn_params`). pub(super) struct ParamCfg { - /// Is `self` is allowed as the first parameter? - pub is_self_allowed: bool, + /// Is `self` is *semantically* allowed as the first parameter? + /// This is only used for diagnostics. + pub in_assoc_item: bool, /// `is_name_required` decides if, per-parameter, /// the parameter must have a pattern or just a type. pub is_name_required: fn(&token::Token) -> bool, @@ -1732,8 +1733,8 @@ impl<'a> Parser<'a> { attrs: Vec, header: FnHeader, ) -> PResult<'a, Option>> { - let (ident, decl, generics) = - self.parse_fn_sig(ParamCfg { is_self_allowed: false, is_name_required: |_| true })?; + let cfg = ParamCfg { in_assoc_item: false, is_name_required: |_| true }; + let (ident, decl, generics) = self.parse_fn_sig(&cfg)?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let kind = ItemKind::Fn(FnSig { decl, header }, generics, body); self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs))) @@ -1747,20 +1748,13 @@ impl<'a> Parser<'a> { attrs: Vec, extern_sp: Span, ) -> PResult<'a, P> { + let cfg = ParamCfg { in_assoc_item: false, is_name_required: |_| true }; self.expect_keyword(kw::Fn)?; - let (ident, decl, generics) = - self.parse_fn_sig(ParamCfg { is_self_allowed: false, is_name_required: |_| true })?; + let (ident, decl, generics) = self.parse_fn_sig(&cfg)?; let span = lo.to(self.token.span); self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?; - Ok(P(ast::ForeignItem { - ident, - attrs, - kind: ForeignItemKind::Fn(decl, generics), - id: DUMMY_NODE_ID, - span, - vis, - tokens: None, - })) + let kind = ForeignItemKind::Fn(decl, generics); + Ok(P(ast::ForeignItem { ident, attrs, kind, id: DUMMY_NODE_ID, span, vis, tokens: None })) } fn parse_assoc_fn( @@ -1769,9 +1763,9 @@ impl<'a> Parser<'a> { attrs: &mut Vec, is_name_required: fn(&token::Token) -> bool, ) -> PResult<'a, (Ident, AssocItemKind, Generics)> { + let cfg = ParamCfg { in_assoc_item: true, is_name_required }; let header = self.parse_fn_front_matter()?; - let (ident, decl, generics) = - self.parse_fn_sig(ParamCfg { is_self_allowed: true, is_name_required })?; + let (ident, decl, generics) = self.parse_fn_sig(&cfg)?; let sig = FnSig { header, decl }; let body = self.parse_assoc_fn_body(at_end, attrs)?; Ok((ident, AssocItemKind::Fn(sig, body), generics)) @@ -1847,7 +1841,7 @@ impl<'a> Parser<'a> { } /// Parse the "signature", including the identifier, parameters, and generics of a function. - fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P, Generics)> { + fn parse_fn_sig(&mut self, cfg: &ParamCfg) -> PResult<'a, (Ident, P, Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; let decl = self.parse_fn_decl(cfg, true)?; @@ -1858,7 +1852,7 @@ impl<'a> Parser<'a> { /// Parses the parameter list and result type of a function declaration. pub(super) fn parse_fn_decl( &mut self, - cfg: ParamCfg, + cfg: &ParamCfg, ret_allow_plus: bool, ) -> PResult<'a, P> { Ok(P(FnDecl { @@ -1868,11 +1862,11 @@ impl<'a> Parser<'a> { } /// Parses the parameter list of a function, including the `(` and `)` delimiters. - fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec> { - let is_trait_item = cfg.is_self_allowed; - // Parse the arguments, starting out with `self` being possibly allowed... + fn parse_fn_params(&mut self, cfg: &ParamCfg) -> PResult<'a, Vec> { + let mut first_param = true; + // Parse the arguments, starting out with `self` being allowed... let (mut params, _) = self.parse_paren_comma_seq(|p| { - let param = p.parse_param_general(&cfg, is_trait_item).or_else(|mut e| { + let param = p.parse_param_general(&cfg, first_param).or_else(|mut e| { e.emit(); let lo = p.prev_span; // Skip every token until next possible arg or end. @@ -1881,7 +1875,7 @@ impl<'a> Parser<'a> { Ok(dummy_arg(Ident::new(kw::Invalid, lo.to(p.prev_span)))) }); // ...now that we've parsed the first argument, `self` is no longer allowed. - cfg.is_self_allowed = false; + first_param = false; param })?; // Replace duplicated recovered params with `_` pattern to avoid unnecessary errors. @@ -1889,20 +1883,20 @@ impl<'a> Parser<'a> { Ok(params) } - /// Skips unexpected attributes and doc comments in this position and emits an appropriate - /// error. - /// This version of parse param doesn't necessarily require identifier names. - fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> { + /// Parses a single function parameter. + /// + /// - `self` is syntactically allowed when `first_param` holds. + fn parse_param_general(&mut self, cfg: &ParamCfg, first_param: bool) -> PResult<'a, Param> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. if let Some(mut param) = self.parse_self_param()? { param.attrs = attrs.into(); - return if cfg.is_self_allowed { + return if first_param { Ok(param) } else { - self.recover_bad_self_param(param, is_trait_item) + self.recover_bad_self_param(param, cfg.in_assoc_item) }; } @@ -1919,8 +1913,8 @@ impl<'a> Parser<'a> { &mut err, pat, is_name_required, - cfg.is_self_allowed, - is_trait_item, + first_param && cfg.in_assoc_item, + cfg.in_assoc_item, ) { err.emit(); Ok(dummy_arg(ident)) @@ -1975,8 +1969,6 @@ impl<'a> Parser<'a> { } /// Returns the parsed optional self parameter and whether a self shortcut was used. - /// - /// See `parse_self_param_with_attrs` to collect attributes. fn parse_self_param(&mut self) -> PResult<'a, Option> { // Extract an identifier *after* having confirmed that the token is one. let expect_self_ident = |this: &mut Self| { diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index a4cc9fa48f2a6..51367a37ad70a 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -288,8 +288,8 @@ impl<'a> Parser<'a> { let unsafety = self.parse_unsafety(); let ext = self.parse_extern()?; self.expect_keyword(kw::Fn)?; - let cfg = ParamCfg { is_self_allowed: false, is_name_required: |_| false }; - let decl = self.parse_fn_decl(cfg, false)?; + let cfg = ParamCfg { in_assoc_item: false, is_name_required: |_| false }; + let decl = self.parse_fn_decl(&cfg, false)?; Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params, decl }))) } diff --git a/src/test/ui/invalid-self-argument/bare-fn-start.rs b/src/test/ui/invalid-self-argument/bare-fn-start.rs index a003a01941bde..8c92b7bc7c4b0 100644 --- a/src/test/ui/invalid-self-argument/bare-fn-start.rs +++ b/src/test/ui/invalid-self-argument/bare-fn-start.rs @@ -1,6 +1,6 @@ fn a(&self) { } -//~^ ERROR unexpected `self` parameter in function -//~| NOTE not valid as function parameter -//~| NOTE `self` is only valid as the first parameter of an associated function +//~^ ERROR `self` parameter only allowed in associated `fn`s +//~| NOTE not semantically valid as function parameter +//~| NOTE associated `fn`s are those in `impl` or `trait` definitions fn main() { } diff --git a/src/test/ui/invalid-self-argument/bare-fn-start.stderr b/src/test/ui/invalid-self-argument/bare-fn-start.stderr index 23de6502094f0..59120a60a6df1 100644 --- a/src/test/ui/invalid-self-argument/bare-fn-start.stderr +++ b/src/test/ui/invalid-self-argument/bare-fn-start.stderr @@ -1,10 +1,10 @@ -error: unexpected `self` parameter in function +error: `self` parameter only allowed in associated `fn`s --> $DIR/bare-fn-start.rs:1:6 | LL | fn a(&self) { } - | ^^^^^ not valid as function parameter + | ^^^^^ not semantically valid as function parameter | - = note: `self` is only valid as the first parameter of an associated function + = note: associated `fn`s are those in `impl` or `trait` definitions error: aborting due to previous error diff --git a/src/test/ui/parser/self-param-semantic-fail.rs b/src/test/ui/parser/self-param-semantic-fail.rs new file mode 100644 index 0000000000000..773cf922b4da9 --- /dev/null +++ b/src/test/ui/parser/self-param-semantic-fail.rs @@ -0,0 +1,64 @@ +// This test ensures that `self` is semantically rejected +// in contexts with `FnDecl` but outside of associated `fn`s. +// FIXME(Centril): For now closures are an exception. + +fn main() {} + +fn free() { + fn f1(self) {} + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f2(mut self) {} + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f3(&self) {} + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f4(&mut self) {} + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f5<'a>(&'a self) {} + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f6<'a>(&'a mut self) {} + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f7(self: u8) {} + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f8(mut self: u8) {} + //~^ ERROR `self` parameter only allowed in associated `fn`s +} + +extern { + fn f1(self); + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f2(mut self); + //~^ ERROR `self` parameter only allowed in associated `fn`s + //~| ERROR patterns aren't allowed in + fn f3(&self); + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f4(&mut self); + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f5<'a>(&'a self); + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f6<'a>(&'a mut self); + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f7(self: u8); + //~^ ERROR `self` parameter only allowed in associated `fn`s + fn f8(mut self: u8); + //~^ ERROR `self` parameter only allowed in associated `fn`s + //~| ERROR patterns aren't allowed in +} + +type X1 = fn(self); +//~^ ERROR `self` parameter only allowed in associated `fn`s +type X2 = fn(mut self); +//~^ ERROR `self` parameter only allowed in associated `fn`s +//~| ERROR patterns aren't allowed in +type X3 = fn(&self); +//~^ ERROR `self` parameter only allowed in associated `fn`s +type X4 = fn(&mut self); +//~^ ERROR `self` parameter only allowed in associated `fn`s +type X5 = for<'a> fn(&'a self); +//~^ ERROR `self` parameter only allowed in associated `fn`s +type X6 = for<'a> fn(&'a mut self); +//~^ ERROR `self` parameter only allowed in associated `fn`s +type X7 = fn(self: u8); +//~^ ERROR `self` parameter only allowed in associated `fn`s +type X8 = fn(mut self: u8); +//~^ ERROR `self` parameter only allowed in associated `fn`s +//~| ERROR patterns aren't allowed in diff --git a/src/test/ui/parser/self-param-semantic-fail.stderr b/src/test/ui/parser/self-param-semantic-fail.stderr new file mode 100644 index 0000000000000..b45e4a5d26f16 --- /dev/null +++ b/src/test/ui/parser/self-param-semantic-fail.stderr @@ -0,0 +1,220 @@ +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:8:11 + | +LL | fn f1(self) {} + | ^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:10:11 + | +LL | fn f2(mut self) {} + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:12:11 + | +LL | fn f3(&self) {} + | ^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:14:11 + | +LL | fn f4(&mut self) {} + | ^^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:16:15 + | +LL | fn f5<'a>(&'a self) {} + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:18:15 + | +LL | fn f6<'a>(&'a mut self) {} + | ^^^^^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:20:11 + | +LL | fn f7(self: u8) {} + | ^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:22:11 + | +LL | fn f8(mut self: u8) {} + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:27:11 + | +LL | fn f1(self); + | ^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:29:11 + | +LL | fn f2(mut self); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/self-param-semantic-fail.rs:29:11 + | +LL | fn f2(mut self); + | ^^^^^^^^ pattern not allowed in foreign function + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:32:11 + | +LL | fn f3(&self); + | ^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:34:11 + | +LL | fn f4(&mut self); + | ^^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:36:15 + | +LL | fn f5<'a>(&'a self); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:38:15 + | +LL | fn f6<'a>(&'a mut self); + | ^^^^^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:40:11 + | +LL | fn f7(self: u8); + | ^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:42:11 + | +LL | fn f8(mut self: u8); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error[E0130]: patterns aren't allowed in foreign function declarations + --> $DIR/self-param-semantic-fail.rs:42:11 + | +LL | fn f8(mut self: u8); + | ^^^^^^^^ pattern not allowed in foreign function + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:47:14 + | +LL | type X1 = fn(self); + | ^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:49:14 + | +LL | type X2 = fn(mut self); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error[E0561]: patterns aren't allowed in function pointer types + --> $DIR/self-param-semantic-fail.rs:49:14 + | +LL | type X2 = fn(mut self); + | ^^^^^^^^ + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:52:14 + | +LL | type X3 = fn(&self); + | ^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:54:14 + | +LL | type X4 = fn(&mut self); + | ^^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:56:22 + | +LL | type X5 = for<'a> fn(&'a self); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:58:22 + | +LL | type X6 = for<'a> fn(&'a mut self); + | ^^^^^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:60:14 + | +LL | type X7 = fn(self: u8); + | ^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error: `self` parameter only allowed in associated `fn`s + --> $DIR/self-param-semantic-fail.rs:62:14 + | +LL | type X8 = fn(mut self: u8); + | ^^^^^^^^ not semantically valid as function parameter + | + = note: associated `fn`s are those in `impl` or `trait` definitions + +error[E0561]: patterns aren't allowed in function pointer types + --> $DIR/self-param-semantic-fail.rs:62:14 + | +LL | type X8 = fn(mut self: u8); + | ^^^^^^^^ + +error: aborting due to 28 previous errors + +Some errors have detailed explanations: E0130, E0561. +For more information about an error, try `rustc --explain E0130`. diff --git a/src/test/ui/parser/self-param-syntactic-pass.rs b/src/test/ui/parser/self-param-syntactic-pass.rs new file mode 100644 index 0000000000000..9e215e6cdd4b7 --- /dev/null +++ b/src/test/ui/parser/self-param-syntactic-pass.rs @@ -0,0 +1,66 @@ +// This test ensures that `self` is syntactically accepted in all places an `FnDecl` is parsed. +// FIXME(Centril): For now closures are an exception. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +fn free() { + fn f(self) {} + fn f(mut self) {} + fn f(&self) {} + fn f(&mut self) {} + fn f(&'a self) {} + fn f(&'a mut self) {} + fn f(self: u8) {} + fn f(mut self: u8) {} +} + +#[cfg(FALSE)] +extern { + fn f(self); + fn f(mut self); + fn f(&self); + fn f(&mut self); + fn f(&'a self); + fn f(&'a mut self); + fn f(self: u8); + fn f(mut self: u8); +} + +#[cfg(FALSE)] +trait X { + fn f(self) {} + fn f(mut self) {} + fn f(&self) {} + fn f(&mut self) {} + fn f(&'a self) {} + fn f(&'a mut self) {} + fn f(self: u8) {} + fn f(mut self: u8) {} +} + +#[cfg(FALSE)] +impl X for Y { + fn f(self) {} + fn f(mut self) {} + fn f(&self) {} + fn f(&mut self) {} + fn f(&'a self) {} + fn f(&'a mut self) {} + fn f(self: u8) {} + fn f(mut self: u8) {} +} + +#[cfg(FALSE)] +impl X for Y { + type X = fn(self); + type X = fn(mut self); + type X = fn(&self); + type X = fn(&mut self); + type X = fn(&'a self); + type X = fn(&'a mut self); + type X = fn(self: u8); + type X = fn(mut self: u8); +} From 71a6f58229c00720b35579856bdb64e2a19af521 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 2 Feb 2020 11:10:27 +0100 Subject: [PATCH 2/2] parser: address review comments re. `self`. --- src/librustc_ast_passes/ast_validation.rs | 4 +- src/librustc_parse/parser/diagnostics.rs | 25 ++--- src/librustc_parse/parser/item.rs | 26 ++--- src/librustc_parse/parser/ty.rs | 3 +- .../ui/invalid-self-argument/bare-fn-start.rs | 4 +- .../bare-fn-start.stderr | 4 +- src/test/ui/invalid-self-argument/bare-fn.rs | 3 +- .../ui/invalid-self-argument/bare-fn.stderr | 4 +- src/test/ui/invalid-self-argument/trait-fn.rs | 2 +- .../ui/invalid-self-argument/trait-fn.stderr | 2 +- src/test/ui/parser/inverted-parameters.rs | 1 + src/test/ui/parser/inverted-parameters.stderr | 6 +- .../ui/parser/omitted-arg-in-item-fn.stderr | 4 + src/test/ui/parser/pat-lt-bracket-2.stderr | 4 + .../ui/parser/self-in-function-arg.stderr | 4 +- .../ui/parser/self-param-semantic-fail.rs | 48 +++++----- .../ui/parser/self-param-semantic-fail.stderr | 96 +++++++++---------- src/test/ui/span/issue-34264.stderr | 8 ++ .../suggestions/issue-64252-self-type.stderr | 4 + 19 files changed, 124 insertions(+), 128 deletions(-) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index f37f93c0254bd..23c5ef9b3d652 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -372,10 +372,10 @@ impl<'a> AstValidator<'a> { self.err_handler() .struct_span_err( param.span, - "`self` parameter only allowed in associated `fn`s", + "`self` parameter is only allowed in associated functions", ) .span_label(param.span, "not semantically valid as function parameter") - .note("associated `fn`s are those in `impl` or `trait` definitions") + .note("associated functions are those in `impl` or `trait` definitions") .emit(); } } diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 09f393a81abad..4f259d314fbf1 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -1336,8 +1336,7 @@ impl<'a> Parser<'a> { err: &mut DiagnosticBuilder<'_>, pat: P, require_name: bool, - is_self_semantic: bool, - in_assoc_item: bool, + first_param: bool, ) -> Option { // If we find a pattern followed by an identifier, it could be an (incorrect) // C-style parameter declaration. @@ -1357,13 +1356,12 @@ impl<'a> Parser<'a> { return Some(ident); } else if let PatKind::Ident(_, ident, _) = pat.kind { if require_name - && (in_assoc_item - || self.token == token::Comma + && (self.token == token::Comma || self.token == token::Lt || self.token == token::CloseDelim(token::Paren)) { // `fn foo(a, b) {}`, `fn foo(a, b) {}` or `fn foo(usize, usize) {}` - if is_self_semantic { + if first_param { err.span_suggestion( pat.span, "if this is a `self` type, give it a parameter name", @@ -1420,21 +1418,12 @@ impl<'a> Parser<'a> { Ok((pat, ty)) } - pub(super) fn recover_bad_self_param( - &mut self, - mut param: ast::Param, - in_assoc_item: bool, - ) -> PResult<'a, ast::Param> { + pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> { let sp = param.pat.span; param.ty.kind = TyKind::Err; - let mut err = self.struct_span_err(sp, "unexpected `self` parameter in function"); - if in_assoc_item { - err.span_label(sp, "must be the first associated function parameter"); - } else { - err.span_label(sp, "not valid as function parameter"); - err.note("`self` is only valid as the first parameter of an associated function"); - } - err.emit(); + self.struct_span_err(sp, "unexpected `self` parameter in function") + .span_label(sp, "must be the first parameter of an associated function") + .emit(); Ok(param) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 0ff595f444413..da5cc0bb83e35 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1715,9 +1715,6 @@ impl<'a> Parser<'a> { /// The parsing configuration used to parse a parameter list (see `parse_fn_params`). pub(super) struct ParamCfg { - /// Is `self` is *semantically* allowed as the first parameter? - /// This is only used for diagnostics. - pub in_assoc_item: bool, /// `is_name_required` decides if, per-parameter, /// the parameter must have a pattern or just a type. pub is_name_required: fn(&token::Token) -> bool, @@ -1733,7 +1730,7 @@ impl<'a> Parser<'a> { attrs: Vec, header: FnHeader, ) -> PResult<'a, Option>> { - let cfg = ParamCfg { in_assoc_item: false, is_name_required: |_| true }; + let cfg = ParamCfg { is_name_required: |_| true }; let (ident, decl, generics) = self.parse_fn_sig(&cfg)?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let kind = ItemKind::Fn(FnSig { decl, header }, generics, body); @@ -1748,7 +1745,7 @@ impl<'a> Parser<'a> { attrs: Vec, extern_sp: Span, ) -> PResult<'a, P> { - let cfg = ParamCfg { in_assoc_item: false, is_name_required: |_| true }; + let cfg = ParamCfg { is_name_required: |_| true }; self.expect_keyword(kw::Fn)?; let (ident, decl, generics) = self.parse_fn_sig(&cfg)?; let span = lo.to(self.token.span); @@ -1763,9 +1760,8 @@ impl<'a> Parser<'a> { attrs: &mut Vec, is_name_required: fn(&token::Token) -> bool, ) -> PResult<'a, (Ident, AssocItemKind, Generics)> { - let cfg = ParamCfg { in_assoc_item: true, is_name_required }; let header = self.parse_fn_front_matter()?; - let (ident, decl, generics) = self.parse_fn_sig(&cfg)?; + let (ident, decl, generics) = self.parse_fn_sig(&ParamCfg { is_name_required })?; let sig = FnSig { header, decl }; let body = self.parse_assoc_fn_body(at_end, attrs)?; Ok((ident, AssocItemKind::Fn(sig, body), generics)) @@ -1893,11 +1889,7 @@ impl<'a> Parser<'a> { // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. if let Some(mut param) = self.parse_self_param()? { param.attrs = attrs.into(); - return if first_param { - Ok(param) - } else { - self.recover_bad_self_param(param, cfg.in_assoc_item) - }; + return if first_param { Ok(param) } else { self.recover_bad_self_param(param) }; } let is_name_required = match self.token.kind { @@ -1909,13 +1901,9 @@ impl<'a> Parser<'a> { let pat = self.parse_fn_param_pat()?; if let Err(mut err) = self.expect(&token::Colon) { - return if let Some(ident) = self.parameter_without_type( - &mut err, - pat, - is_name_required, - first_param && cfg.in_assoc_item, - cfg.in_assoc_item, - ) { + return if let Some(ident) = + self.parameter_without_type(&mut err, pat, is_name_required, first_param) + { err.emit(); Ok(dummy_arg(ident)) } else { diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 51367a37ad70a..c9c2cbb98ca40 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -288,8 +288,7 @@ impl<'a> Parser<'a> { let unsafety = self.parse_unsafety(); let ext = self.parse_extern()?; self.expect_keyword(kw::Fn)?; - let cfg = ParamCfg { in_assoc_item: false, is_name_required: |_| false }; - let decl = self.parse_fn_decl(&cfg, false)?; + let decl = self.parse_fn_decl(&ParamCfg { is_name_required: |_| false }, false)?; Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params, decl }))) } diff --git a/src/test/ui/invalid-self-argument/bare-fn-start.rs b/src/test/ui/invalid-self-argument/bare-fn-start.rs index 8c92b7bc7c4b0..7c580bc5a5dea 100644 --- a/src/test/ui/invalid-self-argument/bare-fn-start.rs +++ b/src/test/ui/invalid-self-argument/bare-fn-start.rs @@ -1,6 +1,6 @@ fn a(&self) { } -//~^ ERROR `self` parameter only allowed in associated `fn`s +//~^ ERROR `self` parameter is only allowed in associated functions //~| NOTE not semantically valid as function parameter -//~| NOTE associated `fn`s are those in `impl` or `trait` definitions +//~| NOTE associated functions are those in `impl` or `trait` definitions fn main() { } diff --git a/src/test/ui/invalid-self-argument/bare-fn-start.stderr b/src/test/ui/invalid-self-argument/bare-fn-start.stderr index 59120a60a6df1..37753e61f582a 100644 --- a/src/test/ui/invalid-self-argument/bare-fn-start.stderr +++ b/src/test/ui/invalid-self-argument/bare-fn-start.stderr @@ -1,10 +1,10 @@ -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/bare-fn-start.rs:1:6 | LL | fn a(&self) { } | ^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions error: aborting due to previous error diff --git a/src/test/ui/invalid-self-argument/bare-fn.rs b/src/test/ui/invalid-self-argument/bare-fn.rs index 73d68e8b7a5ab..342bdc31a7c82 100644 --- a/src/test/ui/invalid-self-argument/bare-fn.rs +++ b/src/test/ui/invalid-self-argument/bare-fn.rs @@ -1,6 +1,5 @@ fn b(foo: u32, &mut self) { } //~^ ERROR unexpected `self` parameter in function -//~| NOTE not valid as function parameter -//~| NOTE `self` is only valid as the first parameter of an associated function +//~| NOTE must be the first parameter of an associated function fn main() { } diff --git a/src/test/ui/invalid-self-argument/bare-fn.stderr b/src/test/ui/invalid-self-argument/bare-fn.stderr index 601a51bb4a96a..ff2217b5e80bc 100644 --- a/src/test/ui/invalid-self-argument/bare-fn.stderr +++ b/src/test/ui/invalid-self-argument/bare-fn.stderr @@ -2,9 +2,7 @@ error: unexpected `self` parameter in function --> $DIR/bare-fn.rs:1:16 | LL | fn b(foo: u32, &mut self) { } - | ^^^^^^^^^ not valid as function parameter - | - = note: `self` is only valid as the first parameter of an associated function + | ^^^^^^^^^ must be the first parameter of an associated function error: aborting due to previous error diff --git a/src/test/ui/invalid-self-argument/trait-fn.rs b/src/test/ui/invalid-self-argument/trait-fn.rs index 1e8220d7b4a78..5ccea589561cb 100644 --- a/src/test/ui/invalid-self-argument/trait-fn.rs +++ b/src/test/ui/invalid-self-argument/trait-fn.rs @@ -3,7 +3,7 @@ struct Foo {} impl Foo { fn c(foo: u32, self) {} //~^ ERROR unexpected `self` parameter in function - //~| NOTE must be the first associated function parameter + //~| NOTE must be the first parameter of an associated function fn good(&mut self, foo: u32) {} } diff --git a/src/test/ui/invalid-self-argument/trait-fn.stderr b/src/test/ui/invalid-self-argument/trait-fn.stderr index 96a2251c036b1..b9887af962cbc 100644 --- a/src/test/ui/invalid-self-argument/trait-fn.stderr +++ b/src/test/ui/invalid-self-argument/trait-fn.stderr @@ -2,7 +2,7 @@ error: unexpected `self` parameter in function --> $DIR/trait-fn.rs:4:20 | LL | fn c(foo: u32, self) {} - | ^^^^ must be the first associated function parameter + | ^^^^ must be the first parameter of an associated function error: aborting due to previous error diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs index d6efc8be072bd..6f19ee9c7dc0d 100644 --- a/src/test/ui/parser/inverted-parameters.rs +++ b/src/test/ui/parser/inverted-parameters.rs @@ -21,6 +21,7 @@ fn pattern((i32, i32) (a, b)) {} fn fizz(i32) {} //~^ ERROR expected one of `:`, `@` //~| HELP if this was a parameter name, give it a type +//~| HELP if this is a `self` type, give it a parameter name //~| HELP if this is a type, explicitly ignore the parameter name fn missing_colon(quux S) {} diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr index 51e9087ffc1e1..043ff65f74e1a 100644 --- a/src/test/ui/parser/inverted-parameters.stderr +++ b/src/test/ui/parser/inverted-parameters.stderr @@ -35,6 +35,10 @@ LL | fn fizz(i32) {} | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn fizz(self: i32) {} + | ^^^^^^^^^ help: if this was a parameter name, give it a type | LL | fn fizz(i32: TypeName) {} @@ -45,7 +49,7 @@ LL | fn fizz(_: i32) {} | ^^^^^^ error: expected one of `:`, `@`, or `|`, found `S` - --> $DIR/inverted-parameters.rs:26:23 + --> $DIR/inverted-parameters.rs:27:23 | LL | fn missing_colon(quux S) {} | -----^ diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr index c7c76a7f1d42c..9f138bf84ce19 100644 --- a/src/test/ui/parser/omitted-arg-in-item-fn.stderr +++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr @@ -5,6 +5,10 @@ LL | fn foo(x) { | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn foo(self: x) { + | ^^^^^^^ help: if this was a parameter name, give it a type | LL | fn foo(x: TypeName) { diff --git a/src/test/ui/parser/pat-lt-bracket-2.stderr b/src/test/ui/parser/pat-lt-bracket-2.stderr index e51dd57f9c707..6db9a4a0f15a6 100644 --- a/src/test/ui/parser/pat-lt-bracket-2.stderr +++ b/src/test/ui/parser/pat-lt-bracket-2.stderr @@ -5,6 +5,10 @@ LL | fn a(B<) {} | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn a(self: B<) {} + | ^^^^^^^ help: if this is a type, explicitly ignore the parameter name | LL | fn a(_: B<) {} diff --git a/src/test/ui/parser/self-in-function-arg.stderr b/src/test/ui/parser/self-in-function-arg.stderr index f58df9b9e79b3..47d8381b0b1da 100644 --- a/src/test/ui/parser/self-in-function-arg.stderr +++ b/src/test/ui/parser/self-in-function-arg.stderr @@ -2,9 +2,7 @@ error: unexpected `self` parameter in function --> $DIR/self-in-function-arg.rs:1:15 | LL | fn foo(x:i32, self: i32) -> i32 { self } - | ^^^^ not valid as function parameter - | - = note: `self` is only valid as the first parameter of an associated function + | ^^^^ must be the first parameter of an associated function error: aborting due to previous error diff --git a/src/test/ui/parser/self-param-semantic-fail.rs b/src/test/ui/parser/self-param-semantic-fail.rs index 773cf922b4da9..5676971b01ae4 100644 --- a/src/test/ui/parser/self-param-semantic-fail.rs +++ b/src/test/ui/parser/self-param-semantic-fail.rs @@ -6,59 +6,59 @@ fn main() {} fn free() { fn f1(self) {} - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f2(mut self) {} - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f3(&self) {} - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f4(&mut self) {} - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f5<'a>(&'a self) {} - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f6<'a>(&'a mut self) {} - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f7(self: u8) {} - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f8(mut self: u8) {} - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions } extern { fn f1(self); - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f2(mut self); - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions //~| ERROR patterns aren't allowed in fn f3(&self); - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f4(&mut self); - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f5<'a>(&'a self); - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f6<'a>(&'a mut self); - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f7(self: u8); - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions fn f8(mut self: u8); - //~^ ERROR `self` parameter only allowed in associated `fn`s + //~^ ERROR `self` parameter is only allowed in associated functions //~| ERROR patterns aren't allowed in } type X1 = fn(self); -//~^ ERROR `self` parameter only allowed in associated `fn`s +//~^ ERROR `self` parameter is only allowed in associated functions type X2 = fn(mut self); -//~^ ERROR `self` parameter only allowed in associated `fn`s +//~^ ERROR `self` parameter is only allowed in associated functions //~| ERROR patterns aren't allowed in type X3 = fn(&self); -//~^ ERROR `self` parameter only allowed in associated `fn`s +//~^ ERROR `self` parameter is only allowed in associated functions type X4 = fn(&mut self); -//~^ ERROR `self` parameter only allowed in associated `fn`s +//~^ ERROR `self` parameter is only allowed in associated functions type X5 = for<'a> fn(&'a self); -//~^ ERROR `self` parameter only allowed in associated `fn`s +//~^ ERROR `self` parameter is only allowed in associated functions type X6 = for<'a> fn(&'a mut self); -//~^ ERROR `self` parameter only allowed in associated `fn`s +//~^ ERROR `self` parameter is only allowed in associated functions type X7 = fn(self: u8); -//~^ ERROR `self` parameter only allowed in associated `fn`s +//~^ ERROR `self` parameter is only allowed in associated functions type X8 = fn(mut self: u8); -//~^ ERROR `self` parameter only allowed in associated `fn`s +//~^ ERROR `self` parameter is only allowed in associated functions //~| ERROR patterns aren't allowed in diff --git a/src/test/ui/parser/self-param-semantic-fail.stderr b/src/test/ui/parser/self-param-semantic-fail.stderr index b45e4a5d26f16..e5d679773696b 100644 --- a/src/test/ui/parser/self-param-semantic-fail.stderr +++ b/src/test/ui/parser/self-param-semantic-fail.stderr @@ -1,82 +1,82 @@ -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:8:11 | LL | fn f1(self) {} | ^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:10:11 | LL | fn f2(mut self) {} | ^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:12:11 | LL | fn f3(&self) {} | ^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:14:11 | LL | fn f4(&mut self) {} | ^^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:16:15 | LL | fn f5<'a>(&'a self) {} | ^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:18:15 | LL | fn f6<'a>(&'a mut self) {} | ^^^^^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:20:11 | LL | fn f7(self: u8) {} | ^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:22:11 | LL | fn f8(mut self: u8) {} | ^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:27:11 | LL | fn f1(self); | ^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:29:11 | LL | fn f2(mut self); | ^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions error[E0130]: patterns aren't allowed in foreign function declarations --> $DIR/self-param-semantic-fail.rs:29:11 @@ -84,53 +84,53 @@ error[E0130]: patterns aren't allowed in foreign function declarations LL | fn f2(mut self); | ^^^^^^^^ pattern not allowed in foreign function -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:32:11 | LL | fn f3(&self); | ^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:34:11 | LL | fn f4(&mut self); | ^^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:36:15 | LL | fn f5<'a>(&'a self); | ^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:38:15 | LL | fn f6<'a>(&'a mut self); | ^^^^^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:40:11 | LL | fn f7(self: u8); | ^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:42:11 | LL | fn f8(mut self: u8); | ^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions error[E0130]: patterns aren't allowed in foreign function declarations --> $DIR/self-param-semantic-fail.rs:42:11 @@ -138,21 +138,21 @@ error[E0130]: patterns aren't allowed in foreign function declarations LL | fn f8(mut self: u8); | ^^^^^^^^ pattern not allowed in foreign function -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:47:14 | LL | type X1 = fn(self); | ^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:49:14 | LL | type X2 = fn(mut self); | ^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions error[E0561]: patterns aren't allowed in function pointer types --> $DIR/self-param-semantic-fail.rs:49:14 @@ -160,53 +160,53 @@ error[E0561]: patterns aren't allowed in function pointer types LL | type X2 = fn(mut self); | ^^^^^^^^ -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:52:14 | LL | type X3 = fn(&self); | ^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:54:14 | LL | type X4 = fn(&mut self); | ^^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:56:22 | LL | type X5 = for<'a> fn(&'a self); | ^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:58:22 | LL | type X6 = for<'a> fn(&'a mut self); | ^^^^^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:60:14 | LL | type X7 = fn(self: u8); | ^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions -error: `self` parameter only allowed in associated `fn`s +error: `self` parameter is only allowed in associated functions --> $DIR/self-param-semantic-fail.rs:62:14 | LL | type X8 = fn(mut self: u8); | ^^^^^^^^ not semantically valid as function parameter | - = note: associated `fn`s are those in `impl` or `trait` definitions + = note: associated functions are those in `impl` or `trait` definitions error[E0561]: patterns aren't allowed in function pointer types --> $DIR/self-param-semantic-fail.rs:62:14 diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 56a2686945ca2..80a237ac6aad4 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -5,6 +5,10 @@ LL | fn foo(Option, String) {} | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn foo(self: Option, String) {} + | ^^^^^^^^^^^^ help: if this is a type, explicitly ignore the parameter name | LL | fn foo(_: Option, String) {} @@ -33,6 +37,10 @@ LL | fn bar(x, y: usize) {} | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | fn bar(self: x, y: usize) {} + | ^^^^^^^ help: if this was a parameter name, give it a type | LL | fn bar(x: TypeName, y: usize) {} diff --git a/src/test/ui/suggestions/issue-64252-self-type.stderr b/src/test/ui/suggestions/issue-64252-self-type.stderr index 4abffb1ad79f6..e96db3f1e8630 100644 --- a/src/test/ui/suggestions/issue-64252-self-type.stderr +++ b/src/test/ui/suggestions/issue-64252-self-type.stderr @@ -5,6 +5,10 @@ LL | pub fn foo(Box) { } | ^ expected one of `:`, `@`, or `|` | = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a `self` type, give it a parameter name + | +LL | pub fn foo(self: Box) { } + | ^^^^^^^^^ help: if this is a type, explicitly ignore the parameter name | LL | pub fn foo(_: Box) { }