MIR-build: No longer emit assumes in enum-as casting
This just uses the `valid_range` from the backend, so it's duplicating the range metadata that now we include on parameters and loads.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
//! See docs in `build/expr/mod.rs`.
|
//! 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_hir::lang_items::LangItem;
|
||||||
use rustc_index::{Idx, IndexVec};
|
use rustc_index::{Idx, IndexVec};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
@@ -9,7 +9,6 @@ use rustc_middle::mir::interpret::Scalar;
|
|||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::cast::{CastTy, mir_cast_kind};
|
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::util::IntTypeExt;
|
||||||
use rustc_middle::ty::{self, Ty, UpvarArgs};
|
use rustc_middle::ty::{self, Ty, UpvarArgs};
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
@@ -200,8 +199,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
{
|
{
|
||||||
let discr_ty = adt_def.repr().discr_type().to_ty(this.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 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);
|
let discr = this.temp(discr_ty, source_expr.span);
|
||||||
this.cfg.push_assign(
|
this.cfg.push_assign(
|
||||||
block,
|
block,
|
||||||
@@ -209,80 +206,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
discr,
|
discr,
|
||||||
Rvalue::Discriminant(temp.into()),
|
Rvalue::Discriminant(temp.into()),
|
||||||
);
|
);
|
||||||
let (op, ty) = (Operand::Move(discr), discr_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)
|
|
||||||
} else {
|
} else {
|
||||||
let ty = source_expr.ty;
|
let ty = source_expr.ty;
|
||||||
let source = unpack!(
|
let source = unpack!(
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
//@ known-bug: #121097
|
|
||||||
#[repr(simd)]
|
|
||||||
enum Aligned {
|
|
||||||
Zero = 0,
|
|
||||||
One = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tou8(al: Aligned) -> u8 {
|
|
||||||
al as u8
|
|
||||||
}
|
|
||||||
@@ -5,16 +5,11 @@ fn bar(_1: Bar) -> usize {
|
|||||||
let mut _0: usize;
|
let mut _0: usize;
|
||||||
let _2: Bar;
|
let _2: Bar;
|
||||||
let mut _3: isize;
|
let mut _3: isize;
|
||||||
let mut _4: u8;
|
|
||||||
let mut _5: bool;
|
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
_2 = move _1;
|
_2 = move _1;
|
||||||
_3 = discriminant(_2);
|
_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);
|
_0 = move _3 as usize (IntToInt);
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5,16 +5,11 @@ fn boo(_1: Boo) -> usize {
|
|||||||
let mut _0: usize;
|
let mut _0: usize;
|
||||||
let _2: Boo;
|
let _2: Boo;
|
||||||
let mut _3: u8;
|
let mut _3: u8;
|
||||||
let mut _4: u8;
|
|
||||||
let mut _5: bool;
|
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
_2 = move _1;
|
_2 = move _1;
|
||||||
_3 = discriminant(_2);
|
_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);
|
_0 = move _3 as usize (IntToInt);
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5,16 +5,11 @@ fn far(_1: Far) -> isize {
|
|||||||
let mut _0: isize;
|
let mut _0: isize;
|
||||||
let _2: Far;
|
let _2: Far;
|
||||||
let mut _3: i16;
|
let mut _3: i16;
|
||||||
let mut _4: u16;
|
|
||||||
let mut _5: bool;
|
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
_2 = move _1;
|
_2 = move _1;
|
||||||
_3 = discriminant(_2);
|
_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);
|
_0 = move _3 as isize (IntToInt);
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5,20 +5,11 @@ fn offsetty(_1: NotStartingAtZero) -> u32 {
|
|||||||
let mut _0: u32;
|
let mut _0: u32;
|
||||||
let _2: NotStartingAtZero;
|
let _2: NotStartingAtZero;
|
||||||
let mut _3: isize;
|
let mut _3: isize;
|
||||||
let mut _4: u8;
|
|
||||||
let mut _5: bool;
|
|
||||||
let mut _6: bool;
|
|
||||||
let mut _7: bool;
|
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
_2 = move _1;
|
_2 = move _1;
|
||||||
_3 = discriminant(_2);
|
_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);
|
_0 = move _3 as u32 (IntToInt);
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
// EMIT_MIR enum_cast.boo.built.after.mir
|
// EMIT_MIR enum_cast.boo.built.after.mir
|
||||||
// EMIT_MIR enum_cast.far.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 {
|
enum Foo {
|
||||||
A,
|
A,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,20 +5,11 @@ fn signy(_1: SignedAroundZero) -> i16 {
|
|||||||
let mut _0: i16;
|
let mut _0: i16;
|
||||||
let _2: SignedAroundZero;
|
let _2: SignedAroundZero;
|
||||||
let mut _3: i16;
|
let mut _3: i16;
|
||||||
let mut _4: u16;
|
|
||||||
let mut _5: bool;
|
|
||||||
let mut _6: bool;
|
|
||||||
let mut _7: bool;
|
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_2);
|
StorageLive(_2);
|
||||||
_2 = move _1;
|
_2 = move _1;
|
||||||
_3 = discriminant(_2);
|
_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);
|
_0 = move _3 as i16 (IntToInt);
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
return;
|
return;
|
||||||
|
|||||||
15
tests/ui/simd/repr-simd-on-enum.rs
Normal file
15
tests/ui/simd/repr-simd-on-enum.rs
Normal file
@@ -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
tests/ui/simd/repr-simd-on-enum.stderr
Normal file
14
tests/ui/simd/repr-simd-on-enum.stderr
Normal file
@@ -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`.
|
||||||
@@ -7,36 +7,6 @@ LL | V3 = Self::V1 {} as u8 + 2,
|
|||||||
note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`...
|
note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`...
|
||||||
--> $DIR/self-in-enum-definition.rs:5:10
|
--> $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,
|
LL | V3 = Self::V1 {} as u8 + 2,
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires computing layout of `Alpha`...
|
= note: ...which requires computing layout of `Alpha`...
|
||||||
|
|||||||
Reference in New Issue
Block a user