Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit dbd1269

Browse files
Add feature gates for for and ? in consts
1 parent a985d8e commit dbd1269

File tree

8 files changed

+91
-4
lines changed

8 files changed

+91
-4
lines changed

compiler/rustc_feature/src/active.rs

Lines changed: 6 additions & 0 deletions
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.55.0", None, None),
682+
683+
/// Allows the `?` operator in const contexts.
684+
(active, const_try, "1.55.0", None, None),
685+
680686
// -------------------------------------------------------------------------
681687
// feature-group-end: actual feature gates
682688
// -------------------------------------------------------------------------

compiler/rustc_passes/src/check_const.rs

Lines changed: 5 additions & 4 deletions
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.

compiler/rustc_span/src/symbol.rs

Lines changed: 2 additions & 0 deletions
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,
Lines changed: 8 additions & 0 deletions
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() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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+
= help: add `#![feature(const_for)]` to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0658`.
Lines changed: 9 additions & 0 deletions
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() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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+
= help: add `#![feature(const_try)]` to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/consts/const-try.rs

Lines changed: 39 additions & 0 deletions
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+
};

0 commit comments

Comments
 (0)