Rollup merge of #111579 - scottmcm:enum-as-signed, r=oli-obk
Also assume wrap-around discriminants in `as` MIR building
Resolves this FIXME:
8d18c32b61/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs (L231)
r? `@oli-obk`
This commit is contained in:
commit
00185bec7c
11 changed files with 234 additions and 67 deletions
|
@ -15,6 +15,7 @@ use rustc_middle::mir::Place;
|
|||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::*;
|
||||
use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
use rustc_middle::ty::{self, Ty, UpvarSubsts};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -225,49 +226,63 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
);
|
||||
let (op,ty) = (Operand::Move(discr), discr_ty);
|
||||
|
||||
if let Abi::Scalar(scalar) = layout.unwrap().abi{
|
||||
if let Primitive::Int(_, signed) = scalar.primitive() {
|
||||
let range = scalar.valid_range(&this.tcx);
|
||||
// FIXME: Handle wraparound cases too.
|
||||
if range.end >= range.start {
|
||||
let mut assumer = |range: u128, bin_op: BinOp| {
|
||||
// We will be overwriting this val if our scalar is signed value
|
||||
// because sign extension on unsigned types might cause unintended things
|
||||
let mut range_val =
|
||||
ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(discr_ty));
|
||||
let bool_ty = this.tcx.types.bool;
|
||||
if signed {
|
||||
let scalar_size_extend = scalar.size(&this.tcx).sign_extend(range);
|
||||
let discr_layout = this.tcx.layout_of(this.param_env.and(discr_ty));
|
||||
let truncated_val = discr_layout.unwrap().size.truncate(scalar_size_extend);
|
||||
range_val = ConstantKind::from_bits(
|
||||
this.tcx,
|
||||
truncated_val,
|
||||
ty::ParamEnv::empty().and(discr_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(((lit_op), (Operand::Copy(discr))))),
|
||||
);
|
||||
this.cfg.push(
|
||||
block,
|
||||
Statement {
|
||||
source_info,
|
||||
kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
|
||||
Operand::Copy(is_bin_op),
|
||||
))),
|
||||
},
|
||||
)
|
||||
};
|
||||
assumer(range.end, BinOp::Ge);
|
||||
assumer(range.start, BinOp::Le);
|
||||
}
|
||||
}
|
||||
if let Abi::Scalar(scalar) = layout.unwrap().abi
|
||||
&& !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> {
|
||||
let range_val =
|
||||
ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(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 {
|
||||
source_info,
|
||||
kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
|
||||
Operand::Move(assert_place),
|
||||
))),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
(op,ty)
|
||||
|
|
28
tests/assembly/option-nonzero-eq.rs
Normal file
28
tests/assembly/option-nonzero-eq.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
// revisions: WIN LIN
|
||||
// [WIN] only-windows
|
||||
// [LIN] only-linux
|
||||
// assembly-output: emit-asm
|
||||
// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel
|
||||
// only-x86_64
|
||||
// ignore-sgx
|
||||
// ignore-debug
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
// CHECK-lABEL: ordering_eq:
|
||||
#[no_mangle]
|
||||
pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
|
||||
// Linux (System V): first two arguments are rdi then rsi
|
||||
// Windows: first two arguments are rcx then rdx
|
||||
// Both use rax for the return value.
|
||||
|
||||
// CHECK-NOT: mov
|
||||
// CHECK-NOT: test
|
||||
// CHECK-NOT: cmp
|
||||
|
||||
// LIN: cmp dil, sil
|
||||
// WIN: cmp cl, dl
|
||||
// CHECK-NEXT: sete al
|
||||
// CHECK-NEXT: ret
|
||||
l == r
|
||||
}
|
|
@ -7,6 +7,9 @@ use core::cmp::Ordering;
|
|||
use core::num::{NonZeroU32, NonZeroI64};
|
||||
use core::ptr::NonNull;
|
||||
|
||||
// See also tests/assembly/option-nonzero-eq.rs, for cases with `assume`s in the
|
||||
// LLVM and thus don't optimize down clearly here, but do in assembly.
|
||||
|
||||
// CHECK-lABEL: @non_zero_eq
|
||||
#[no_mangle]
|
||||
pub fn non_zero_eq(l: Option<NonZeroU32>, r: Option<NonZeroU32>) -> bool {
|
||||
|
@ -33,12 +36,3 @@ pub fn non_null_eq(l: Option<NonNull<u8>>, r: Option<NonNull<u8>>) -> bool {
|
|||
// CHECK-NEXT: ret i1
|
||||
l == r
|
||||
}
|
||||
|
||||
// CHECK-lABEL: @ordering_eq
|
||||
#[no_mangle]
|
||||
pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
|
||||
// CHECK: start:
|
||||
// CHECK-NEXT: icmp eq i8
|
||||
// CHECK-NEXT: ret i1
|
||||
l == r
|
||||
}
|
||||
|
|
|
@ -5,17 +5,16 @@ fn bar(_1: Bar) -> usize {
|
|||
let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
|
||||
let _2: Bar; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
let mut _3: isize; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
let mut _4: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
let mut _4: u8; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
let mut _5: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_4 = Ge(const 1_isize, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
assume(_4); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_5 = Le(const 0_isize, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
assume(_5); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_4 = _3 as u8 (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_5 = Le(_4, const 1_u8); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
assume(move _5); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
|
||||
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
|
||||
|
|
|
@ -5,17 +5,16 @@ fn boo(_1: Boo) -> usize {
|
|||
let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
|
||||
let _2: Boo; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
let mut _3: u8; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
let mut _4: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
let mut _4: u8; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
let mut _5: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_4 = Ge(const 1_u8, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
assume(_4); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_5 = Le(const 0_u8, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
assume(_5); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_4 = _3 as u8 (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_5 = Le(_4, const 1_u8); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
assume(move _5); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
|
||||
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
|
||||
|
|
|
@ -6,7 +6,7 @@ fn droppy() -> () {
|
|||
let _2: Droppy; // in scope 0 at $DIR/enum_cast.rs:+2:13: +2:14
|
||||
let _4: Droppy; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
|
||||
let mut _5: isize; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
|
||||
let mut _6: bool; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
let mut _6: u8; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
let mut _7: bool; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
let _8: Droppy; // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
|
||||
scope 1 {
|
||||
|
@ -31,10 +31,9 @@ fn droppy() -> () {
|
|||
StorageLive(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
|
||||
_4 = move _2; // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
|
||||
_5 = discriminant(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
_6 = Ge(const 2_isize, _5); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
assume(_6); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
_7 = Le(const 0_isize, _5); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
assume(_7); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
_6 = _5 as u8 (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
_7 = Le(_6, const 2_u8); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
assume(move _7); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
_3 = move _5 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
|
||||
drop(_4) -> [return: bb1, unwind: bb4]; // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27
|
||||
}
|
||||
|
|
22
tests/mir-opt/building/enum_cast.far.built.after.mir
Normal file
22
tests/mir-opt/building/enum_cast.far.built.after.mir
Normal file
|
@ -0,0 +1,22 @@
|
|||
// MIR for `far` after built
|
||||
|
||||
fn far(_1: Far) -> isize {
|
||||
debug far => _1; // in scope 0 at $DIR/enum_cast.rs:+0:8: +0:11
|
||||
let mut _0: isize; // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
|
||||
let _2: Far; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
let mut _3: i16; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
let mut _4: u16; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
let mut _5: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
|
||||
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_4 = _3 as u16 (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_5 = Le(_4, const 1_u16); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
assume(move _5); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
_0 = move _3 as isize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
|
||||
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
|
||||
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
|
||||
}
|
||||
}
|
26
tests/mir-opt/building/enum_cast.offsetty.built.after.mir
Normal file
26
tests/mir-opt/building/enum_cast.offsetty.built.after.mir
Normal file
|
@ -0,0 +1,26 @@
|
|||
// MIR for `offsetty` after built
|
||||
|
||||
fn offsetty(_1: NotStartingAtZero) -> u32 {
|
||||
debug x => _1; // in scope 0 at $DIR/enum_cast.rs:+0:13: +0:14
|
||||
let mut _0: u32; // return place in scope 0 at $DIR/enum_cast.rs:+0:38: +0:41
|
||||
let _2: NotStartingAtZero; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
|
||||
let mut _3: isize; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
|
||||
let mut _4: u8; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
let mut _5: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
let mut _6: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
let mut _7: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
|
||||
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
|
||||
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
_4 = _3 as u8 (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
_5 = Ge(_4, const 4_u8); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
_6 = Le(_4, const 8_u8); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
_7 = BitAnd(move _5, move _6); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
assume(move _7); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
_0 = move _3 as u32 (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:12: +1:13
|
||||
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
// EMIT_MIR enum_cast.foo.built.after.mir
|
||||
// EMIT_MIR enum_cast.bar.built.after.mir
|
||||
// EMIT_MIR enum_cast.boo.built.after.mir
|
||||
// EMIT_MIR enum_cast.far.built.after.mir
|
||||
|
||||
enum Foo {
|
||||
A
|
||||
|
@ -15,6 +16,11 @@ enum Boo {
|
|||
A, B
|
||||
}
|
||||
|
||||
#[repr(i16)]
|
||||
enum Far {
|
||||
A, B
|
||||
}
|
||||
|
||||
fn foo(foo: Foo) -> usize {
|
||||
foo as usize
|
||||
}
|
||||
|
@ -27,6 +33,10 @@ fn boo(boo: Boo) -> usize {
|
|||
boo as usize
|
||||
}
|
||||
|
||||
fn far(far: Far) -> isize {
|
||||
far as isize
|
||||
}
|
||||
|
||||
// EMIT_MIR enum_cast.droppy.built.after.mir
|
||||
enum Droppy {
|
||||
A, B, C
|
||||
|
@ -46,5 +56,37 @@ fn droppy() {
|
|||
let z = Droppy::B;
|
||||
}
|
||||
|
||||
#[repr(i16)]
|
||||
enum SignedAroundZero {
|
||||
A = -2,
|
||||
B = 0,
|
||||
C = 2,
|
||||
}
|
||||
|
||||
#[repr(u16)]
|
||||
enum UnsignedAroundZero {
|
||||
A = 65535,
|
||||
B = 0,
|
||||
C = 1,
|
||||
}
|
||||
|
||||
// EMIT_MIR enum_cast.signy.built.after.mir
|
||||
fn signy(x: SignedAroundZero) -> i16 {
|
||||
x as i16
|
||||
}
|
||||
|
||||
// EMIT_MIR enum_cast.unsigny.built.after.mir
|
||||
fn unsigny(x: UnsignedAroundZero) -> u16 {
|
||||
// FIXME: This doesn't get an around-the-end range today, sadly.
|
||||
x as u16
|
||||
}
|
||||
|
||||
enum NotStartingAtZero { A = 4, B = 6, C = 8 }
|
||||
|
||||
// EMIT_MIR enum_cast.offsetty.built.after.mir
|
||||
fn offsetty(x: NotStartingAtZero) -> u32 {
|
||||
x as u32
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
|
26
tests/mir-opt/building/enum_cast.signy.built.after.mir
Normal file
26
tests/mir-opt/building/enum_cast.signy.built.after.mir
Normal file
|
@ -0,0 +1,26 @@
|
|||
// MIR for `signy` after built
|
||||
|
||||
fn signy(_1: SignedAroundZero) -> i16 {
|
||||
debug x => _1; // in scope 0 at $DIR/enum_cast.rs:+0:10: +0:11
|
||||
let mut _0: i16; // return place in scope 0 at $DIR/enum_cast.rs:+0:34: +0:37
|
||||
let _2: SignedAroundZero; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
|
||||
let mut _3: i16; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
|
||||
let mut _4: u16; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
let mut _5: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
let mut _6: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
let mut _7: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
|
||||
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
|
||||
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
_4 = _3 as u16 (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
_5 = Ge(_4, const 65534_u16); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
_6 = Le(_4, const 2_u16); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
_7 = BitOr(move _5, move _6); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
assume(move _7); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
_0 = move _3 as i16 (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
|
||||
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:12: +1:13
|
||||
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
|
||||
}
|
||||
}
|
17
tests/mir-opt/building/enum_cast.unsigny.built.after.mir
Normal file
17
tests/mir-opt/building/enum_cast.unsigny.built.after.mir
Normal file
|
@ -0,0 +1,17 @@
|
|||
// MIR for `unsigny` after built
|
||||
|
||||
fn unsigny(_1: UnsignedAroundZero) -> u16 {
|
||||
debug x => _1; // in scope 0 at $DIR/enum_cast.rs:+0:12: +0:13
|
||||
let mut _0: u16; // return place in scope 0 at $DIR/enum_cast.rs:+0:38: +0:41
|
||||
let _2: UnsignedAroundZero; // in scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
|
||||
let mut _3: u16; // in scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
|
||||
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
|
||||
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+2:5: +2:13
|
||||
_0 = move _3 as u16 (IntToInt); // scope 0 at $DIR/enum_cast.rs:+2:5: +2:13
|
||||
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+2:12: +2:13
|
||||
return; // scope 0 at $DIR/enum_cast.rs:+3:2: +3:2
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue