Pass THIR ExprIds in MIR building

This commit is contained in:
Matthew Jasper 2023-12-15 15:16:24 +00:00
parent e004adb556
commit 68d684cbff
10 changed files with 209 additions and 235 deletions

View File

@ -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()));

View File

@ -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)
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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()
}

View File

@ -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;

View File

@ -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: &region::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(

View File

@ -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(

View File

@ -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<()> {