diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index cd3b8db2303b3..350a372a684cc 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1808,9 +1808,13 @@ impl<'a> Parser<'a> { return Ok(false); // Don't continue. } - /// Handle a generic const argument that had not been enclosed in braces, and suggest enclosing - /// it braces. In this situation, unlike in `handle_ambiguous_unbraced_const_arg`, this is - /// almost certainly a const argument, so we always offer a suggestion. + /// Attempt to parse a generic const argument that has not been enclosed in braces. + /// There are a limited number of expressions that are permitted without being encoded + /// in braces: + /// - Literals. + /// - Single-segment paths (i.e. standalone generic const parameters). + /// All other expressions that can be parsed will emit an error suggesting the expression be + /// wrapped in braces. pub fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P> { let start = self.token.span; let expr = self.parse_expr_res(Restrictions::CONST_EXPR, None).map_err(|mut err| { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 79e737490386c..d64fd59b0a657 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -489,6 +489,7 @@ impl<'a> Parser<'a> { /// - An expression surrounded in `{}`. /// - A literal. /// - A numeric literal prefixed by `-`. + /// - A single-segment path. pub(super) fn expr_is_valid_const_arg(&self, expr: &P) -> bool { match &expr.kind { ast::ExprKind::Block(_, _) | ast::ExprKind::Lit(_) => true, @@ -496,6 +497,13 @@ impl<'a> Parser<'a> { ast::ExprKind::Lit(_) => true, _ => false, }, + // We can only resolve single-segment paths at the moment, because multi-segment paths + // require type-checking: see `visit_generic_arg` in `src/librustc_resolve/late.rs`. + ast::ExprKind::Path(None, path) + if path.segments.len() == 1 && path.segments[0].args.is_none() => + { + true + } _ => false, } } diff --git a/src/test/ui/const-generics/macro_rules-braces.full.stderr b/src/test/ui/const-generics/macro_rules-braces.full.stderr index e5b67f61a25b7..3c9d4c9b4700f 100644 --- a/src/test/ui/const-generics/macro_rules-braces.full.stderr +++ b/src/test/ui/const-generics/macro_rules-braces.full.stderr @@ -1,16 +1,16 @@ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/macro_rules-braces.rs:34:17 + --> $DIR/macro_rules-braces.rs:49:17 | -LL | let _: baz!(N); - | ^ +LL | let _: baz!(m::P); + | ^^^^ | help: enclose the `const` expression in braces | -LL | let _: baz!({ N }); - | ^ ^ +LL | let _: baz!({ m::P }); + | ^ ^ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/macro_rules-braces.rs:54:17 + --> $DIR/macro_rules-braces.rs:69:17 | LL | let _: baz!(10 + 7); | ^^^^^^ @@ -21,7 +21,7 @@ LL | let _: baz!({ 10 + 7 }); | ^ ^ error: constant expression depends on a generic parameter - --> $DIR/macro_rules-braces.rs:10:13 + --> $DIR/macro_rules-braces.rs:16:13 | LL | [u8; $x] | ^^^^^^^^ @@ -33,7 +33,7 @@ LL | let _: foo!({{ N }}); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: constant expression depends on a generic parameter - --> $DIR/macro_rules-braces.rs:15:13 + --> $DIR/macro_rules-braces.rs:21:13 | LL | [u8; { $x }] | ^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | let _: bar!({ N }); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: constant expression depends on a generic parameter - --> $DIR/macro_rules-braces.rs:20:13 + --> $DIR/macro_rules-braces.rs:26:13 | LL | Foo<$x> | ^^^^^^^ @@ -57,7 +57,7 @@ LL | let _: baz!({{ N }}); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: constant expression depends on a generic parameter - --> $DIR/macro_rules-braces.rs:25:13 + --> $DIR/macro_rules-braces.rs:31:13 | LL | Foo<{ $x }> | ^^^^^^^^^^^ diff --git a/src/test/ui/const-generics/macro_rules-braces.min.stderr b/src/test/ui/const-generics/macro_rules-braces.min.stderr index a4ef732017dd5..c6425edc10f15 100644 --- a/src/test/ui/const-generics/macro_rules-braces.min.stderr +++ b/src/test/ui/const-generics/macro_rules-braces.min.stderr @@ -1,16 +1,16 @@ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/macro_rules-braces.rs:34:17 + --> $DIR/macro_rules-braces.rs:49:17 | -LL | let _: baz!(N); - | ^ +LL | let _: baz!(m::P); + | ^^^^ | help: enclose the `const` expression in braces | -LL | let _: baz!({ N }); - | ^ ^ +LL | let _: baz!({ m::P }); + | ^ ^ error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/macro_rules-braces.rs:54:17 + --> $DIR/macro_rules-braces.rs:69:17 | LL | let _: baz!(10 + 7); | ^^^^^^ @@ -21,7 +21,7 @@ LL | let _: baz!({ 10 + 7 }); | ^ ^ error: generic parameters may not be used in const operations - --> $DIR/macro_rules-braces.rs:31:20 + --> $DIR/macro_rules-braces.rs:37:20 | LL | let _: foo!({{ N }}); | ^ cannot perform const operation using `N` @@ -29,7 +29,7 @@ LL | let _: foo!({{ N }}); = help: const parameters may only be used as standalone arguments, i.e. `N` error: generic parameters may not be used in const operations - --> $DIR/macro_rules-braces.rs:33:19 + --> $DIR/macro_rules-braces.rs:41:19 | LL | let _: bar!({ N }); | ^ cannot perform const operation using `N` @@ -37,7 +37,7 @@ LL | let _: bar!({ N }); = help: const parameters may only be used as standalone arguments, i.e. `N` error: generic parameters may not be used in const operations - --> $DIR/macro_rules-braces.rs:36:20 + --> $DIR/macro_rules-braces.rs:46:20 | LL | let _: baz!({{ N }}); | ^ cannot perform const operation using `N` @@ -45,7 +45,7 @@ LL | let _: baz!({{ N }}); = help: const parameters may only be used as standalone arguments, i.e. `N` error: generic parameters may not be used in const operations - --> $DIR/macro_rules-braces.rs:38:19 + --> $DIR/macro_rules-braces.rs:51:19 | LL | let _: biz!({ N }); | ^ cannot perform const operation using `N` diff --git a/src/test/ui/const-generics/macro_rules-braces.rs b/src/test/ui/const-generics/macro_rules-braces.rs index bc67d464f11bb..c6b43bec243f4 100644 --- a/src/test/ui/const-generics/macro_rules-braces.rs +++ b/src/test/ui/const-generics/macro_rules-braces.rs @@ -3,6 +3,12 @@ #![cfg_attr(full, feature(const_generics))] #![cfg_attr(min, feature(min_const_generics))] +mod m { + pub const P: usize = 0; +} + +const Q: usize = 0; + fn test() { struct Foo; macro_rules! foo { @@ -29,13 +35,22 @@ fn test() { let _: foo!(N); let _: foo!({ N }); let _: foo!({{ N }}); //[min]~ ERROR generic parameters may not + let _: foo!(Q); + let _: foo!(m::P); let _: bar!(N); let _: bar!({ N }); //[min]~ ERROR generic parameters may not - let _: baz!(N); //~ ERROR expressions must be enclosed in braces + let _: bar!(Q); + let _: bar!(m::P); + let _: baz!(N); let _: baz!({ N }); let _: baz!({{ N }}); //[min]~ ERROR generic parameters may not + let _: baz!(Q); + let _: baz!({ m::P }); + let _: baz!(m::P); //~ ERROR expressions must be enclosed in braces let _: biz!(N); let _: biz!({ N }); //[min]~ ERROR generic parameters may not + let _: biz!(Q); + let _: biz!(m::P); let _: foo!(3); let _: foo!({ 3 }); let _: foo!({{ 3 }});