From efcbf1b00bb8997f1e1ee0740640f67fbe32c615 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 18 Nov 2020 12:49:39 +0000 Subject: [PATCH] Permit standalone generic parameters as const generic arguments in macros --- compiler/rustc_parse/src/parser/diagnostics.rs | 10 +++++++--- compiler/rustc_parse/src/parser/path.rs | 8 ++++++++ .../const-generics/macro_rules-braces.full.stderr | 13 +------------ .../ui/const-generics/macro_rules-braces.min.stderr | 13 +------------ src/test/ui/const-generics/macro_rules-braces.rs | 2 +- 5 files changed, 18 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index cd3b8db2303..350a372a684 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1808,9 +1808,13 @@ pub fn handle_ambiguous_unbraced_const_arg( 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 79e73749038..d64fd59b0a6 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -489,6 +489,7 @@ fn parse_assoc_equality_term(&mut self, ident: Ident, eq: Span) -> PResult<'a, P /// - 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 @@ pub(super) fn expr_is_valid_const_arg(&self, expr: &P) -> bool 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 e5b67f61a25..273766b0b0e 100644 --- a/src/test/ui/const-generics/macro_rules-braces.full.stderr +++ b/src/test/ui/const-generics/macro_rules-braces.full.stderr @@ -1,14 +1,3 @@ -error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/macro_rules-braces.rs:34:17 - | -LL | let _: baz!(N); - | ^ - | -help: enclose the `const` expression in braces - | -LL | let _: baz!({ N }); - | ^ ^ - error: expressions must be enclosed in braces to be used as const generic arguments --> $DIR/macro_rules-braces.rs:54:17 | @@ -68,5 +57,5 @@ LL | let _: biz!({ N }); = note: this may fail depending on what value the parameter takes = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors 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 a4ef732017d..10c2a596ca5 100644 --- a/src/test/ui/const-generics/macro_rules-braces.min.stderr +++ b/src/test/ui/const-generics/macro_rules-braces.min.stderr @@ -1,14 +1,3 @@ -error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/macro_rules-braces.rs:34:17 - | -LL | let _: baz!(N); - | ^ - | -help: enclose the `const` expression in braces - | -LL | let _: baz!({ N }); - | ^ ^ - error: expressions must be enclosed in braces to be used as const generic arguments --> $DIR/macro_rules-braces.rs:54:17 | @@ -52,5 +41,5 @@ LL | let _: biz!({ N }); | = help: const parameters may only be used as standalone arguments, i.e. `N` -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/const-generics/macro_rules-braces.rs b/src/test/ui/const-generics/macro_rules-braces.rs index bc67d464f11..bc2eca81b61 100644 --- a/src/test/ui/const-generics/macro_rules-braces.rs +++ b/src/test/ui/const-generics/macro_rules-braces.rs @@ -31,7 +31,7 @@ macro_rules! biz { let _: foo!({{ N }}); //[min]~ ERROR generic parameters may not let _: bar!(N); let _: bar!({ N }); //[min]~ ERROR generic parameters may not - let _: baz!(N); //~ ERROR expressions must be enclosed in braces + let _: baz!(N); let _: baz!({ N }); let _: baz!({{ N }}); //[min]~ ERROR generic parameters may not let _: biz!(N); -- 2.44.0