@@ -203,7 +203,7 @@ impl Scope {
203203pub type ScopeDepth = u32 ;
204204
205205/// The region scope tree encodes information about region relationships.
206- #[ derive( Default , Debug ) ]
206+ #[ derive( TyEncodable , TyDecodable , Default , Debug ) ]
207207pub struct ScopeTree {
208208 /// If not empty, this body is the root of this region hierarchy.
209209 pub root_body : Option < hir:: HirId > ,
@@ -223,15 +223,12 @@ pub struct ScopeTree {
223223 /// Maps from a `NodeId` to the associated destruction scope (if any).
224224 destruction_scopes : FxIndexMap < hir:: ItemLocalId , Scope > ,
225225
226- /// `rvalue_scopes` includes entries for those expressions whose
227- /// cleanup scope is larger than the default. The map goes from the
228- /// expression ID to the cleanup scope id. For rvalues not present in
229- /// this table, the appropriate cleanup scope is the innermost
230- /// enclosing statement, conditional expression, or repeating
231- /// block (see `terminating_scopes`).
232- /// In constants, None is used to indicate that certain expressions
233- /// escape into 'static and should have no local cleanup scope.
234- rvalue_scopes : FxHashMap < hir:: ItemLocalId , Option < Scope > > ,
226+ /// Identifies expressions which, if captured into a temporary, ought to
227+ /// have a temporary whose lifetime extends to the end of the enclosing *block*,
228+ /// and not the enclosing *statement*. Expressions that are not present in this
229+ /// table are not rvalue candidates. The set of rvalue candidates is computed
230+ /// during type check based on a traversal of the AST.
231+ pub rvalue_candidates : FxHashMap < hir:: HirId , RvalueCandidateType > ,
235232
236233 /// If there are any `yield` nested within a scope, this map
237234 /// stores the `Span` of the last one and its index in the
@@ -315,6 +312,17 @@ pub struct ScopeTree {
315312 pub body_expr_count : FxHashMap < hir:: BodyId , usize > ,
316313}
317314
315+ /// Identifies the reason that a given expression is an rvalue candidate
316+ /// (see the `rvalue_candidates` field for more information what rvalue
317+ /// candidates in general). In constants, the `lifetime` field is None
318+ /// to indicate that certain expressions escape into 'static and
319+ /// should have no local cleanup scope.
320+ #[ derive( Debug , Copy , Clone , TyEncodable , TyDecodable , HashStable ) ]
321+ pub enum RvalueCandidateType {
322+ Borrow { target : hir:: ItemLocalId , lifetime : Option < Scope > } ,
323+ Pattern { target : hir:: ItemLocalId , lifetime : Option < Scope > } ,
324+ }
325+
318326#[ derive( Debug , Copy , Clone , TyEncodable , TyDecodable , HashStable ) ]
319327pub struct YieldData {
320328 /// The `Span` of the yield.
@@ -349,12 +357,20 @@ impl ScopeTree {
349357 self . var_map . insert ( var, lifetime) ;
350358 }
351359
352- pub fn record_rvalue_scope ( & mut self , var : hir:: ItemLocalId , lifetime : Option < Scope > ) {
353- debug ! ( "record_rvalue_scope(sub={:?}, sup={:?})" , var, lifetime) ;
354- if let Some ( lifetime) = lifetime {
355- assert ! ( var != lifetime. item_local_id( ) ) ;
360+ pub fn record_rvalue_candidate (
361+ & mut self ,
362+ var : hir:: HirId ,
363+ candidate_type : RvalueCandidateType ,
364+ ) {
365+ debug ! ( "record_rvalue_candidate(var={var:?}, type={candidate_type:?})" ) ;
366+ match & candidate_type {
367+ RvalueCandidateType :: Borrow { lifetime : Some ( lifetime) , .. }
368+ | RvalueCandidateType :: Pattern { lifetime : Some ( lifetime) , .. } => {
369+ assert ! ( var. local_id != lifetime. item_local_id( ) )
370+ }
371+ _ => { }
356372 }
357- self . rvalue_scopes . insert ( var, lifetime ) ;
373+ self . rvalue_candidates . insert ( var, candidate_type ) ;
358374 }
359375
360376 /// Returns the narrowest scope that encloses `id`, if any.
@@ -367,34 +383,6 @@ impl ScopeTree {
367383 self . var_map . get ( & var_id) . cloned ( )
368384 }
369385
370- /// Returns the scope when the temp created by `expr_id` will be cleaned up.
371- pub fn temporary_scope ( & self , expr_id : hir:: ItemLocalId ) -> Option < Scope > {
372- // Check for a designated rvalue scope.
373- if let Some ( & s) = self . rvalue_scopes . get ( & expr_id) {
374- debug ! ( "temporary_scope({:?}) = {:?} [custom]" , expr_id, s) ;
375- return s;
376- }
377-
378- // Otherwise, locate the innermost terminating scope
379- // if there's one. Static items, for instance, won't
380- // have an enclosing scope, hence no scope will be
381- // returned.
382- let mut id = Scope { id : expr_id, data : ScopeData :: Node } ;
383-
384- while let Some ( & ( p, _) ) = self . parent_map . get ( & id) {
385- match p. data {
386- ScopeData :: Destruction => {
387- debug ! ( "temporary_scope({:?}) = {:?} [enclosing]" , expr_id, id) ;
388- return Some ( id) ;
389- }
390- _ => id = p,
391- }
392- }
393-
394- debug ! ( "temporary_scope({:?}) = None" , expr_id) ;
395- None
396- }
397-
398386 /// Returns `true` if `subscope` is equal to or is lexically nested inside `superscope`, and
399387 /// `false` otherwise.
400388 ///
@@ -439,7 +427,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ScopeTree {
439427 ref parent_map,
440428 ref var_map,
441429 ref destruction_scopes,
442- ref rvalue_scopes ,
430+ ref rvalue_candidates ,
443431 ref yield_in_scope,
444432 } = * self ;
445433
@@ -448,7 +436,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ScopeTree {
448436 parent_map. hash_stable ( hcx, hasher) ;
449437 var_map. hash_stable ( hcx, hasher) ;
450438 destruction_scopes. hash_stable ( hcx, hasher) ;
451- rvalue_scopes . hash_stable ( hcx, hasher) ;
439+ rvalue_candidates . hash_stable ( hcx, hasher) ;
452440 yield_in_scope. hash_stable ( hcx, hasher) ;
453441 }
454442}
0 commit comments