Skip to content

Commit efcbf1b

Browse files
committed
Permit standalone generic parameters as const generic arguments in macros
1 parent c4f836a commit efcbf1b

File tree

5 files changed

+18
-28
lines changed

5 files changed

+18
-28
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1808,9 +1808,13 @@ impl<'a> Parser<'a> {
18081808
return Ok(false); // Don't continue.
18091809
}
18101810

1811-
/// Handle a generic const argument that had not been enclosed in braces, and suggest enclosing
1812-
/// it braces. In this situation, unlike in `handle_ambiguous_unbraced_const_arg`, this is
1813-
/// almost certainly a const argument, so we always offer a suggestion.
1811+
/// Attempt to parse a generic const argument that has not been enclosed in braces.
1812+
/// There are a limited number of expressions that are permitted without being encoded
1813+
/// in braces:
1814+
/// - Literals.
1815+
/// - Single-segment paths (i.e. standalone generic const parameters).
1816+
/// All other expressions that can be parsed will emit an error suggesting the expression be
1817+
/// wrapped in braces.
18141818
pub fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> {
18151819
let start = self.token.span;
18161820
let expr = self.parse_expr_res(Restrictions::CONST_EXPR, None).map_err(|mut err| {

compiler/rustc_parse/src/parser/path.rs

+8
Original file line numberDiff line numberDiff line change
@@ -489,13 +489,21 @@ impl<'a> Parser<'a> {
489489
/// - An expression surrounded in `{}`.
490490
/// - A literal.
491491
/// - A numeric literal prefixed by `-`.
492+
/// - A single-segment path.
492493
pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool {
493494
match &expr.kind {
494495
ast::ExprKind::Block(_, _) | ast::ExprKind::Lit(_) => true,
495496
ast::ExprKind::Unary(ast::UnOp::Neg, expr) => match &expr.kind {
496497
ast::ExprKind::Lit(_) => true,
497498
_ => false,
498499
},
500+
// We can only resolve single-segment paths at the moment, because multi-segment paths
501+
// require type-checking: see `visit_generic_arg` in `src/librustc_resolve/late.rs`.
502+
ast::ExprKind::Path(None, path)
503+
if path.segments.len() == 1 && path.segments[0].args.is_none() =>
504+
{
505+
true
506+
}
499507
_ => false,
500508
}
501509
}

src/test/ui/const-generics/macro_rules-braces.full.stderr

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
error: expressions must be enclosed in braces to be used as const generic arguments
2-
--> $DIR/macro_rules-braces.rs:34:17
3-
|
4-
LL | let _: baz!(N);
5-
| ^
6-
|
7-
help: enclose the `const` expression in braces
8-
|
9-
LL | let _: baz!({ N });
10-
| ^ ^
11-
121
error: expressions must be enclosed in braces to be used as const generic arguments
132
--> $DIR/macro_rules-braces.rs:54:17
143
|
@@ -68,5 +57,5 @@ LL | let _: biz!({ N });
6857
= note: this may fail depending on what value the parameter takes
6958
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
7059

71-
error: aborting due to 6 previous errors
60+
error: aborting due to 5 previous errors
7261

src/test/ui/const-generics/macro_rules-braces.min.stderr

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
error: expressions must be enclosed in braces to be used as const generic arguments
2-
--> $DIR/macro_rules-braces.rs:34:17
3-
|
4-
LL | let _: baz!(N);
5-
| ^
6-
|
7-
help: enclose the `const` expression in braces
8-
|
9-
LL | let _: baz!({ N });
10-
| ^ ^
11-
121
error: expressions must be enclosed in braces to be used as const generic arguments
132
--> $DIR/macro_rules-braces.rs:54:17
143
|
@@ -52,5 +41,5 @@ LL | let _: biz!({ N });
5241
|
5342
= help: const parameters may only be used as standalone arguments, i.e. `N`
5443

55-
error: aborting due to 6 previous errors
44+
error: aborting due to 5 previous errors
5645

src/test/ui/const-generics/macro_rules-braces.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn test<const N: usize>() {
3131
let _: foo!({{ N }}); //[min]~ ERROR generic parameters may not
3232
let _: bar!(N);
3333
let _: bar!({ N }); //[min]~ ERROR generic parameters may not
34-
let _: baz!(N); //~ ERROR expressions must be enclosed in braces
34+
let _: baz!(N);
3535
let _: baz!({ N });
3636
let _: baz!({{ N }}); //[min]~ ERROR generic parameters may not
3737
let _: biz!(N);

0 commit comments

Comments
 (0)