Skip to content

Commit d186978

Browse files
committed
compute temporary scopes when building MIR, not THIR
1 parent 0e50d5a commit d186978

File tree

20 files changed

+138
-265
lines changed

20 files changed

+138
-265
lines changed

compiler/rustc_middle/src/middle/region.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,17 @@ pub struct ScopeTree {
234234
pub backwards_incompatible_scope: UnordMap<hir::ItemLocalId, Scope>,
235235
}
236236

237+
/// Temporary lifetime information for expressions, used when lowering to MIR.
238+
#[derive(Clone, Copy, Debug, HashStable)]
239+
pub struct TempLifetime {
240+
/// The scope in which a temporary should be dropped. If `None`, no drop is scheduled; this is
241+
/// the case for lifetime-extended temporaries extended by a const/static item or const block.
242+
pub temp_lifetime: Option<Scope>,
243+
/// If `Some(lt)`, indicates that the lifetime of this temporary will change to `lt` in a future edition.
244+
/// If `None`, then no changes are expected, or lints are disabled.
245+
pub backwards_incompatible: Option<Scope>,
246+
}
247+
237248
impl ScopeTree {
238249
pub fn record_scope_parent(&mut self, child: Scope, parent: Option<Scope>) {
239250
debug!("{:?}.parent = {:?}", child, parent);
@@ -332,16 +343,16 @@ impl ScopeTree {
332343
/// Returns the scope when the temp created by `expr_id` will be cleaned up.
333344
/// It also emits a lint on potential backwards incompatible change to the temporary scope
334345
/// which is *for now* always shortening.
335-
pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> (Option<Scope>, Option<Scope>) {
346+
pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> TempLifetime {
336347
// Check for a designated extended temporary scope.
337348
if let Some(&s) = self.extended_temp_scopes.get(&expr_id) {
338349
debug!("temporary_scope({expr_id:?}) = {s:?} [custom]");
339-
return (s, None);
350+
return TempLifetime { temp_lifetime: s, backwards_incompatible: None };
340351
}
341352

342353
// Otherwise, locate the innermost terminating scope.
343-
let (scope, backward_incompatible) =
354+
let (scope, backwards_incompatible) =
344355
self.default_temporary_scope(Scope { local_id: expr_id, data: ScopeData::Node });
345-
(Some(scope), backward_incompatible)
356+
TempLifetime { temp_lifetime: Some(scope), backwards_incompatible }
346357
}
347358
}

compiler/rustc_middle/src/thir.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -256,25 +256,15 @@ pub struct Expr<'tcx> {
256256
/// The type of this expression
257257
pub ty: Ty<'tcx>,
258258

259-
/// The lifetime of this expression if it should be spilled into a
260-
/// temporary
261-
pub temp_lifetime: TempLifetime,
259+
/// The id of the HIR expression whose [temporary scope] should be used for this expression.
260+
///
261+
/// [temporary scope]: https://doc.rust-lang.org/reference/destructors.html#temporary-scopes
262+
pub temp_scope_id: hir::ItemLocalId,
262263

263264
/// span of the expression in the source
264265
pub span: Span,
265266
}
266267

267-
/// Temporary lifetime information for THIR expressions
268-
#[derive(Clone, Copy, Debug, HashStable)]
269-
pub struct TempLifetime {
270-
/// Lifetime for temporaries as expected.
271-
/// This should be `None` in a constant context.
272-
pub temp_lifetime: Option<region::Scope>,
273-
/// If `Some(lt)`, indicates that the lifetime of this temporary will change to `lt` in a future edition.
274-
/// If `None`, then no changes are expected, or lints are disabled.
275-
pub backwards_incompatible: Option<region::Scope>,
276-
}
277-
278268
#[derive(Clone, Debug, HashStable)]
279269
pub enum ExprKind<'tcx> {
280270
/// `Scope`s are used to explicitly mark destruction scopes,
@@ -1127,7 +1117,7 @@ mod size_asserts {
11271117
use super::*;
11281118
// tidy-alphabetical-start
11291119
static_assert_size!(Block, 48);
1130-
static_assert_size!(Expr<'_>, 72);
1120+
static_assert_size!(Expr<'_>, 64);
11311121
static_assert_size!(ExprKind<'_>, 40);
11321122
static_assert_size!(Pat<'_>, 64);
11331123
static_assert_size!(PatKind<'_>, 48);

compiler/rustc_middle/src/thir/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
4545
expr: &'thir Expr<'tcx>,
4646
) {
4747
use ExprKind::*;
48-
let Expr { kind, ty: _, temp_lifetime: _, span: _ } = expr;
48+
let Expr { kind, ty: _, temp_scope_id: _, span: _ } = expr;
4949
match *kind {
5050
Scope { value, region_scope: _, lint_level: _ } => {
5151
visitor.visit_expr(&visitor.thir()[value])

compiler/rustc_mir_build/src/builder/expr/as_constant.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2121
pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> ConstOperand<'tcx> {
2222
let this = self;
2323
let tcx = this.tcx;
24-
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
24+
let Expr { ty, temp_scope_id: _, span, ref kind } = *expr;
2525
match kind {
2626
ExprKind::Scope { region_scope: _, lint_level: _, value } => {
2727
this.as_constant(&this.thir[*value])
@@ -46,7 +46,7 @@ pub(crate) fn as_constant_inner<'tcx>(
4646
push_cuta: impl FnMut(&Box<CanonicalUserType<'tcx>>) -> Option<UserTypeAnnotationIndex>,
4747
tcx: TyCtxt<'tcx>,
4848
) -> ConstOperand<'tcx> {
49-
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
49+
let Expr { ty, temp_scope_id: _, span, ref kind } = *expr;
5050
match *kind {
5151
ExprKind::Literal { lit, neg } => {
5252
let const_ = lit_to_mir_constant(tcx, LitToConstInput { lit: lit.node, ty, neg });

compiler/rustc_mir_build/src/builder/expr/as_operand.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! See docs in build/expr/mod.rs
22
3+
use rustc_middle::middle::region::TempLifetime;
34
use rustc_middle::mir::*;
45
use rustc_middle::thir::*;
56
use tracing::{debug, instrument};

compiler/rustc_mir_build/src/builder/expr/as_place.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -503,10 +503,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
503503
block.and(place_builder)
504504
}
505505
ExprKind::ValueTypeAscription { source, ref user_ty, user_ty_span } => {
506-
let source_expr = &this.thir[source];
507-
let temp = unpack!(
508-
block = this.as_temp(block, source_expr.temp_lifetime, source, mutability)
509-
);
506+
let temp_lifetime =
507+
this.region_scope_tree.temporary_scope(this.thir[source].temp_scope_id);
508+
let temp = unpack!(block = this.as_temp(block, temp_lifetime, source, mutability));
510509
if let Some(user_ty) = user_ty {
511510
let ty_source_info = this.source_info(user_ty_span);
512511
let annotation_index =
@@ -539,10 +538,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
539538
block.and(place_builder.project(PlaceElem::UnwrapUnsafeBinder(expr.ty)))
540539
}
541540
ExprKind::ValueUnwrapUnsafeBinder { source } => {
542-
let source_expr = &this.thir[source];
543-
let temp = unpack!(
544-
block = this.as_temp(block, source_expr.temp_lifetime, source, mutability)
545-
);
541+
let temp_lifetime =
542+
this.region_scope_tree.temporary_scope(this.thir[source].temp_scope_id);
543+
let temp = unpack!(block = this.as_temp(block, temp_lifetime, source, mutability));
546544
block.and(PlaceBuilder::from(temp).project(PlaceElem::UnwrapUnsafeBinder(expr.ty)))
547545
}
548546

@@ -590,8 +588,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
590588
| ExprKind::WrapUnsafeBinder { .. } => {
591589
// these are not places, so we need to make a temporary.
592590
debug_assert!(!matches!(Category::of(&expr.kind), Some(Category::Place)));
593-
let temp =
594-
unpack!(block = this.as_temp(block, expr.temp_lifetime, expr_id, mutability));
591+
let temp_lifetime = this.region_scope_tree.temporary_scope(expr.temp_scope_id);
592+
let temp = unpack!(block = this.as_temp(block, temp_lifetime, expr_id, mutability));
595593
block.and(PlaceBuilder::from(temp))
596594
}
597595
}
@@ -637,7 +635,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
637635
// Making this a *fresh* temporary means we do not have to worry about
638636
// the index changing later: Nothing will ever change this temporary.
639637
// The "retagging" transformation (for Stacked Borrows) relies on this.
640-
let index_lifetime = self.thir[index].temp_lifetime;
638+
// Using the enclosing temporary scope for the index ensures it will live past where this
639+
// place is used. This lifetime may be larger than strictly necessary but it means we don't
640+
// need to pass a scope for operands to `as_place`.
641+
let index_lifetime = self.region_scope_tree.temporary_scope(self.thir[index].temp_scope_id);
641642
let idx = unpack!(block = self.as_temp(block, index_lifetime, index, Mutability::Not));
642643

643644
block = self.bounds_check(block, &base_place, idx, expr_span, source_info);

compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_abi::FieldIdx;
44
use rustc_hir::lang_items::LangItem;
55
use rustc_index::{Idx, IndexVec};
66
use rustc_middle::bug;
7-
use rustc_middle::middle::region;
7+
use rustc_middle::middle::region::{self, TempLifetime};
88
use rustc_middle::mir::interpret::Scalar;
99
use rustc_middle::mir::*;
1010
use rustc_middle::thir::*;

compiler/rustc_mir_build/src/builder/expr/as_temp.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use rustc_data_structures::stack::ensure_sufficient_stack;
44
use rustc_hir::HirId;
5-
use rustc_middle::middle::region::{Scope, ScopeData};
5+
use rustc_middle::middle::region::{Scope, ScopeData, TempLifetime};
66
use rustc_middle::mir::*;
77
use rustc_middle::thir::*;
88
use tracing::{debug, instrument};

compiler/rustc_mir_build/src/builder/expr/stmt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_middle::middle::region;
1+
use rustc_middle::middle::region::{self, TempLifetime};
22
use rustc_middle::mir::*;
33
use rustc_middle::span_bug;
44
use rustc_middle::thir::*;

compiler/rustc_mir_build/src/builder/matches/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
1515
use rustc_data_structures::fx::FxIndexMap;
1616
use rustc_data_structures::stack::ensure_sufficient_stack;
1717
use rustc_hir::{BindingMode, ByRef, LangItem, LetStmt, LocalSource, Node, Pinnedness};
18-
use rustc_middle::middle::region;
18+
use rustc_middle::middle::region::{self, TempLifetime};
1919
use rustc_middle::mir::*;
2020
use rustc_middle::thir::{self, *};
2121
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, ValTree, ValTreeKind};

0 commit comments

Comments
 (0)