rustc_middle/ty/
rvalue_scopes.rs1use rustc_hir as hir;
2use rustc_hir::ItemLocalMap;
3use rustc_macros::{HashStable, TyDecodable, TyEncodable};
4use tracing::debug;
5
6use crate::middle::region::{Scope, ScopeData, ScopeTree};
7
8#[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)]
11pub struct RvalueScopes {
12 map: ItemLocalMap<Option<Scope>>,
13}
14
15impl RvalueScopes {
16 pub fn new() -> Self {
17 Self { map: <_>::default() }
18 }
19
20 pub fn temporary_scope(
24 &self,
25 region_scope_tree: &ScopeTree,
26 expr_id: hir::ItemLocalId,
27 ) -> (Option<Scope>, Option<Scope>) {
28 if let Some(&s) = self.map.get(&expr_id) {
30 debug!("temporary_scope({expr_id:?}) = {s:?} [custom]");
31 return (s, None);
32 }
33
34 let mut id = Scope { local_id: expr_id, data: ScopeData::Node };
39 let mut backwards_incompatible = None;
40
41 while let Some(&p) = region_scope_tree.parent_map.get(&id) {
42 match p.data {
43 ScopeData::Destruction => {
44 debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]");
45 return (Some(id), backwards_incompatible);
46 }
47 ScopeData::IfThenRescope => {
48 debug!("temporary_scope({expr_id:?}) = {p:?} [enclosing]");
49 return (Some(p), backwards_incompatible);
50 }
51 ScopeData::Node
52 | ScopeData::CallSite
53 | ScopeData::Arguments
54 | ScopeData::IfThen
55 | ScopeData::Remainder(_) => {
56 if backwards_incompatible.is_none() {
61 backwards_incompatible = region_scope_tree
62 .backwards_incompatible_scope
63 .get(&p.local_id)
64 .copied();
65 }
66 id = p
67 }
68 }
69 }
70
71 debug!("temporary_scope({expr_id:?}) = None");
72 (None, backwards_incompatible)
73 }
74
75 pub fn record_rvalue_scope(&mut self, var: hir::ItemLocalId, lifetime: Option<Scope>) {
77 debug!("record_rvalue_scope(var={var:?}, lifetime={lifetime:?})");
78 if let Some(lifetime) = lifetime {
79 assert!(var != lifetime.local_id);
80 }
81 self.map.insert(var, lifetime);
82 }
83}