Skip to content

Commit 87dc824

Browse files
committed
Auto merge of #87237 - jonas-schievink:const-for-and-try, r=oli-obk
Add feature gates for `for` and `?` in consts These operations seems *relatively* straightforward to support, and only seem to be blocked on `impl const Trait`. I have included a working test for `const_try`, but `const_for` is currently unusable without reimplementing *every single* defaulted `Iterator` method, so I didn't do that. (both features still need tracking issues before this is merged)
2 parents 1195bea + c5a29f9 commit 87dc824

File tree

19 files changed

+162
-34
lines changed

19 files changed

+162
-34
lines changed

Diff for: compiler/rustc_error_codes/src/error_codes/E0744.md

+4-14
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,15 @@ An unsupported expression was used inside a const context.
22

33
Erroneous code example:
44

5-
```compile_fail,E0744
5+
```compile_fail,edition2018,E0744
66
const _: i32 = {
7-
let mut x = 0;
8-
9-
for i in 0..4 { // error!
10-
x += i;
11-
}
7+
async { 0 }.await
128
};
139
```
1410

15-
At the moment, `for` loops, `.await`, and the `Try` operator (`?`) are forbidden
16-
inside a `const`, `static`, or `const fn`.
11+
At the moment, `.await` is forbidden inside a `const`, `static`, or `const fn`.
1712

1813
This may be allowed at some point in the future, but the implementation is not
19-
yet complete. See the tracking issues for [`async`] and [`?`] in `const fn`, and
20-
(to support `for` loops in `const fn`) the tracking issues for [`impl const
21-
Trait for Ty`] and [`&mut T`] in `const fn`.
14+
yet complete. See the tracking issue for [`async`] in `const fn`.
2215

2316
[`async`]: https://github.com/rust-lang/rust/issues/69431
24-
[`?`]: https://github.com/rust-lang/rust/issues/74935
25-
[`impl const Trait for Ty`]: https://github.com/rust-lang/rust/issues/67792
26-
[`&mut T`]: https://github.com/rust-lang/rust/issues/57349

Diff for: compiler/rustc_feature/src/active.rs

+6
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,12 @@ declare_features! (
677677
/// Allows `#[derive(Default)]` and `#[default]` on enums.
678678
(active, derive_default_enum, "1.56.0", Some(86985), None),
679679

680+
/// Allows `for _ in _` loops in const contexts.
681+
(active, const_for, "1.56.0", Some(87575), None),
682+
683+
/// Allows the `?` operator in const contexts.
684+
(active, const_try, "1.56.0", Some(74935), None),
685+
680686
// -------------------------------------------------------------------------
681687
// feature-group-end: actual feature gates
682688
// -------------------------------------------------------------------------

Diff for: compiler/rustc_passes/src/check_const.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,14 @@ impl NonConstExpr {
4040
use hir::MatchSource::*;
4141

4242
let gates: &[_] = match self {
43-
// A `for` loop's desugaring contains a call to `IntoIterator::into_iter`,
44-
// so they are not yet allowed.
45-
// Likewise, `?` desugars to a call to `Try::into_result`.
46-
Self::Loop(ForLoop) | Self::Match(ForLoopDesugar | TryDesugar | AwaitDesugar) => {
43+
Self::Match(AwaitDesugar) => {
4744
return None;
4845
}
4946

47+
Self::Loop(ForLoop) | Self::Match(ForLoopDesugar) => &[sym::const_for],
48+
49+
Self::Match(TryDesugar) => &[sym::const_try],
50+
5051
Self::Match(IfLetGuardDesugar) => bug!("`if let` guard outside a `match` expression"),
5152

5253
// All other expressions are allowed.

Diff for: compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ symbols! {
410410
const_fn_transmute,
411411
const_fn_union,
412412
const_fn_unsize,
413+
const_for,
413414
const_format_args,
414415
const_generic_defaults,
415416
const_generics,
@@ -432,6 +433,7 @@ symbols! {
432433
const_trait_bound_opt_out,
433434
const_trait_impl,
434435
const_transmute,
436+
const_try,
435437
constant,
436438
constructor,
437439
contents,

Diff for: src/test/ui/consts/const-fn-error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const fn f(x: usize) -> usize {
77
//~| ERROR calls in constant functions
88
//~| ERROR calls in constant functions
99
//~| ERROR E0080
10-
//~| ERROR E0744
10+
//~| ERROR `for` is not allowed in a `const fn`
1111
sum += i;
1212
}
1313
sum

Diff for: src/test/ui/consts/const-fn-error.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0744]: `for` is not allowed in a `const fn`
1+
error[E0658]: `for` is not allowed in a `const fn`
22
--> $DIR/const-fn-error.rs:5:5
33
|
44
LL | / for i in 0..x {
@@ -9,6 +9,9 @@ LL | |
99
LL | | sum += i;
1010
LL | | }
1111
| |_____^
12+
|
13+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
14+
= help: add `#![feature(const_for)]` to the crate attributes to enable
1215

1316
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
1417
--> $DIR/const-fn-error.rs:5:14
@@ -45,5 +48,5 @@ LL | let a : [i32; f(X)];
4548

4649
error: aborting due to 5 previous errors
4750

48-
Some errors have detailed explanations: E0015, E0080, E0658, E0744.
51+
Some errors have detailed explanations: E0015, E0080, E0658.
4952
For more information about an error, try `rustc --explain E0015`.

Diff for: src/test/ui/consts/const-for-feature-gate.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// gate-test-const_for
2+
3+
const _: () = {
4+
for _ in 0..5 {}
5+
//~^ error: `for` is not allowed in a `const`
6+
};
7+
8+
fn main() {}

Diff for: src/test/ui/consts/const-for-feature-gate.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: `for` is not allowed in a `const`
2+
--> $DIR/const-for-feature-gate.rs:4:5
3+
|
4+
LL | for _ in 0..5 {}
5+
| ^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
8+
= help: add `#![feature(const_for)]` to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.

Diff for: src/test/ui/consts/const-for.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(const_for)]
2+
#![feature(const_mut_refs)]
3+
4+
const _: () = {
5+
for _ in 0..5 {}
6+
//~^ error: calls in constants are limited to
7+
//~| error: calls in constants are limited to
8+
};
9+
10+
fn main() {}

Diff for: src/test/ui/consts/const-for.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
2+
--> $DIR/const-for.rs:5:14
3+
|
4+
LL | for _ in 0..5 {}
5+
| ^^^^
6+
7+
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
8+
--> $DIR/const-for.rs:5:14
9+
|
10+
LL | for _ in 0..5 {}
11+
| ^^^^
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0015`.

Diff for: src/test/ui/consts/const-try-feature-gate.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// gate-test-const_try
2+
3+
const fn t() -> Option<()> {
4+
Some(())?;
5+
//~^ error: `?` is not allowed in a `const fn`
6+
None
7+
}
8+
9+
fn main() {}

Diff for: src/test/ui/consts/const-try-feature-gate.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: `?` is not allowed in a `const fn`
2+
--> $DIR/const-try-feature-gate.rs:4:5
3+
|
4+
LL | Some(())?;
5+
| ^^^^^^^^^
6+
|
7+
= note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
8+
= help: add `#![feature(const_try)]` to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.

Diff for: src/test/ui/consts/const-try.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// check-pass
2+
3+
// Demonstrates what's needed to make use of `?` in const contexts.
4+
5+
#![crate_type = "lib"]
6+
#![feature(try_trait_v2)]
7+
#![feature(const_trait_impl)]
8+
#![feature(const_try)]
9+
10+
use std::ops::{ControlFlow, FromResidual, Try};
11+
12+
struct TryMe;
13+
struct Error;
14+
15+
impl const FromResidual<Error> for TryMe {
16+
fn from_residual(residual: Error) -> Self {
17+
TryMe
18+
}
19+
}
20+
21+
impl const Try for TryMe {
22+
type Output = ();
23+
type Residual = Error;
24+
fn from_output(output: Self::Output) -> Self {
25+
TryMe
26+
}
27+
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
28+
ControlFlow::Break(Error)
29+
}
30+
}
31+
32+
const fn t() -> TryMe {
33+
TryMe?;
34+
TryMe
35+
}
36+
37+
const _: () = {
38+
t();
39+
};

Diff for: src/test/ui/consts/control-flow/loop.stderr

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
1-
error[E0744]: `for` is not allowed in a `const`
1+
error[E0658]: `for` is not allowed in a `const`
22
--> $DIR/loop.rs:53:5
33
|
44
LL | / for i in 0..4 {
55
LL | | x += i;
66
LL | | }
77
| |_____^
8+
|
9+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
10+
= help: add `#![feature(const_for)]` to the crate attributes to enable
811

9-
error[E0744]: `for` is not allowed in a `const`
12+
error[E0658]: `for` is not allowed in a `const`
1013
--> $DIR/loop.rs:57:5
1114
|
1215
LL | / for i in 0..4 {
1316
LL | | x += i;
1417
LL | | }
1518
| |_____^
19+
|
20+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
21+
= help: add `#![feature(const_for)]` to the crate attributes to enable
1622

1723
error: aborting due to 2 previous errors
1824

19-
For more information about this error, try `rustc --explain E0744`.
25+
For more information about this error, try `rustc --explain E0658`.

Diff for: src/test/ui/consts/control-flow/try.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
error[E0744]: `?` is not allowed in a `const fn`
1+
error[E0658]: `?` is not allowed in a `const fn`
22
--> $DIR/try.rs:6:5
33
|
44
LL | x?;
55
| ^^
6+
|
7+
= note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
8+
= help: add `#![feature(const_try)]` to the crate attributes to enable
69

710
error: aborting due to previous error
811

9-
For more information about this error, try `rustc --explain E0744`.
12+
For more information about this error, try `rustc --explain E0658`.

Diff for: src/test/ui/issues/issue-50582.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
error[E0744]: `for` is not allowed in a `const`
1+
error[E0658]: `for` is not allowed in a `const`
22
--> $DIR/issue-50582.rs:2:20
33
|
44
LL | Vec::<[(); 1 + for x in 0..1 {}]>::new();
55
| ^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
8+
= help: add `#![feature(const_for)]` to the crate attributes to enable
69

710
error[E0277]: cannot add `()` to `{integer}`
811
--> $DIR/issue-50582.rs:2:18
@@ -14,5 +17,5 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new();
1417

1518
error: aborting due to 2 previous errors
1619

17-
Some errors have detailed explanations: E0277, E0744.
20+
Some errors have detailed explanations: E0277, E0658.
1821
For more information about an error, try `rustc --explain E0277`.

Diff for: src/test/ui/issues/issue-50585.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
error[E0744]: `for` is not allowed in a `const`
1+
error[E0658]: `for` is not allowed in a `const`
22
--> $DIR/issue-50585.rs:2:18
33
|
44
LL | |y: Vec<[(); for x in 0..2 {}]>| {};
55
| ^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
8+
= help: add `#![feature(const_for)]` to the crate attributes to enable
69

710
error[E0308]: mismatched types
811
--> $DIR/issue-50585.rs:2:18
@@ -12,5 +15,5 @@ LL | |y: Vec<[(); for x in 0..2 {}]>| {};
1215

1316
error: aborting due to 2 previous errors
1417

15-
Some errors have detailed explanations: E0308, E0744.
18+
Some errors have detailed explanations: E0308, E0658.
1619
For more information about an error, try `rustc --explain E0308`.

Diff for: src/test/ui/never_type/issue-52443.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ LL | [(); {while true {break}; 0}];
66
|
77
= note: `#[warn(while_true)]` on by default
88

9-
error[E0744]: `for` is not allowed in a `const`
9+
error[E0658]: `for` is not allowed in a `const`
1010
--> $DIR/issue-52443.rs:9:12
1111
|
1212
LL | [(); { for _ in 0usize.. {}; 0}];
1313
| ^^^^^^^^^^^^^^^^^^^^
14+
|
15+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
16+
= help: add `#![feature(const_for)]` to the crate attributes to enable
1417

1518
error[E0308]: mismatched types
1619
--> $DIR/issue-52443.rs:2:10
@@ -56,5 +59,5 @@ LL | [(); { for _ in 0usize.. {}; 0}];
5659

5760
error: aborting due to 6 previous errors; 1 warning emitted
5861

59-
Some errors have detailed explanations: E0015, E0308, E0658, E0744.
62+
Some errors have detailed explanations: E0015, E0308, E0658.
6063
For more information about an error, try `rustc --explain E0015`.
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
error[E0744]: `?` is not allowed in a `const fn`
1+
error[E0658]: `?` is not allowed in a `const fn`
22
--> $DIR/hir-const-check.rs:11:9
33
|
44
LL | Some(())?;
55
| ^^^^^^^^^
6+
|
7+
= note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
8+
= help: add `#![feature(const_try)]` to the crate attributes to enable
69

710
error: aborting due to previous error
811

9-
For more information about this error, try `rustc --explain E0744`.
12+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)