1 use crate::middle::region::{Scope, ScopeData, ScopeTree}; 2 use rustc_data_structures::fx::FxHashMap; 3 use rustc_hir as hir; 4 5 /// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by 6 /// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`. 7 #[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)] 8 pub struct RvalueScopes { 9 map: FxHashMap<hir::ItemLocalId, Option<Scope>>, 10 } 11 12 impl RvalueScopes { new() -> Self13 pub fn new() -> Self { 14 Self { map: <_>::default() } 15 } 16 17 /// Returns the scope when the temp created by `expr_id` will be cleaned up. temporary_scope( &self, region_scope_tree: &ScopeTree, expr_id: hir::ItemLocalId, ) -> Option<Scope>18 pub fn temporary_scope( 19 &self, 20 region_scope_tree: &ScopeTree, 21 expr_id: hir::ItemLocalId, 22 ) -> Option<Scope> { 23 // Check for a designated rvalue scope. 24 if let Some(&s) = self.map.get(&expr_id) { 25 debug!("temporary_scope({expr_id:?}) = {s:?} [custom]"); 26 return s; 27 } 28 29 // Otherwise, locate the innermost terminating scope 30 // if there's one. Static items, for instance, won't 31 // have an enclosing scope, hence no scope will be 32 // returned. 33 let mut id = Scope { id: expr_id, data: ScopeData::Node }; 34 35 while let Some(&(p, _)) = region_scope_tree.parent_map.get(&id) { 36 match p.data { 37 ScopeData::Destruction => { 38 debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]"); 39 return Some(id); 40 } 41 _ => id = p, 42 } 43 } 44 45 debug!("temporary_scope({expr_id:?}) = None"); 46 None 47 } 48 49 /// Make an association between a sub-expression and an extended lifetime record_rvalue_scope(&mut self, var: hir::ItemLocalId, lifetime: Option<Scope>)50 pub fn record_rvalue_scope(&mut self, var: hir::ItemLocalId, lifetime: Option<Scope>) { 51 debug!("record_rvalue_scope(var={var:?}, lifetime={lifetime:?})"); 52 if let Some(lifetime) = lifetime { 53 assert!(var != lifetime.item_local_id()); 54 } 55 self.map.insert(var, lifetime); 56 } 57 } 58