diff --git a/compiler/rustc_error_codes/src/error_codes/E0744.md b/compiler/rustc_error_codes/src/error_codes/E0744.md index 45804ab266e28..9a8ef3b840dff 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0744.md +++ b/compiler/rustc_error_codes/src/error_codes/E0744.md @@ -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 diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index bf99d2988178d..1ec9a0518b809 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -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 // ------------------------------------------------------------------------- diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 6ee54cfe37f30..f6a93f5e02d5f 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -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. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 114750d9b7b3a..295e53aba3542 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -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, diff --git a/src/test/ui/consts/const-fn-error.rs b/src/test/ui/consts/const-fn-error.rs index b9c5a0e040ddc..948c162e8946d 100644 --- a/src/test/ui/consts/const-fn-error.rs +++ b/src/test/ui/consts/const-fn-error.rs @@ -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 diff --git a/src/test/ui/consts/const-fn-error.stderr b/src/test/ui/consts/const-fn-error.stderr index f5e69bba4c5b7..df24585e5551a 100644 --- a/src/test/ui/consts/const-fn-error.stderr +++ b/src/test/ui/consts/const-fn-error.stderr @@ -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 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`. diff --git a/src/test/ui/consts/const-for-feature-gate.rs b/src/test/ui/consts/const-for-feature-gate.rs new file mode 100644 index 0000000000000..bec7b80890536 --- /dev/null +++ b/src/test/ui/consts/const-for-feature-gate.rs @@ -0,0 +1,8 @@ +// gate-test-const_for + +const _: () = { + for _ in 0..5 {} + //~^ error: `for` is not allowed in a `const` +}; + +fn main() {} diff --git a/src/test/ui/consts/const-for-feature-gate.stderr b/src/test/ui/consts/const-for-feature-gate.stderr new file mode 100644 index 0000000000000..2ea377e09f61e --- /dev/null +++ b/src/test/ui/consts/const-for-feature-gate.stderr @@ -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 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`. diff --git a/src/test/ui/consts/const-for.rs b/src/test/ui/consts/const-for.rs new file mode 100644 index 0000000000000..5fc1ee0e36948 --- /dev/null +++ b/src/test/ui/consts/const-for.rs @@ -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() {} diff --git a/src/test/ui/consts/const-for.stderr b/src/test/ui/consts/const-for.stderr new file mode 100644 index 0000000000000..a35c04b3570b2 --- /dev/null +++ b/src/test/ui/consts/const-for.stderr @@ -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`. diff --git a/src/test/ui/consts/const-try-feature-gate.rs b/src/test/ui/consts/const-try-feature-gate.rs new file mode 100644 index 0000000000000..0839c23a0b99b --- /dev/null +++ b/src/test/ui/consts/const-try-feature-gate.rs @@ -0,0 +1,9 @@ +// gate-test-const_try + +const fn t() -> Option<()> { + Some(())?; + //~^ error: `?` is not allowed in a `const fn` + None +} + +fn main() {} diff --git a/src/test/ui/consts/const-try-feature-gate.stderr b/src/test/ui/consts/const-try-feature-gate.stderr new file mode 100644 index 0000000000000..cd1a063043207 --- /dev/null +++ b/src/test/ui/consts/const-try-feature-gate.stderr @@ -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 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`. diff --git a/src/test/ui/consts/const-try.rs b/src/test/ui/consts/const-try.rs new file mode 100644 index 0000000000000..e199fd9ff8a1a --- /dev/null +++ b/src/test/ui/consts/const-try.rs @@ -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 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 { + ControlFlow::Break(Error) + } +} + +const fn t() -> TryMe { + TryMe?; + TryMe +} + +const _: () = { + t(); +}; diff --git a/src/test/ui/consts/control-flow/loop.stderr b/src/test/ui/consts/control-flow/loop.stderr index 7b99fa4fe4609..5f6ad8c105d74 100644 --- a/src/test/ui/consts/control-flow/loop.stderr +++ b/src/test/ui/consts/control-flow/loop.stderr @@ -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 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 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`. diff --git a/src/test/ui/consts/control-flow/try.stderr b/src/test/ui/consts/control-flow/try.stderr index 35075a3e60b98..5aeec8fbf8665 100644 --- a/src/test/ui/consts/control-flow/try.stderr +++ b/src/test/ui/consts/control-flow/try.stderr @@ -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 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`. diff --git a/src/test/ui/issues/issue-50582.stderr b/src/test/ui/issues/issue-50582.stderr index 4f531460e69e2..465fb9baac3f0 100644 --- a/src/test/ui/issues/issue-50582.stderr +++ b/src/test/ui/issues/issue-50582.stderr @@ -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 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`. diff --git a/src/test/ui/issues/issue-50585.stderr b/src/test/ui/issues/issue-50585.stderr index c2630b664b55f..e43cc20cbb57d 100644 --- a/src/test/ui/issues/issue-50585.stderr +++ b/src/test/ui/issues/issue-50585.stderr @@ -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 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`. diff --git a/src/test/ui/never_type/issue-52443.stderr b/src/test/ui/never_type/issue-52443.stderr index 1683841e9d781..26ab5f43a27b8 100644 --- a/src/test/ui/never_type/issue-52443.stderr +++ b/src/test/ui/never_type/issue-52443.stderr @@ -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 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`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr index 3ec329cba1eb2..32df63e449d4a 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr @@ -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 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`.