Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature gates for for and ? in consts #87237

Merged
merged 5 commits into from
Jul 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 4 additions & 14 deletions compiler/rustc_error_codes/src/error_codes/E0744.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 6 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
// -------------------------------------------------------------------------
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_passes/src/check_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ symbols! {
const_fn_transmute,
const_fn_union,
const_fn_unsize,
const_for,
const_format_args,
const_generic_defaults,
const_generics,
Expand All @@ -432,6 +433,7 @@ symbols! {
const_trait_bound_opt_out,
const_trait_impl,
const_transmute,
const_try,
constant,
constructor,
contents,
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/consts/const-fn-error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/consts/const-fn-error.stderr
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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 changes: 8 additions & 0 deletions src/test/ui/consts/const-for-feature-gate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// gate-test-const_for

const _: () = {
for _ in 0..5 {}
//~^ error: `for` is not allowed in a `const`
};

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/consts/const-for-feature-gate.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 10 additions & 0 deletions src/test/ui/consts/const-for.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions src/test/ui/consts/const-for.stderr
Original file line number Diff line number Diff line change
@@ -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 {}
| ^^^^
Comment on lines +1 to +5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we should start printing the function's name in the diagnostic. Very uninformative this error XD


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 changes: 9 additions & 0 deletions src/test/ui/consts/const-try-feature-gate.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions src/test/ui/consts/const-try-feature-gate.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 39 additions & 0 deletions src/test/ui/consts/const-try.rs
Original file line number Diff line number Diff line change
@@ -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();
};
12 changes: 9 additions & 3 deletions src/test/ui/consts/control-flow/loop.stderr
Original file line number Diff line number Diff line change
@@ -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`.
7 changes: 5 additions & 2 deletions src/test/ui/consts/control-flow/try.stderr
Original file line number Diff line number Diff line change
@@ -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`.
7 changes: 5 additions & 2 deletions src/test/ui/issues/issue-50582.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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`.
7 changes: 5 additions & 2 deletions src/test/ui/issues/issue-50585.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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`.
7 changes: 5 additions & 2 deletions src/test/ui/never_type/issue-52443.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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`.
7 changes: 5 additions & 2 deletions src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr
Original file line number Diff line number Diff line change
@@ -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`.