]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/rvalue_scopes.rs
Rollup merge of #95446 - notseanray:master, r=Mark-Simulacrum
[rust.git] / compiler / rustc_middle / src / ty / rvalue_scopes.rs
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_typeck::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 {
13     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.
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
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 }