Skip to content

Commit 6fc1714

Browse files
authored
Rollup merge of rust-lang#72437 - ecstatic-morse:stabilize-const-if-match, r=oli-obk
Stabilize `#![feature(const_if_match)]` Quoting from the [stabilization report](rust-lang#49146 (comment)): > `if` and `match` expressions as well as the short-circuiting logic operators `&&` and `||` will become legal in all [const contexts](https://doc.rust-lang.org/reference/const_eval.html#const-context). A const context is any of the following: > > - The initializer of a `const`, `static`, `static mut` or enum discriminant. > - The body of a `const fn`. > - The value of a const generic (nightly only). > - The length of an array type (`[u8; 3]`) or an array repeat expression (`[0u8; 3]`). > > Furthermore, the short-circuiting logic operators will no longer be lowered to their bitwise equivalents (`&` and `|` respectively) in `const` and `static` initializers (see rust-lang#57175). As a result, `let` bindings can be used alongside short-circuiting logic in those initializers. Resolves rust-lang#49146. Ideally, we would resolve 🐳 rust-lang#66753 before this lands on stable, so it might be worth pushing this back a release. Also, this means we should get the process started for rust-lang#52000, otherwise people will have no recourse except recursion for iterative `const fn`. r? @oli-obk
2 parents 394e1b4 + 63078c3 commit 6fc1714

File tree

129 files changed

+348
-1757
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+348
-1757
lines changed

src/doc/unstable-book/src/language-features/const-if-match.md

-14
This file was deleted.

src/liballoc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
#![feature(const_generic_impls_guard)]
8888
#![feature(const_generics)]
8989
#![feature(const_in_array_repeat_expressions)]
90-
#![feature(const_if_match)]
90+
#![cfg_attr(bootstrap, feature(const_if_match))]
9191
#![feature(cow_is_borrowed)]
9292
#![feature(dispatch_from_dyn)]
9393
#![feature(core_intrinsics)]

src/libcore/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@
7373
#![feature(const_ascii_ctype_on_intrinsics)]
7474
#![feature(const_alloc_layout)]
7575
#![feature(const_discriminant)]
76-
#![feature(const_if_match)]
77-
#![feature(const_loop)]
76+
#![cfg_attr(bootstrap, feature(const_if_match))]
77+
#![cfg_attr(bootstrap, feature(const_loop))]
7878
#![feature(const_checked_int_methods)]
7979
#![feature(const_euclidean_int_methods)]
8080
#![feature(const_overflowing_int_methods)]

src/libcore/num/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1578,7 +1578,7 @@ $EndFeature, "
15781578
#[stable(feature = "no_panic_abs", since = "1.13.0")]
15791579
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
15801580
#[allow(unused_attributes)]
1581-
#[allow_internal_unstable(const_if_match)]
1581+
#[cfg_attr(bootstrap, allow_internal_unstable(const_if_match))]
15821582
#[inline]
15831583
pub const fn wrapping_abs(self) -> Self {
15841584
if self.is_negative() {
@@ -1867,7 +1867,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($Self
18671867
#[stable(feature = "wrapping", since = "1.7.0")]
18681868
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
18691869
#[allow(unused_attributes)]
1870-
#[allow_internal_unstable(const_if_match)]
1870+
#[cfg_attr(bootstrap, allow_internal_unstable(const_if_match))]
18711871
pub const fn overflowing_neg(self) -> (Self, bool) {
18721872
if self == Self::MIN {
18731873
(Self::MIN, true)
@@ -2160,7 +2160,7 @@ $EndFeature, "
21602160
#[stable(feature = "rust1", since = "1.0.0")]
21612161
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
21622162
#[allow(unused_attributes)]
2163-
#[allow_internal_unstable(const_if_match)]
2163+
#[cfg_attr(bootstrap, allow_internal_unstable(const_if_match))]
21642164
#[inline]
21652165
#[rustc_inherit_overflow_checks]
21662166
pub const fn abs(self) -> Self {

src/librustc_ast/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
88
#![feature(bool_to_option)]
99
#![feature(box_syntax)]
10-
#![feature(const_if_match)]
10+
#![cfg_attr(bootstrap, feature(const_if_match))]
1111
#![feature(const_fn)] // For the `transmute` in `P::new`
1212
#![feature(const_panic)]
1313
#![feature(const_transmute)]

src/librustc_feature/accepted.rs

+4
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ declare_features! (
261261
(accepted, transparent_enums, "1.42.0", Some(60405), None),
262262
/// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`.
263263
(accepted, slice_patterns, "1.42.0", Some(62254), None),
264+
/// Allows the use of `if` and `match` in constants.
265+
(accepted, const_if_match, "1.45.0", Some(49146), None),
266+
/// Allows the use of `loop` and `while` in constants.
267+
(accepted, const_loop, "1.45.0", Some(52000), None),
264268

265269
// -------------------------------------------------------------------------
266270
// feature-group-end: accepted features

src/librustc_feature/active.rs

-6
Original file line numberDiff line numberDiff line change
@@ -518,9 +518,6 @@ declare_features! (
518518
/// Allows using the `#[register_tool]` attribute.
519519
(active, register_tool, "1.41.0", Some(66079), None),
520520

521-
/// Allows the use of `if` and `match` in constants.
522-
(active, const_if_match, "1.41.0", Some(49146), None),
523-
524521
/// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
525522
(active, cfg_sanitize, "1.41.0", Some(39699), None),
526523

@@ -530,9 +527,6 @@ declare_features! (
530527
/// Allows using `&mut` in constant functions.
531528
(active, const_mut_refs, "1.41.0", Some(57349), None),
532529

533-
/// Allows the use of `loop` and `while` in constants.
534-
(active, const_loop, "1.41.0", Some(52000), None),
535-
536530
/// Allows bindings in the subpattern of a binding pattern.
537531
/// For example, you can write `x @ Some(y)`.
538532
(active, bindings_after_at, "1.41.0", Some(65490), None),

src/librustc_hir/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
44
55
#![feature(crate_visibility_modifier)]
6-
#![feature(const_if_match)]
6+
#![cfg_attr(bootstrap, feature(const_if_match))]
77
#![feature(const_fn)] // For the unsizing cast on `&[]`
88
#![feature(const_panic)]
99
#![feature(in_band_lifetimes)]

src/librustc_index/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![feature(allow_internal_unstable)]
2-
#![feature(const_if_match)]
2+
#![cfg_attr(bootstrap, feature(const_if_match))]
33
#![feature(const_fn)]
44
#![feature(const_panic)]
55
#![feature(extend_one)]

src/librustc_infer/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#![feature(box_patterns)]
1818
#![feature(box_syntax)]
1919
#![feature(const_fn)]
20-
#![feature(const_if_match)]
20+
#![cfg_attr(bootstrap, feature(const_if_match))]
2121
#![feature(const_panic)]
2222
#![feature(extend_one)]
2323
#![feature(never_type)]

src/librustc_middle/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#![feature(bool_to_option)]
2828
#![feature(box_patterns)]
2929
#![feature(box_syntax)]
30-
#![feature(const_if_match)]
30+
#![cfg_attr(bootstrap, feature(const_if_match))]
3131
#![feature(const_fn)]
3232
#![feature(const_panic)]
3333
#![feature(const_transmute)]

src/librustc_middle/mir/mod.rs

-13
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
//!
33
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
44
5-
// ignore-tidy-filelength
6-
75
use crate::mir::interpret::{GlobalAlloc, Scalar};
86
use crate::mir::visit::MirVisitable;
97
use crate::ty::adjustment::PointerCast;
@@ -148,14 +146,6 @@ pub struct Body<'tcx> {
148146
/// Debug information pertaining to user variables, including captures.
149147
pub var_debug_info: Vec<VarDebugInfo<'tcx>>,
150148

151-
/// Mark this MIR of a const context other than const functions as having converted a `&&` or
152-
/// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
153-
/// this conversion from happening and use short circuiting, we will cause the following code
154-
/// to change the value of `x`: `let mut x = 42; false && { x = 55; true };`
155-
///
156-
/// List of places where control flow was destroyed. Used for error reporting.
157-
pub control_flow_destroyed: Vec<(Span, String)>,
158-
159149
/// A span representing this MIR, for error reporting.
160150
pub span: Span,
161151

@@ -185,7 +175,6 @@ impl<'tcx> Body<'tcx> {
185175
arg_count: usize,
186176
var_debug_info: Vec<VarDebugInfo<'tcx>>,
187177
span: Span,
188-
control_flow_destroyed: Vec<(Span, String)>,
189178
generator_kind: Option<GeneratorKind>,
190179
) -> Self {
191180
// We need `arg_count` locals, and one for the return place.
@@ -212,7 +201,6 @@ impl<'tcx> Body<'tcx> {
212201
span,
213202
required_consts: Vec::new(),
214203
ignore_interior_mut_in_const_validation: false,
215-
control_flow_destroyed,
216204
predecessor_cache: PredecessorCache::new(),
217205
}
218206
}
@@ -236,7 +224,6 @@ impl<'tcx> Body<'tcx> {
236224
spread_arg: None,
237225
span: DUMMY_SP,
238226
required_consts: Vec::new(),
239-
control_flow_destroyed: Vec::new(),
240227
generator_kind: None,
241228
var_debug_info: Vec::new(),
242229
ignore_interior_mut_in_const_validation: false,

src/librustc_mir/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ Rust MIR: a lowered representation of Rust.
1010
#![feature(box_patterns)]
1111
#![feature(box_syntax)]
1212
#![feature(const_fn)]
13-
#![feature(const_if_match)]
14-
#![feature(const_loop)]
13+
#![cfg_attr(bootstrap, feature(const_if_match))]
14+
#![cfg_attr(bootstrap, feature(const_loop))]
1515
#![feature(const_panic)]
1616
#![feature(crate_visibility_modifier)]
1717
#![feature(decl_macro)]

src/librustc_mir/shim.rs

-1
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,6 @@ fn new_body<'tcx>(
251251
arg_count,
252252
vec![],
253253
span,
254-
vec![],
255254
None,
256255
)
257256
}

src/librustc_mir/transform/check_consts/ops.rs

-26
Original file line numberDiff line numberDiff line change
@@ -142,19 +142,6 @@ impl NonConstOp for HeapAllocation {
142142
}
143143
}
144144

145-
#[derive(Debug)]
146-
pub struct IfOrMatch;
147-
impl NonConstOp for IfOrMatch {
148-
fn feature_gate() -> Option<Symbol> {
149-
Some(sym::const_if_match)
150-
}
151-
152-
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
153-
// This should be caught by the HIR const-checker.
154-
ccx.tcx.sess.delay_span_bug(span, "complex control flow is forbidden in a const context");
155-
}
156-
}
157-
158145
#[derive(Debug)]
159146
pub struct InlineAsm;
160147
impl NonConstOp for InlineAsm {}
@@ -177,19 +164,6 @@ impl NonConstOp for LiveDrop {
177164
}
178165
}
179166

180-
#[derive(Debug)]
181-
pub struct Loop;
182-
impl NonConstOp for Loop {
183-
fn feature_gate() -> Option<Symbol> {
184-
Some(sym::const_loop)
185-
}
186-
187-
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
188-
// This should be caught by the HIR const-checker.
189-
ccx.tcx.sess.delay_span_bug(span, "complex control flow is forbidden in a const context");
190-
}
191-
}
192-
193167
#[derive(Debug)]
194168
pub struct CellBorrow;
195169
impl NonConstOp for CellBorrow {

src/librustc_mir/transform/check_consts/validation.rs

+1-56
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,6 @@ impl Validator<'mir, 'tcx> {
207207
}
208208
}
209209

210-
check_short_circuiting_in_const_local(self.ccx);
211-
212-
if body.is_cfg_cyclic() {
213-
// We can't provide a good span for the error here, but this should be caught by the
214-
// HIR const-checker anyways.
215-
self.check_op_spanned(ops::Loop, body.span);
216-
}
217-
218210
self.visit_body(&body);
219211

220212
// Ensure that the end result is `Sync` in a non-thread local `static`.
@@ -483,21 +475,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
483475
self.super_statement(statement, location);
484476
}
485477

486-
StatementKind::FakeRead(
487-
FakeReadCause::ForMatchedPlace
488-
| FakeReadCause::ForMatchGuard
489-
| FakeReadCause::ForGuardBinding,
490-
_,
491-
) => {
492-
self.super_statement(statement, location);
493-
self.check_op(ops::IfOrMatch);
494-
}
495478
StatementKind::LlvmInlineAsm { .. } => {
496479
self.super_statement(statement, location);
497480
self.check_op(ops::InlineAsm);
498481
}
499482

500-
StatementKind::FakeRead(FakeReadCause::ForLet | FakeReadCause::ForIndex, _)
483+
StatementKind::FakeRead(..)
501484
| StatementKind::StorageLive(_)
502485
| StatementKind::StorageDead(_)
503486
| StatementKind::Retag { .. }
@@ -626,44 +609,6 @@ fn error_min_const_fn_violation(tcx: TyCtxt<'_>, span: Span, msg: Cow<'_, str>)
626609
.emit();
627610
}
628611

629-
fn check_short_circuiting_in_const_local(ccx: &ConstCx<'_, 'tcx>) {
630-
let body = ccx.body;
631-
632-
if body.control_flow_destroyed.is_empty() {
633-
return;
634-
}
635-
636-
let mut locals = body.vars_iter();
637-
if let Some(local) = locals.next() {
638-
let span = body.local_decls[local].source_info.span;
639-
let mut error = ccx.tcx.sess.struct_span_err(
640-
span,
641-
&format!(
642-
"new features like let bindings are not permitted in {}s \
643-
which also use short circuiting operators",
644-
ccx.const_kind(),
645-
),
646-
);
647-
for (span, kind) in body.control_flow_destroyed.iter() {
648-
error.span_note(
649-
*span,
650-
&format!(
651-
"use of {} here does not actually short circuit due to \
652-
the const evaluator presently not being able to do control flow. \
653-
See issue #49146 <https://github.com/rust-lang/rust/issues/49146> \
654-
for more information.",
655-
kind
656-
),
657-
);
658-
}
659-
for local in locals {
660-
let span = body.local_decls[local].source_info.span;
661-
error.span_note(span, "more locals are defined here");
662-
}
663-
error.emit();
664-
}
665-
}
666-
667612
fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId) {
668613
let ty = body.return_ty();
669614
tcx.infer_ctxt().enter(|infcx| {

src/librustc_mir/transform/const_prop.rs

-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
133133
body.arg_count,
134134
Default::default(),
135135
tcx.def_span(source.def_id()),
136-
Default::default(),
137136
body.generator_kind,
138137
);
139138

src/librustc_mir/transform/promote_consts.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,6 @@ pub fn promote_candidates<'tcx>(
11421142
0,
11431143
vec![],
11441144
body.span,
1145-
vec![],
11461145
body.generator_kind,
11471146
);
11481147
promoted.ignore_interior_mut_in_const_validation = true;

src/librustc_mir/transform/qualify_min_const_fn.rs

-10
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,6 @@ fn check_statement(
239239
check_rvalue(tcx, body, def_id, rval, span)
240240
}
241241

242-
StatementKind::FakeRead(FakeReadCause::ForMatchedPlace, _)
243-
if !feature_allowed(tcx, def_id, sym::const_if_match) =>
244-
{
245-
Err((span, "loops and conditional expressions are not stable in const fn".into()))
246-
}
247-
248242
StatementKind::FakeRead(_, place) => check_place(tcx, **place, span, def_id, body),
249243

250244
// just an assignment
@@ -355,10 +349,6 @@ fn check_terminator(
355349
check_operand(tcx, value, span, def_id, body)
356350
}
357351

358-
TerminatorKind::SwitchInt { .. } if !feature_allowed(tcx, def_id, sym::const_if_match) => {
359-
Err((span, "loops and conditional expressions are not stable in const fn".into()))
360-
}
361-
362352
TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => {
363353
check_operand(tcx, discr, span, def_id, body)
364354
}

src/librustc_mir_build/build/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
778778
self.arg_count,
779779
self.var_debug_info,
780780
self.fn_span,
781-
self.hir.control_flow_destroyed(),
782781
self.generator_kind,
783782
)
784783
}

src/librustc_mir_build/hair/cx/expr.rs

-14
Original file line numberDiff line numberDiff line change
@@ -255,20 +255,6 @@ fn make_mirror_unadjusted<'a, 'tcx>(
255255
} else {
256256
// FIXME overflow
257257
match (op.node, cx.constness) {
258-
// Destroy control flow if `#![feature(const_if_match)]` is not enabled.
259-
(hir::BinOpKind::And, hir::Constness::Const)
260-
if !cx.tcx.features().const_if_match =>
261-
{
262-
cx.control_flow_destroyed.push((op.span, "`&&` operator".into()));
263-
ExprKind::Binary { op: BinOp::BitAnd, lhs: lhs.to_ref(), rhs: rhs.to_ref() }
264-
}
265-
(hir::BinOpKind::Or, hir::Constness::Const)
266-
if !cx.tcx.features().const_if_match =>
267-
{
268-
cx.control_flow_destroyed.push((op.span, "`||` operator".into()));
269-
ExprKind::Binary { op: BinOp::BitOr, lhs: lhs.to_ref(), rhs: rhs.to_ref() }
270-
}
271-
272258
(hir::BinOpKind::And, _) => ExprKind::LogicalOp {
273259
op: LogicalOp::And,
274260
lhs: lhs.to_ref(),

0 commit comments

Comments
 (0)