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)
This commit is contained in:
commit
87dc824248
19 changed files with 162 additions and 34 deletions
|
@ -2,25 +2,15 @@ An unsupported expression was used inside a const context.
|
|||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0744
|
||||
```compile_fail,edition2018,E0744
|
||||
const _: i32 = {
|
||||
let mut x = 0;
|
||||
|
||||
for i in 0..4 { // error!
|
||||
x += i;
|
||||
}
|
||||
async { 0 }.await
|
||||
};
|
||||
```
|
||||
|
||||
At the moment, `for` loops, `.await`, and the `Try` operator (`?`) are forbidden
|
||||
inside a `const`, `static`, or `const fn`.
|
||||
At the moment, `.await` is forbidden inside a `const`, `static`, or `const fn`.
|
||||
|
||||
This may be allowed at some point in the future, but the implementation is not
|
||||
yet complete. See the tracking issues for [`async`] and [`?`] in `const fn`, and
|
||||
(to support `for` loops in `const fn`) the tracking issues for [`impl const
|
||||
Trait for Ty`] and [`&mut T`] in `const fn`.
|
||||
yet complete. See the tracking issue for [`async`] in `const fn`.
|
||||
|
||||
[`async`]: https://github.com/rust-lang/rust/issues/69431
|
||||
[`?`]: https://github.com/rust-lang/rust/issues/74935
|
||||
[`impl const Trait for Ty`]: https://github.com/rust-lang/rust/issues/67792
|
||||
[`&mut T`]: https://github.com/rust-lang/rust/issues/57349
|
||||
|
|
|
@ -677,6 +677,12 @@ declare_features! (
|
|||
/// Allows `#[derive(Default)]` and `#[default]` on enums.
|
||||
(active, derive_default_enum, "1.56.0", Some(86985), None),
|
||||
|
||||
/// Allows `for _ in _` loops in const contexts.
|
||||
(active, const_for, "1.56.0", Some(87575), None),
|
||||
|
||||
/// Allows the `?` operator in const contexts.
|
||||
(active, const_try, "1.56.0", Some(74935), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// feature-group-end: actual feature gates
|
||||
// -------------------------------------------------------------------------
|
||||
|
|
|
@ -40,13 +40,14 @@ impl NonConstExpr {
|
|||
use hir::MatchSource::*;
|
||||
|
||||
let gates: &[_] = match self {
|
||||
// A `for` loop's desugaring contains a call to `IntoIterator::into_iter`,
|
||||
// so they are not yet allowed.
|
||||
// Likewise, `?` desugars to a call to `Try::into_result`.
|
||||
Self::Loop(ForLoop) | Self::Match(ForLoopDesugar | TryDesugar | AwaitDesugar) => {
|
||||
Self::Match(AwaitDesugar) => {
|
||||
return None;
|
||||
}
|
||||
|
||||
Self::Loop(ForLoop) | Self::Match(ForLoopDesugar) => &[sym::const_for],
|
||||
|
||||
Self::Match(TryDesugar) => &[sym::const_try],
|
||||
|
||||
Self::Match(IfLetGuardDesugar) => bug!("`if let` guard outside a `match` expression"),
|
||||
|
||||
// All other expressions are allowed.
|
||||
|
|
|
@ -410,6 +410,7 @@ symbols! {
|
|||
const_fn_transmute,
|
||||
const_fn_union,
|
||||
const_fn_unsize,
|
||||
const_for,
|
||||
const_format_args,
|
||||
const_generic_defaults,
|
||||
const_generics,
|
||||
|
@ -432,6 +433,7 @@ symbols! {
|
|||
const_trait_bound_opt_out,
|
||||
const_trait_impl,
|
||||
const_transmute,
|
||||
const_try,
|
||||
constant,
|
||||
constructor,
|
||||
contents,
|
||||
|
|
|
@ -7,7 +7,7 @@ const fn f(x: usize) -> usize {
|
|||
//~| ERROR calls in constant functions
|
||||
//~| ERROR calls in constant functions
|
||||
//~| ERROR E0080
|
||||
//~| ERROR E0744
|
||||
//~| ERROR `for` is not allowed in a `const fn`
|
||||
sum += i;
|
||||
}
|
||||
sum
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0744]: `for` is not allowed in a `const fn`
|
||||
error[E0658]: `for` is not allowed in a `const fn`
|
||||
--> $DIR/const-fn-error.rs:5:5
|
||||
|
|
||||
LL | / for i in 0..x {
|
||||
|
@ -9,6 +9,9 @@ LL | |
|
|||
LL | | sum += i;
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
|
||||
= help: add `#![feature(const_for)]` to the crate attributes to enable
|
||||
|
||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
--> $DIR/const-fn-error.rs:5:14
|
||||
|
@ -45,5 +48,5 @@ LL | let a : [i32; f(X)];
|
|||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0015, E0080, E0658, E0744.
|
||||
Some errors have detailed explanations: E0015, E0080, E0658.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
|
|
8
src/test/ui/consts/const-for-feature-gate.rs
Normal file
8
src/test/ui/consts/const-for-feature-gate.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
// gate-test-const_for
|
||||
|
||||
const _: () = {
|
||||
for _ in 0..5 {}
|
||||
//~^ error: `for` is not allowed in a `const`
|
||||
};
|
||||
|
||||
fn main() {}
|
12
src/test/ui/consts/const-for-feature-gate.stderr
Normal file
12
src/test/ui/consts/const-for-feature-gate.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0658]: `for` is not allowed in a `const`
|
||||
--> $DIR/const-for-feature-gate.rs:4:5
|
||||
|
|
||||
LL | for _ in 0..5 {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
|
||||
= help: add `#![feature(const_for)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
10
src/test/ui/consts/const-for.rs
Normal file
10
src/test/ui/consts/const-for.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
#![feature(const_for)]
|
||||
#![feature(const_mut_refs)]
|
||||
|
||||
const _: () = {
|
||||
for _ in 0..5 {}
|
||||
//~^ error: calls in constants are limited to
|
||||
//~| error: calls in constants are limited to
|
||||
};
|
||||
|
||||
fn main() {}
|
15
src/test/ui/consts/const-for.stderr
Normal file
15
src/test/ui/consts/const-for.stderr
Normal file
|
@ -0,0 +1,15 @@
|
|||
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||
--> $DIR/const-for.rs:5:14
|
||||
|
|
||||
LL | for _ in 0..5 {}
|
||||
| ^^^^
|
||||
|
||||
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||
--> $DIR/const-for.rs:5:14
|
||||
|
|
||||
LL | for _ in 0..5 {}
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0015`.
|
9
src/test/ui/consts/const-try-feature-gate.rs
Normal file
9
src/test/ui/consts/const-try-feature-gate.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
// gate-test-const_try
|
||||
|
||||
const fn t() -> Option<()> {
|
||||
Some(())?;
|
||||
//~^ error: `?` is not allowed in a `const fn`
|
||||
None
|
||||
}
|
||||
|
||||
fn main() {}
|
12
src/test/ui/consts/const-try-feature-gate.stderr
Normal file
12
src/test/ui/consts/const-try-feature-gate.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0658]: `?` is not allowed in a `const fn`
|
||||
--> $DIR/const-try-feature-gate.rs:4:5
|
||||
|
|
||||
LL | Some(())?;
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
|
||||
= help: add `#![feature(const_try)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
39
src/test/ui/consts/const-try.rs
Normal file
39
src/test/ui/consts/const-try.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
// check-pass
|
||||
|
||||
// Demonstrates what's needed to make use of `?` in const contexts.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_try)]
|
||||
|
||||
use std::ops::{ControlFlow, FromResidual, Try};
|
||||
|
||||
struct TryMe;
|
||||
struct Error;
|
||||
|
||||
impl const FromResidual<Error> for TryMe {
|
||||
fn from_residual(residual: Error) -> Self {
|
||||
TryMe
|
||||
}
|
||||
}
|
||||
|
||||
impl const Try for TryMe {
|
||||
type Output = ();
|
||||
type Residual = Error;
|
||||
fn from_output(output: Self::Output) -> Self {
|
||||
TryMe
|
||||
}
|
||||
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
||||
ControlFlow::Break(Error)
|
||||
}
|
||||
}
|
||||
|
||||
const fn t() -> TryMe {
|
||||
TryMe?;
|
||||
TryMe
|
||||
}
|
||||
|
||||
const _: () = {
|
||||
t();
|
||||
};
|
|
@ -1,19 +1,25 @@
|
|||
error[E0744]: `for` is not allowed in a `const`
|
||||
error[E0658]: `for` is not allowed in a `const`
|
||||
--> $DIR/loop.rs:53:5
|
||||
|
|
||||
LL | / for i in 0..4 {
|
||||
LL | | x += i;
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
|
||||
= help: add `#![feature(const_for)]` to the crate attributes to enable
|
||||
|
||||
error[E0744]: `for` is not allowed in a `const`
|
||||
error[E0658]: `for` is not allowed in a `const`
|
||||
--> $DIR/loop.rs:57:5
|
||||
|
|
||||
LL | / for i in 0..4 {
|
||||
LL | | x += i;
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
|
||||
= help: add `#![feature(const_for)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0744`.
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
error[E0744]: `?` is not allowed in a `const fn`
|
||||
error[E0658]: `?` is not allowed in a `const fn`
|
||||
--> $DIR/try.rs:6:5
|
||||
|
|
||||
LL | x?;
|
||||
| ^^
|
||||
|
|
||||
= note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
|
||||
= help: add `#![feature(const_try)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0744`.
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
error[E0744]: `for` is not allowed in a `const`
|
||||
error[E0658]: `for` is not allowed in a `const`
|
||||
--> $DIR/issue-50582.rs:2:20
|
||||
|
|
||||
LL | Vec::<[(); 1 + for x in 0..1 {}]>::new();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
|
||||
= help: add `#![feature(const_for)]` to the crate attributes to enable
|
||||
|
||||
error[E0277]: cannot add `()` to `{integer}`
|
||||
--> $DIR/issue-50582.rs:2:18
|
||||
|
@ -14,5 +17,5 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new();
|
|||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0744.
|
||||
Some errors have detailed explanations: E0277, E0658.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
error[E0744]: `for` is not allowed in a `const`
|
||||
error[E0658]: `for` is not allowed in a `const`
|
||||
--> $DIR/issue-50585.rs:2:18
|
||||
|
|
||||
LL | |y: Vec<[(); for x in 0..2 {}]>| {};
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
|
||||
= help: add `#![feature(const_for)]` to the crate attributes to enable
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-50585.rs:2:18
|
||||
|
@ -12,5 +15,5 @@ LL | |y: Vec<[(); for x in 0..2 {}]>| {};
|
|||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0744.
|
||||
Some errors have detailed explanations: E0308, E0658.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -6,11 +6,14 @@ LL | [(); {while true {break}; 0}];
|
|||
|
|
||||
= note: `#[warn(while_true)]` on by default
|
||||
|
||||
error[E0744]: `for` is not allowed in a `const`
|
||||
error[E0658]: `for` is not allowed in a `const`
|
||||
--> $DIR/issue-52443.rs:9:12
|
||||
|
|
||||
LL | [(); { for _ in 0usize.. {}; 0}];
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
|
||||
= help: add `#![feature(const_for)]` to the crate attributes to enable
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-52443.rs:2:10
|
||||
|
@ -56,5 +59,5 @@ LL | [(); { for _ in 0usize.. {}; 0}];
|
|||
|
||||
error: aborting due to 6 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0015, E0308, E0658, E0744.
|
||||
Some errors have detailed explanations: E0015, E0308, E0658.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
error[E0744]: `?` is not allowed in a `const fn`
|
||||
error[E0658]: `?` is not allowed in a `const fn`
|
||||
--> $DIR/hir-const-check.rs:11:9
|
||||
|
|
||||
LL | Some(())?;
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #74935 <https://github.com/rust-lang/rust/issues/74935> for more information
|
||||
= help: add `#![feature(const_try)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0744`.
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
Loading…
Add table
Reference in a new issue