summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src/build/expr/as_rvalue.rs')
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs58
1 files changed, 53 insertions, 5 deletions
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 3dafdcb78..0814793f2 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -2,6 +2,7 @@
use rustc_index::vec::Idx;
use rustc_middle::ty::util::IntTypeExt;
+use rustc_target::abi::{Abi, Primitive};
use crate::build::expr::as_place::PlaceBase;
use crate::build::expr::category::{Category, RvalueFunc};
@@ -198,6 +199,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let (source, ty) = if let ty::Adt(adt_def, ..) = source.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.param_env.and(source.ty));
let discr = this.temp(discr_ty, source.span);
this.cfg.push_assign(
block,
@@ -205,8 +207,55 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
discr,
Rvalue::Discriminant(temp.into()),
);
+ 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);
+ }
+ }
+ }
+
+ (op,ty)
- (Operand::Move(discr), discr_ty)
} else {
let ty = source.ty;
let source = unpack!(
@@ -320,8 +369,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let place_builder =
unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
- if let Ok(place_builder_resolved) = place_builder.try_upvars_resolved(this) {
- let mir_place = place_builder_resolved.into_place(this);
+ if let Some(mir_place) = place_builder.try_to_place(this) {
this.cfg.push_fake_read(
block,
this.source_info(this.tcx.hir().span(*hir_id)),
@@ -612,7 +660,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// by the parent itself. The mutability of the current capture
// is same as that of the capture in the parent closure.
PlaceBase::Upvar { .. } => {
- let enclosing_upvars_resolved = arg_place_builder.clone().into_place(this);
+ let enclosing_upvars_resolved = arg_place_builder.to_place(this);
match enclosing_upvars_resolved.as_ref() {
PlaceRef {
@@ -649,7 +697,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
};
- let arg_place = arg_place_builder.into_place(this);
+ let arg_place = arg_place_builder.to_place(this);
this.cfg.push_assign(
block,