diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index c1e23cb54117b..d49f0ae286fae 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -23,7 +23,7 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::cast::CastTy; +use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ @@ -2183,11 +2183,24 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } CastKind::Transmute => { - span_mirbug!( - self, - rvalue, - "Unexpected CastKind::Transmute, which is not permitted in Analysis MIR", - ); + let ty_from = op.ty(body, tcx); + let cast_ty_from = CastTy::from_ty(ty_from); + let cast_ty_to = CastTy::from_ty(*ty); + match (cast_ty_from, cast_ty_to) { + ( + Some(CastTy::Int(IntTy::CEnum)), + Some(CastTy::Int(IntTy::U(_) | IntTy::I)), + ) => (), + _ => { + span_mirbug!( + self, + rvalue, + "Invalid CastKind::Transmute cast {:?} -> {:?}", + ty_from, + ty + ) + } + } } } } diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs index 97d34b85f50da..fcd7d676ab8d2 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs @@ -1,6 +1,8 @@ //! See docs in `build/expr/mod.rs`. -use rustc_abi::{BackendRepr, FieldIdx, Primitive}; +use std::assert_matches::assert_matches; + +use rustc_abi::{BackendRepr, FieldIdx, TagEncoding, Variants}; use rustc_hir::lang_items::LangItem; use rustc_index::{Idx, IndexVec}; use rustc_middle::bug; @@ -9,8 +11,8 @@ 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::layout::PrimitiveExt; +use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{self, Ty, UpvarArgs}; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span}; @@ -197,97 +199,78 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Cast { source } => { let source_expr = &this.thir[source]; - // Casting an enum to an integer is equivalent to computing the discriminant and casting the - // discriminant. Previously every backend had to repeat the logic for this operation. Now we - // create all the steps directly in MIR with operations all backends need to support anyway. let (source, ty) = if let ty::Adt(adt_def, ..) = source_expr.ty.kind() && adt_def.is_enum() { - 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( + let layout = this + .tcx + .layout_of(this.typing_env().as_query_input(source_expr.ty)) + .unwrap(); + match layout.variants { + // Uninhabited enum, so we're in dead code. + Variants::Empty => { + let false_lit = this.zero_literal(expr_span, this.tcx.types.bool); + this.cfg.push( 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), + Statement { + source_info, + kind: StatementKind::Intrinsic(Box::new( + NonDivergingIntrinsic::Assume(false_lit), )), - ), + }, ); - merge_place - }; - this.cfg.push( - block, - Statement { - source_info, - kind: StatementKind::Intrinsic(Box::new( - NonDivergingIntrinsic::Assume(Operand::Move(assert_place)), - )), - }, - ); + // We still need to emit *something*, to keep the following MIR legal, + // so give a zero of the type the cast was asking for. + (this.zero_literal(expr_span, expr.ty), expr.ty) + } + // Only one legal variant, so we can just look up its + // discriminant directly and return it as a constant. + // (In the discriminant's type, not the cast-to type, + // to avoid worrying about truncation or extension.) + Variants::Single { index } => { + let Discr { val, ty } = + adt_def.discriminant_for_variant(this.tcx, index); + let val = Const::from_bits(this.tcx, val, this.typing_env(), ty); + (this.literal_operand(expr_span, val), ty) + } + // Casting an enum to an integer is only supported for enums which + // have no fields, so we can transmute the stored tag. + // This used to emit `Assume`s into the MIR, but that bloated it, + // so now we re-use the `Transmute` checks that backends ought to + // support anyway for polymorphic MIR cases. + Variants::Multiple { tag, ref tag_encoding, .. } => { + assert_matches!(tag_encoding, TagEncoding::Direct); + if let BackendRepr::Scalar(repr) = layout.backend_repr { + assert_eq!(repr, tag); + let tag_ty = tag.primitive().to_ty(this.tcx); + let tag = this.temp(tag_ty, expr_span); + this.cfg.push_assign( + block, + source_info, + tag, + Rvalue::Cast( + CastKind::Transmute, + Operand::Move(Place::from(temp)), + tag_ty, + ), + ); + (Operand::Move(tag), tag_ty) + } else { + // FIXME: One `Transmute` works union-style (so it can truncate + // the padding down to just the tag) we can remove this fallback. + let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx); + let discr = this.temp(discr_ty, source_expr.span); + this.cfg.push_assign( + block, + source_info, + discr, + Rvalue::Discriminant(temp.into()), + ); + (Operand::Move(discr), discr_ty) + } + } } - - (op, ty) } else { let ty = source_expr.ty; let source = unpack!( diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 4ac3a268c9c33..aa8aae010d883 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1303,37 +1303,27 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } CastKind::Transmute => { - if let MirPhase::Runtime(..) = self.body.phase { - // Unlike `mem::transmute`, a MIR `Transmute` is well-formed - // for any two `Sized` types, just potentially UB to run. - - if !self - .tcx - .normalize_erasing_regions(self.typing_env, op_ty) - .is_sized(self.tcx, self.typing_env) - { - self.fail( - location, - format!("Cannot transmute from non-`Sized` type {op_ty:?}"), - ); - } - if !self - .tcx - .normalize_erasing_regions(self.typing_env, *target_type) - .is_sized(self.tcx, self.typing_env) - { - self.fail( - location, - format!("Cannot transmute to non-`Sized` type {target_type:?}"), - ); - } - } else { + // Unlike `mem::transmute`, a MIR `Transmute` is well-formed + // for any two `Sized` types, just potentially UB to run. + + if !self + .tcx + .normalize_erasing_regions(self.typing_env, op_ty) + .is_sized(self.tcx, self.typing_env) + { self.fail( location, - format!( - "Transmute is not supported in non-runtime phase {:?}.", - self.body.phase - ), + format!("Cannot transmute from non-`Sized` type {op_ty:?}"), + ); + } + if !self + .tcx + .normalize_erasing_regions(self.typing_env, *target_type) + .is_sized(self.tcx, self.typing_env) + { + self.fail( + location, + format!("Cannot transmute to non-`Sized` type {target_type:?}"), ); } } diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index b29251b4b436c..ca0529105c111 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -400,7 +400,7 @@ impl Ordering { #[inline] const fn as_raw(self) -> i8 { // FIXME(const-hack): just use `PartialOrd` against `Equal` once that's const - crate::intrinsics::discriminant_value(&self) + self as i8 } /// Returns `true` if the ordering is the `Equal` variant. diff --git a/tests/mir-opt/building/enum_cast.bar.built.after.mir b/tests/mir-opt/building/enum_cast.bar.built.after.mir index 72d0cf5d1e823..aa856be5706d3 100644 --- a/tests/mir-opt/building/enum_cast.bar.built.after.mir +++ b/tests/mir-opt/building/enum_cast.bar.built.after.mir @@ -4,17 +4,12 @@ fn bar(_1: Bar) -> usize { debug bar => _1; let mut _0: usize; let _2: Bar; - let mut _3: isize; - let mut _4: u8; - let mut _5: bool; + let mut _3: u8; 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); + _3 = move _2 as u8 (Transmute); _0 = move _3 as usize (IntToInt); StorageDead(_2); return; diff --git a/tests/mir-opt/building/enum_cast.boo.built.after.mir b/tests/mir-opt/building/enum_cast.boo.built.after.mir index 91e06dc886299..59a85c7012821 100644 --- a/tests/mir-opt/building/enum_cast.boo.built.after.mir +++ b/tests/mir-opt/building/enum_cast.boo.built.after.mir @@ -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); + _3 = move _2 as u8 (Transmute); _0 = move _3 as usize (IntToInt); StorageDead(_2); return; diff --git a/tests/mir-opt/building/enum_cast.custom_single_variant.built.after.mir b/tests/mir-opt/building/enum_cast.custom_single_variant.built.after.mir new file mode 100644 index 0000000000000..da334ad19ee9c --- /dev/null +++ b/tests/mir-opt/building/enum_cast.custom_single_variant.built.after.mir @@ -0,0 +1,84 @@ +// MIR for `custom_single_variant` after built + +fn custom_single_variant(_1: SingleVariantWithCustomDiscriminant, _2: SingleVariantWithCustomDiscriminantAndRepr) -> impl Sized { + debug a => _1; + debug b => _2; + let mut _0: impl Sized; + let mut _3: isize; + let _4: SingleVariantWithCustomDiscriminant; + let mut _5: usize; + let _6: SingleVariantWithCustomDiscriminant; + let mut _7: i16; + let _8: SingleVariantWithCustomDiscriminant; + let mut _9: u16; + let _10: SingleVariantWithCustomDiscriminant; + let mut _11: isize; + let _12: SingleVariantWithCustomDiscriminantAndRepr; + let mut _13: u16; + let mut _14: usize; + let _15: SingleVariantWithCustomDiscriminantAndRepr; + let mut _16: u16; + let mut _17: i16; + let _18: SingleVariantWithCustomDiscriminantAndRepr; + let mut _19: u16; + let mut _20: u16; + let _21: SingleVariantWithCustomDiscriminantAndRepr; + let mut _22: u16; + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + _3 = const 42_isize as isize (IntToInt); + StorageDead(_4); + StorageLive(_5); + StorageLive(_6); + _6 = copy _1; + _5 = const 42_isize as usize (IntToInt); + StorageDead(_6); + StorageLive(_7); + StorageLive(_8); + _8 = copy _1; + _7 = const 42_isize as i16 (IntToInt); + StorageDead(_8); + StorageLive(_9); + StorageLive(_10); + _10 = copy _1; + _9 = const 42_isize as u16 (IntToInt); + StorageDead(_10); + StorageLive(_11); + StorageLive(_12); + _12 = copy _2; + _13 = move _12 as u16 (Transmute); + _11 = move _13 as isize (IntToInt); + StorageDead(_12); + StorageLive(_14); + StorageLive(_15); + _15 = copy _2; + _16 = move _15 as u16 (Transmute); + _14 = move _16 as usize (IntToInt); + StorageDead(_15); + StorageLive(_17); + StorageLive(_18); + _18 = copy _2; + _19 = move _18 as u16 (Transmute); + _17 = move _19 as i16 (IntToInt); + StorageDead(_18); + StorageLive(_20); + StorageLive(_21); + _21 = copy _2; + _22 = move _21 as u16 (Transmute); + _20 = move _22 as u16 (IntToInt); + StorageDead(_21); + _0 = (move _3, move _5, move _7, move _9, move _11, move _14, move _17, move _20); + StorageDead(_20); + StorageDead(_17); + StorageDead(_14); + StorageDead(_11); + StorageDead(_9); + StorageDead(_7); + StorageDead(_5); + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/building/enum_cast.far.built.after.mir b/tests/mir-opt/building/enum_cast.far.built.after.mir index 14eaf34419034..0e9d3e70b0b83 100644 --- a/tests/mir-opt/building/enum_cast.far.built.after.mir +++ b/tests/mir-opt/building/enum_cast.far.built.after.mir @@ -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); + _3 = move _2 as i16 (Transmute); _0 = move _3 as isize (IntToInt); StorageDead(_2); return; diff --git a/tests/mir-opt/building/enum_cast.foo.built.after.mir b/tests/mir-opt/building/enum_cast.foo.built.after.mir index d4eea0534f830..662c162b6e192 100644 --- a/tests/mir-opt/building/enum_cast.foo.built.after.mir +++ b/tests/mir-opt/building/enum_cast.foo.built.after.mir @@ -4,13 +4,11 @@ fn foo(_1: Foo) -> usize { debug foo => _1; let mut _0: usize; let _2: Foo; - let mut _3: isize; bb0: { StorageLive(_2); _2 = move _1; - _3 = discriminant(_2); - _0 = move _3 as usize (IntToInt); + _0 = const 0_isize as usize (IntToInt); StorageDead(_2); return; } diff --git a/tests/mir-opt/building/enum_cast.offsetty.built.after.mir b/tests/mir-opt/building/enum_cast.offsetty.built.after.mir index 1c2acbe3023fe..b0f447729ea33 100644 --- a/tests/mir-opt/building/enum_cast.offsetty.built.after.mir +++ b/tests/mir-opt/building/enum_cast.offsetty.built.after.mir @@ -4,21 +4,12 @@ fn offsetty(_1: NotStartingAtZero) -> u32 { debug x => _1; 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; + let mut _3: u8; 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); + _3 = move _2 as u8 (Transmute); _0 = move _3 as u32 (IntToInt); StorageDead(_2); return; diff --git a/tests/mir-opt/building/enum_cast.rs b/tests/mir-opt/building/enum_cast.rs index 4fb9a27e3093b..cc0a33bdc9f87 100644 --- a/tests/mir-opt/building/enum_cast.rs +++ b/tests/mir-opt/building/enum_cast.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR enum_cast.foo.built.after.mir // EMIT_MIR enum_cast.bar.built.after.mir // EMIT_MIR enum_cast.boo.built.after.mir @@ -25,22 +24,79 @@ enum Far { B, } +// CHECK-LABEL: fn foo( fn foo(foo: Foo) -> usize { + // CHECK: _0 = const 0_usize; foo as usize } +// CHECK-LABEL: fn bar( fn bar(bar: Bar) -> usize { + // CHECK: _2 = copy _1 as u8 (Transmute); + // CHECK: _0 = move _2 as usize (IntToInt); bar as usize } +// CHECK-LABEL: fn boo( fn boo(boo: Boo) -> usize { + // CHECK: _2 = copy _1 as u8 (Transmute); + // CHECK: _0 = move _2 as usize (IntToInt); boo as usize } +// CHECK-LABEL: fn far( fn far(far: Far) -> isize { + // CHECK: _2 = copy _1 as i16 (Transmute); + // CHECK: _0 = move _2 as isize (IntToInt); far as isize } +#[derive(Copy, Clone)] +enum SingleVariantWithCustomDiscriminant { + FourtyTwo = 42, +} + +#[derive(Copy, Clone)] +#[repr(u16)] +enum SingleVariantWithCustomDiscriminantAndRepr { + FourtyTwo = 42, +} + +// EMIT_MIR enum_cast.custom_single_variant.built.after.mir +// CHECK-LABEL: fn custom_single_variant( +#[rustfmt::skip] // No, I don't want the comments on the same lines with the commas +fn custom_single_variant( + a: SingleVariantWithCustomDiscriminant, + b: SingleVariantWithCustomDiscriminantAndRepr, +) -> impl Sized { + ( + a as isize, + a as usize, + a as i16, + a as u16, + // CHECK: [[REPR:_.+]] = copy _2 as u16 (Transmute) + // CHECK: [[B0:_.+]] = copy [[REPR]] as isize (IntToInt) + b as isize, + // CHECK: [[B1:_.+]] = copy [[REPR]] as usize (IntToInt) + b as usize, + // CHECK: [[B2:_.+]] = copy [[REPR]] as i16 (IntToInt) + b as i16, + b as u16, + ) + // CHECK: _0 = (const 42_isize, const 42_usize, const 42_i16, const 42_u16, + // CHECK-SAME: move [[B0]], move [[B1]], move [[B2]], copy [[REPR]]); +} + +// EMIT_MIR enum_cast.unreachable.built.after.mir +// CHECK-LABEL: fn unreachable +fn unreachable(x: std::convert::Infallible) -> u16 { + // CHECK: debug x => const ZeroSized: Infallible; + // CHECK: bb0: { + // CHECK-NEXT: unreachable; + // CHECK-NEXT: } + x as _ +} + #[repr(i16)] enum SignedAroundZero { A = -2, @@ -56,13 +112,16 @@ enum UnsignedAroundZero { } // EMIT_MIR enum_cast.signy.built.after.mir +// CHECK-LABEL: fn signy( fn signy(x: SignedAroundZero) -> i16 { + // CHECK: _0 = copy _1 as i16 (Transmute); x as i16 } // EMIT_MIR enum_cast.unsigny.built.after.mir +// CHECK-LABEL: fn unsigny( fn unsigny(x: UnsignedAroundZero) -> u16 { - // FIXME: This doesn't get an around-the-end range today, sadly. + // CHECK: _0 = copy _1 as u16 (Transmute); x as u16 } @@ -73,8 +132,36 @@ enum NotStartingAtZero { } // EMIT_MIR enum_cast.offsetty.built.after.mir +// CHECK-LABEL: fn offsetty( fn offsetty(x: NotStartingAtZero) -> u32 { + // CHECK: _2 = copy _1 as u8 (Transmute); + // CHECK: _0 = move _2 as u32 (IntToInt); x as u32 } +enum ReallyBigDiscr { + One = 0x4321, +} + +// CHECK-LABEL: fn really_big_discr( +fn really_big_discr(x: ReallyBigDiscr) -> u8 { + // Better not ICE on this! + // CHECK: _0 = const 33_u8; + x as u8 +} + +// `align` gives this `Memory` ABI instead of `Scalar` +#[repr(align(8))] +enum Aligned { + Zero = 0, + One = 1, +} + +// CHECK-LABEL: fn aligned_as( +fn aligned_as(x: Aligned) -> u8 { + // CHECK: _2 = discriminant(_1); + // CHECK: _0 = move _2 as u8 (IntToInt); + x as u8 +} + fn main() {} diff --git a/tests/mir-opt/building/enum_cast.signy.built.after.mir b/tests/mir-opt/building/enum_cast.signy.built.after.mir index 39b6dfaf005e3..cea5a0ef18a5e 100644 --- a/tests/mir-opt/building/enum_cast.signy.built.after.mir +++ b/tests/mir-opt/building/enum_cast.signy.built.after.mir @@ -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); + _3 = move _2 as i16 (Transmute); _0 = move _3 as i16 (IntToInt); StorageDead(_2); return; diff --git a/tests/mir-opt/building/enum_cast.unreachable.built.after.mir b/tests/mir-opt/building/enum_cast.unreachable.built.after.mir new file mode 100644 index 0000000000000..e69498ed7c4d5 --- /dev/null +++ b/tests/mir-opt/building/enum_cast.unreachable.built.after.mir @@ -0,0 +1,24 @@ +// MIR for `unreachable` after built + +| User Type Annotations +| 0: user_ty: Canonical { value: Ty(^0), max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }] }, span: $DIR/enum_cast.rs:97:10: 97:11, inferred_ty: u16 +| +fn unreachable(_1: Infallible) -> u16 { + debug x => _1; + let mut _0: u16; + let mut _2: u16; + let _3: std::convert::Infallible; + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = copy _1; + assume(const false); + _2 = const 0_u16 as u16 (IntToInt); + AscribeUserType(_2, o, UserTypeProjection { base: UserType(0), projs: [] }); + _0 = copy _2; + StorageDead(_3); + StorageDead(_2); + return; + } +} diff --git a/tests/mir-opt/building/enum_cast.unsigny.built.after.mir b/tests/mir-opt/building/enum_cast.unsigny.built.after.mir index a232ab942b7ae..ca5cf29a8ef5f 100644 --- a/tests/mir-opt/building/enum_cast.unsigny.built.after.mir +++ b/tests/mir-opt/building/enum_cast.unsigny.built.after.mir @@ -9,7 +9,7 @@ fn unsigny(_1: UnsignedAroundZero) -> u16 { bb0: { StorageLive(_2); _2 = move _1; - _3 = discriminant(_2); + _3 = move _2 as u16 (Transmute); _0 = move _3 as u16 (IntToInt); StorageDead(_2); return; diff --git a/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir index 49314a64c3fc9..8850ca80d87a2 100644 --- a/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir @@ -79,7 +79,7 @@ fn demo_le(_1: &MultiField, _2: &MultiField) -> bool { bb3: { _12 = move ((_11 as Some).0: std::cmp::Ordering); StorageLive(_13); - _13 = discriminant(_12); + _13 = copy _12 as i8 (Transmute); _0 = Le(move _13, const 0_i8); StorageDead(_13); StorageDead(_11); diff --git a/tests/mir-opt/pre-codegen/derived_ord.rs b/tests/mir-opt/pre-codegen/derived_ord.rs index 73ae923a6cb9c..eef91b7a927c7 100644 --- a/tests/mir-opt/pre-codegen/derived_ord.rs +++ b/tests/mir-opt/pre-codegen/derived_ord.rs @@ -24,7 +24,7 @@ pub fn demo_le(a: &MultiField, b: &MultiField) -> bool { // CHECK: [[B1:_[0-9]+]] = copy ((*_2).1: i16); // CHECK: Cmp(move [[A1]], move [[B1]]); - // CHECK: [[D1:_[0-9]+]] = discriminant({{.+}}); + // CHECK: [[D1:_[0-9]+]] = copy {{.+}} as i8 (Transmute); // CHECK: _0 = Le(move [[D1]], const 0_i8); *a <= *b }