Skip to content

Commit c2e32f1

Browse files
Auto merge of #146098 - dianne:extending-blocks, r=<try>
Temporary lifetime extension for blocks
2 parents c90bcb9 + 8626bd8 commit c2e32f1

24 files changed

+581
-501
lines changed

compiler/rustc_hir_analysis/src/check/region.rs

Lines changed: 238 additions & 166 deletions
Large diffs are not rendered by default.

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use tracing::{debug, instrument};
4040
use crate::callee::{self, DeferredCallResolution};
4141
use crate::errors::{self, CtorIsPrivate};
4242
use crate::method::{self, MethodCallee};
43-
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy, rvalue_scopes};
43+
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy};
4444

4545
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4646
/// Produces warning on the given node, if the current point in the
@@ -604,13 +604,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
604604
self.normalize(span, field.ty(self.tcx, args))
605605
}
606606

607-
pub(crate) fn resolve_rvalue_scopes(&self, def_id: DefId) {
608-
let scope_tree = self.tcx.region_scope_tree(def_id);
609-
let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, scope_tree, def_id) };
610-
let mut typeck_results = self.typeck_results.borrow_mut();
611-
typeck_results.rvalue_scopes = rvalue_scopes;
612-
}
613-
614607
/// Drain all obligations that are stalled on coroutines defined in this body.
615608
#[instrument(level = "debug", skip(self))]
616609
pub(crate) fn drain_stalled_coroutine_obligations(&self) {

compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ mod op;
3737
mod opaque_types;
3838
mod pat;
3939
mod place_op;
40-
mod rvalue_scopes;
4140
mod typeck_root_ctxt;
4241
mod upvar;
4342
mod writeback;
@@ -237,9 +236,6 @@ fn typeck_with_inspect<'tcx>(
237236
// because they don't constrain other type variables.
238237
fcx.closure_analyze(body);
239238
assert!(fcx.deferred_call_resolutions.borrow().is_empty());
240-
// Before the coroutine analysis, temporary scopes shall be marked to provide more
241-
// precise information on types to be captured.
242-
fcx.resolve_rvalue_scopes(def_id.to_def_id());
243239

244240
for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
245241
let ty = fcx.normalize(span, ty);

compiler/rustc_hir_typeck/src/rvalue_scopes.rs

Lines changed: 0 additions & 79 deletions
This file was deleted.

compiler/rustc_hir_typeck/src/writeback.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7979
wbcx.visit_offset_of_container_types();
8080
wbcx.visit_potentially_region_dependent_goals();
8181

82-
wbcx.typeck_results.rvalue_scopes =
83-
mem::take(&mut self.typeck_results.borrow_mut().rvalue_scopes);
84-
8582
let used_trait_imports =
8683
mem::take(&mut self.typeck_results.borrow_mut().used_trait_imports);
8784
debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);

compiler/rustc_middle/src/middle/region.rs

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ use std::fmt;
1111
use rustc_data_structures::fx::FxIndexMap;
1212
use rustc_data_structures::unord::UnordMap;
1313
use rustc_hir as hir;
14-
use rustc_hir::{HirId, HirIdMap, Node};
14+
use rustc_hir::{HirId, ItemLocalMap, Node};
1515
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
1616
use rustc_span::{DUMMY_SP, Span};
1717
use tracing::debug;
1818

19+
use crate::thir::TempLifetime;
1920
use crate::ty::{self, TyCtxt};
2021

2122
/// Represents a statically-describable scope that can be used to
@@ -221,29 +222,17 @@ pub struct ScopeTree {
221222
/// variable is declared.
222223
var_map: FxIndexMap<hir::ItemLocalId, Scope>,
223224

224-
/// Identifies expressions which, if captured into a temporary, ought to
225-
/// have a temporary whose lifetime extends to the end of the enclosing *block*,
226-
/// and not the enclosing *statement*. Expressions that are not present in this
227-
/// table are not rvalue candidates. The set of rvalue candidates is computed
228-
/// during type check based on a traversal of the AST.
229-
pub rvalue_candidates: HirIdMap<RvalueCandidate>,
225+
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
226+
/// by applying extended parameter rules.
227+
/// Further details may be found in `rustc_hir_analysis::check::region`.
228+
rvalue_scopes: ItemLocalMap<TempLifetime>,
230229

231230
/// Backwards incompatible scoping that will be introduced in future editions.
232231
/// This information is used later for linting to identify locals and
233232
/// temporary values that will receive backwards-incompatible drop orders.
234233
pub backwards_incompatible_scope: UnordMap<hir::ItemLocalId, Scope>,
235234
}
236235

237-
/// See the `rvalue_candidates` field for more information on rvalue
238-
/// candidates in general.
239-
/// The `lifetime` field is None to indicate that certain expressions escape
240-
/// into 'static and should have no local cleanup scope.
241-
#[derive(Debug, Copy, Clone, HashStable)]
242-
pub struct RvalueCandidate {
243-
pub target: hir::ItemLocalId,
244-
pub lifetime: Option<Scope>,
245-
}
246-
247236
impl ScopeTree {
248237
pub fn record_scope_parent(&mut self, child: Scope, parent: Option<Scope>) {
249238
debug!("{:?}.parent = {:?}", child, parent);
@@ -260,12 +249,14 @@ impl ScopeTree {
260249
self.var_map.insert(var, lifetime);
261250
}
262251

263-
pub fn record_rvalue_candidate(&mut self, var: HirId, candidate: RvalueCandidate) {
264-
debug!("record_rvalue_candidate(var={var:?}, candidate={candidate:?})");
265-
if let Some(lifetime) = &candidate.lifetime {
266-
assert!(var.local_id != lifetime.local_id)
252+
/// Make an association between a sub-expression and an extended lifetime
253+
pub fn record_rvalue_scope(&mut self, var: hir::ItemLocalId, lifetime: TempLifetime) {
254+
debug!("record_rvalue_scope(var={var:?}, lifetime={lifetime:?})");
255+
if let Some(lifetime) = lifetime.temp_lifetime {
256+
assert!(var != lifetime.local_id);
267257
}
268-
self.rvalue_candidates.insert(var, candidate);
258+
let old_lifetime = self.rvalue_scopes.insert(var, lifetime);
259+
assert!(old_lifetime.is_none_or(|old| old == lifetime));
269260
}
270261

271262
/// Returns the narrowest scope that encloses `id`, if any.
@@ -337,4 +328,20 @@ impl ScopeTree {
337328

338329
span_bug!(ty::tls::with(|tcx| inner.span(tcx, self)), "no enclosing temporary scope")
339330
}
331+
332+
/// Returns the scope when the temp created by `expr_id` will be cleaned up.
333+
/// It also emits a lint on potential backwards incompatible change to the temporary scope
334+
/// which is *for now* always shortening.
335+
pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> TempLifetime {
336+
// Check for a designated rvalue scope.
337+
if let Some(&s) = self.rvalue_scopes.get(&expr_id) {
338+
debug!("temporary_scope({expr_id:?}) = {s:?} [custom]");
339+
return s;
340+
}
341+
342+
// Otherwise, locate the innermost terminating scope.
343+
let (scope, backwards_incompatible) =
344+
self.default_temporary_scope(Scope { local_id: expr_id, data: ScopeData::Node });
345+
TempLifetime { temp_lifetime: Some(scope), backwards_incompatible }
346+
}
340347
}

compiler/rustc_middle/src/thir.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ pub struct Expr<'tcx> {
265265
}
266266

267267
/// Temporary lifetime information for THIR expressions
268-
#[derive(Clone, Copy, Debug, HashStable)]
268+
#[derive(Clone, Copy, Debug, PartialEq, Eq, HashStable)]
269269
pub struct TempLifetime {
270270
/// Lifetime for temporaries as expected.
271271
/// This should be `None` in a constant context.

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ pub use self::region::{
9797
BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region,
9898
RegionKind, RegionVid,
9999
};
100-
pub use self::rvalue_scopes::RvalueScopes;
101100
pub use self::sty::{
102101
AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
103102
CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst,
@@ -156,7 +155,6 @@ mod list;
156155
mod opaque_types;
157156
mod predicate;
158157
mod region;
159-
mod rvalue_scopes;
160158
mod structural_impls;
161159
#[allow(hidden_glob_reexports)]
162160
mod sty;

compiler/rustc_middle/src/ty/rvalue_scopes.rs

Lines changed: 0 additions & 48 deletions
This file was deleted.

compiler/rustc_middle/src/ty/typeck_results.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisit
1818
use rustc_session::Session;
1919
use rustc_span::Span;
2020

21-
use super::RvalueScopes;
2221
use crate::hir::place::Place as HirPlace;
2322
use crate::infer::canonical::Canonical;
2423
use crate::mir::FakeReadCause;
@@ -198,11 +197,6 @@ pub struct TypeckResults<'tcx> {
198197
/// issue by fake reading `t`.
199198
pub closure_fake_reads: LocalDefIdMap<Vec<(HirPlace<'tcx>, FakeReadCause, HirId)>>,
200199

201-
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
202-
/// by applying extended parameter rules.
203-
/// Details may be found in `rustc_hir_analysis::check::rvalue_scopes`.
204-
pub rvalue_scopes: RvalueScopes,
205-
206200
/// Stores the predicates that apply on coroutine witness types.
207201
/// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
208202
pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
@@ -254,7 +248,6 @@ impl<'tcx> TypeckResults<'tcx> {
254248
hidden_types: Default::default(),
255249
closure_min_captures: Default::default(),
256250
closure_fake_reads: Default::default(),
257-
rvalue_scopes: Default::default(),
258251
coroutine_stalled_predicates: Default::default(),
259252
potentially_region_dependent_goals: Default::default(),
260253
closure_size_eval: Default::default(),

0 commit comments

Comments
 (0)