diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 5e537d7b95c..0bccf4dc2ce 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -624,9 +624,18 @@ pub(super) fn parse_generic_arg( GenericArg::Const(self.parse_const_arg()?) } else if self.check_type() { // Parse type argument. + let is_const_fn = self.look_ahead(1, |t| t.kind == token::OpenDelim(token::Paren)); + let mut snapshot = self.clone(); match self.parse_ty() { Ok(ty) => GenericArg::Type(ty), Err(err) => { + if is_const_fn { + if let Ok(expr) = snapshot.parse_expr_res(Restrictions::CONST_EXPR, None) { + *self = snapshot; + return Ok(Some(self.dummy_const_arg_needs_braces(err, expr.span))); + } + } + // self.parse_fn_call_expr(); // Try to recover from possible `const` arg without braces. return self.recover_const_arg(start, err).map(Some); } diff --git a/src/test/ui/const-generics/const-generic-function.rs b/src/test/ui/const-generics/const-generic-function.rs new file mode 100644 index 00000000000..c8d2683e53f --- /dev/null +++ b/src/test/ui/const-generics/const-generic-function.rs @@ -0,0 +1,21 @@ +fn foo() -> i32 { + N +} + +const fn bar(n: i32, m: i32) -> i32 { + n +} + +const fn baz() -> i32 { + 1 +} + +const FOO: i32 = 3; + +fn main() { + foo::(); //~ ERROR expected type, found function `baz` + //~| ERROR unresolved item provided when a constant was expected + foo::(); //~ ERROR expected type, found `1` + foo::(); //~ ERROR expected type, found `1` + foo::(); //~ ERROR expected type, found `2` +} diff --git a/src/test/ui/const-generics/const-generic-function.stderr b/src/test/ui/const-generics/const-generic-function.stderr new file mode 100644 index 00000000000..5ad3f1006c1 --- /dev/null +++ b/src/test/ui/const-generics/const-generic-function.stderr @@ -0,0 +1,54 @@ +error: expected type, found `1` + --> $DIR/const-generic-function.rs:18:19 + | +LL | foo::(); + | ^ expected type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar(bar(1, 1), bar(1, 1)) }>(); + | + + + +error: expected type, found `1` + --> $DIR/const-generic-function.rs:19:15 + | +LL | foo::(); + | ^ expected type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar(1, 1) }>(); + | + + + +error: expected type, found `2` + --> $DIR/const-generic-function.rs:20:20 + | +LL | foo::(); + | ^ expected type + | +help: expressions must be enclosed in braces to be used as const generic arguments + | +LL | foo::<{ bar(FOO, 2) }>(); + | + + + +error[E0573]: expected type, found function `baz` + --> $DIR/const-generic-function.rs:16:11 + | +LL | foo::(); + | ^^^^^ not a type + +error[E0747]: unresolved item provided when a constant was expected + --> $DIR/const-generic-function.rs:16:11 + | +LL | foo::(); + | ^^^^^ + | +help: if this generic argument was intended as a const parameter, surround it with braces + | +LL | foo::<{ baz() }>(); + | + + + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0573, E0747. +For more information about an error, try `rustc --explain E0573`.