Skip to content

Commit b5fffdc

Browse files
authored
Rollup merge of #79164 - varkor:unbraced-single-segment-const-arguments, r=petrochenkov
Permit standalone generic parameters as const generic arguments in macros Fixes #79127. r? ```@petrochenkov```
2 parents de62272 + 85bc953 commit b5fffdc

File tree

5 files changed

+51
-24
lines changed

5 files changed

+51
-24
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

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
error: expressions must be enclosed in braces to be used as const generic arguments
2-
--> $DIR/macro_rules-braces.rs:34:17
2+
--> $DIR/macro_rules-braces.rs:49:17
33
|
4-
LL | let _: baz!(N);
5-
| ^
4+
LL | let _: baz!(m::P);
5+
| ^^^^
66
|
77
help: enclose the `const` expression in braces
88
|
9-
LL | let _: baz!({ N });
10-
| ^ ^
9+
LL | let _: baz!({ m::P });
10+
| ^ ^
1111

1212
error: expressions must be enclosed in braces to be used as const generic arguments
13-
--> $DIR/macro_rules-braces.rs:54:17
13+
--> $DIR/macro_rules-braces.rs:69:17
1414
|
1515
LL | let _: baz!(10 + 7);
1616
| ^^^^^^
@@ -21,7 +21,7 @@ LL | let _: baz!({ 10 + 7 });
2121
| ^ ^
2222

2323
error: constant expression depends on a generic parameter
24-
--> $DIR/macro_rules-braces.rs:10:13
24+
--> $DIR/macro_rules-braces.rs:16:13
2525
|
2626
LL | [u8; $x]
2727
| ^^^^^^^^
@@ -33,7 +33,7 @@ LL | let _: foo!({{ N }});
3333
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
3434

3535
error: constant expression depends on a generic parameter
36-
--> $DIR/macro_rules-braces.rs:15:13
36+
--> $DIR/macro_rules-braces.rs:21:13
3737
|
3838
LL | [u8; { $x }]
3939
| ^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL | let _: bar!({ N });
4545
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
4646

4747
error: constant expression depends on a generic parameter
48-
--> $DIR/macro_rules-braces.rs:20:13
48+
--> $DIR/macro_rules-braces.rs:26:13
4949
|
5050
LL | Foo<$x>
5151
| ^^^^^^^
@@ -57,7 +57,7 @@ LL | let _: baz!({{ N }});
5757
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
5858

5959
error: constant expression depends on a generic parameter
60-
--> $DIR/macro_rules-braces.rs:25:13
60+
--> $DIR/macro_rules-braces.rs:31:13
6161
|
6262
LL | Foo<{ $x }>
6363
| ^^^^^^^^^^^

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

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
error: expressions must be enclosed in braces to be used as const generic arguments
2-
--> $DIR/macro_rules-braces.rs:34:17
2+
--> $DIR/macro_rules-braces.rs:49:17
33
|
4-
LL | let _: baz!(N);
5-
| ^
4+
LL | let _: baz!(m::P);
5+
| ^^^^
66
|
77
help: enclose the `const` expression in braces
88
|
9-
LL | let _: baz!({ N });
10-
| ^ ^
9+
LL | let _: baz!({ m::P });
10+
| ^ ^
1111

1212
error: expressions must be enclosed in braces to be used as const generic arguments
13-
--> $DIR/macro_rules-braces.rs:54:17
13+
--> $DIR/macro_rules-braces.rs:69:17
1414
|
1515
LL | let _: baz!(10 + 7);
1616
| ^^^^^^
@@ -21,31 +21,31 @@ LL | let _: baz!({ 10 + 7 });
2121
| ^ ^
2222

2323
error: generic parameters may not be used in const operations
24-
--> $DIR/macro_rules-braces.rs:31:20
24+
--> $DIR/macro_rules-braces.rs:37:20
2525
|
2626
LL | let _: foo!({{ N }});
2727
| ^ cannot perform const operation using `N`
2828
|
2929
= help: const parameters may only be used as standalone arguments, i.e. `N`
3030

3131
error: generic parameters may not be used in const operations
32-
--> $DIR/macro_rules-braces.rs:33:19
32+
--> $DIR/macro_rules-braces.rs:41:19
3333
|
3434
LL | let _: bar!({ N });
3535
| ^ cannot perform const operation using `N`
3636
|
3737
= help: const parameters may only be used as standalone arguments, i.e. `N`
3838

3939
error: generic parameters may not be used in const operations
40-
--> $DIR/macro_rules-braces.rs:36:20
40+
--> $DIR/macro_rules-braces.rs:46:20
4141
|
4242
LL | let _: baz!({{ N }});
4343
| ^ cannot perform const operation using `N`
4444
|
4545
= help: const parameters may only be used as standalone arguments, i.e. `N`
4646

4747
error: generic parameters may not be used in const operations
48-
--> $DIR/macro_rules-braces.rs:38:19
48+
--> $DIR/macro_rules-braces.rs:51:19
4949
|
5050
LL | let _: biz!({ N });
5151
| ^ cannot perform const operation using `N`

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

+16-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
#![cfg_attr(full, feature(const_generics))]
44
#![cfg_attr(min, feature(min_const_generics))]
55

6+
mod m {
7+
pub const P: usize = 0;
8+
}
9+
10+
const Q: usize = 0;
11+
612
fn test<const N: usize>() {
713
struct Foo<const M: usize>;
814
macro_rules! foo {
@@ -29,13 +35,22 @@ fn test<const N: usize>() {
2935
let _: foo!(N);
3036
let _: foo!({ N });
3137
let _: foo!({{ N }}); //[min]~ ERROR generic parameters may not
38+
let _: foo!(Q);
39+
let _: foo!(m::P);
3240
let _: bar!(N);
3341
let _: bar!({ N }); //[min]~ ERROR generic parameters may not
34-
let _: baz!(N); //~ ERROR expressions must be enclosed in braces
42+
let _: bar!(Q);
43+
let _: bar!(m::P);
44+
let _: baz!(N);
3545
let _: baz!({ N });
3646
let _: baz!({{ N }}); //[min]~ ERROR generic parameters may not
47+
let _: baz!(Q);
48+
let _: baz!({ m::P });
49+
let _: baz!(m::P); //~ ERROR expressions must be enclosed in braces
3750
let _: biz!(N);
3851
let _: biz!({ N }); //[min]~ ERROR generic parameters may not
52+
let _: biz!(Q);
53+
let _: biz!(m::P);
3954
let _: foo!(3);
4055
let _: foo!({ 3 });
4156
let _: foo!({{ 3 }});

0 commit comments

Comments
 (0)