Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 66a06f3

Browse files
authoredFeb 2, 2020
Rollup merge of rust-lang#68764 - Centril:self-semantic, r=petrochenkov
parser: syntactically allow `self` in all `fn` contexts Part of rust-lang#68728. `self` parameters are now *syntactically* allowed as the first parameter irrespective of item context (and in function pointers). Instead, semantic validation (`ast_validation`) is used. r? @petrochenkov
2 parents 62cde17 + 71a6f58 commit 66a06f3

20 files changed

+453
-87
lines changed
 

‎src/librustc_ast_passes/ast_validation.rs

+36-8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ use syntax::expand::is_proc_macro_attr;
2323
use syntax::visit::{self, Visitor};
2424
use syntax::walk_list;
2525

26+
/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
27+
enum SelfSemantic {
28+
Yes,
29+
No,
30+
}
31+
2632
/// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
2733
#[derive(Clone, Copy)]
2834
enum BoundContext {
@@ -302,7 +308,13 @@ impl<'a> AstValidator<'a> {
302308
}
303309
}
304310

305-
fn check_fn_decl(&self, fn_decl: &FnDecl) {
311+
fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
312+
self.check_decl_cvaradic_pos(fn_decl);
313+
self.check_decl_attrs(fn_decl);
314+
self.check_decl_self_param(fn_decl, self_semantic);
315+
}
316+
317+
fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
306318
match &*fn_decl.inputs {
307319
[Param { ty, span, .. }] => {
308320
if let TyKind::CVarArgs = ty.kind {
@@ -324,7 +336,9 @@ impl<'a> AstValidator<'a> {
324336
}
325337
_ => {}
326338
}
339+
}
327340

341+
fn check_decl_attrs(&self, fn_decl: &FnDecl) {
328342
fn_decl
329343
.inputs
330344
.iter()
@@ -352,6 +366,21 @@ impl<'a> AstValidator<'a> {
352366
});
353367
}
354368

369+
fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
370+
if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
371+
if param.is_self() {
372+
self.err_handler()
373+
.struct_span_err(
374+
param.span,
375+
"`self` parameter is only allowed in associated functions",
376+
)
377+
.span_label(param.span, "not semantically valid as function parameter")
378+
.note("associated functions are those in `impl` or `trait` definitions")
379+
.emit();
380+
}
381+
}
382+
}
383+
355384
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
356385
if let Defaultness::Default = defaultness {
357386
self.err_handler()
@@ -504,7 +533,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
504533
fn visit_expr(&mut self, expr: &'a Expr) {
505534
match &expr.kind {
506535
ExprKind::Closure(_, _, _, fn_decl, _, _) => {
507-
self.check_fn_decl(fn_decl);
536+
self.check_fn_decl(fn_decl, SelfSemantic::No);
508537
}
509538
ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
510539
struct_span_err!(
@@ -524,7 +553,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
524553
fn visit_ty(&mut self, ty: &'a Ty) {
525554
match ty.kind {
526555
TyKind::BareFn(ref bfty) => {
527-
self.check_fn_decl(&bfty.decl);
556+
self.check_fn_decl(&bfty.decl, SelfSemantic::No);
528557
Self::check_decl_no_pat(&bfty.decl, |span, _| {
529558
struct_span_err!(
530559
self.session,
@@ -685,7 +714,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
685714
}
686715
ItemKind::Fn(ref sig, ref generics, _) => {
687716
self.visit_fn_header(&sig.header);
688-
self.check_fn_decl(&sig.decl);
717+
self.check_fn_decl(&sig.decl, SelfSemantic::No);
689718
// We currently do not permit const generics in `const fn`, as
690719
// this is tantamount to allowing compile-time dependent typing.
691720
if sig.header.constness.node == Constness::Const {
@@ -793,7 +822,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
793822
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
794823
match fi.kind {
795824
ForeignItemKind::Fn(ref decl, _) => {
796-
self.check_fn_decl(decl);
825+
self.check_fn_decl(decl, SelfSemantic::No);
797826
Self::check_decl_no_pat(decl, |span, _| {
798827
struct_span_err!(
799828
self.session,
@@ -987,9 +1016,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
9871016
AssocItemKind::Const(_, body) => {
9881017
self.check_impl_item_provided(ii.span, body, "constant", " = <expr>;");
9891018
}
990-
AssocItemKind::Fn(sig, body) => {
1019+
AssocItemKind::Fn(_, body) => {
9911020
self.check_impl_item_provided(ii.span, body, "function", " { <body> }");
992-
self.check_fn_decl(&sig.decl);
9931021
}
9941022
AssocItemKind::TyAlias(bounds, body) => {
9951023
self.check_impl_item_provided(ii.span, body, "type", " = <type>;");
@@ -1005,7 +1033,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10051033
self.check_defaultness(ti.span, ti.defaultness);
10061034

10071035
if let AssocItemKind::Fn(sig, block) = &ti.kind {
1008-
self.check_fn_decl(&sig.decl);
10091036
self.check_trait_fn_not_async(ti.span, sig.header.asyncness.node);
10101037
self.check_trait_fn_not_const(sig.header.constness);
10111038
if block.is_none() {
@@ -1035,6 +1062,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10351062

10361063
fn visit_assoc_item(&mut self, item: &'a AssocItem) {
10371064
if let AssocItemKind::Fn(sig, _) = &item.kind {
1065+
self.check_fn_decl(&sig.decl, SelfSemantic::Yes);
10381066
self.check_c_varadic_type(&sig.decl);
10391067
}
10401068
visit::walk_assoc_item(self, item);

‎src/librustc_parse/parser/diagnostics.rs

+7-18
Original file line numberDiff line numberDiff line change
@@ -1336,8 +1336,7 @@ impl<'a> Parser<'a> {
13361336
err: &mut DiagnosticBuilder<'_>,
13371337
pat: P<ast::Pat>,
13381338
require_name: bool,
1339-
is_self_allowed: bool,
1340-
is_trait_item: bool,
1339+
first_param: bool,
13411340
) -> Option<Ident> {
13421341
// If we find a pattern followed by an identifier, it could be an (incorrect)
13431342
// C-style parameter declaration.
@@ -1357,13 +1356,12 @@ impl<'a> Parser<'a> {
13571356
return Some(ident);
13581357
} else if let PatKind::Ident(_, ident, _) = pat.kind {
13591358
if require_name
1360-
&& (is_trait_item
1361-
|| self.token == token::Comma
1359+
&& (self.token == token::Comma
13621360
|| self.token == token::Lt
13631361
|| self.token == token::CloseDelim(token::Paren))
13641362
{
13651363
// `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
1366-
if is_self_allowed {
1364+
if first_param {
13671365
err.span_suggestion(
13681366
pat.span,
13691367
"if this is a `self` type, give it a parameter name",
@@ -1420,21 +1418,12 @@ impl<'a> Parser<'a> {
14201418
Ok((pat, ty))
14211419
}
14221420

1423-
pub(super) fn recover_bad_self_param(
1424-
&mut self,
1425-
mut param: ast::Param,
1426-
is_trait_item: bool,
1427-
) -> PResult<'a, ast::Param> {
1421+
pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> {
14281422
let sp = param.pat.span;
14291423
param.ty.kind = TyKind::Err;
1430-
let mut err = self.struct_span_err(sp, "unexpected `self` parameter in function");
1431-
if is_trait_item {
1432-
err.span_label(sp, "must be the first associated function parameter");
1433-
} else {
1434-
err.span_label(sp, "not valid as function parameter");
1435-
err.note("`self` is only valid as the first parameter of an associated function");
1436-
}
1437-
err.emit();
1424+
self.struct_span_err(sp, "unexpected `self` parameter in function")
1425+
.span_label(sp, "must be the first parameter of an associated function")
1426+
.emit();
14381427
Ok(param)
14391428
}
14401429

‎src/librustc_parse/parser/item.rs

+22-42
Original file line numberDiff line numberDiff line change
@@ -1715,8 +1715,6 @@ impl<'a> Parser<'a> {
17151715

17161716
/// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
17171717
pub(super) struct ParamCfg {
1718-
/// Is `self` is allowed as the first parameter?
1719-
pub is_self_allowed: bool,
17201718
/// `is_name_required` decides if, per-parameter,
17211719
/// the parameter must have a pattern or just a type.
17221720
pub is_name_required: fn(&token::Token) -> bool,
@@ -1732,8 +1730,8 @@ impl<'a> Parser<'a> {
17321730
attrs: Vec<Attribute>,
17331731
header: FnHeader,
17341732
) -> PResult<'a, Option<P<Item>>> {
1735-
let (ident, decl, generics) =
1736-
self.parse_fn_sig(ParamCfg { is_self_allowed: false, is_name_required: |_| true })?;
1733+
let cfg = ParamCfg { is_name_required: |_| true };
1734+
let (ident, decl, generics) = self.parse_fn_sig(&cfg)?;
17371735
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
17381736
let kind = ItemKind::Fn(FnSig { decl, header }, generics, body);
17391737
self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs)))
@@ -1747,20 +1745,13 @@ impl<'a> Parser<'a> {
17471745
attrs: Vec<Attribute>,
17481746
extern_sp: Span,
17491747
) -> PResult<'a, P<ForeignItem>> {
1748+
let cfg = ParamCfg { is_name_required: |_| true };
17501749
self.expect_keyword(kw::Fn)?;
1751-
let (ident, decl, generics) =
1752-
self.parse_fn_sig(ParamCfg { is_self_allowed: false, is_name_required: |_| true })?;
1750+
let (ident, decl, generics) = self.parse_fn_sig(&cfg)?;
17531751
let span = lo.to(self.token.span);
17541752
self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?;
1755-
Ok(P(ast::ForeignItem {
1756-
ident,
1757-
attrs,
1758-
kind: ForeignItemKind::Fn(decl, generics),
1759-
id: DUMMY_NODE_ID,
1760-
span,
1761-
vis,
1762-
tokens: None,
1763-
}))
1753+
let kind = ForeignItemKind::Fn(decl, generics);
1754+
Ok(P(ast::ForeignItem { ident, attrs, kind, id: DUMMY_NODE_ID, span, vis, tokens: None }))
17641755
}
17651756

17661757
fn parse_assoc_fn(
@@ -1770,8 +1761,7 @@ impl<'a> Parser<'a> {
17701761
is_name_required: fn(&token::Token) -> bool,
17711762
) -> PResult<'a, (Ident, AssocItemKind, Generics)> {
17721763
let header = self.parse_fn_front_matter()?;
1773-
let (ident, decl, generics) =
1774-
self.parse_fn_sig(ParamCfg { is_self_allowed: true, is_name_required })?;
1764+
let (ident, decl, generics) = self.parse_fn_sig(&ParamCfg { is_name_required })?;
17751765
let sig = FnSig { header, decl };
17761766
let body = self.parse_assoc_fn_body(at_end, attrs)?;
17771767
Ok((ident, AssocItemKind::Fn(sig, body), generics))
@@ -1847,7 +1837,7 @@ impl<'a> Parser<'a> {
18471837
}
18481838

18491839
/// Parse the "signature", including the identifier, parameters, and generics of a function.
1850-
fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
1840+
fn parse_fn_sig(&mut self, cfg: &ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
18511841
let ident = self.parse_ident()?;
18521842
let mut generics = self.parse_generics()?;
18531843
let decl = self.parse_fn_decl(cfg, true)?;
@@ -1858,7 +1848,7 @@ impl<'a> Parser<'a> {
18581848
/// Parses the parameter list and result type of a function declaration.
18591849
pub(super) fn parse_fn_decl(
18601850
&mut self,
1861-
cfg: ParamCfg,
1851+
cfg: &ParamCfg,
18621852
ret_allow_plus: bool,
18631853
) -> PResult<'a, P<FnDecl>> {
18641854
Ok(P(FnDecl {
@@ -1868,11 +1858,11 @@ impl<'a> Parser<'a> {
18681858
}
18691859

18701860
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
1871-
fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> {
1872-
let is_trait_item = cfg.is_self_allowed;
1873-
// Parse the arguments, starting out with `self` being possibly allowed...
1861+
fn parse_fn_params(&mut self, cfg: &ParamCfg) -> PResult<'a, Vec<Param>> {
1862+
let mut first_param = true;
1863+
// Parse the arguments, starting out with `self` being allowed...
18741864
let (mut params, _) = self.parse_paren_comma_seq(|p| {
1875-
let param = p.parse_param_general(&cfg, is_trait_item).or_else(|mut e| {
1865+
let param = p.parse_param_general(&cfg, first_param).or_else(|mut e| {
18761866
e.emit();
18771867
let lo = p.prev_span;
18781868
// Skip every token until next possible arg or end.
@@ -1881,29 +1871,25 @@ impl<'a> Parser<'a> {
18811871
Ok(dummy_arg(Ident::new(kw::Invalid, lo.to(p.prev_span))))
18821872
});
18831873
// ...now that we've parsed the first argument, `self` is no longer allowed.
1884-
cfg.is_self_allowed = false;
1874+
first_param = false;
18851875
param
18861876
})?;
18871877
// Replace duplicated recovered params with `_` pattern to avoid unnecessary errors.
18881878
self.deduplicate_recovered_params_names(&mut params);
18891879
Ok(params)
18901880
}
18911881

1892-
/// Skips unexpected attributes and doc comments in this position and emits an appropriate
1893-
/// error.
1894-
/// This version of parse param doesn't necessarily require identifier names.
1895-
fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> {
1882+
/// Parses a single function parameter.
1883+
///
1884+
/// - `self` is syntactically allowed when `first_param` holds.
1885+
fn parse_param_general(&mut self, cfg: &ParamCfg, first_param: bool) -> PResult<'a, Param> {
18961886
let lo = self.token.span;
18971887
let attrs = self.parse_outer_attributes()?;
18981888

18991889
// Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
19001890
if let Some(mut param) = self.parse_self_param()? {
19011891
param.attrs = attrs.into();
1902-
return if cfg.is_self_allowed {
1903-
Ok(param)
1904-
} else {
1905-
self.recover_bad_self_param(param, is_trait_item)
1906-
};
1892+
return if first_param { Ok(param) } else { self.recover_bad_self_param(param) };
19071893
}
19081894

19091895
let is_name_required = match self.token.kind {
@@ -1915,13 +1901,9 @@ impl<'a> Parser<'a> {
19151901

19161902
let pat = self.parse_fn_param_pat()?;
19171903
if let Err(mut err) = self.expect(&token::Colon) {
1918-
return if let Some(ident) = self.parameter_without_type(
1919-
&mut err,
1920-
pat,
1921-
is_name_required,
1922-
cfg.is_self_allowed,
1923-
is_trait_item,
1924-
) {
1904+
return if let Some(ident) =
1905+
self.parameter_without_type(&mut err, pat, is_name_required, first_param)
1906+
{
19251907
err.emit();
19261908
Ok(dummy_arg(ident))
19271909
} else {
@@ -1975,8 +1957,6 @@ impl<'a> Parser<'a> {
19751957
}
19761958

19771959
/// Returns the parsed optional self parameter and whether a self shortcut was used.
1978-
///
1979-
/// See `parse_self_param_with_attrs` to collect attributes.
19801960
fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
19811961
// Extract an identifier *after* having confirmed that the token is one.
19821962
let expect_self_ident = |this: &mut Self| {

‎src/librustc_parse/parser/ty.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,7 @@ impl<'a> Parser<'a> {
288288
let unsafety = self.parse_unsafety();
289289
let ext = self.parse_extern()?;
290290
self.expect_keyword(kw::Fn)?;
291-
let cfg = ParamCfg { is_self_allowed: false, is_name_required: |_| false };
292-
let decl = self.parse_fn_decl(cfg, false)?;
291+
let decl = self.parse_fn_decl(&ParamCfg { is_name_required: |_| false }, false)?;
293292
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params, decl })))
294293
}
295294

Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fn a(&self) { }
2-
//~^ ERROR unexpected `self` parameter in function
3-
//~| NOTE not valid as function parameter
4-
//~| NOTE `self` is only valid as the first parameter of an associated function
2+
//~^ ERROR `self` parameter is only allowed in associated functions
3+
//~| NOTE not semantically valid as function parameter
4+
//~| NOTE associated functions are those in `impl` or `trait` definitions
55

66
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: unexpected `self` parameter in function
1+
error: `self` parameter is only allowed in associated functions
22
--> $DIR/bare-fn-start.rs:1:6
33
|
44
LL | fn a(&self) { }
5-
| ^^^^^ not valid as function parameter
5+
| ^^^^^ not semantically valid as function parameter
66
|
7-
= note: `self` is only valid as the first parameter of an associated function
7+
= note: associated functions are those in `impl` or `trait` definitions
88

99
error: aborting due to previous error
1010

Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
fn b(foo: u32, &mut self) { }
22
//~^ ERROR unexpected `self` parameter in function
3-
//~| NOTE not valid as function parameter
4-
//~| NOTE `self` is only valid as the first parameter of an associated function
3+
//~| NOTE must be the first parameter of an associated function
54

65
fn main() { }

‎src/test/ui/invalid-self-argument/bare-fn.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ error: unexpected `self` parameter in function
22
--> $DIR/bare-fn.rs:1:16
33
|
44
LL | fn b(foo: u32, &mut self) { }
5-
| ^^^^^^^^^ not valid as function parameter
6-
|
7-
= note: `self` is only valid as the first parameter of an associated function
5+
| ^^^^^^^^^ must be the first parameter of an associated function
86

97
error: aborting due to previous error
108

‎src/test/ui/invalid-self-argument/trait-fn.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ struct Foo {}
33
impl Foo {
44
fn c(foo: u32, self) {}
55
//~^ ERROR unexpected `self` parameter in function
6-
//~| NOTE must be the first associated function parameter
6+
//~| NOTE must be the first parameter of an associated function
77

88
fn good(&mut self, foo: u32) {}
99
}

‎src/test/ui/invalid-self-argument/trait-fn.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: unexpected `self` parameter in function
22
--> $DIR/trait-fn.rs:4:20
33
|
44
LL | fn c(foo: u32, self) {}
5-
| ^^^^ must be the first associated function parameter
5+
| ^^^^ must be the first parameter of an associated function
66

77
error: aborting due to previous error
88

‎src/test/ui/parser/inverted-parameters.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ fn pattern((i32, i32) (a, b)) {}
2121
fn fizz(i32) {}
2222
//~^ ERROR expected one of `:`, `@`
2323
//~| HELP if this was a parameter name, give it a type
24+
//~| HELP if this is a `self` type, give it a parameter name
2425
//~| HELP if this is a type, explicitly ignore the parameter name
2526

2627
fn missing_colon(quux S) {}

‎src/test/ui/parser/inverted-parameters.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ LL | fn fizz(i32) {}
3535
| ^ expected one of `:`, `@`, or `|`
3636
|
3737
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
38+
help: if this is a `self` type, give it a parameter name
39+
|
40+
LL | fn fizz(self: i32) {}
41+
| ^^^^^^^^^
3842
help: if this was a parameter name, give it a type
3943
|
4044
LL | fn fizz(i32: TypeName) {}
@@ -45,7 +49,7 @@ LL | fn fizz(_: i32) {}
4549
| ^^^^^^
4650

4751
error: expected one of `:`, `@`, or `|`, found `S`
48-
--> $DIR/inverted-parameters.rs:26:23
52+
--> $DIR/inverted-parameters.rs:27:23
4953
|
5054
LL | fn missing_colon(quux S) {}
5155
| -----^

‎src/test/ui/parser/omitted-arg-in-item-fn.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ LL | fn foo(x) {
55
| ^ expected one of `:`, `@`, or `|`
66
|
77
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
8+
help: if this is a `self` type, give it a parameter name
9+
|
10+
LL | fn foo(self: x) {
11+
| ^^^^^^^
812
help: if this was a parameter name, give it a type
913
|
1014
LL | fn foo(x: TypeName) {

‎src/test/ui/parser/pat-lt-bracket-2.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ LL | fn a(B<) {}
55
| ^ expected one of `:`, `@`, or `|`
66
|
77
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
8+
help: if this is a `self` type, give it a parameter name
9+
|
10+
LL | fn a(self: B<) {}
11+
| ^^^^^^^
812
help: if this is a type, explicitly ignore the parameter name
913
|
1014
LL | fn a(_: B<) {}

‎src/test/ui/parser/self-in-function-arg.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ error: unexpected `self` parameter in function
22
--> $DIR/self-in-function-arg.rs:1:15
33
|
44
LL | fn foo(x:i32, self: i32) -> i32 { self }
5-
| ^^^^ not valid as function parameter
6-
|
7-
= note: `self` is only valid as the first parameter of an associated function
5+
| ^^^^ must be the first parameter of an associated function
86

97
error: aborting due to previous error
108

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// This test ensures that `self` is semantically rejected
2+
// in contexts with `FnDecl` but outside of associated `fn`s.
3+
// FIXME(Centril): For now closures are an exception.
4+
5+
fn main() {}
6+
7+
fn free() {
8+
fn f1(self) {}
9+
//~^ ERROR `self` parameter is only allowed in associated functions
10+
fn f2(mut self) {}
11+
//~^ ERROR `self` parameter is only allowed in associated functions
12+
fn f3(&self) {}
13+
//~^ ERROR `self` parameter is only allowed in associated functions
14+
fn f4(&mut self) {}
15+
//~^ ERROR `self` parameter is only allowed in associated functions
16+
fn f5<'a>(&'a self) {}
17+
//~^ ERROR `self` parameter is only allowed in associated functions
18+
fn f6<'a>(&'a mut self) {}
19+
//~^ ERROR `self` parameter is only allowed in associated functions
20+
fn f7(self: u8) {}
21+
//~^ ERROR `self` parameter is only allowed in associated functions
22+
fn f8(mut self: u8) {}
23+
//~^ ERROR `self` parameter is only allowed in associated functions
24+
}
25+
26+
extern {
27+
fn f1(self);
28+
//~^ ERROR `self` parameter is only allowed in associated functions
29+
fn f2(mut self);
30+
//~^ ERROR `self` parameter is only allowed in associated functions
31+
//~| ERROR patterns aren't allowed in
32+
fn f3(&self);
33+
//~^ ERROR `self` parameter is only allowed in associated functions
34+
fn f4(&mut self);
35+
//~^ ERROR `self` parameter is only allowed in associated functions
36+
fn f5<'a>(&'a self);
37+
//~^ ERROR `self` parameter is only allowed in associated functions
38+
fn f6<'a>(&'a mut self);
39+
//~^ ERROR `self` parameter is only allowed in associated functions
40+
fn f7(self: u8);
41+
//~^ ERROR `self` parameter is only allowed in associated functions
42+
fn f8(mut self: u8);
43+
//~^ ERROR `self` parameter is only allowed in associated functions
44+
//~| ERROR patterns aren't allowed in
45+
}
46+
47+
type X1 = fn(self);
48+
//~^ ERROR `self` parameter is only allowed in associated functions
49+
type X2 = fn(mut self);
50+
//~^ ERROR `self` parameter is only allowed in associated functions
51+
//~| ERROR patterns aren't allowed in
52+
type X3 = fn(&self);
53+
//~^ ERROR `self` parameter is only allowed in associated functions
54+
type X4 = fn(&mut self);
55+
//~^ ERROR `self` parameter is only allowed in associated functions
56+
type X5 = for<'a> fn(&'a self);
57+
//~^ ERROR `self` parameter is only allowed in associated functions
58+
type X6 = for<'a> fn(&'a mut self);
59+
//~^ ERROR `self` parameter is only allowed in associated functions
60+
type X7 = fn(self: u8);
61+
//~^ ERROR `self` parameter is only allowed in associated functions
62+
type X8 = fn(mut self: u8);
63+
//~^ ERROR `self` parameter is only allowed in associated functions
64+
//~| ERROR patterns aren't allowed in
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
error: `self` parameter is only allowed in associated functions
2+
--> $DIR/self-param-semantic-fail.rs:8:11
3+
|
4+
LL | fn f1(self) {}
5+
| ^^^^ not semantically valid as function parameter
6+
|
7+
= note: associated functions are those in `impl` or `trait` definitions
8+
9+
error: `self` parameter is only allowed in associated functions
10+
--> $DIR/self-param-semantic-fail.rs:10:11
11+
|
12+
LL | fn f2(mut self) {}
13+
| ^^^^^^^^ not semantically valid as function parameter
14+
|
15+
= note: associated functions are those in `impl` or `trait` definitions
16+
17+
error: `self` parameter is only allowed in associated functions
18+
--> $DIR/self-param-semantic-fail.rs:12:11
19+
|
20+
LL | fn f3(&self) {}
21+
| ^^^^^ not semantically valid as function parameter
22+
|
23+
= note: associated functions are those in `impl` or `trait` definitions
24+
25+
error: `self` parameter is only allowed in associated functions
26+
--> $DIR/self-param-semantic-fail.rs:14:11
27+
|
28+
LL | fn f4(&mut self) {}
29+
| ^^^^^^^^^ not semantically valid as function parameter
30+
|
31+
= note: associated functions are those in `impl` or `trait` definitions
32+
33+
error: `self` parameter is only allowed in associated functions
34+
--> $DIR/self-param-semantic-fail.rs:16:15
35+
|
36+
LL | fn f5<'a>(&'a self) {}
37+
| ^^^^^^^^ not semantically valid as function parameter
38+
|
39+
= note: associated functions are those in `impl` or `trait` definitions
40+
41+
error: `self` parameter is only allowed in associated functions
42+
--> $DIR/self-param-semantic-fail.rs:18:15
43+
|
44+
LL | fn f6<'a>(&'a mut self) {}
45+
| ^^^^^^^^^^^^ not semantically valid as function parameter
46+
|
47+
= note: associated functions are those in `impl` or `trait` definitions
48+
49+
error: `self` parameter is only allowed in associated functions
50+
--> $DIR/self-param-semantic-fail.rs:20:11
51+
|
52+
LL | fn f7(self: u8) {}
53+
| ^^^^ not semantically valid as function parameter
54+
|
55+
= note: associated functions are those in `impl` or `trait` definitions
56+
57+
error: `self` parameter is only allowed in associated functions
58+
--> $DIR/self-param-semantic-fail.rs:22:11
59+
|
60+
LL | fn f8(mut self: u8) {}
61+
| ^^^^^^^^ not semantically valid as function parameter
62+
|
63+
= note: associated functions are those in `impl` or `trait` definitions
64+
65+
error: `self` parameter is only allowed in associated functions
66+
--> $DIR/self-param-semantic-fail.rs:27:11
67+
|
68+
LL | fn f1(self);
69+
| ^^^^ not semantically valid as function parameter
70+
|
71+
= note: associated functions are those in `impl` or `trait` definitions
72+
73+
error: `self` parameter is only allowed in associated functions
74+
--> $DIR/self-param-semantic-fail.rs:29:11
75+
|
76+
LL | fn f2(mut self);
77+
| ^^^^^^^^ not semantically valid as function parameter
78+
|
79+
= note: associated functions are those in `impl` or `trait` definitions
80+
81+
error[E0130]: patterns aren't allowed in foreign function declarations
82+
--> $DIR/self-param-semantic-fail.rs:29:11
83+
|
84+
LL | fn f2(mut self);
85+
| ^^^^^^^^ pattern not allowed in foreign function
86+
87+
error: `self` parameter is only allowed in associated functions
88+
--> $DIR/self-param-semantic-fail.rs:32:11
89+
|
90+
LL | fn f3(&self);
91+
| ^^^^^ not semantically valid as function parameter
92+
|
93+
= note: associated functions are those in `impl` or `trait` definitions
94+
95+
error: `self` parameter is only allowed in associated functions
96+
--> $DIR/self-param-semantic-fail.rs:34:11
97+
|
98+
LL | fn f4(&mut self);
99+
| ^^^^^^^^^ not semantically valid as function parameter
100+
|
101+
= note: associated functions are those in `impl` or `trait` definitions
102+
103+
error: `self` parameter is only allowed in associated functions
104+
--> $DIR/self-param-semantic-fail.rs:36:15
105+
|
106+
LL | fn f5<'a>(&'a self);
107+
| ^^^^^^^^ not semantically valid as function parameter
108+
|
109+
= note: associated functions are those in `impl` or `trait` definitions
110+
111+
error: `self` parameter is only allowed in associated functions
112+
--> $DIR/self-param-semantic-fail.rs:38:15
113+
|
114+
LL | fn f6<'a>(&'a mut self);
115+
| ^^^^^^^^^^^^ not semantically valid as function parameter
116+
|
117+
= note: associated functions are those in `impl` or `trait` definitions
118+
119+
error: `self` parameter is only allowed in associated functions
120+
--> $DIR/self-param-semantic-fail.rs:40:11
121+
|
122+
LL | fn f7(self: u8);
123+
| ^^^^ not semantically valid as function parameter
124+
|
125+
= note: associated functions are those in `impl` or `trait` definitions
126+
127+
error: `self` parameter is only allowed in associated functions
128+
--> $DIR/self-param-semantic-fail.rs:42:11
129+
|
130+
LL | fn f8(mut self: u8);
131+
| ^^^^^^^^ not semantically valid as function parameter
132+
|
133+
= note: associated functions are those in `impl` or `trait` definitions
134+
135+
error[E0130]: patterns aren't allowed in foreign function declarations
136+
--> $DIR/self-param-semantic-fail.rs:42:11
137+
|
138+
LL | fn f8(mut self: u8);
139+
| ^^^^^^^^ pattern not allowed in foreign function
140+
141+
error: `self` parameter is only allowed in associated functions
142+
--> $DIR/self-param-semantic-fail.rs:47:14
143+
|
144+
LL | type X1 = fn(self);
145+
| ^^^^ not semantically valid as function parameter
146+
|
147+
= note: associated functions are those in `impl` or `trait` definitions
148+
149+
error: `self` parameter is only allowed in associated functions
150+
--> $DIR/self-param-semantic-fail.rs:49:14
151+
|
152+
LL | type X2 = fn(mut self);
153+
| ^^^^^^^^ not semantically valid as function parameter
154+
|
155+
= note: associated functions are those in `impl` or `trait` definitions
156+
157+
error[E0561]: patterns aren't allowed in function pointer types
158+
--> $DIR/self-param-semantic-fail.rs:49:14
159+
|
160+
LL | type X2 = fn(mut self);
161+
| ^^^^^^^^
162+
163+
error: `self` parameter is only allowed in associated functions
164+
--> $DIR/self-param-semantic-fail.rs:52:14
165+
|
166+
LL | type X3 = fn(&self);
167+
| ^^^^^ not semantically valid as function parameter
168+
|
169+
= note: associated functions are those in `impl` or `trait` definitions
170+
171+
error: `self` parameter is only allowed in associated functions
172+
--> $DIR/self-param-semantic-fail.rs:54:14
173+
|
174+
LL | type X4 = fn(&mut self);
175+
| ^^^^^^^^^ not semantically valid as function parameter
176+
|
177+
= note: associated functions are those in `impl` or `trait` definitions
178+
179+
error: `self` parameter is only allowed in associated functions
180+
--> $DIR/self-param-semantic-fail.rs:56:22
181+
|
182+
LL | type X5 = for<'a> fn(&'a self);
183+
| ^^^^^^^^ not semantically valid as function parameter
184+
|
185+
= note: associated functions are those in `impl` or `trait` definitions
186+
187+
error: `self` parameter is only allowed in associated functions
188+
--> $DIR/self-param-semantic-fail.rs:58:22
189+
|
190+
LL | type X6 = for<'a> fn(&'a mut self);
191+
| ^^^^^^^^^^^^ not semantically valid as function parameter
192+
|
193+
= note: associated functions are those in `impl` or `trait` definitions
194+
195+
error: `self` parameter is only allowed in associated functions
196+
--> $DIR/self-param-semantic-fail.rs:60:14
197+
|
198+
LL | type X7 = fn(self: u8);
199+
| ^^^^ not semantically valid as function parameter
200+
|
201+
= note: associated functions are those in `impl` or `trait` definitions
202+
203+
error: `self` parameter is only allowed in associated functions
204+
--> $DIR/self-param-semantic-fail.rs:62:14
205+
|
206+
LL | type X8 = fn(mut self: u8);
207+
| ^^^^^^^^ not semantically valid as function parameter
208+
|
209+
= note: associated functions are those in `impl` or `trait` definitions
210+
211+
error[E0561]: patterns aren't allowed in function pointer types
212+
--> $DIR/self-param-semantic-fail.rs:62:14
213+
|
214+
LL | type X8 = fn(mut self: u8);
215+
| ^^^^^^^^
216+
217+
error: aborting due to 28 previous errors
218+
219+
Some errors have detailed explanations: E0130, E0561.
220+
For more information about an error, try `rustc --explain E0130`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// This test ensures that `self` is syntactically accepted in all places an `FnDecl` is parsed.
2+
// FIXME(Centril): For now closures are an exception.
3+
4+
// check-pass
5+
6+
fn main() {}
7+
8+
#[cfg(FALSE)]
9+
fn free() {
10+
fn f(self) {}
11+
fn f(mut self) {}
12+
fn f(&self) {}
13+
fn f(&mut self) {}
14+
fn f(&'a self) {}
15+
fn f(&'a mut self) {}
16+
fn f(self: u8) {}
17+
fn f(mut self: u8) {}
18+
}
19+
20+
#[cfg(FALSE)]
21+
extern {
22+
fn f(self);
23+
fn f(mut self);
24+
fn f(&self);
25+
fn f(&mut self);
26+
fn f(&'a self);
27+
fn f(&'a mut self);
28+
fn f(self: u8);
29+
fn f(mut self: u8);
30+
}
31+
32+
#[cfg(FALSE)]
33+
trait X {
34+
fn f(self) {}
35+
fn f(mut self) {}
36+
fn f(&self) {}
37+
fn f(&mut self) {}
38+
fn f(&'a self) {}
39+
fn f(&'a mut self) {}
40+
fn f(self: u8) {}
41+
fn f(mut self: u8) {}
42+
}
43+
44+
#[cfg(FALSE)]
45+
impl X for Y {
46+
fn f(self) {}
47+
fn f(mut self) {}
48+
fn f(&self) {}
49+
fn f(&mut self) {}
50+
fn f(&'a self) {}
51+
fn f(&'a mut self) {}
52+
fn f(self: u8) {}
53+
fn f(mut self: u8) {}
54+
}
55+
56+
#[cfg(FALSE)]
57+
impl X for Y {
58+
type X = fn(self);
59+
type X = fn(mut self);
60+
type X = fn(&self);
61+
type X = fn(&mut self);
62+
type X = fn(&'a self);
63+
type X = fn(&'a mut self);
64+
type X = fn(self: u8);
65+
type X = fn(mut self: u8);
66+
}

‎src/test/ui/span/issue-34264.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ LL | fn foo(Option<i32>, String) {}
55
| ^ expected one of `:`, `@`, or `|`
66
|
77
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
8+
help: if this is a `self` type, give it a parameter name
9+
|
10+
LL | fn foo(self: Option<i32>, String) {}
11+
| ^^^^^^^^^^^^
812
help: if this is a type, explicitly ignore the parameter name
913
|
1014
LL | fn foo(_: Option<i32>, String) {}
@@ -33,6 +37,10 @@ LL | fn bar(x, y: usize) {}
3337
| ^ expected one of `:`, `@`, or `|`
3438
|
3539
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
40+
help: if this is a `self` type, give it a parameter name
41+
|
42+
LL | fn bar(self: x, y: usize) {}
43+
| ^^^^^^^
3644
help: if this was a parameter name, give it a type
3745
|
3846
LL | fn bar(x: TypeName, y: usize) {}

‎src/test/ui/suggestions/issue-64252-self-type.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ LL | pub fn foo(Box<Self>) { }
55
| ^ expected one of `:`, `@`, or `|`
66
|
77
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
8+
help: if this is a `self` type, give it a parameter name
9+
|
10+
LL | pub fn foo(self: Box<Self>) { }
11+
| ^^^^^^^^^
812
help: if this is a type, explicitly ignore the parameter name
913
|
1014
LL | pub fn foo(_: Box<Self>) { }

0 commit comments

Comments
 (0)
Please sign in to comment.