mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 05:26:47 +00:00
Pass THIR ExprIds in MIR building
This commit is contained in:
parent
e004adb556
commit
68d684cbff
@ -15,7 +15,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
) -> BlockAnd<()> {
|
||||
let Block { region_scope, span, ref stmts, expr, targeted_by_break, safety_mode } =
|
||||
self.thir[ast_block];
|
||||
let expr = expr.map(|expr| &self.thir[expr]);
|
||||
self.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
|
||||
if targeted_by_break {
|
||||
this.in_breakable_scope(None, destination, span, |this| {
|
||||
@ -49,7 +48,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
mut block: BasicBlock,
|
||||
span: Span,
|
||||
stmts: &[StmtId],
|
||||
expr: Option<&Expr<'tcx>>,
|
||||
expr: Option<ExprId>,
|
||||
safety_mode: BlockSafety,
|
||||
region_scope: Scope,
|
||||
) -> BlockAnd<()> {
|
||||
@ -90,7 +89,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let si = (*scope, source_info);
|
||||
unpack!(
|
||||
block = this.in_scope(si, LintLevel::Inherited, |this| {
|
||||
this.stmt_expr(block, &this.thir[*expr], Some(*scope))
|
||||
this.stmt_expr(block, *expr, Some(*scope))
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -205,8 +204,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let visibility_scope =
|
||||
Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
|
||||
|
||||
let init = &this.thir[*initializer];
|
||||
let initializer_span = init.span;
|
||||
let initializer_span = this.thir[*initializer].span;
|
||||
let scope = (*init_scope, source_info);
|
||||
let failure = unpack!(
|
||||
block = this.in_scope(scope, *lint_level, |this| {
|
||||
@ -232,7 +230,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
);
|
||||
this.ast_let_else(
|
||||
block,
|
||||
init,
|
||||
*initializer,
|
||||
initializer_span,
|
||||
*else_block,
|
||||
&last_remainder_scope,
|
||||
@ -276,9 +274,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
|
||||
|
||||
// Evaluate the initializer, if present.
|
||||
if let Some(init) = initializer {
|
||||
let init = &this.thir[*init];
|
||||
let initializer_span = init.span;
|
||||
if let Some(init) = *initializer {
|
||||
let initializer_span = this.thir[init].span;
|
||||
let scope = (*init_scope, source_info);
|
||||
|
||||
unpack!(
|
||||
@ -334,13 +331,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// of the block, which is stored into `destination`.
|
||||
let tcx = this.tcx;
|
||||
let destination_ty = destination.ty(&this.local_decls, tcx).ty;
|
||||
if let Some(expr) = expr {
|
||||
if let Some(expr_id) = expr {
|
||||
let expr = &this.thir[expr_id];
|
||||
let tail_result_is_ignored =
|
||||
destination_ty.is_unit() || this.block_context.currently_ignores_tail_results();
|
||||
this.block_context
|
||||
.push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span });
|
||||
|
||||
unpack!(block = this.expr_into_dest(destination, block, expr));
|
||||
unpack!(block = this.expr_into_dest(destination, block, expr_id));
|
||||
let popped = this.block_context.pop();
|
||||
|
||||
assert!(popped.is_some_and(|bf| bf.is_tail_expr()));
|
||||
|
@ -17,10 +17,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn as_local_operand(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<Operand<'tcx>> {
|
||||
let local_scope = self.local_scope();
|
||||
self.as_operand(block, Some(local_scope), expr, LocalInfo::Boring, NeedsTemporary::Maybe)
|
||||
self.as_operand(block, Some(local_scope), expr_id, LocalInfo::Boring, NeedsTemporary::Maybe)
|
||||
}
|
||||
|
||||
/// Returns an operand suitable for use until the end of the current scope expression and
|
||||
@ -76,7 +76,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn as_local_call_operand(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr: ExprId,
|
||||
) -> BlockAnd<Operand<'tcx>> {
|
||||
let local_scope = self.local_scope();
|
||||
self.as_call_operand(block, Some(local_scope), expr)
|
||||
@ -101,17 +101,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
scope: Option<region::Scope>,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
local_info: LocalInfo<'tcx>,
|
||||
needs_temporary: NeedsTemporary,
|
||||
) -> BlockAnd<Operand<'tcx>> {
|
||||
let this = self;
|
||||
|
||||
let expr = &this.thir[expr_id];
|
||||
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
|
||||
let source_info = this.source_info(expr.span);
|
||||
let region_scope = (region_scope, source_info);
|
||||
return this.in_scope(region_scope, lint_level, |this| {
|
||||
this.as_operand(block, scope, &this.thir[value], local_info, needs_temporary)
|
||||
this.as_operand(block, scope, value, local_info, needs_temporary)
|
||||
});
|
||||
}
|
||||
|
||||
@ -126,7 +127,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block.and(Operand::Constant(Box::new(constant)))
|
||||
}
|
||||
Category::Constant | Category::Place | Category::Rvalue(..) => {
|
||||
let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
|
||||
let operand = unpack!(block = this.as_temp(block, scope, expr_id, Mutability::Mut));
|
||||
// Overwrite temp local info if we have something more interesting to record.
|
||||
if !matches!(local_info, LocalInfo::Boring) {
|
||||
let decl_info =
|
||||
@ -144,16 +145,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
scope: Option<region::Scope>,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<Operand<'tcx>> {
|
||||
debug!("as_call_operand(block={:?}, expr={:?})", block, expr);
|
||||
let this = self;
|
||||
let expr = &this.thir[expr_id];
|
||||
debug!("as_call_operand(block={:?}, expr={:?})", block, expr);
|
||||
|
||||
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
|
||||
let source_info = this.source_info(expr.span);
|
||||
let region_scope = (region_scope, source_info);
|
||||
return this.in_scope(region_scope, lint_level, |this| {
|
||||
this.as_call_operand(block, scope, &this.thir[value])
|
||||
this.as_call_operand(block, scope, value)
|
||||
});
|
||||
}
|
||||
|
||||
@ -171,9 +173,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// type, and that value is coming from the deref of a box.
|
||||
if let ExprKind::Deref { arg } = expr.kind {
|
||||
// Generate let tmp0 = arg0
|
||||
let operand = unpack!(
|
||||
block = this.as_temp(block, scope, &this.thir[arg], Mutability::Mut)
|
||||
);
|
||||
let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut));
|
||||
|
||||
// Return the operand *tmp0 to be used as the call argument
|
||||
let place = Place {
|
||||
@ -186,6 +186,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::Maybe)
|
||||
this.as_operand(block, scope, expr_id, LocalInfo::Boring, NeedsTemporary::Maybe)
|
||||
}
|
||||
}
|
||||
|
@ -354,9 +354,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn as_place(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<Place<'tcx>> {
|
||||
let place_builder = unpack!(block = self.as_place_builder(block, expr));
|
||||
let place_builder = unpack!(block = self.as_place_builder(block, expr_id));
|
||||
block.and(place_builder.to_place(self))
|
||||
}
|
||||
|
||||
@ -365,9 +365,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn as_place_builder(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<PlaceBuilder<'tcx>> {
|
||||
self.expr_as_place(block, expr, Mutability::Mut, None)
|
||||
self.expr_as_place(block, expr_id, Mutability::Mut, None)
|
||||
}
|
||||
|
||||
/// Compile `expr`, yielding a place that we can move from etc.
|
||||
@ -378,9 +378,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn as_read_only_place(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<Place<'tcx>> {
|
||||
let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
|
||||
let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr_id));
|
||||
block.and(place_builder.to_place(self))
|
||||
}
|
||||
|
||||
@ -393,18 +393,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fn as_read_only_place_builder(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<PlaceBuilder<'tcx>> {
|
||||
self.expr_as_place(block, expr, Mutability::Not, None)
|
||||
self.expr_as_place(block, expr_id, Mutability::Not, None)
|
||||
}
|
||||
|
||||
fn expr_as_place(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
mutability: Mutability,
|
||||
fake_borrow_temps: Option<&mut Vec<Local>>,
|
||||
) -> BlockAnd<PlaceBuilder<'tcx>> {
|
||||
let expr = &self.thir[expr_id];
|
||||
debug!("expr_as_place(block={:?}, expr={:?}, mutability={:?})", block, expr, mutability);
|
||||
|
||||
let this = self;
|
||||
@ -413,14 +414,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
match expr.kind {
|
||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||
this.in_scope((region_scope, source_info), lint_level, |this| {
|
||||
this.expr_as_place(block, &this.thir[value], mutability, fake_borrow_temps)
|
||||
this.expr_as_place(block, value, mutability, fake_borrow_temps)
|
||||
})
|
||||
}
|
||||
ExprKind::Field { lhs, variant_index, name } => {
|
||||
let lhs = &this.thir[lhs];
|
||||
let lhs_expr = &this.thir[lhs];
|
||||
let mut place_builder =
|
||||
unpack!(block = this.expr_as_place(block, lhs, mutability, fake_borrow_temps,));
|
||||
if let ty::Adt(adt_def, _) = lhs.ty.kind() {
|
||||
if let ty::Adt(adt_def, _) = lhs_expr.ty.kind() {
|
||||
if adt_def.is_enum() {
|
||||
place_builder = place_builder.downcast(*adt_def, variant_index);
|
||||
}
|
||||
@ -428,16 +429,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block.and(place_builder.field(name, expr.ty))
|
||||
}
|
||||
ExprKind::Deref { arg } => {
|
||||
let place_builder = unpack!(
|
||||
block =
|
||||
this.expr_as_place(block, &this.thir[arg], mutability, fake_borrow_temps,)
|
||||
);
|
||||
let place_builder =
|
||||
unpack!(block = this.expr_as_place(block, arg, mutability, fake_borrow_temps,));
|
||||
block.and(place_builder.deref())
|
||||
}
|
||||
ExprKind::Index { lhs, index } => this.lower_index_expression(
|
||||
block,
|
||||
&this.thir[lhs],
|
||||
&this.thir[index],
|
||||
lhs,
|
||||
index,
|
||||
mutability,
|
||||
fake_borrow_temps,
|
||||
expr.temp_lifetime,
|
||||
@ -461,12 +460,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
ExprKind::PlaceTypeAscription { source, ref user_ty } => {
|
||||
let place_builder = unpack!(
|
||||
block = this.expr_as_place(
|
||||
block,
|
||||
&this.thir[source],
|
||||
mutability,
|
||||
fake_borrow_temps,
|
||||
)
|
||||
block = this.expr_as_place(block, source, mutability, fake_borrow_temps,)
|
||||
);
|
||||
if let Some(user_ty) = user_ty {
|
||||
let annotation_index =
|
||||
@ -494,9 +488,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block.and(place_builder)
|
||||
}
|
||||
ExprKind::ValueTypeAscription { source, ref user_ty } => {
|
||||
let source = &this.thir[source];
|
||||
let temp =
|
||||
unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability));
|
||||
let source_expr = &this.thir[source];
|
||||
let temp = unpack!(
|
||||
block = this.as_temp(block, source_expr.temp_lifetime, source, mutability)
|
||||
);
|
||||
if let Some(user_ty) = user_ty {
|
||||
let annotation_index =
|
||||
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
||||
@ -562,7 +557,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// these are not places, so we need to make a temporary.
|
||||
debug_assert!(!matches!(Category::of(&expr.kind), Some(Category::Place)));
|
||||
let temp =
|
||||
unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability));
|
||||
unpack!(block = this.as_temp(block, expr.temp_lifetime, expr_id, mutability));
|
||||
block.and(PlaceBuilder::from(temp))
|
||||
}
|
||||
}
|
||||
@ -591,8 +586,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fn lower_index_expression(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
base: &Expr<'tcx>,
|
||||
index: &Expr<'tcx>,
|
||||
base: ExprId,
|
||||
index: ExprId,
|
||||
mutability: Mutability,
|
||||
fake_borrow_temps: Option<&mut Vec<Local>>,
|
||||
temp_lifetime: Option<region::Scope>,
|
||||
@ -609,7 +604,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// Making this a *fresh* temporary means we do not have to worry about
|
||||
// the index changing later: Nothing will ever change this temporary.
|
||||
// The "retagging" transformation (for Stacked Borrows) relies on this.
|
||||
let idx = unpack!(block = self.as_temp(block, temp_lifetime, index, Mutability::Not,));
|
||||
let idx = unpack!(block = self.as_temp(block, temp_lifetime, index, Mutability::Not));
|
||||
|
||||
block = self.bounds_check(block, &base_place, idx, expr_span, source_info);
|
||||
|
||||
|
@ -27,10 +27,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn as_local_rvalue(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<Rvalue<'tcx>> {
|
||||
let local_scope = self.local_scope();
|
||||
self.as_rvalue(block, Some(local_scope), expr)
|
||||
self.as_rvalue(block, Some(local_scope), expr_id)
|
||||
}
|
||||
|
||||
/// Compile `expr`, yielding an rvalue.
|
||||
@ -38,11 +38,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
scope: Option<region::Scope>,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<Rvalue<'tcx>> {
|
||||
let this = self;
|
||||
let expr = &this.thir[expr_id];
|
||||
debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr);
|
||||
|
||||
let this = self;
|
||||
let expr_span = expr.span;
|
||||
let source_info = this.source_info(expr_span);
|
||||
|
||||
@ -50,9 +51,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(did)),
|
||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||
let region_scope = (region_scope, source_info);
|
||||
this.in_scope(region_scope, lint_level, |this| {
|
||||
this.as_rvalue(block, scope, &this.thir[value])
|
||||
})
|
||||
this.in_scope(region_scope, lint_level, |this| this.as_rvalue(block, scope, value))
|
||||
}
|
||||
ExprKind::Repeat { value, count } => {
|
||||
if Some(0) == count.try_eval_target_usize(this.tcx, this.param_env) {
|
||||
@ -62,7 +61,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block = this.as_operand(
|
||||
block,
|
||||
scope,
|
||||
&this.thir[value],
|
||||
value,
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::No
|
||||
)
|
||||
@ -75,31 +74,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block = this.as_operand(
|
||||
block,
|
||||
scope,
|
||||
&this.thir[lhs],
|
||||
lhs,
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::Maybe
|
||||
)
|
||||
);
|
||||
let rhs = unpack!(
|
||||
block = this.as_operand(
|
||||
block,
|
||||
scope,
|
||||
&this.thir[rhs],
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::No
|
||||
)
|
||||
block =
|
||||
this.as_operand(block, scope, 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],
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::No
|
||||
)
|
||||
block =
|
||||
this.as_operand(block, scope, arg, LocalInfo::Boring, NeedsTemporary::No)
|
||||
);
|
||||
// Check for -MIN on signed integers
|
||||
if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() {
|
||||
@ -126,7 +115,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block.and(Rvalue::UnaryOp(op, arg))
|
||||
}
|
||||
ExprKind::Box { value } => {
|
||||
let value = &this.thir[value];
|
||||
let value_ty = this.thir[value].ty;
|
||||
let tcx = this.tcx;
|
||||
|
||||
// `exchange_malloc` is unsafe but box is safe, so need a new scope.
|
||||
@ -142,7 +131,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block,
|
||||
synth_info,
|
||||
size,
|
||||
Rvalue::NullaryOp(NullOp::SizeOf, value.ty),
|
||||
Rvalue::NullaryOp(NullOp::SizeOf, value_ty),
|
||||
);
|
||||
|
||||
let align = this.temp(tcx.types.usize, expr_span);
|
||||
@ -150,7 +139,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block,
|
||||
synth_info,
|
||||
align,
|
||||
Rvalue::NullaryOp(NullOp::AlignOf, value.ty),
|
||||
Rvalue::NullaryOp(NullOp::AlignOf, value_ty),
|
||||
);
|
||||
|
||||
// malloc some memory of suitable size and align:
|
||||
@ -192,7 +181,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// Transmute `*mut u8` to the box (thus far, uninitialized):
|
||||
let box_ = Rvalue::ShallowInitBox(Operand::Move(storage), value.ty);
|
||||
let box_ = Rvalue::ShallowInitBox(Operand::Move(storage), value_ty);
|
||||
this.cfg.push_assign(block, source_info, Place::from(result), box_);
|
||||
|
||||
// initialize the box contents:
|
||||
@ -200,24 +189,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block = this.expr_into_dest(
|
||||
this.tcx.mk_place_deref(Place::from(result)),
|
||||
block,
|
||||
value
|
||||
value,
|
||||
)
|
||||
);
|
||||
block.and(Rvalue::Use(Operand::Move(Place::from(result))))
|
||||
}
|
||||
ExprKind::Cast { source } => {
|
||||
let source = &this.thir[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.ty.kind()
|
||||
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.param_env.and(source.ty));
|
||||
let discr = this.temp(discr_ty, source.span);
|
||||
let layout = this.tcx.layout_of(this.param_env.and(source_expr.ty));
|
||||
let discr = this.temp(discr_ty, source_expr.span);
|
||||
this.cfg.push_assign(
|
||||
block,
|
||||
source_info,
|
||||
@ -296,7 +285,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
(op, ty)
|
||||
} else {
|
||||
let ty = source.ty;
|
||||
let ty = source_expr.ty;
|
||||
let source = unpack!(
|
||||
block = this.as_operand(
|
||||
block,
|
||||
@ -310,7 +299,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
};
|
||||
let from_ty = CastTy::from_ty(ty);
|
||||
let cast_ty = CastTy::from_ty(expr.ty);
|
||||
debug!("ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}", expr.ty,);
|
||||
debug!("ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}", expr.ty);
|
||||
let cast_kind = mir_cast_kind(ty, expr.ty);
|
||||
block.and(Rvalue::Cast(cast_kind, source, expr.ty))
|
||||
}
|
||||
@ -319,7 +308,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block = this.as_operand(
|
||||
block,
|
||||
scope,
|
||||
&this.thir[source],
|
||||
source,
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::No
|
||||
)
|
||||
@ -363,7 +352,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block = this.as_operand(
|
||||
block,
|
||||
scope,
|
||||
&this.thir[f],
|
||||
f,
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::Maybe
|
||||
)
|
||||
@ -384,7 +373,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block = this.as_operand(
|
||||
block,
|
||||
scope,
|
||||
&this.thir[f],
|
||||
f,
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::Maybe
|
||||
)
|
||||
@ -416,8 +405,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// ```
|
||||
//
|
||||
for (thir_place, cause, hir_id) in fake_reads.into_iter() {
|
||||
let place_builder =
|
||||
unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
|
||||
let place_builder = unpack!(block = this.as_place_builder(block, *thir_place));
|
||||
|
||||
if let Some(mir_place) = place_builder.try_to_place(this) {
|
||||
this.cfg.push_fake_read(
|
||||
@ -434,8 +422,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
.into_iter()
|
||||
.copied()
|
||||
.map(|upvar| {
|
||||
let upvar = &this.thir[upvar];
|
||||
match Category::of(&upvar.kind) {
|
||||
let upvar_expr = &this.thir[upvar];
|
||||
match Category::of(&upvar_expr.kind) {
|
||||
// Use as_place to avoid creating a temporary when
|
||||
// moving a variable into a closure, so that
|
||||
// borrowck knows which variables to mark as being
|
||||
@ -453,18 +441,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// borrow captures when capturing an immutable
|
||||
// variable. This is sound because the mutation
|
||||
// that caused the capture will cause an error.
|
||||
match upvar.kind {
|
||||
match upvar_expr.kind {
|
||||
ExprKind::Borrow {
|
||||
borrow_kind:
|
||||
BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||
arg,
|
||||
} => unpack!(
|
||||
block = this.limit_capture_mutability(
|
||||
upvar.span,
|
||||
upvar.ty,
|
||||
upvar_expr.span,
|
||||
upvar_expr.ty,
|
||||
scope,
|
||||
block,
|
||||
&this.thir[arg],
|
||||
arg,
|
||||
)
|
||||
),
|
||||
_ => {
|
||||
@ -498,7 +486,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block.and(Rvalue::Aggregate(result, operands))
|
||||
}
|
||||
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
|
||||
block = unpack!(this.stmt_expr(block, expr, None));
|
||||
block = unpack!(this.stmt_expr(block, expr_id, None));
|
||||
block.and(Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
||||
span: expr_span,
|
||||
user_ty: None,
|
||||
@ -553,8 +541,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
Some(Category::Rvalue(RvalueFunc::AsRvalue) | Category::Constant)
|
||||
));
|
||||
let operand = unpack!(
|
||||
block =
|
||||
this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No)
|
||||
block = this.as_operand(
|
||||
block,
|
||||
scope,
|
||||
expr_id,
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::No,
|
||||
)
|
||||
);
|
||||
block.and(Rvalue::Use(operand))
|
||||
}
|
||||
@ -719,9 +712,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
outer_source_info: SourceInfo,
|
||||
) -> BlockAnd<Rvalue<'tcx>> {
|
||||
let this = self;
|
||||
let value = &this.thir[value];
|
||||
let elem_ty = value.ty;
|
||||
if let Some(Category::Constant) = Category::of(&value.kind) {
|
||||
let value_expr = &this.thir[value];
|
||||
let elem_ty = value_expr.ty;
|
||||
if let Some(Category::Constant) = Category::of(&value_expr.kind) {
|
||||
// Repeating a const does nothing
|
||||
} else {
|
||||
// For a non-const, we may need to generate an appropriate `Drop`
|
||||
@ -754,7 +747,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
upvar_ty: Ty<'tcx>,
|
||||
temp_lifetime: Option<region::Scope>,
|
||||
mut block: BasicBlock,
|
||||
arg: &Expr<'tcx>,
|
||||
arg: ExprId,
|
||||
) -> BlockAnd<Operand<'tcx>> {
|
||||
let this = self;
|
||||
|
||||
|
@ -14,13 +14,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
temp_lifetime: Option<region::Scope>,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
mutability: Mutability,
|
||||
) -> BlockAnd<Local> {
|
||||
// this is the only place in mir building that we need to truly need to worry about
|
||||
// infinite recursion. Everything else does recurse, too, but it always gets broken up
|
||||
// at some point by inserting an intermediate temporary
|
||||
ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability))
|
||||
ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr_id, mutability))
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
@ -28,16 +28,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
temp_lifetime: Option<region::Scope>,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
mutability: Mutability,
|
||||
) -> BlockAnd<Local> {
|
||||
let this = self;
|
||||
|
||||
let expr = &this.thir[expr_id];
|
||||
let expr_span = expr.span;
|
||||
let source_info = this.source_info(expr_span);
|
||||
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
|
||||
return this.in_scope((region_scope, source_info), lint_level, |this| {
|
||||
this.as_temp(block, temp_lifetime, &this.thir[value], mutability)
|
||||
this.as_temp(block, temp_lifetime, value, mutability)
|
||||
});
|
||||
}
|
||||
|
||||
@ -103,7 +104,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
unpack!(block = this.expr_into_dest(temp_place, block, expr));
|
||||
unpack!(block = this.expr_into_dest(temp_place, block, expr_id));
|
||||
|
||||
if let Some(temp_lifetime) = temp_lifetime {
|
||||
this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Value);
|
||||
|
@ -19,12 +19,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut self,
|
||||
destination: Place<'tcx>,
|
||||
mut block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<()> {
|
||||
// since we frequently have to reference `self` from within a
|
||||
// closure, where `self` would be shadowed, it's easier to
|
||||
// just use the name `this` uniformly
|
||||
let this = self;
|
||||
let expr = &this.thir[expr_id];
|
||||
let expr_span = expr.span;
|
||||
let source_info = this.source_info(expr_span);
|
||||
|
||||
@ -40,20 +41,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let region_scope = (region_scope, source_info);
|
||||
ensure_sufficient_stack(|| {
|
||||
this.in_scope(region_scope, lint_level, |this| {
|
||||
this.expr_into_dest(destination, block, &this.thir[value])
|
||||
this.expr_into_dest(destination, block, value)
|
||||
})
|
||||
})
|
||||
}
|
||||
ExprKind::Block { block: ast_block } => {
|
||||
this.ast_block(destination, block, ast_block, source_info)
|
||||
}
|
||||
ExprKind::Match { scrutinee, ref arms, .. } => {
|
||||
this.match_expr(destination, expr_span, block, &this.thir[scrutinee], arms)
|
||||
}
|
||||
ExprKind::Match { scrutinee, ref arms, .. } => this.match_expr(
|
||||
destination,
|
||||
block,
|
||||
scrutinee,
|
||||
arms,
|
||||
expr_span,
|
||||
this.thir[scrutinee].span,
|
||||
),
|
||||
ExprKind::If { cond, then, else_opt, if_then_scope } => {
|
||||
let then_blk;
|
||||
let then_expr = &this.thir[then];
|
||||
let then_source_info = this.source_info(then_expr.span);
|
||||
let then_span = this.thir[then].span;
|
||||
let then_source_info = this.source_info(then_span);
|
||||
let condition_scope = this.local_scope();
|
||||
|
||||
let mut else_blk = unpack!(
|
||||
@ -62,27 +68,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
LintLevel::Inherited,
|
||||
|this| {
|
||||
let source_info = if this.is_let(cond) {
|
||||
let variable_scope = this.new_source_scope(
|
||||
then_expr.span,
|
||||
LintLevel::Inherited,
|
||||
None,
|
||||
);
|
||||
let variable_scope =
|
||||
this.new_source_scope(then_span, LintLevel::Inherited, None);
|
||||
this.source_scope = variable_scope;
|
||||
SourceInfo { span: then_expr.span, scope: variable_scope }
|
||||
SourceInfo { span: then_span, scope: variable_scope }
|
||||
} else {
|
||||
this.source_info(then_expr.span)
|
||||
this.source_info(then_span)
|
||||
};
|
||||
let (then_block, else_block) =
|
||||
this.in_if_then_scope(condition_scope, then_expr.span, |this| {
|
||||
this.in_if_then_scope(condition_scope, then_span, |this| {
|
||||
let then_blk = unpack!(this.then_else_break(
|
||||
block,
|
||||
&this.thir[cond],
|
||||
cond,
|
||||
Some(condition_scope),
|
||||
condition_scope,
|
||||
source_info
|
||||
));
|
||||
|
||||
this.expr_into_dest(destination, then_blk, then_expr)
|
||||
this.expr_into_dest(destination, then_blk, then)
|
||||
});
|
||||
then_block.and(else_block)
|
||||
},
|
||||
@ -90,7 +93,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
);
|
||||
|
||||
else_blk = if let Some(else_opt) = else_opt {
|
||||
unpack!(this.expr_into_dest(destination, else_blk, &this.thir[else_opt]))
|
||||
unpack!(this.expr_into_dest(destination, else_blk, else_opt))
|
||||
} else {
|
||||
// Body of the `if` expression without an `else` clause must return `()`, thus
|
||||
// we implicitly generate an `else {}` if it is not specified.
|
||||
@ -107,7 +110,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
ExprKind::Let { expr, ref pat } => {
|
||||
let scope = this.local_scope();
|
||||
let (true_block, false_block) = this.in_if_then_scope(scope, expr_span, |this| {
|
||||
this.lower_let_expr(block, &this.thir[expr], pat, scope, None, expr_span, true)
|
||||
this.lower_let_expr(block, expr, pat, scope, None, expr_span, true)
|
||||
});
|
||||
|
||||
this.cfg.push_assign_constant(
|
||||
@ -138,14 +141,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
join_block.unit()
|
||||
}
|
||||
ExprKind::NeverToAny { source } => {
|
||||
let source = &this.thir[source];
|
||||
let source_expr = &this.thir[source];
|
||||
let is_call =
|
||||
matches!(source.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. });
|
||||
matches!(source_expr.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. });
|
||||
|
||||
// (#66975) Source could be a const of type `!`, so has to
|
||||
// exist in the generated MIR.
|
||||
unpack!(
|
||||
block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut,)
|
||||
block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut)
|
||||
);
|
||||
|
||||
// This is an optimization. If the expression was a call then we already have an
|
||||
@ -166,7 +169,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
this.in_if_then_scope(condition_scope, expr.span, |this| {
|
||||
this.then_else_break(
|
||||
block,
|
||||
&this.thir[lhs],
|
||||
lhs,
|
||||
Some(condition_scope),
|
||||
condition_scope,
|
||||
source_info,
|
||||
@ -192,7 +195,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
const_: Const::from_bool(this.tcx, constant),
|
||||
},
|
||||
);
|
||||
let rhs = unpack!(this.expr_into_dest(destination, continuation, &this.thir[rhs]));
|
||||
let rhs = unpack!(this.expr_into_dest(destination, continuation, rhs));
|
||||
let target = this.cfg.start_new_block();
|
||||
this.cfg.goto(rhs, source_info, target);
|
||||
this.cfg.goto(short_circuit, source_info, target);
|
||||
@ -231,8 +234,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// introduce a unit temporary as the destination for the loop body.
|
||||
let tmp = this.get_unit_temp();
|
||||
// Execute the body, branching back to the test.
|
||||
let body_block_end =
|
||||
unpack!(this.expr_into_dest(tmp, body_block, &this.thir[body]));
|
||||
let body_block_end = unpack!(this.expr_into_dest(tmp, body_block, body));
|
||||
this.cfg.goto(body_block_end, source_info, loop_block);
|
||||
|
||||
// Loops are only exited by `break` expressions.
|
||||
@ -240,11 +242,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
})
|
||||
}
|
||||
ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => {
|
||||
let fun = unpack!(block = this.as_local_operand(block, &this.thir[fun]));
|
||||
let fun = unpack!(block = this.as_local_operand(block, fun));
|
||||
let args: Vec<_> = args
|
||||
.into_iter()
|
||||
.copied()
|
||||
.map(|arg| unpack!(block = this.as_local_call_operand(block, &this.thir[arg])))
|
||||
.map(|arg| unpack!(block = this.as_local_call_operand(block, arg)))
|
||||
.collect();
|
||||
|
||||
let success = this.cfg.start_new_block();
|
||||
@ -280,16 +282,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
this.diverge_from(block);
|
||||
success.unit()
|
||||
}
|
||||
ExprKind::Use { source } => this.expr_into_dest(destination, block, &this.thir[source]),
|
||||
ExprKind::Use { source } => this.expr_into_dest(destination, block, source),
|
||||
ExprKind::Borrow { arg, borrow_kind } => {
|
||||
let arg = &this.thir[arg];
|
||||
// We don't do this in `as_rvalue` because we use `as_place`
|
||||
// for borrow expressions, so we cannot create an `RValue` that
|
||||
// remains valid across user code. `as_rvalue` is usually called
|
||||
// by this method anyway, so this shouldn't cause too many
|
||||
// unnecessary temporaries.
|
||||
let arg_place = match borrow_kind {
|
||||
BorrowKind::Shared => unpack!(block = this.as_read_only_place(block, arg)),
|
||||
BorrowKind::Shared => {
|
||||
unpack!(block = this.as_read_only_place(block, arg))
|
||||
}
|
||||
_ => unpack!(block = this.as_place(block, arg)),
|
||||
};
|
||||
let borrow = Rvalue::Ref(this.tcx.lifetimes.re_erased, borrow_kind, arg_place);
|
||||
@ -297,7 +300,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block.unit()
|
||||
}
|
||||
ExprKind::AddressOf { mutability, arg } => {
|
||||
let arg = &this.thir[arg];
|
||||
let place = match mutability {
|
||||
hir::Mutability::Not => this.as_read_only_place(block, arg),
|
||||
hir::Mutability::Mut => this.as_place(block, arg),
|
||||
@ -332,7 +334,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block = this.as_operand(
|
||||
block,
|
||||
Some(scope),
|
||||
&this.thir[f.expr],
|
||||
f.expr,
|
||||
LocalInfo::AggregateTemp,
|
||||
NeedsTemporary::Maybe,
|
||||
)
|
||||
@ -344,8 +346,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let field_names = adt_def.variant(variant_index).fields.indices();
|
||||
|
||||
let fields = if let Some(FruInfo { base, field_types }) = base {
|
||||
let place_builder =
|
||||
unpack!(block = this.as_place_builder(block, &this.thir[*base]));
|
||||
let place_builder = unpack!(block = this.as_place_builder(block, *base));
|
||||
|
||||
// MIR does not natively support FRU, so for each
|
||||
// base-supplied field, generate an operand that
|
||||
@ -398,19 +399,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
.map(|op| match *op {
|
||||
thir::InlineAsmOperand::In { reg, expr } => mir::InlineAsmOperand::In {
|
||||
reg,
|
||||
value: unpack!(block = this.as_local_operand(block, &this.thir[expr])),
|
||||
value: unpack!(block = this.as_local_operand(block, expr)),
|
||||
},
|
||||
thir::InlineAsmOperand::Out { reg, late, expr } => {
|
||||
mir::InlineAsmOperand::Out {
|
||||
reg,
|
||||
late,
|
||||
place: expr.map(|expr| {
|
||||
unpack!(block = this.as_place(block, &this.thir[expr]))
|
||||
}),
|
||||
place: expr.map(|expr| unpack!(block = this.as_place(block, expr))),
|
||||
}
|
||||
}
|
||||
thir::InlineAsmOperand::InOut { reg, late, expr } => {
|
||||
let place = unpack!(block = this.as_place(block, &this.thir[expr]));
|
||||
let place = unpack!(block = this.as_place(block, expr));
|
||||
mir::InlineAsmOperand::InOut {
|
||||
reg,
|
||||
late,
|
||||
@ -423,11 +422,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
mir::InlineAsmOperand::InOut {
|
||||
reg,
|
||||
late,
|
||||
in_value: unpack!(
|
||||
block = this.as_local_operand(block, &this.thir[in_expr])
|
||||
),
|
||||
in_value: unpack!(block = this.as_local_operand(block, in_expr)),
|
||||
out_place: out_expr.map(|out_expr| {
|
||||
unpack!(block = this.as_place(block, &this.thir[out_expr]))
|
||||
unpack!(block = this.as_place(block, out_expr))
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -488,7 +485,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
// These cases don't actually need a destination
|
||||
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
|
||||
unpack!(block = this.stmt_expr(block, expr, None));
|
||||
unpack!(block = this.stmt_expr(block, expr_id, None));
|
||||
this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
|
||||
block.unit()
|
||||
}
|
||||
@ -497,7 +494,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
| ExprKind::Break { .. }
|
||||
| ExprKind::Return { .. }
|
||||
| ExprKind::Become { .. } => {
|
||||
unpack!(block = this.stmt_expr(block, expr, None));
|
||||
unpack!(block = this.stmt_expr(block, expr_id, None));
|
||||
// No assign, as these have type `!`.
|
||||
block.unit()
|
||||
}
|
||||
@ -509,7 +506,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
| ExprKind::ValueTypeAscription { .. } => {
|
||||
debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
|
||||
|
||||
let place = unpack!(block = this.as_place(block, expr));
|
||||
let place = unpack!(block = this.as_place(block, expr_id));
|
||||
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
|
||||
this.cfg.push_assign(block, source_info, destination, rvalue);
|
||||
block.unit()
|
||||
@ -524,7 +521,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
this.local_decls.push(LocalDecl::new(expr.ty, expr.span));
|
||||
}
|
||||
|
||||
let place = unpack!(block = this.as_place(block, expr));
|
||||
let place = unpack!(block = this.as_place(block, expr_id));
|
||||
let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
|
||||
this.cfg.push_assign(block, source_info, destination, rvalue);
|
||||
block.unit()
|
||||
@ -536,7 +533,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block = this.as_operand(
|
||||
block,
|
||||
Some(scope),
|
||||
&this.thir[value],
|
||||
value,
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::No
|
||||
)
|
||||
@ -582,7 +579,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
_ => true,
|
||||
});
|
||||
|
||||
let rvalue = unpack!(block = this.as_local_rvalue(block, expr));
|
||||
let rvalue = unpack!(block = this.as_local_rvalue(block, expr_id));
|
||||
this.cfg.push_assign(block, source_info, destination, rvalue);
|
||||
block.unit()
|
||||
}
|
||||
|
@ -11,10 +11,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn stmt_expr(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
statement_scope: Option<region::Scope>,
|
||||
) -> BlockAnd<()> {
|
||||
let this = self;
|
||||
let expr = &this.thir[expr_id];
|
||||
let expr_span = expr.span;
|
||||
let source_info = this.source_info(expr.span);
|
||||
// Handle a number of expressions that don't need a destination at all. This
|
||||
@ -22,13 +23,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
match expr.kind {
|
||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||
this.in_scope((region_scope, source_info), lint_level, |this| {
|
||||
this.stmt_expr(block, &this.thir[value], statement_scope)
|
||||
this.stmt_expr(block, value, statement_scope)
|
||||
})
|
||||
}
|
||||
ExprKind::Assign { lhs, rhs } => {
|
||||
let lhs = &this.thir[lhs];
|
||||
let rhs = &this.thir[rhs];
|
||||
let lhs_span = lhs.span;
|
||||
let lhs_expr = &this.thir[lhs];
|
||||
|
||||
// Note: we evaluate assignments right-to-left. This
|
||||
// is better for borrowck interaction with overloaded
|
||||
@ -39,10 +38,10 @@ 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) {
|
||||
if lhs_expr.ty.needs_drop(this.tcx, this.param_env) {
|
||||
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));
|
||||
unpack!(block = this.build_drop_and_replace(block, lhs_expr.span, lhs, rhs));
|
||||
} else {
|
||||
let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
|
||||
let lhs = unpack!(block = this.as_place(block, lhs));
|
||||
@ -61,9 +60,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// only affects weird things like `x += {x += 1; x}`
|
||||
// -- is that equal to `x + (x + 1)` or `2*(x+1)`?
|
||||
|
||||
let lhs = &this.thir[lhs];
|
||||
let rhs = &this.thir[rhs];
|
||||
let lhs_ty = lhs.ty;
|
||||
let lhs_ty = this.thir[lhs].ty;
|
||||
|
||||
debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr);
|
||||
this.block_context.push(BlockFrame::SubExpr);
|
||||
@ -87,25 +84,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
ExprKind::Continue { label } => {
|
||||
this.break_scope(block, None, BreakableTarget::Continue(label), source_info)
|
||||
}
|
||||
ExprKind::Break { label, value } => this.break_scope(
|
||||
block,
|
||||
value.map(|value| &this.thir[value]),
|
||||
BreakableTarget::Break(label),
|
||||
source_info,
|
||||
),
|
||||
ExprKind::Return { value } => this.break_scope(
|
||||
block,
|
||||
value.map(|value| &this.thir[value]),
|
||||
BreakableTarget::Return,
|
||||
source_info,
|
||||
),
|
||||
ExprKind::Break { label, value } => {
|
||||
this.break_scope(block, value, BreakableTarget::Break(label), source_info)
|
||||
}
|
||||
ExprKind::Return { value } => {
|
||||
this.break_scope(block, value, BreakableTarget::Return, source_info)
|
||||
}
|
||||
// FIXME(explicit_tail_calls): properly lower tail calls here
|
||||
ExprKind::Become { value } => this.break_scope(
|
||||
block,
|
||||
Some(&this.thir[value]),
|
||||
BreakableTarget::Return,
|
||||
source_info,
|
||||
),
|
||||
ExprKind::Become { value } => {
|
||||
this.break_scope(block, Some(value), BreakableTarget::Return, source_info)
|
||||
}
|
||||
_ => {
|
||||
assert!(
|
||||
statement_scope.is_some(),
|
||||
@ -147,7 +135,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
};
|
||||
|
||||
let temp =
|
||||
unpack!(block = this.as_temp(block, statement_scope, expr, Mutability::Not));
|
||||
unpack!(block = this.as_temp(block, statement_scope, expr_id, Mutability::Not));
|
||||
|
||||
if let Some(span) = adjusted_span {
|
||||
this.local_decls[temp].source_info.span = span;
|
||||
|
@ -36,19 +36,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn then_else_break(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
temp_scope_override: Option<region::Scope>,
|
||||
break_scope: region::Scope,
|
||||
variable_source_info: SourceInfo,
|
||||
) -> BlockAnd<()> {
|
||||
let this = self;
|
||||
let expr = &this.thir[expr_id];
|
||||
let expr_span = expr.span;
|
||||
|
||||
match expr.kind {
|
||||
ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => {
|
||||
let lhs_then_block = unpack!(this.then_else_break(
|
||||
block,
|
||||
&this.thir[lhs],
|
||||
lhs,
|
||||
temp_scope_override,
|
||||
break_scope,
|
||||
variable_source_info,
|
||||
@ -56,7 +57,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
let rhs_then_block = unpack!(this.then_else_break(
|
||||
lhs_then_block,
|
||||
&this.thir[rhs],
|
||||
rhs,
|
||||
temp_scope_override,
|
||||
break_scope,
|
||||
variable_source_info,
|
||||
@ -70,7 +71,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
this.in_if_then_scope(local_scope, expr_span, |this| {
|
||||
this.then_else_break(
|
||||
block,
|
||||
&this.thir[lhs],
|
||||
lhs,
|
||||
temp_scope_override,
|
||||
local_scope,
|
||||
variable_source_info,
|
||||
@ -78,7 +79,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
});
|
||||
let rhs_success_block = unpack!(this.then_else_break(
|
||||
failure_block,
|
||||
&this.thir[rhs],
|
||||
rhs,
|
||||
temp_scope_override,
|
||||
break_scope,
|
||||
variable_source_info,
|
||||
@ -97,7 +98,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
this.then_else_break(
|
||||
block,
|
||||
&this.thir[arg],
|
||||
arg,
|
||||
temp_scope_override,
|
||||
local_scope,
|
||||
variable_source_info,
|
||||
@ -111,7 +112,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
this.in_scope(region_scope, lint_level, |this| {
|
||||
this.then_else_break(
|
||||
block,
|
||||
&this.thir[value],
|
||||
value,
|
||||
temp_scope_override,
|
||||
break_scope,
|
||||
variable_source_info,
|
||||
@ -120,14 +121,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
ExprKind::Use { source } => this.then_else_break(
|
||||
block,
|
||||
&this.thir[source],
|
||||
source,
|
||||
temp_scope_override,
|
||||
break_scope,
|
||||
variable_source_info,
|
||||
),
|
||||
ExprKind::Let { expr, ref pat } => this.lower_let_expr(
|
||||
block,
|
||||
&this.thir[expr],
|
||||
expr,
|
||||
pat,
|
||||
break_scope,
|
||||
Some(variable_source_info.scope),
|
||||
@ -138,7 +139,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
|
||||
let mutability = Mutability::Mut;
|
||||
let place =
|
||||
unpack!(block = this.as_temp(block, Some(temp_scope), expr, mutability));
|
||||
unpack!(block = this.as_temp(block, Some(temp_scope), expr_id, mutability));
|
||||
let operand = Operand::Move(Place::from(place));
|
||||
|
||||
let then_block = this.cfg.start_new_block();
|
||||
@ -208,14 +209,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn match_expr(
|
||||
&mut self,
|
||||
destination: Place<'tcx>,
|
||||
span: Span,
|
||||
mut block: BasicBlock,
|
||||
scrutinee: &Expr<'tcx>,
|
||||
scrutinee_id: ExprId,
|
||||
arms: &[ArmId],
|
||||
span: Span,
|
||||
scrutinee_span: Span,
|
||||
) -> BlockAnd<()> {
|
||||
let scrutinee_span = scrutinee.span;
|
||||
let scrutinee_span = scrutinee_span;
|
||||
let scrutinee_place =
|
||||
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,));
|
||||
unpack!(block = self.lower_scrutinee(block, scrutinee_id, scrutinee_span));
|
||||
|
||||
let mut arm_candidates = self.create_match_candidates(&scrutinee_place, arms);
|
||||
|
||||
@ -223,7 +225,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let mut candidates =
|
||||
arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::<Vec<_>>();
|
||||
|
||||
let match_start_span = span.shrink_to_lo().to(scrutinee.span);
|
||||
let match_start_span = span.shrink_to_lo().to(scrutinee_span);
|
||||
|
||||
let fake_borrow_temps = self.lower_match_tree(
|
||||
block,
|
||||
@ -248,10 +250,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fn lower_scrutinee(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
scrutinee: &Expr<'tcx>,
|
||||
scrutinee_id: ExprId,
|
||||
scrutinee_span: Span,
|
||||
) -> BlockAnd<PlaceBuilder<'tcx>> {
|
||||
let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee));
|
||||
let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee_id));
|
||||
if let Some(scrutinee_place) = scrutinee_place_builder.try_to_place(self) {
|
||||
let source_info = self.source_info(scrutinee_span);
|
||||
self.cfg.push_place_mention(block, source_info, scrutinee_place);
|
||||
@ -429,7 +431,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
this.source_scope = source_scope;
|
||||
}
|
||||
|
||||
this.expr_into_dest(destination, arm_block, &this.thir[arm.body])
|
||||
this.expr_into_dest(destination, arm_block, arm.body)
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
@ -538,14 +540,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
irrefutable_pat: &Pat<'tcx>,
|
||||
initializer: &Expr<'tcx>,
|
||||
initializer_id: ExprId,
|
||||
) -> BlockAnd<()> {
|
||||
match irrefutable_pat.kind {
|
||||
// Optimize the case of `let x = ...` to write directly into `x`
|
||||
PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => {
|
||||
let place =
|
||||
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
|
||||
unpack!(block = self.expr_into_dest(place, block, initializer));
|
||||
unpack!(block = self.expr_into_dest(place, block, initializer_id));
|
||||
|
||||
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
|
||||
let source_info = self.source_info(irrefutable_pat.span);
|
||||
@ -576,7 +578,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
} => {
|
||||
let place =
|
||||
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
|
||||
unpack!(block = self.expr_into_dest(place, block, initializer));
|
||||
unpack!(block = self.expr_into_dest(place, block, initializer_id));
|
||||
|
||||
// Inject a fake read, see comments on `FakeReadCause::ForLet`.
|
||||
let pattern_source_info = self.source_info(irrefutable_pat.span);
|
||||
@ -616,8 +618,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
_ => {
|
||||
let initializer = &self.thir[initializer_id];
|
||||
let place_builder =
|
||||
unpack!(block = self.lower_scrutinee(block, initializer, initializer.span));
|
||||
unpack!(block = self.lower_scrutinee(block, initializer_id, initializer.span));
|
||||
self.place_into_pattern(block, irrefutable_pat, place_builder, true)
|
||||
}
|
||||
}
|
||||
@ -1839,15 +1842,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn lower_let_expr(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
pat: &Pat<'tcx>,
|
||||
else_target: region::Scope,
|
||||
source_scope: Option<SourceScope>,
|
||||
span: Span,
|
||||
declare_bindings: bool,
|
||||
) -> BlockAnd<()> {
|
||||
let expr_span = expr.span;
|
||||
let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
|
||||
let expr_span = self.thir[expr_id].span;
|
||||
let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span));
|
||||
let wildcard = Pat::wildcard_from_ty(pat.ty);
|
||||
let mut guard_candidate = Candidate::new(expr_place_builder.clone(), pat, false, self);
|
||||
let mut otherwise_candidate =
|
||||
@ -1873,7 +1876,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
self.source_info(pat.span),
|
||||
guard_candidate,
|
||||
&fake_borrow_temps,
|
||||
expr.span,
|
||||
expr_span,
|
||||
None,
|
||||
false,
|
||||
);
|
||||
@ -2036,8 +2039,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let (post_guard_block, otherwise_post_guard_block) =
|
||||
self.in_if_then_scope(match_scope, guard_span, |this| match *guard {
|
||||
Guard::If(e) => {
|
||||
let e = &this.thir[e];
|
||||
guard_span = e.span;
|
||||
guard_span = this.thir[e].span;
|
||||
this.then_else_break(
|
||||
block,
|
||||
e,
|
||||
@ -2046,9 +2048,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
this.source_info(arm.span),
|
||||
)
|
||||
}
|
||||
Guard::IfLet(ref pat, scrutinee) => {
|
||||
let s = &this.thir[scrutinee];
|
||||
guard_span = s.span;
|
||||
Guard::IfLet(ref pat, s) => {
|
||||
guard_span = this.thir[s].span;
|
||||
this.lower_let_expr(block, s, pat, match_scope, None, arm.span, false)
|
||||
}
|
||||
});
|
||||
@ -2342,7 +2343,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn ast_let_else(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
init: &Expr<'tcx>,
|
||||
init_id: ExprId,
|
||||
initializer_span: Span,
|
||||
else_block: BlockId,
|
||||
let_else_scope: ®ion::Scope,
|
||||
@ -2350,8 +2351,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
) -> BlockAnd<BasicBlock> {
|
||||
let else_block_span = self.thir[else_block].span;
|
||||
let (matching, failure) = self.in_if_then_scope(*let_else_scope, else_block_span, |this| {
|
||||
let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
|
||||
let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild };
|
||||
let scrutinee = unpack!(block = this.lower_scrutinee(block, init_id, initializer_span));
|
||||
let pat = Pat { ty: pattern.ty, span: else_block_span, kind: PatKind::Wild };
|
||||
let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false, this);
|
||||
let mut candidate = Candidate::new(scrutinee.clone(), pattern, false, this);
|
||||
let fake_borrow_temps = this.lower_match_tree(
|
||||
|
@ -18,7 +18,7 @@ use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::interpret::Scalar;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::{
|
||||
self, BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
|
||||
self, BindingMode, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
|
||||
};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::symbol::sym;
|
||||
@ -539,7 +539,7 @@ fn construct_fn<'tcx>(
|
||||
let return_block =
|
||||
unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
|
||||
Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
|
||||
builder.args_and_body(START_BLOCK, arguments, arg_scope, &thir[expr])
|
||||
builder.args_and_body(START_BLOCK, arguments, arg_scope, expr)
|
||||
}))
|
||||
}));
|
||||
let source_info = builder.source_info(fn_end);
|
||||
@ -606,7 +606,7 @@ fn construct_const<'a, 'tcx>(
|
||||
);
|
||||
|
||||
let mut block = START_BLOCK;
|
||||
unpack!(block = builder.expr_into_dest(Place::return_place(), block, &thir[expr]));
|
||||
unpack!(block = builder.expr_into_dest(Place::return_place(), block, expr));
|
||||
|
||||
let source_info = builder.source_info(span);
|
||||
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
|
||||
@ -865,8 +865,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
mut block: BasicBlock,
|
||||
arguments: &IndexSlice<ParamId, Param<'tcx>>,
|
||||
argument_scope: region::Scope,
|
||||
expr: &Expr<'tcx>,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<()> {
|
||||
let expr_span = self.thir[expr_id].span;
|
||||
// Allocate locals for the function arguments
|
||||
for (argument_index, param) in arguments.iter().enumerate() {
|
||||
let source_info =
|
||||
@ -899,7 +900,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
// Make sure we drop (parts of) the argument even when not matched on.
|
||||
self.schedule_drop(
|
||||
param.pat.as_ref().map_or(expr.span, |pat| pat.span),
|
||||
param.pat.as_ref().map_or(expr_span, |pat| pat.span),
|
||||
argument_scope,
|
||||
local,
|
||||
DropKind::Value,
|
||||
@ -941,8 +942,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
_ => {
|
||||
scope = self.declare_bindings(
|
||||
scope,
|
||||
expr.span,
|
||||
pat,
|
||||
expr_span,
|
||||
&pat,
|
||||
None,
|
||||
Some((Some(&place), span)),
|
||||
);
|
||||
@ -958,7 +959,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
self.source_scope = source_scope;
|
||||
}
|
||||
|
||||
self.expr_into_dest(Place::return_place(), block, expr)
|
||||
self.expr_into_dest(Place::return_place(), block, expr_id)
|
||||
}
|
||||
|
||||
fn set_correct_source_scope_for_arg(
|
||||
|
@ -89,7 +89,7 @@ use rustc_hir::HirId;
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::{Expr, LintLevel};
|
||||
use rustc_middle::thir::{ExprId, LintLevel};
|
||||
use rustc_session::lint::Level;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
@ -592,7 +592,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn break_scope(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
value: Option<&Expr<'tcx>>,
|
||||
value: Option<ExprId>,
|
||||
target: BreakableTarget,
|
||||
source_info: SourceInfo,
|
||||
) -> BlockAnd<()> {
|
||||
|
Loading…
Reference in New Issue
Block a user