summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/build
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src/build')
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/cfg.rs11
-rw-r--r--compiler/rustc_mir_build/src/build/custom/mod.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs56
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs14
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs10
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs174
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_temp.rs25
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs28
-rw-r--r--compiler/rustc_mir_build/src/build/expr/stmt.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs34
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/misc.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs45
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs68
17 files changed, 327 insertions, 166 deletions
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 2643d33ce..609ab1928 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -115,6 +115,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
initializer: Some(initializer),
lint_level,
else_block: Some(else_block),
+ span: _,
} => {
// When lowering the statement `let <pat> = <expr> else { <else> };`,
// the `<else>` block is nested in the parent scope enclosing this statement.
@@ -278,6 +279,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
initializer,
lint_level,
else_block: None,
+ span: _,
} => {
let ignores_expr_result = matches!(pattern.kind, PatKind::Wild);
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs
index d7b4b1f73..4f1623b4c 100644
--- a/compiler/rustc_mir_build/src/build/cfg.rs
+++ b/compiler/rustc_mir_build/src/build/cfg.rs
@@ -90,6 +90,17 @@ impl<'tcx> CFG<'tcx> {
self.push(block, stmt);
}
+ pub(crate) fn push_place_mention(
+ &mut self,
+ block: BasicBlock,
+ source_info: SourceInfo,
+ place: Place<'tcx>,
+ ) {
+ let kind = StatementKind::PlaceMention(Box::new(place));
+ let stmt = Statement { source_info, kind };
+ self.push(block, stmt);
+ }
+
pub(crate) fn terminate(
&mut self,
block: BasicBlock,
diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs
index 33fdc1901..d385153ba 100644
--- a/compiler/rustc_mir_build/src/build/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/build/custom/mod.rs
@@ -21,7 +21,7 @@ use rustc_ast::Attribute;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_hir::HirId;
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::{IndexSlice, IndexVec};
use rustc_middle::{
mir::*,
thir::*,
@@ -37,7 +37,7 @@ pub(super) fn build_custom_mir<'tcx>(
hir_id: HirId,
thir: &Thir<'tcx>,
expr: ExprId,
- params: &IndexVec<ParamId, Param<'tcx>>,
+ params: &IndexSlice<ParamId, Param<'tcx>>,
return_ty: Ty<'tcx>,
return_ty_span: Span,
span: Span,
@@ -49,7 +49,7 @@ pub(super) fn build_custom_mir<'tcx>(
phase: MirPhase::Built,
source_scopes: IndexVec::new(),
generator: None,
- local_decls: LocalDecls::new(),
+ local_decls: IndexVec::new(),
user_type_annotations: IndexVec::new(),
arg_count: params.len(),
spread_arg: None,
diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs
index d72770e70..12b2f5d80 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse.rs
@@ -1,4 +1,4 @@
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::IndexSlice;
use rustc_middle::{mir::*, thir::*, ty::Ty};
use rustc_span::Span;
@@ -81,7 +81,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
}
}
- pub fn parse_args(&mut self, params: &IndexVec<ParamId, Param<'tcx>>) -> PResult<()> {
+ pub fn parse_args(&mut self, params: &IndexSlice<ParamId, Param<'tcx>>) -> PResult<()> {
for param in params.iter() {
let (var, span) = {
let pat = param.pat.as_ref().unwrap();
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index dbba529ae..931fe1b24 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -1,8 +1,9 @@
use rustc_middle::mir::interpret::{ConstValue, Scalar};
use rustc_middle::mir::tcx::PlaceTy;
+use rustc_middle::ty::cast::mir_cast_kind;
use rustc_middle::{mir::*, thir::*, ty};
use rustc_span::Span;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{FieldIdx, VariantIdx};
use crate::build::custom::ParseError;
use crate::build::expr::as_constant::as_constant_inner;
@@ -55,15 +56,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
Ok(TerminatorKind::Drop {
place: self.parse_place(args[0])?,
target: self.parse_block(args[1])?,
- unwind: None,
- })
- },
- @call("mir_drop_and_replace", args) => {
- Ok(TerminatorKind::DropAndReplace {
- place: self.parse_place(args[0])?,
- value: self.parse_operand(args[1])?,
- target: self.parse_block(args[2])?,
- unwind: None,
+ unwind: UnwindAction::Continue,
})
},
@call("mir_call", args) => {
@@ -133,7 +126,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
args,
destination,
target: Some(target),
- cleanup: None,
+ unwind: UnwindAction::Continue,
from_hir_call: *from_hir_call,
fn_span: *fn_span,
})
@@ -142,8 +135,12 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
}
fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
- parse_by_kind!(self, expr_id, _, "rvalue",
+ parse_by_kind!(self, expr_id, expr, "rvalue",
@call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
+ @call("mir_cast_transmute", args) => {
+ let source = self.parse_operand(args[0])?;
+ Ok(Rvalue::Cast(CastKind::Transmute, source, expr.ty))
+ },
@call("mir_checked", args) => {
parse_by_kind!(self, args[0], _, "binary op",
ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp(
@@ -151,6 +148,11 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
)),
)
},
+ @call("mir_offset", args) => {
+ let ptr = self.parse_operand(args[0])?;
+ let offset = self.parse_operand(args[1])?;
+ Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset))))
+ },
@call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
ExprKind::Borrow { borrow_kind, arg } => Ok(
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
@@ -167,6 +169,34 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
ExprKind::Repeat { value, count } => Ok(
Rvalue::Repeat(self.parse_operand(*value)?, *count)
),
+ ExprKind::Cast { source } => {
+ let source = self.parse_operand(*source)?;
+ let source_ty = source.ty(self.body.local_decls(), self.tcx);
+ let cast_kind = mir_cast_kind(source_ty, expr.ty);
+ Ok(Rvalue::Cast(cast_kind, source, expr.ty))
+ },
+ ExprKind::Tuple { fields } => Ok(
+ Rvalue::Aggregate(
+ Box::new(AggregateKind::Tuple),
+ fields.iter().map(|e| self.parse_operand(*e)).collect::<Result<_, _>>()?
+ )
+ ),
+ ExprKind::Array { fields } => {
+ let elem_ty = expr.ty.builtin_index().expect("ty must be an array");
+ Ok(Rvalue::Aggregate(
+ Box::new(AggregateKind::Array(elem_ty)),
+ fields.iter().map(|e| self.parse_operand(*e)).collect::<Result<_, _>>()?
+ ))
+ },
+ ExprKind::Adt(box AdtExpr{ adt_def, variant_index, substs, fields, .. }) => {
+ let is_union = adt_def.is_union();
+ let active_field_index = is_union.then(|| fields[0].name);
+
+ Ok(Rvalue::Aggregate(
+ Box::new(AggregateKind::Adt(adt_def.did(), *variant_index, substs, None, active_field_index)),
+ fields.iter().map(|f| self.parse_operand(f.expr)).collect::<Result<_, _>>()?
+ ))
+ },
_ => self.parse_operand(expr_id).map(Rvalue::Use),
)
}
@@ -198,7 +228,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
let (parent, proj) = parse_by_kind!(self, expr_id, expr, "place",
@call("mir_field", args) => {
let (parent, ty) = self.parse_place_inner(args[0])?;
- let field = Field::from_u32(self.parse_integer_literal(args[1])? as u32);
+ let field = FieldIdx::from_u32(self.parse_integer_literal(args[1])? as u32);
let field_ty = ty.field_ty(self.tcx, field);
let proj = PlaceElem::Field(field, field_ty);
let place = parent.project_deeper(&[proj], self.tcx);
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index cfacb5ea3..99291740a 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -62,21 +62,21 @@ pub fn as_constant_inner<'tcx>(
Constant { span, user_ty: None, literal }
}
ExprKind::NonHirLiteral { lit, ref user_ty } => {
- let user_ty = user_ty.as_ref().map(push_cuta).flatten();
+ let user_ty = user_ty.as_ref().and_then(push_cuta);
let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty);
Constant { span, user_ty, literal }
}
ExprKind::ZstLiteral { ref user_ty } => {
- let user_ty = user_ty.as_ref().map(push_cuta).flatten();
+ let user_ty = user_ty.as_ref().and_then(push_cuta);
let literal = ConstantKind::Val(ConstValue::ZeroSized, ty);
Constant { span, user_ty, literal }
}
ExprKind::NamedConst { def_id, substs, ref user_ty } => {
- let user_ty = user_ty.as_ref().map(push_cuta).flatten();
+ let user_ty = user_ty.as_ref().and_then(push_cuta);
let uneval = mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
let literal = ConstantKind::Unevaluated(uneval, ty);
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index ff3198847..6941da331 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -20,7 +20,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>,
) -> BlockAnd<Operand<'tcx>> {
let local_scope = self.local_scope();
- self.as_operand(block, Some(local_scope), expr, None, NeedsTemporary::Maybe)
+ self.as_operand(block, Some(local_scope), expr, LocalInfo::Boring, NeedsTemporary::Maybe)
}
/// Returns an operand suitable for use until the end of the current scope expression and
@@ -102,7 +102,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
mut block: BasicBlock,
scope: Option<region::Scope>,
expr: &Expr<'tcx>,
- local_info: Option<Box<LocalInfo<'tcx>>>,
+ local_info: LocalInfo<'tcx>,
needs_temporary: NeedsTemporary,
) -> BlockAnd<Operand<'tcx>> {
let this = self;
@@ -124,8 +124,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
Category::Constant | Category::Place | Category::Rvalue(..) => {
let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
- if this.local_decls[operand].local_info.is_none() {
- this.local_decls[operand].local_info = local_info;
+ // Overwrite temp local info if we have something more interesting to record.
+ if !matches!(local_info, LocalInfo::Boring) {
+ let decl_info = this.local_decls[operand].local_info.as_mut().assert_crate_local();
+ if let LocalInfo::Boring | LocalInfo::BlockTailTemp(_) = **decl_info {
+ **decl_info = local_info;
+ }
}
block.and(Operand::Move(Place::from(operand)))
}
@@ -178,6 +182,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
- this.as_operand(block, scope, expr, None, NeedsTemporary::Maybe)
+ this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::Maybe)
}
}
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 33200b80a..fb775766c 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -13,9 +13,7 @@ use rustc_middle::thir::*;
use rustc_middle::ty::AdtDef;
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance};
use rustc_span::Span;
-use rustc_target::abi::VariantIdx;
-
-use rustc_index::vec::Idx;
+use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
use std::assert_matches::assert_matches;
use std::iter;
@@ -91,8 +89,8 @@ fn convert_to_hir_projections_and_truncate_for_capture(
let hir_projection = match mir_projection {
ProjectionElem::Deref => HirProjectionKind::Deref,
ProjectionElem::Field(field, _) => {
- let variant = variant.unwrap_or(VariantIdx::new(0));
- HirProjectionKind::Field(field.index() as u32, variant)
+ let variant = variant.unwrap_or(FIRST_VARIANT);
+ HirProjectionKind::Field(*field, variant)
}
ProjectionElem::Downcast(.., idx) => {
// We don't expect to see multi-variant enums here, as earlier
@@ -295,7 +293,7 @@ impl<'tcx> PlaceBuilder<'tcx> {
&self.projection
}
- pub(crate) fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
+ pub(crate) fn field(self, f: FieldIdx, ty: Ty<'tcx>) -> Self {
self.project(PlaceElem::Field(f, ty))
}
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 a4e48c154..8631749a5 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -1,14 +1,15 @@
//! See docs in `build/expr/mod.rs`.
-use rustc_index::vec::Idx;
+use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ty::util::IntTypeExt;
-use rustc_target::abi::{Abi, Primitive};
+use rustc_target::abi::{Abi, FieldIdx, Primitive};
use crate::build::expr::as_place::PlaceBase;
use crate::build::expr::category::{Category, RvalueFunc};
use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
use rustc_hir::lang_items::LangItem;
use rustc_middle::middle::region;
+use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::Place;
use rustc_middle::mir::*;
@@ -63,7 +64,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
scope,
&this.thir[value],
- None,
+ LocalInfo::Boring,
NeedsTemporary::No
)
);
@@ -72,19 +73,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
ExprKind::Binary { op, lhs, rhs } => {
let lhs = unpack!(
- block =
- this.as_operand(block, scope, &this.thir[lhs], None, NeedsTemporary::Maybe)
+ block = this.as_operand(
+ block,
+ scope,
+ &this.thir[lhs],
+ LocalInfo::Boring,
+ NeedsTemporary::Maybe
+ )
);
let rhs = unpack!(
- block =
- this.as_operand(block, scope, &this.thir[rhs], None, NeedsTemporary::No)
+ block = this.as_operand(
+ block,
+ scope,
+ &this.thir[rhs],
+ LocalInfo::Boring,
+ NeedsTemporary::No
+ )
);
this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs)
}
ExprKind::Unary { op, arg } => {
let arg = unpack!(
- block =
- this.as_operand(block, scope, &this.thir[arg], None, NeedsTemporary::No)
+ block = this.as_operand(
+ block,
+ scope,
+ &this.thir[arg],
+ LocalInfo::Boring,
+ NeedsTemporary::No
+ )
);
// Check for -MIN on signed integers
if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() {
@@ -155,7 +171,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
args: vec![Operand::Move(size), Operand::Move(align)],
destination: storage,
target: Some(success),
- cleanup: None,
+ unwind: UnwindAction::Continue,
from_hir_call: false,
fn_span: expr_span,
},
@@ -259,7 +275,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} else {
let ty = source.ty;
let source = unpack!(
- block = this.as_operand(block, scope, source, None, NeedsTemporary::No)
+ block = this.as_operand(block, scope, source, LocalInfo::Boring, NeedsTemporary::No)
);
(source, ty)
};
@@ -271,8 +287,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
ExprKind::Pointer { cast, source } => {
let source = unpack!(
- block =
- this.as_operand(block, scope, &this.thir[source], None, NeedsTemporary::No)
+ block = this.as_operand(
+ block,
+ scope,
+ &this.thir[source],
+ LocalInfo::Boring,
+ NeedsTemporary::No
+ )
);
block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
}
@@ -305,7 +326,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// first process the set of fields
let el_ty = expr.ty.sequence_element_type(this.tcx);
- let fields: Vec<_> = fields
+ let fields: IndexVec<FieldIdx, _> = fields
.into_iter()
.copied()
.map(|f| {
@@ -314,7 +335,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
scope,
&this.thir[f],
- None,
+ LocalInfo::Boring,
NeedsTemporary::Maybe
)
)
@@ -326,7 +347,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ExprKind::Tuple { ref fields } => {
// see (*) above
// first process the set of fields
- let fields: Vec<_> = fields
+ let fields: IndexVec<FieldIdx, _> = fields
.into_iter()
.copied()
.map(|f| {
@@ -335,7 +356,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
scope,
&this.thir[f],
- None,
+ LocalInfo::Boring,
NeedsTemporary::Maybe
)
)
@@ -380,7 +401,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
// see (*) above
- let operands: Vec<_> = upvars
+ let operands: IndexVec<FieldIdx, _> = upvars
.into_iter()
.copied()
.map(|upvar| {
@@ -423,7 +444,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
scope,
upvar,
- None,
+ LocalInfo::Boring,
NeedsTemporary::Maybe
)
)
@@ -501,8 +522,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Category::of(&expr.kind),
Some(Category::Rvalue(RvalueFunc::AsRvalue) | Category::Constant)
));
- let operand =
- unpack!(block = this.as_operand(block, scope, expr, None, NeedsTemporary::No));
+ let operand = unpack!(
+ block =
+ this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No)
+ );
block.and(Rvalue::Use(operand))
}
}
@@ -519,30 +542,78 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
) -> BlockAnd<Rvalue<'tcx>> {
let source_info = self.source_info(span);
let bool_ty = self.tcx.types.bool;
- if self.check_overflow && op.is_checkable() && ty.is_integral() {
- let result_tup = self.tcx.mk_tup(&[ty, bool_ty]);
- let result_value = self.temp(result_tup, span);
-
- self.cfg.push_assign(
- block,
- source_info,
- result_value,
- Rvalue::CheckedBinaryOp(op, Box::new((lhs.to_copy(), rhs.to_copy()))),
- );
- let val_fld = Field::new(0);
- let of_fld = Field::new(1);
+ let rvalue = match op {
+ BinOp::Add | BinOp::Sub | BinOp::Mul if self.check_overflow && ty.is_integral() => {
+ let result_tup = self.tcx.mk_tup(&[ty, bool_ty]);
+ let result_value = self.temp(result_tup, span);
- let tcx = self.tcx;
- let val = tcx.mk_place_field(result_value, val_fld, ty);
- let of = tcx.mk_place_field(result_value, of_fld, bool_ty);
+ self.cfg.push_assign(
+ block,
+ source_info,
+ result_value,
+ Rvalue::CheckedBinaryOp(op, Box::new((lhs.to_copy(), rhs.to_copy()))),
+ );
+ let val_fld = FieldIdx::new(0);
+ let of_fld = FieldIdx::new(1);
- let err = AssertKind::Overflow(op, lhs, rhs);
+ let tcx = self.tcx;
+ let val = tcx.mk_place_field(result_value, val_fld, ty);
+ let of = tcx.mk_place_field(result_value, of_fld, bool_ty);
- block = self.assert(block, Operand::Move(of), false, err, span);
+ let err = AssertKind::Overflow(op, lhs, rhs);
+ block = self.assert(block, Operand::Move(of), false, err, span);
- block.and(Rvalue::Use(Operand::Move(val)))
- } else {
- if ty.is_integral() && (op == BinOp::Div || op == BinOp::Rem) {
+ Rvalue::Use(Operand::Move(val))
+ }
+ BinOp::Shl | BinOp::Shr if self.check_overflow && ty.is_integral() => {
+ // For an unsigned RHS, the shift is in-range for `rhs < bits`.
+ // For a signed RHS, `IntToInt` cast to the equivalent unsigned
+ // type and do that same comparison. Because the type is the
+ // same size, there's no negative shift amount that ends up
+ // overlapping with valid ones, thus it catches negatives too.
+ let (lhs_size, _) = ty.int_size_and_signed(self.tcx);
+ let rhs_ty = rhs.ty(&self.local_decls, self.tcx);
+ let (rhs_size, _) = rhs_ty.int_size_and_signed(self.tcx);
+
+ let (unsigned_rhs, unsigned_ty) = match rhs_ty.kind() {
+ ty::Uint(_) => (rhs.to_copy(), rhs_ty),
+ ty::Int(int_width) => {
+ let uint_ty = self.tcx.mk_mach_uint(int_width.to_unsigned());
+ let rhs_temp = self.temp(uint_ty, span);
+ self.cfg.push_assign(
+ block,
+ source_info,
+ rhs_temp,
+ Rvalue::Cast(CastKind::IntToInt, rhs.to_copy(), uint_ty),
+ );
+ (Operand::Move(rhs_temp), uint_ty)
+ }
+ _ => unreachable!("only integers are shiftable"),
+ };
+
+ // This can't overflow because the largest shiftable types are 128-bit,
+ // which fits in `u8`, the smallest possible `unsigned_ty`.
+ // (And `from_uint` will `bug!` if that's ever no longer true.)
+ let lhs_bits = Operand::const_from_scalar(
+ self.tcx,
+ unsigned_ty,
+ Scalar::from_uint(lhs_size.bits(), rhs_size),
+ span,
+ );
+
+ let inbounds = self.temp(bool_ty, span);
+ self.cfg.push_assign(
+ block,
+ source_info,
+ inbounds,
+ Rvalue::BinaryOp(BinOp::Lt, Box::new((unsigned_rhs, lhs_bits))),
+ );
+
+ let overflow_err = AssertKind::Overflow(op, lhs.to_copy(), rhs.to_copy());
+ block = self.assert(block, Operand::Move(inbounds), true, overflow_err, span);
+ Rvalue::BinaryOp(op, Box::new((lhs, rhs)))
+ }
+ BinOp::Div | BinOp::Rem if ty.is_integral() => {
// Checking division and remainder is more complex, since we 1. always check
// and 2. there are two possible failure cases, divide-by-zero and overflow.
@@ -601,10 +672,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block = self.assert(block, Operand::Move(of), false, overflow_err, span);
}
- }
- block.and(Rvalue::BinaryOp(op, Box::new((lhs, rhs))))
- }
+ Rvalue::BinaryOp(op, Box::new((lhs, rhs)))
+ }
+ _ => Rvalue::BinaryOp(op, Box::new((lhs, rhs))),
+ };
+ block.and(rvalue)
}
fn build_zero_repeat(
@@ -621,21 +694,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Repeating a const does nothing
} else {
// For a non-const, we may need to generate an appropriate `Drop`
- let value_operand =
- unpack!(block = this.as_operand(block, scope, value, None, NeedsTemporary::No));
+ let value_operand = unpack!(
+ block = this.as_operand(block, scope, value, LocalInfo::Boring, NeedsTemporary::No)
+ );
if let Operand::Move(to_drop) = value_operand {
let success = this.cfg.start_new_block();
this.cfg.terminate(
block,
outer_source_info,
- TerminatorKind::Drop { place: to_drop, target: success, unwind: None },
+ TerminatorKind::Drop {
+ place: to_drop,
+ target: success,
+ unwind: UnwindAction::Continue,
+ },
);
this.diverge_from(block);
block = success;
}
this.record_operands_moved(&[value_operand]);
}
- block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(elem_ty)), Vec::new()))
+ block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(elem_ty)), IndexVec::new()))
}
fn limit_capture_mutability(
diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
index 3d3cf7555..c8910c272 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -49,29 +49,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
debug!("creating temp {:?} with block_context: {:?}", local_decl, this.block_context);
- // Find out whether this temp is being created within the
- // tail expression of a block whose result is ignored.
- if let Some(tail_info) = this.block_context.currently_in_block_tail() {
- local_decl = local_decl.block_tail(tail_info);
- }
- match expr.kind {
+ let local_info = match expr.kind {
ExprKind::StaticRef { def_id, .. } => {
assert!(!this.tcx.is_thread_local_static(def_id));
local_decl.internal = true;
- local_decl.local_info =
- Some(Box::new(LocalInfo::StaticRef { def_id, is_thread_local: false }));
+ LocalInfo::StaticRef { def_id, is_thread_local: false }
}
ExprKind::ThreadLocalRef(def_id) => {
assert!(this.tcx.is_thread_local_static(def_id));
local_decl.internal = true;
- local_decl.local_info =
- Some(Box::new(LocalInfo::StaticRef { def_id, is_thread_local: true }));
+ LocalInfo::StaticRef { def_id, is_thread_local: true }
}
ExprKind::NamedConst { def_id, .. } | ExprKind::ConstParam { def_id, .. } => {
- local_decl.local_info = Some(Box::new(LocalInfo::ConstRef { def_id }));
+ LocalInfo::ConstRef { def_id }
}
- _ => {}
- }
+ // Find out whether this temp is being created within the
+ // tail expression of a block whose result is ignored.
+ _ if let Some(tail_info) = this.block_context.currently_in_block_tail() => {
+ LocalInfo::BlockTailTemp(tail_info)
+ }
+ _ => LocalInfo::Boring,
+ };
+ **local_decl.local_info.as_mut().assert_crate_local() = local_info;
this.local_decls.push(local_decl)
};
let temp_place = Place::from(temp);
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index dac9bf0a8..05a723a6b 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -6,7 +6,6 @@ use rustc_ast::InlineAsmOptions;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir;
-use rustc_index::vec::Idx;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty::CanonicalUserTypeAnnotation;
@@ -229,7 +228,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.cfg.terminate(
loop_block,
source_info,
- TerminatorKind::FalseUnwind { real_target: body_block, unwind: None },
+ TerminatorKind::FalseUnwind {
+ real_target: body_block,
+ unwind: UnwindAction::Continue,
+ },
);
this.diverge_from(loop_block);
@@ -265,7 +267,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
TerminatorKind::Call {
func: fun,
args,
- cleanup: None,
+ unwind: UnwindAction::Continue,
destination,
// The presence or absence of a return edge affects control-flow sensitive
// MIR checks and ultimately whether code is accepted or not. We can only
@@ -319,7 +321,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// See the notes for `ExprKind::Array` in `as_rvalue` and for
// `ExprKind::Borrow` above.
let is_union = adt_def.is_union();
- let active_field_index = is_union.then(|| fields[0].name.index());
+ let active_field_index = is_union.then(|| fields[0].name);
let scope = this.local_scope();
@@ -328,7 +330,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let fields_map: FxHashMap<_, _> = fields
.into_iter()
.map(|f| {
- let local_info = Box::new(LocalInfo::AggregateTemp);
(
f.name,
unpack!(
@@ -336,7 +337,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
Some(scope),
&this.thir[f.expr],
- Some(local_info),
+ LocalInfo::AggregateTemp,
NeedsTemporary::Maybe,
)
),
@@ -344,10 +345,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
})
.collect();
- let field_names: Vec<_> =
- (0..adt_def.variant(variant_index).fields.len()).map(Field::new).collect();
+ let field_names = adt_def.variant(variant_index).fields.indices();
- let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base {
+ let fields = if let Some(FruInfo { base, field_types }) = base {
let place_builder =
unpack!(block = this.as_place_builder(block, &this.thir[*base]));
@@ -364,7 +364,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
})
.collect()
} else {
- field_names.iter().filter_map(|n| fields_map.get(n).cloned()).collect()
+ field_names.filter_map(|n| fields_map.get(&n).cloned()).collect()
};
let inferred_ty = expr.ty;
@@ -469,7 +469,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} else {
Some(destination_block)
},
- cleanup: None,
+ unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) {
+ UnwindAction::Continue
+ } else {
+ UnwindAction::Unreachable
+ },
},
);
if options.contains(InlineAsmOptions::MAY_UNWIND) {
@@ -526,7 +530,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
Some(scope),
&this.thir[value],
- None,
+ LocalInfo::Boring,
NeedsTemporary::No
)
);
diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs
index 780836851..ea5aeb67d 100644
--- a/compiler/rustc_mir_build/src/build/expr/stmt.rs
+++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs
@@ -40,7 +40,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Generate better code for things that don't need to be
// dropped.
if lhs.ty.needs_drop(this.tcx, this.param_env) {
- let rhs = unpack!(block = this.as_local_operand(block, rhs));
+ let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
let lhs = unpack!(block = this.as_place(block, lhs));
unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs));
} else {
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index de2851a1a..4926ff85d 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -556,6 +556,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
_ => {
let place_builder = unpack!(block = self.as_place_builder(block, initializer));
+
+ if let Some(place) = place_builder.try_to_place(self) {
+ let source_info = self.source_info(initializer.span);
+ self.cfg.push_place_mention(block, source_info, place);
+ }
+
self.place_into_pattern(block, &irrefutable_pat, place_builder, true)
}
}
@@ -576,13 +582,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
false,
&mut [&mut candidate],
);
+
// For matches and function arguments, the place that is being matched
// can be set when creating the variables. But the place for
// let PATTERN = ... might not even exist until we do the assignment.
// so we set it here instead.
if set_match_place {
- let mut candidate_ref = &candidate;
- while let Some(next) = {
+ let mut next = Some(&candidate);
+ while let Some(candidate_ref) = next.take() {
for binding in &candidate_ref.bindings {
let local = self.var_local_id(binding.var_id, OutsideGuard);
// `try_to_place` may fail if it is unable to resolve the given
@@ -600,9 +607,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// };
// ```
if let Some(place) = initializer.try_to_place(self) {
- let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+ let LocalInfo::User(BindingForm::Var(
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
- )))) = self.local_decls[local].local_info else {
+ )) = **self.local_decls[local].local_info.as_mut().assert_crate_local() else {
bug!("Let binding to non-user variable.")
};
*match_place = Some(place);
@@ -610,9 +617,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
// All of the subcandidates should bind the same locals, so we
// only visit the first one.
- candidate_ref.subcandidates.get(0)
- } {
- candidate_ref = next;
+ next = candidate_ref.subcandidates.get(0)
}
}
@@ -1749,7 +1754,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let fake_borrow_ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty);
let mut fake_borrow_temp = LocalDecl::new(fake_borrow_ty, temp_span);
fake_borrow_temp.internal = self.local_decls[matched_place.local].internal;
- fake_borrow_temp.local_info = Some(Box::new(LocalInfo::FakeBorrow));
+ fake_borrow_temp.local_info = ClearCrossCrate::Set(Box::new(LocalInfo::FakeBorrow));
let fake_borrow_temp = self.local_decls.push(fake_borrow_temp);
(matched_place, fake_borrow_temp)
@@ -1881,6 +1886,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// let place = Foo::new();
// match place { Foo { .. } if { let tmp1 = &place; inspect(*tmp1) }
// => { let tmp2 = place; feed(tmp2) }, ... }
+ // ```
//
// And an input like:
//
@@ -2218,8 +2224,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) },
source_info,
internal: false,
- is_block_tail: None,
- local_info: Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+ local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var(
VarBindingForm {
binding_mode,
// hypothetically, `visit_primary_bindings` could try to unzip
@@ -2230,13 +2235,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
opt_match_place,
pat_span,
},
- ))))),
+ )))),
};
let for_arm_body = self.local_decls.push(local);
self.var_debug_info.push(VarDebugInfo {
name,
source_info: debug_source_info,
value: VarDebugInfoContents::Place(for_arm_body.into()),
+ argument_index: None,
});
let locals = if has_guard.0 {
let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> {
@@ -2247,15 +2253,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
user_ty: None,
source_info,
internal: false,
- is_block_tail: None,
- local_info: Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(
+ local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(
BindingForm::RefForGuard,
- )))),
+ ))),
});
self.var_debug_info.push(VarDebugInfo {
name,
source_info: debug_source_info,
value: VarDebugInfoContents::Place(ref_for_guard.into()),
+ argument_index: None,
});
LocalsForNode::ForGuard { ref_for_guard, for_arm_body }
} else {
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 2de89f67d..8a03ea7e2 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -263,7 +263,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
args: vec![Operand::Move(ref_string)],
destination: ref_str,
target: Some(eq_block),
- cleanup: None,
+ unwind: UnwindAction::Continue,
from_hir_call: false,
fn_span: source_info.span
}
@@ -466,7 +466,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
args: vec![val, expect],
destination: eq_result,
target: Some(eq_block),
- cleanup: None,
+ unwind: UnwindAction::Continue,
from_hir_call: false,
fn_span: source_info.span,
},
diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs
index baeb2718c..90d78658f 100644
--- a/compiler/rustc_mir_build/src/build/misc.rs
+++ b/compiler/rustc_mir_build/src/build/misc.rs
@@ -5,7 +5,7 @@ use crate::build::Builder;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;
impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -66,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
pub(crate) fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
let tcx = self.tcx;
let ty = place.ty(&self.local_decls, tcx).ty;
- if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, DUMMY_SP) {
+ if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty) {
Operand::Move(place)
} else {
Operand::Copy(place)
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index b3f9d8282..bc50bcbc3 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -3,6 +3,7 @@ use crate::build::expr::as_place::PlaceBuilder;
use crate::build::scope::DropKind;
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
+use rustc_ast::attr;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sorted_map::SortedIndexMultiMap;
use rustc_errors::ErrorGuaranteed;
@@ -10,7 +11,7 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{GeneratorKind, Node};
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::{Idx, IndexSlice, IndexVec};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
use rustc_middle::middle::region;
@@ -24,6 +25,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_span::Symbol;
+use rustc_target::abi::FieldIdx;
use rustc_target::spec::abi::Abi;
use super::lints;
@@ -48,17 +50,15 @@ pub(crate) fn mir_built(
/// Construct the MIR for a given `DefId`.
fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
// Ensure unsafeck and abstract const building is ran before we steal the THIR.
- // We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query
- // if inputs are green. This can cause ICEs when calling `thir_abstract_const` after
- // THIR has been stolen if we haven't computed this query yet.
match def {
ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => {
- tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did));
- drop(tcx.thir_abstract_const_of_const_arg((did, const_param_did)));
+ tcx.ensure_with_value().thir_check_unsafety_for_const_arg((did, const_param_did));
+ tcx.ensure_with_value().thir_abstract_const_of_const_arg((did, const_param_did));
}
ty::WithOptConstParam { did, const_param_did: None } => {
- tcx.ensure().thir_check_unsafety(did);
- drop(tcx.thir_abstract_const(did));
+ tcx.ensure_with_value().thir_check_unsafety(did);
+ tcx.ensure_with_value().thir_abstract_const(did);
+ tcx.ensure_with_value().check_match(did);
}
}
@@ -683,7 +683,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Some functions always have overflow checks enabled,
// however, they may not get codegen'd, depending on
// the settings for the crate they are codegened in.
- let mut check_overflow = tcx.sess.contains_name(attrs, sym::rustc_inherit_overflow_checks);
+ let mut check_overflow = attr::contains_name(attrs, sym::rustc_inherit_overflow_checks);
// Respect -C overflow-checks.
check_overflow |= tcx.sess.overflow_checks();
// Constants always need overflow checks.
@@ -795,7 +795,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let mutability = captured_place.mutability;
let mut projs = closure_env_projs.clone();
- projs.push(ProjectionElem::Field(Field::new(i), ty));
+ projs.push(ProjectionElem::Field(FieldIdx::new(i), ty));
match capture {
ty::UpvarCapture::ByValue => {}
ty::UpvarCapture::ByRef(..) => {
@@ -811,6 +811,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
name,
source_info: SourceInfo::outermost(captured_place.var_ident.span),
value: VarDebugInfoContents::Place(use_place),
+ argument_index: None,
});
let capture = Capture { captured_place, use_place, mutability };
@@ -822,12 +823,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn args_and_body(
&mut self,
mut block: BasicBlock,
- arguments: &IndexVec<ParamId, Param<'tcx>>,
+ arguments: &IndexSlice<ParamId, Param<'tcx>>,
argument_scope: region::Scope,
expr: &Expr<'tcx>,
) -> BlockAnd<()> {
// Allocate locals for the function arguments
- for param in arguments.iter() {
+ for (argument_index, param) in arguments.iter().enumerate() {
let source_info =
SourceInfo::outermost(param.pat.as_ref().map_or(self.fn_span, |pat| pat.span));
let arg_local =
@@ -839,6 +840,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
name,
source_info,
value: VarDebugInfoContents::Place(arg_local.into()),
+ argument_index: Some(argument_index as u16 + 1),
});
}
}
@@ -879,21 +881,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} => {
self.local_decls[local].mutability = mutability;
self.local_decls[local].source_info.scope = self.source_scope;
- self.local_decls[local].local_info = if let Some(kind) = param.self_kind {
- Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(
- BindingForm::ImplicitSelf(kind),
- ))))
- } else {
- let binding_mode = ty::BindingMode::BindByValue(mutability);
- Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
- VarBindingForm {
+ **self.local_decls[local].local_info.as_mut().assert_crate_local() =
+ if let Some(kind) = param.self_kind {
+ LocalInfo::User(BindingForm::ImplicitSelf(kind))
+ } else {
+ let binding_mode = ty::BindingMode::BindByValue(mutability);
+ LocalInfo::User(BindingForm::Var(VarBindingForm {
binding_mode,
opt_ty_info: param.ty_span,
opt_match_place: Some((None, span)),
pat_span: span,
- },
- )))))
- };
+ }))
+ };
self.var_indices.insert(var, LocalsForNode::One(local));
}
_ => {
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 591b41633..f32d2db4e 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -86,12 +86,12 @@ use std::mem;
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::HirId;
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::{IndexSlice, IndexVec};
use rustc_middle::middle::region;
use rustc_middle::mir::*;
use rustc_middle::thir::{Expr, LintLevel};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{DesugaringKind, Span, DUMMY_SP};
#[derive(Debug)]
pub struct Scopes<'tcx> {
@@ -360,7 +360,7 @@ impl DropTree {
fn link_blocks<'tcx>(
&self,
cfg: &mut CFG<'tcx>,
- blocks: &IndexVec<DropIdx, Option<BasicBlock>>,
+ blocks: &IndexSlice<DropIdx, Option<BasicBlock>>,
) {
for (drop_idx, drop_data) in self.drops.iter_enumerated().rev() {
let Some(block) = blocks[drop_idx] else { continue };
@@ -369,7 +369,7 @@ impl DropTree {
let terminator = TerminatorKind::Drop {
target: blocks[drop_data.1].unwrap(),
// The caller will handle this if needed.
- unwind: None,
+ unwind: UnwindAction::Terminate,
place: drop_data.0.local.into(),
};
cfg.terminate(block, drop_data.0.source_info, terminator);
@@ -1072,7 +1072,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. }
- | TerminatorKind::DropAndReplace { .. }
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::InlineAsm { .. }
),
@@ -1118,24 +1117,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
/// Utility function for *non*-scope code to build their own drops
+ /// Force a drop at this point in the MIR by creating a new block.
pub(crate) fn build_drop_and_replace(
&mut self,
block: BasicBlock,
span: Span,
place: Place<'tcx>,
- value: Operand<'tcx>,
+ value: Rvalue<'tcx>,
) -> BlockAnd<()> {
+ let span = self.tcx.with_stable_hashing_context(|hcx| {
+ span.mark_with_reason(None, DesugaringKind::Replace, self.tcx.sess.edition(), hcx)
+ });
let source_info = self.source_info(span);
- let next_target = self.cfg.start_new_block();
+
+ // create the new block for the assignment
+ let assign = self.cfg.start_new_block();
+ self.cfg.push_assign(assign, source_info, place, value.clone());
+
+ // create the new block for the assignment in the case of unwinding
+ let assign_unwind = self.cfg.start_new_cleanup_block();
+ self.cfg.push_assign(assign_unwind, source_info, place, value.clone());
self.cfg.terminate(
block,
source_info,
- TerminatorKind::DropAndReplace { place, value, target: next_target, unwind: None },
+ TerminatorKind::Drop {
+ place,
+ target: assign,
+ unwind: UnwindAction::Cleanup(assign_unwind),
+ },
);
self.diverge_from(block);
- next_target.unit()
+ assign.unit()
}
/// Creates an `Assert` terminator and return the success block.
@@ -1155,7 +1169,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.cfg.terminate(
block,
source_info,
- TerminatorKind::Assert { cond, expected, msg, target: success_block, cleanup: None },
+ TerminatorKind::Assert {
+ cond,
+ expected,
+ msg,
+ target: success_block,
+ unwind: UnwindAction::Continue,
+ },
);
self.diverge_from(block);
@@ -1234,7 +1254,11 @@ fn build_scope_drops<'tcx>(
cfg.terminate(
block,
source_info,
- TerminatorKind::Drop { place: local.into(), target: next, unwind: None },
+ TerminatorKind::Drop {
+ place: local.into(),
+ target: next,
+ unwind: UnwindAction::Continue,
+ },
);
block = next;
}
@@ -1413,18 +1437,24 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
let term = &mut cfg.block_data_mut(from).terminator_mut();
match &mut term.kind {
- TerminatorKind::Drop { unwind, .. }
- | TerminatorKind::DropAndReplace { unwind, .. }
- | TerminatorKind::FalseUnwind { unwind, .. }
- | TerminatorKind::Call { cleanup: unwind, .. }
- | TerminatorKind::Assert { cleanup: unwind, .. }
- | TerminatorKind::InlineAsm { cleanup: unwind, .. } => {
- *unwind = Some(to);
+ TerminatorKind::Drop { unwind, .. } => {
+ if let UnwindAction::Cleanup(unwind) = *unwind {
+ let source_info = term.source_info;
+ cfg.terminate(unwind, source_info, TerminatorKind::Goto { target: to });
+ } else {
+ *unwind = UnwindAction::Cleanup(to);
+ }
+ }
+ TerminatorKind::FalseUnwind { unwind, .. }
+ | TerminatorKind::Call { unwind, .. }
+ | TerminatorKind::Assert { unwind, .. }
+ | TerminatorKind::InlineAsm { unwind, .. } => {
+ *unwind = UnwindAction::Cleanup(to);
}
TerminatorKind::Goto { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::Resume
- | TerminatorKind::Abort
+ | TerminatorKind::Terminate
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::Yield { .. }