@@ -203,7 +203,7 @@ impl Scope {
203
203
pub type ScopeDepth = u32 ;
204
204
205
205
/// The region scope tree encodes information about region relationships.
206
- #[ derive( Default , Debug ) ]
206
+ #[ derive( TyEncodable , TyDecodable , Default , Debug ) ]
207
207
pub struct ScopeTree {
208
208
/// If not empty, this body is the root of this region hierarchy.
209
209
pub root_body : Option < hir:: HirId > ,
@@ -223,15 +223,12 @@ pub struct ScopeTree {
223
223
/// Maps from a `NodeId` to the associated destruction scope (if any).
224
224
destruction_scopes : FxIndexMap < hir:: ItemLocalId , Scope > ,
225
225
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 > ,
235
232
236
233
/// If there are any `yield` nested within a scope, this map
237
234
/// stores the `Span` of the last one and its index in the
@@ -315,6 +312,17 @@ pub struct ScopeTree {
315
312
pub body_expr_count : FxHashMap < hir:: BodyId , usize > ,
316
313
}
317
314
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
+
318
326
#[ derive( Debug , Copy , Clone , TyEncodable , TyDecodable , HashStable ) ]
319
327
pub struct YieldData {
320
328
/// The `Span` of the yield.
@@ -349,12 +357,20 @@ impl ScopeTree {
349
357
self . var_map . insert ( var, lifetime) ;
350
358
}
351
359
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
+ _ => { }
356
372
}
357
- self . rvalue_scopes . insert ( var, lifetime ) ;
373
+ self . rvalue_candidates . insert ( var, candidate_type ) ;
358
374
}
359
375
360
376
/// Returns the narrowest scope that encloses `id`, if any.
@@ -367,34 +383,6 @@ impl ScopeTree {
367
383
self . var_map . get ( & var_id) . cloned ( )
368
384
}
369
385
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
-
398
386
/// Returns `true` if `subscope` is equal to or is lexically nested inside `superscope`, and
399
387
/// `false` otherwise.
400
388
///
@@ -439,7 +427,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ScopeTree {
439
427
ref parent_map,
440
428
ref var_map,
441
429
ref destruction_scopes,
442
- ref rvalue_scopes ,
430
+ ref rvalue_candidates ,
443
431
ref yield_in_scope,
444
432
} = * self ;
445
433
@@ -448,7 +436,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ScopeTree {
448
436
parent_map. hash_stable ( hcx, hasher) ;
449
437
var_map. hash_stable ( hcx, hasher) ;
450
438
destruction_scopes. hash_stable ( hcx, hasher) ;
451
- rvalue_scopes . hash_stable ( hcx, hasher) ;
439
+ rvalue_candidates . hash_stable ( hcx, hasher) ;
452
440
yield_in_scope. hash_stable ( hcx, hasher) ;
453
441
}
454
442
}
0 commit comments