Skip to content

MIR-build: No longer emit assumes in enum-as casting #144389

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

Merged
merged 1 commit into from
Jul 24, 2025
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
80 changes: 2 additions & 78 deletions compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! See docs in `build/expr/mod.rs`.

use rustc_abi::{BackendRepr, FieldIdx, Primitive};
use rustc_abi::FieldIdx;
use rustc_hir::lang_items::LangItem;
use rustc_index::{Idx, IndexVec};
use rustc_middle::bug;
Expand All @@ -9,7 +9,6 @@ use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty::cast::{CastTy, mir_cast_kind};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, Ty, UpvarArgs};
use rustc_span::source_map::Spanned;
Expand Down Expand Up @@ -200,89 +199,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
{
let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
let layout =
this.tcx.layout_of(this.typing_env().as_query_input(source_expr.ty));
let discr = this.temp(discr_ty, source_expr.span);
this.cfg.push_assign(
block,
source_info,
discr,
Rvalue::Discriminant(temp.into()),
);
let (op, ty) = (Operand::Move(discr), discr_ty);

if let BackendRepr::Scalar(scalar) = layout.unwrap().backend_repr
&& !scalar.is_always_valid(&this.tcx)
&& let Primitive::Int(int_width, _signed) = scalar.primitive()
{
let unsigned_ty = int_width.to_ty(this.tcx, false);
let unsigned_place = this.temp(unsigned_ty, expr_span);
this.cfg.push_assign(
block,
source_info,
unsigned_place,
Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr), unsigned_ty),
);

let bool_ty = this.tcx.types.bool;
let range = scalar.valid_range(&this.tcx);
let merge_op =
if range.start <= range.end { BinOp::BitAnd } else { BinOp::BitOr };

let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> {
// We can use `ty::TypingEnv::fully_monomorphized()` here
// as we only need it to compute the layout of a primitive.
let range_val = Const::from_bits(
this.tcx,
range,
ty::TypingEnv::fully_monomorphized(),
unsigned_ty,
);
let lit_op = this.literal_operand(expr.span, range_val);
let is_bin_op = this.temp(bool_ty, expr_span);
this.cfg.push_assign(
block,
source_info,
is_bin_op,
Rvalue::BinaryOp(
bin_op,
Box::new((Operand::Copy(unsigned_place), lit_op)),
),
);
is_bin_op
};
let assert_place = if range.start == 0 {
comparer(range.end, BinOp::Le)
} else {
let start_place = comparer(range.start, BinOp::Ge);
let end_place = comparer(range.end, BinOp::Le);
let merge_place = this.temp(bool_ty, expr_span);
this.cfg.push_assign(
block,
source_info,
merge_place,
Rvalue::BinaryOp(
merge_op,
Box::new((
Operand::Move(start_place),
Operand::Move(end_place),
)),
),
);
merge_place
};
this.cfg.push(
block,
Statement::new(
source_info,
StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
Operand::Move(assert_place),
))),
),
);
}

(op, ty)
(Operand::Move(discr), discr_ty)
} else {
let ty = source_expr.ty;
let source = unpack!(
Expand Down
10 changes: 0 additions & 10 deletions tests/crashes/121097.rs

This file was deleted.

5 changes: 0 additions & 5 deletions tests/mir-opt/building/enum_cast.bar.built.after.mir
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@ fn bar(_1: Bar) -> usize {
let mut _0: usize;
let _2: Bar;
let mut _3: isize;
let mut _4: u8;
let mut _5: bool;

bb0: {
StorageLive(_2);
_2 = move _1;
_3 = discriminant(_2);
_4 = copy _3 as u8 (IntToInt);
_5 = Le(copy _4, const 1_u8);
assume(move _5);
_0 = move _3 as usize (IntToInt);
StorageDead(_2);
return;
Expand Down
5 changes: 0 additions & 5 deletions tests/mir-opt/building/enum_cast.boo.built.after.mir
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@ fn boo(_1: Boo) -> usize {
let mut _0: usize;
let _2: Boo;
let mut _3: u8;
let mut _4: u8;
let mut _5: bool;

bb0: {
StorageLive(_2);
_2 = move _1;
_3 = discriminant(_2);
_4 = copy _3 as u8 (IntToInt);
_5 = Le(copy _4, const 1_u8);
assume(move _5);
_0 = move _3 as usize (IntToInt);
StorageDead(_2);
return;
Expand Down
5 changes: 0 additions & 5 deletions tests/mir-opt/building/enum_cast.far.built.after.mir
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@ fn far(_1: Far) -> isize {
let mut _0: isize;
let _2: Far;
let mut _3: i16;
let mut _4: u16;
let mut _5: bool;

bb0: {
StorageLive(_2);
_2 = move _1;
_3 = discriminant(_2);
_4 = copy _3 as u16 (IntToInt);
_5 = Le(copy _4, const 1_u16);
assume(move _5);
_0 = move _3 as isize (IntToInt);
StorageDead(_2);
return;
Expand Down
9 changes: 0 additions & 9 deletions tests/mir-opt/building/enum_cast.offsetty.built.after.mir
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,11 @@ fn offsetty(_1: NotStartingAtZero) -> u32 {
let mut _0: u32;
let _2: NotStartingAtZero;
let mut _3: isize;
let mut _4: u8;
let mut _5: bool;
let mut _6: bool;
let mut _7: bool;

bb0: {
StorageLive(_2);
_2 = move _1;
_3 = discriminant(_2);
_4 = copy _3 as u8 (IntToInt);
_5 = Ge(copy _4, const 4_u8);
_6 = Le(copy _4, const 8_u8);
_7 = BitAnd(move _5, move _6);
assume(move _7);
_0 = move _3 as u32 (IntToInt);
StorageDead(_2);
return;
Expand Down
7 changes: 7 additions & 0 deletions tests/mir-opt/building/enum_cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
// EMIT_MIR enum_cast.boo.built.after.mir
// EMIT_MIR enum_cast.far.built.after.mir

// Previously MIR building included range `Assume`s in the MIR statements,
// which these tests demonstrated, but now that we have range metadata on
// parameters in LLVM (in addition to !range metadata on loads) the impact
// of the extra volume of MIR is worse than its value.
// Thus these are now about the discriminant type and the cast type,
// both of which might be different from the backend type of the tag.

enum Foo {
A,
}
Expand Down
9 changes: 0 additions & 9 deletions tests/mir-opt/building/enum_cast.signy.built.after.mir
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,11 @@ fn signy(_1: SignedAroundZero) -> i16 {
let mut _0: i16;
let _2: SignedAroundZero;
let mut _3: i16;
let mut _4: u16;
let mut _5: bool;
let mut _6: bool;
let mut _7: bool;

bb0: {
StorageLive(_2);
_2 = move _1;
_3 = discriminant(_2);
_4 = copy _3 as u16 (IntToInt);
_5 = Ge(copy _4, const 65534_u16);
_6 = Le(copy _4, const 2_u16);
_7 = BitOr(move _5, move _6);
assume(move _7);
_0 = move _3 as i16 (IntToInt);
StorageDead(_2);
return;
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/simd/repr-simd-on-enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Used to ICE; see <https://github.com/rust-lang/rust/issues/121097>

#![feature(repr_simd)]

#[repr(simd)] //~ ERROR attribute should be applied to a struct
enum Aligned {
Zero = 0,
One = 1,
}

fn tou8(al: Aligned) -> u8 {
al as u8
}

fn main() {}
14 changes: 14 additions & 0 deletions tests/ui/simd/repr-simd-on-enum.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0517]: attribute should be applied to a struct
--> $DIR/repr-simd-on-enum.rs:5:8
|
LL | #[repr(simd)]
| ^^^^
LL | / enum Aligned {
LL | | Zero = 0,
LL | | One = 1,
LL | | }
| |_- not a struct

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0517`.
30 changes: 0 additions & 30 deletions tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,6 @@ LL | V3 = Self::V1 {} as u8 + 2,
note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`...
--> $DIR/self-in-enum-definition.rs:5:10
|
LL | V3 = Self::V1 {} as u8 + 2,
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires caching mir of `Alpha::V3::{constant#0}` for CTFE...
--> $DIR/self-in-enum-definition.rs:5:10
|
LL | V3 = Self::V1 {} as u8 + 2,
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires elaborating drops for `Alpha::V3::{constant#0}`...
--> $DIR/self-in-enum-definition.rs:5:10
|
LL | V3 = Self::V1 {} as u8 + 2,
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires borrow-checking `Alpha::V3::{constant#0}`...
--> $DIR/self-in-enum-definition.rs:5:10
|
LL | V3 = Self::V1 {} as u8 + 2,
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires promoting constants in MIR for `Alpha::V3::{constant#0}`...
--> $DIR/self-in-enum-definition.rs:5:10
|
LL | V3 = Self::V1 {} as u8 + 2,
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const checking `Alpha::V3::{constant#0}`...
--> $DIR/self-in-enum-definition.rs:5:10
|
LL | V3 = Self::V1 {} as u8 + 2,
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building MIR for `Alpha::V3::{constant#0}`...
--> $DIR/self-in-enum-definition.rs:5:10
|
LL | V3 = Self::V1 {} as u8 + 2,
| ^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `Alpha`...
Expand Down
Loading