Skip to content

Commit 9336c1b

Browse files
committed
merge RvalueScopes into ScopeTree
This removes some unneeded indirection and consolidates the logic for scope resolution.
1 parent 3eef21e commit 9336c1b

File tree

11 files changed

+94
-204
lines changed

11 files changed

+94
-204
lines changed

compiler/rustc_hir_analysis/src/check/region.rs

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -516,12 +516,10 @@ fn resolve_local<'tcx>(
516516

517517
if let Some(pat) = pat {
518518
if is_binding_pat(pat) {
519-
visitor.scope_tree.record_rvalue_candidate(
520-
expr.hir_id,
521-
RvalueCandidate {
522-
target: expr.hir_id.local_id,
523-
lifetime: visitor.cx.var_parent,
524-
},
519+
record_projection_rvalue_scopes(
520+
&mut visitor.scope_tree,
521+
expr,
522+
visitor.cx.var_parent,
525523
);
526524
}
527525
}
@@ -627,10 +625,7 @@ fn resolve_local<'tcx>(
627625
match expr.kind {
628626
hir::ExprKind::AddrOf(_, _, subexpr) => {
629627
record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
630-
visitor.scope_tree.record_rvalue_candidate(
631-
subexpr.hir_id,
632-
RvalueCandidate { target: subexpr.hir_id.local_id, lifetime: blk_id },
633-
);
628+
record_projection_rvalue_scopes(&mut visitor.scope_tree, subexpr, blk_id);
634629
}
635630
hir::ExprKind::Struct(_, fields, _) => {
636631
for field in fields {
@@ -687,6 +682,53 @@ fn resolve_local<'tcx>(
687682
}
688683
}
689684

685+
/// Applied to an expression `expr` if `expr` -- or something owned or partially owned by
686+
/// `expr` -- is going to be indirectly referenced by a variable in a let statement. In that
687+
/// case, the "temporary lifetime" or `expr` is extended to be the block enclosing the `let`
688+
/// statement.
689+
///
690+
/// More formally, if `expr` matches the grammar `ET`, record the rvalue scope of the matching
691+
/// `<rvalue>` as `blk_id`:
692+
///
693+
/// ```text
694+
/// ET = *ET
695+
/// | ET[...]
696+
/// | ET.f
697+
/// | (ET)
698+
/// | <rvalue>
699+
/// ```
700+
///
701+
/// Note: ET is intended to match "rvalues or places based on rvalues".
702+
fn record_projection_rvalue_scopes(
703+
scope_tree: &mut ScopeTree,
704+
mut expr: &hir::Expr<'_>,
705+
lifetime: Option<Scope>,
706+
) {
707+
debug!(?expr, ?lifetime);
708+
709+
loop {
710+
// Note: give all the expressions matching `ET` with the
711+
// extended temporary lifetime, not just the innermost rvalue,
712+
// because in MIR building if we must compile e.g., `*rvalue()`
713+
// into a temporary, we request the temporary scope of the
714+
// outer expression.
715+
716+
scope_tree.record_rvalue_scope(expr.hir_id.local_id, lifetime);
717+
718+
match expr.kind {
719+
hir::ExprKind::AddrOf(_, _, subexpr)
720+
| hir::ExprKind::Unary(hir::UnOp::Deref, subexpr)
721+
| hir::ExprKind::Field(subexpr, _)
722+
| hir::ExprKind::Index(subexpr, _, _) => {
723+
expr = subexpr;
724+
}
725+
_ => {
726+
return;
727+
}
728+
}
729+
}
730+
}
731+
690732
impl<'tcx> ScopeResolutionVisitor<'tcx> {
691733
/// Records the current parent (if any) as the parent of `child_scope`.
692734
fn record_child_scope(&mut self, child_scope: Scope) {

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
@@ -36,7 +36,6 @@ mod op;
3636
mod opaque_types;
3737
mod pat;
3838
mod place_op;
39-
mod rvalue_scopes;
4039
mod typeck_root_ctxt;
4140
mod upvar;
4241
mod writeback;
@@ -236,9 +235,6 @@ fn typeck_with_inspect<'tcx>(
236235
// because they don't constrain other type variables.
237236
fcx.closure_analyze(body);
238237
assert!(fcx.deferred_call_resolutions.borrow().is_empty());
239-
// Before the coroutine analysis, temporary scopes shall be marked to provide more
240-
// precise information on types to be captured.
241-
fcx.resolve_rvalue_scopes(def_id.to_def_id());
242238

243239
for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
244240
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: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ 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;
@@ -221,29 +221,17 @@ pub struct ScopeTree {
221221
/// variable is declared.
222222
var_map: FxIndexMap<hir::ItemLocalId, Scope>,
223223

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>,
224+
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
225+
/// by applying extended parameter rules.
226+
/// Further details may be found in `rustc_hir_analysis::check::region`.
227+
rvalue_scopes: ItemLocalMap<Option<Scope>>,
230228

231229
/// Backwards incompatible scoping that will be introduced in future editions.
232230
/// This information is used later for linting to identify locals and
233231
/// temporary values that will receive backwards-incompatible drop orders.
234232
pub backwards_incompatible_scope: UnordMap<hir::ItemLocalId, Scope>,
235233
}
236234

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-
247235
impl ScopeTree {
248236
pub fn record_scope_parent(&mut self, child: Scope, parent: Option<Scope>) {
249237
debug!("{:?}.parent = {:?}", child, parent);
@@ -260,12 +248,13 @@ impl ScopeTree {
260248
self.var_map.insert(var, lifetime);
261249
}
262250

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)
251+
/// Make an association between a sub-expression and an extended lifetime
252+
pub fn record_rvalue_scope(&mut self, var: hir::ItemLocalId, lifetime: Option<Scope>) {
253+
debug!("record_rvalue_scope(var={var:?}, lifetime={lifetime:?})");
254+
if let Some(lifetime) = lifetime {
255+
assert!(var != lifetime.local_id);
267256
}
268-
self.rvalue_candidates.insert(var, candidate);
257+
self.rvalue_scopes.insert(var, lifetime);
269258
}
270259

271260
/// Returns the narrowest scope that encloses `id`, if any.
@@ -337,4 +326,20 @@ impl ScopeTree {
337326

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

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
@@ -17,7 +17,6 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisit
1717
use rustc_session::Session;
1818
use rustc_span::Span;
1919

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

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

0 commit comments

Comments
 (0)