Skip to content

Commit 9a5a4b0

Browse files
committed
Deny bare const expressions
1 parent 200034a commit 9a5a4b0

7 files changed

+102
-30
lines changed

src/librustc_parse/parser/path.rs

+33-7
Original file line numberDiff line numberDiff line change
@@ -593,13 +593,39 @@ impl<'a> Parser<'a> {
593593
// we should introduce a GenericArg::Ident in the AST and distinguish when
594594
// lowering to the HIR. For now, idents for const args are not permitted.
595595
let start = self.token.span;
596-
self.parse_expr_res(Restrictions::CONST_EXPR, None).map_err(|mut err| {
597-
err.span_label(
598-
start.shrink_to_lo(),
599-
"while parsing a `const` argument starting here",
600-
);
601-
err
602-
})?
596+
let expr =
597+
self.parse_expr_res(Restrictions::CONST_EXPR, None).map_err(|mut err| {
598+
err.span_label(
599+
start.shrink_to_lo(),
600+
"while parsing a `const` argument starting here",
601+
);
602+
err
603+
})?;
604+
let valid_const = match &expr.kind {
605+
ast::ExprKind::Block(_, _) | ast::ExprKind::Lit(_) => true,
606+
ast::ExprKind::Unary(ast::UnOp::Neg, expr) => match &expr.kind {
607+
ast::ExprKind::Lit(_) => true,
608+
_ => false,
609+
},
610+
_ => false,
611+
};
612+
if !valid_const {
613+
self.struct_span_err(
614+
expr.span,
615+
"`const` generic expressions without braces are not supported",
616+
)
617+
.note("only literals are supported as `const` generic without braces")
618+
.multipart_suggestion(
619+
"surround `const` expressions with braces",
620+
vec![
621+
(expr.span.shrink_to_lo(), "{ ".to_string()),
622+
(expr.span.shrink_to_hi(), " }".to_string()),
623+
],
624+
Applicability::MachineApplicable,
625+
)
626+
.emit();
627+
}
628+
expr
603629
};
604630
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
605631
} else if self.check_type() {

src/test/ui/const-generics/const-expression-missing-braces.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,22 @@ fn foo<const C: usize>() {}
66
const BAR: usize = 42;
77

88
fn a() {
9-
foo::<BAR + 3>();
10-
//~^ ERROR expected one of
9+
foo::<BAR + 3>(); //~ ERROR expected one of
1110
}
1211
fn b() {
13-
foo::<BAR + BAR>();
14-
//~^ ERROR likely `const` expression parsed as trait bounds
12+
foo::<BAR + BAR>(); //~ ERROR likely `const` expression parsed as trait bounds
1513
}
1614
fn c() {
17-
foo::<3 + 3>(); // ok
15+
foo::<3 + 3>(); //~ ERROR `const` generic expressions without braces are not supported
1816
}
1917
fn d() {
20-
foo::<BAR - 3>();
21-
//~^ ERROR expected one of
18+
foo::<BAR - 3>(); //~ ERROR expected one of
2219
}
2320
fn e() {
24-
foo::<BAR - BAR>();
25-
//~^ ERROR expected one of
21+
foo::<BAR - BAR>(); //~ ERROR expected one of
2622
}
2723
fn f() {
28-
foo::<100 - BAR>(); // ok
24+
foo::<100 - BAR>(); //~ ERROR `const` generic expressions without braces are not supported
2925
}
3026
fn g() {
3127
foo::<bar<i32>()>(); //~ ERROR expected one of

src/test/ui/const-generics/const-expression-missing-braces.stderr

+34-10
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,20 @@ help: to write a `const` expression, surround it with braces for it to be unambi
99
LL | foo::<{ BAR + 3 }>();
1010
| ^ ^
1111

12+
error: `const` generic expressions without braces are not supported
13+
--> $DIR/const-expression-missing-braces.rs:15:11
14+
|
15+
LL | foo::<3 + 3>();
16+
| ^^^^^
17+
|
18+
= note: only literals are supported as `const` generic without braces
19+
help: surround `const` expressions with braces
20+
|
21+
LL | foo::<{ 3 + 3 }>();
22+
| ^ ^
23+
1224
error: expected one of `,` or `>`, found `-`
13-
--> $DIR/const-expression-missing-braces.rs:20:15
25+
--> $DIR/const-expression-missing-braces.rs:18:15
1426
|
1527
LL | foo::<BAR - 3>();
1628
| ^ expected one of `,` or `>`
@@ -21,7 +33,7 @@ LL | foo::<{ BAR - 3 }>();
2133
| ^ ^
2234

2335
error: expected one of `,` or `>`, found `-`
24-
--> $DIR/const-expression-missing-braces.rs:24:15
36+
--> $DIR/const-expression-missing-braces.rs:21:15
2537
|
2638
LL | foo::<BAR - BAR>();
2739
| ^ expected one of `,` or `>`
@@ -31,8 +43,20 @@ help: to write a `const` expression, surround it with braces for it to be unambi
3143
LL | foo::<{ BAR - BAR }>();
3244
| ^ ^
3345

46+
error: `const` generic expressions without braces are not supported
47+
--> $DIR/const-expression-missing-braces.rs:24:11
48+
|
49+
LL | foo::<100 - BAR>();
50+
| ^^^^^^^^^
51+
|
52+
= note: only literals are supported as `const` generic without braces
53+
help: surround `const` expressions with braces
54+
|
55+
LL | foo::<{ 100 - BAR }>();
56+
| ^ ^
57+
3458
error: expected one of `,` or `>`, found `(`
35-
--> $DIR/const-expression-missing-braces.rs:31:19
59+
--> $DIR/const-expression-missing-braces.rs:27:19
3660
|
3761
LL | foo::<bar<i32>()>();
3862
| ^ expected one of `,` or `>`
@@ -43,7 +67,7 @@ LL | foo::<{ bar<i32>() }>();
4367
| ^ ^
4468

4569
error: expected one of `,` or `>`, found `(`
46-
--> $DIR/const-expression-missing-braces.rs:34:21
70+
--> $DIR/const-expression-missing-braces.rs:30:21
4771
|
4872
LL | foo::<bar::<i32>()>();
4973
| ^ expected one of `,` or `>`
@@ -54,7 +78,7 @@ LL | foo::<{ bar::<i32>() }>();
5478
| ^ ^
5579

5680
error: expected one of `,` or `>`, found `(`
57-
--> $DIR/const-expression-missing-braces.rs:37:21
81+
--> $DIR/const-expression-missing-braces.rs:33:21
5882
|
5983
LL | foo::<bar::<i32>() + BAR>();
6084
| ^ expected one of `,` or `>`
@@ -65,7 +89,7 @@ LL | foo::<{ bar::<i32>() + BAR }>();
6589
| ^ ^
6690

6791
error: expected one of `,` or `>`, found `(`
68-
--> $DIR/const-expression-missing-braces.rs:40:21
92+
--> $DIR/const-expression-missing-braces.rs:36:21
6993
|
7094
LL | foo::<bar::<i32>() - BAR>();
7195
| ^ expected one of `,` or `>`
@@ -76,7 +100,7 @@ LL | foo::<{ bar::<i32>() - BAR }>();
76100
| ^ ^
77101

78102
error: expected one of `,` or `>`, found `-`
79-
--> $DIR/const-expression-missing-braces.rs:43:15
103+
--> $DIR/const-expression-missing-braces.rs:39:15
80104
|
81105
LL | foo::<BAR - bar::<i32>()>();
82106
| ^ expected one of `,` or `>`
@@ -87,7 +111,7 @@ LL | foo::<{ BAR - bar::<i32>() }>();
87111
| ^ ^
88112

89113
error: expected one of `,` or `>`, found `-`
90-
--> $DIR/const-expression-missing-braces.rs:46:15
114+
--> $DIR/const-expression-missing-braces.rs:42:15
91115
|
92116
LL | foo::<BAR - bar::<i32>()>();
93117
| ^ expected one of `,` or `>`
@@ -98,7 +122,7 @@ LL | foo::<{ BAR - bar::<i32>() }>();
98122
| ^ ^
99123

100124
error: likely `const` expression parsed as trait bounds
101-
--> $DIR/const-expression-missing-braces.rs:13:11
125+
--> $DIR/const-expression-missing-braces.rs:12:11
102126
|
103127
LL | foo::<BAR + BAR>();
104128
| ^^^^^^^^^ parsed as trait bounds but traits weren't found
@@ -108,5 +132,5 @@ help: if you meant to write a `const` expression, surround the expression with b
108132
LL | foo::<{ BAR + BAR }>();
109133
| ^ ^
110134

111-
error: aborting due to 10 previous errors
135+
error: aborting due to 12 previous errors
112136

src/test/ui/const-generics/const-expression-parameter.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// check-pass
21
#![allow(incomplete_features)]
32
#![feature(const_generics)]
43

@@ -11,7 +10,7 @@ fn foo_a() {
1110
}
1211

1312
fn foo_b() {
14-
i32_identity::<1 + 2>(); // ok
13+
i32_identity::<1 + 2>(); //~ ERROR `const` generic expressions without braces are not supported
1514
}
1615

1716
fn foo_c() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: `const` generic expressions without braces are not supported
2+
--> $DIR/const-expression-parameter.rs:13:20
3+
|
4+
LL | i32_identity::<1 + 2>();
5+
| ^^^^^
6+
|
7+
= note: only literals are supported as `const` generic without braces
8+
help: surround `const` expressions with braces
9+
|
10+
LL | i32_identity::<{ 1 + 2 }>();
11+
| ^ ^
12+
13+
error: aborting due to previous error
14+

src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs

+1
Original file line numberDiff line numberDiff line change
@@ -237,5 +237,6 @@ fn inside_const_generic_arguments() {
237237
if A::<
238238
true && let 1 = 1 //~ ERROR `let` expressions are not supported here
239239
//~^ ERROR `match` is not allowed in a `const`
240+
//~| ERROR `const` generic expressions without braces are not supported
240241
>::O == 5 {}
241242
}

src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error: `const` generic expressions without braces are not supported
2+
--> $DIR/disallowed-positions.rs:238:9
3+
|
4+
LL | true && let 1 = 1
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= note: only literals are supported as `const` generic without braces
8+
help: surround `const` expressions with braces
9+
|
10+
LL | { true && let 1 = 1 }
11+
| ^ ^
12+
113
error: `let` expressions are not supported here
214
--> $DIR/disallowed-positions.rs:32:9
315
|
@@ -992,7 +1004,7 @@ LL | let 0 = 0?;
9921004
= help: the trait `std::ops::Try` is not implemented for `{integer}`
9931005
= note: required by `std::ops::Try::into_result`
9941006

995-
error: aborting due to 107 previous errors; 2 warnings emitted
1007+
error: aborting due to 108 previous errors; 2 warnings emitted
9961008

9971009
Some errors have detailed explanations: E0277, E0308, E0600, E0614, E0658.
9981010
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)