Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_parse/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1843,7 +1843,7 @@ pub(crate) struct AttributeOnEmptyType {
}

#[derive(Diagnostic)]
#[diag("patterns aren't allowed in methods without bodies", code = E0642)]
#[diag("patterns aren't allowed in {$target}", code = E0642)]
pub(crate) struct PatternMethodParamWithoutBody {
#[primary_span]
#[suggestion(
Expand All @@ -1853,6 +1853,7 @@ pub(crate) struct PatternMethodParamWithoutBody {
style = "verbose"
)]
pub span: Span,
pub target: &'static str,
}

#[derive(Diagnostic)]
Expand Down
16 changes: 13 additions & 3 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2385,12 +2385,22 @@ impl<'a> Parser<'a> {
}

#[cold]
pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (Box<ast::Pat>, Box<ast::Ty>)> {
pub(super) fn recover_arg_parse(
&mut self,
context: FnContext,
) -> PResult<'a, (Box<ast::Pat>, Box<ast::Ty>)> {
let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?;
self.expect(exp!(Colon))?;
let ty = self.parse_ty()?;

self.dcx().emit_err(PatternMethodParamWithoutBody { span: pat.span });
self.dcx().emit_err(PatternMethodParamWithoutBody {
span: pat.span,
target: match context {
FnContext::Trait => "methods without bodies",
FnContext::FunctionPtrType => "function pointer types",
FnContext::Free => unreachable!("This method is not called in free functions, as patterns are always allowed there"),
FnContext::Impl => unreachable!("This method is not called in impls, as patterns are always allowed there"),
},
});

// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
let pat = Box::new(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID });
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_parse/src/parser/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ pub(crate) struct FnParseMode {
pub(crate) enum FnContext {
/// Free context.
Free,
/// A Function Pointer Type `fn(..)`.
FunctionPtrType,
/// A Trait context.
Trait,
/// An Impl block.
Expand Down Expand Up @@ -818,7 +820,7 @@ impl<'a> Parser<'a> {
// Recover from attempting to parse the argument as a type without pattern.
err.cancel();
this.restore_snapshot(parser_snapshot_before_ty);
this.recover_arg_parse()?
this.recover_arg_parse(fn_parse_mode.context)?
}
Err(err) => return Err(err),
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ impl<'a> Parser<'a> {
}
let mode = crate::parser::FnParseMode {
req_name: |_, _| false,
context: FnContext::Free,
context: FnContext::FunctionPtrType,
req_body: false,
};
let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?;
Expand Down
28 changes: 28 additions & 0 deletions tests/ui/fn/fn-ptr-pattern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
fn patterns<F>(
pat1: fn(true: bool),
//~^ ERROR patterns aren't allowed in function pointer types
pat2: fn(1..3: bool),
//~^ ERROR patterns aren't allowed in function pointer types
pat3: fn((x, y): (bool, bool)),
//~^ ERROR patterns aren't allowed in function pointer types
pat4: fn(self),
//~^ ERROR `self` parameter is only allowed in associated functions
pat5: fn(self, self),
//~^ ERROR `self` parameter is only allowed in associated functions
//~| ERROR unexpected `self` parameter in function
pat6: fn(bool, self),
//~^ ERROR unexpected `self` parameter in function
pat7: fn(Thing { a, b }: Thing),
//~^ ERROR patterns aren't allowed in function pointer types
pat8: fn(NoThing { a, b }: NoThing),
//~^ ERROR patterns aren't allowed in function pointer types
//~| ERROR cannot find type `NoThing` in this scope
pat9: fn((((((x))))): bool),
//~^ ERROR patterns aren't allowed in function pointer types
) { }

struct Thing { a: bool, b: bool }

fn main() {

}
113 changes: 113 additions & 0 deletions tests/ui/fn/fn-ptr-pattern.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
error[E0642]: patterns aren't allowed in function pointer types
--> $DIR/fn-ptr-pattern.rs:4:14
|
LL | pat2: fn(1..3: bool),
| ^^^^
|
help: give this argument a name or use an underscore to ignore it
|
LL - pat2: fn(1..3: bool),
LL + pat2: fn(_: bool),
|

error[E0642]: patterns aren't allowed in function pointer types
--> $DIR/fn-ptr-pattern.rs:6:14
|
LL | pat3: fn((x, y): (bool, bool)),
| ^^^^^^
|
help: give this argument a name or use an underscore to ignore it
|
LL - pat3: fn((x, y): (bool, bool)),
LL + pat3: fn(_: (bool, bool)),
|

error: unexpected `self` parameter in function
--> $DIR/fn-ptr-pattern.rs:10:20
|
LL | pat5: fn(self, self),
| ^^^^ must be the first parameter of an associated function

error: unexpected `self` parameter in function
--> $DIR/fn-ptr-pattern.rs:13:20
|
LL | pat6: fn(bool, self),
| ^^^^ must be the first parameter of an associated function

error[E0642]: patterns aren't allowed in function pointer types
--> $DIR/fn-ptr-pattern.rs:15:14
|
LL | pat7: fn(Thing { a, b }: Thing),
| ^^^^^^^^^^^^^^
|
help: give this argument a name or use an underscore to ignore it
|
LL - pat7: fn(Thing { a, b }: Thing),
LL + pat7: fn(_: Thing),
|

error[E0642]: patterns aren't allowed in function pointer types
--> $DIR/fn-ptr-pattern.rs:17:14
|
LL | pat8: fn(NoThing { a, b }: NoThing),
| ^^^^^^^^^^^^^^^^
|
help: give this argument a name or use an underscore to ignore it
|
LL - pat8: fn(NoThing { a, b }: NoThing),
LL + pat8: fn(_: NoThing),
|

error[E0642]: patterns aren't allowed in function pointer types
--> $DIR/fn-ptr-pattern.rs:20:14
|
LL | pat9: fn((((((x))))): bool),
| ^^^^^^^^^^^
|
help: give this argument a name or use an underscore to ignore it
|
LL - pat9: fn((((((x))))): bool),
LL + pat9: fn(_: bool),
|

error[E0561]: patterns aren't allowed in function pointer types
--> $DIR/fn-ptr-pattern.rs:2:14
|
LL | pat1: fn(true: bool),
| ^^^^

error: `self` parameter is only allowed in associated functions
--> $DIR/fn-ptr-pattern.rs:8:14
|
LL | pat4: fn(self),
| ^^^^ not semantically valid as function parameter
|
= note: associated functions are those in `impl` or `trait` definitions

error: `self` parameter is only allowed in associated functions
--> $DIR/fn-ptr-pattern.rs:10:14
|
LL | pat5: fn(self, self),
| ^^^^ not semantically valid as function parameter
|
= note: associated functions are those in `impl` or `trait` definitions

error[E0425]: cannot find type `NoThing` in this scope
--> $DIR/fn-ptr-pattern.rs:17:32
|
LL | pat8: fn(NoThing { a, b }: NoThing),
| ^^^^^^^
...
LL | struct Thing { a: bool, b: bool }
| ------------ similarly named struct `Thing` defined here
|
help: a struct with a similar name exists
|
LL - pat8: fn(NoThing { a, b }: NoThing),
LL + pat8: fn(NoThing { a, b }: Thing),
|

error: aborting due to 11 previous errors

Some errors have detailed explanations: E0425, E0561, E0642.
For more information about an error, try `rustc --explain E0425`.
Loading