rustc_hir_typeck/
rvalue_scopes.rs
1use hir::Node;
2use hir::def_id::DefId;
3use rustc_hir as hir;
4use rustc_middle::bug;
5use rustc_middle::middle::region::{RvalueCandidateType, Scope, ScopeTree};
6use rustc_middle::ty::RvalueScopes;
7use tracing::debug;
8
9use super::FnCtxt;
10
11fn record_rvalue_scope_rec(
29 rvalue_scopes: &mut RvalueScopes,
30 mut expr: &hir::Expr<'_>,
31 lifetime: Option<Scope>,
32) {
33 loop {
34 rvalue_scopes.record_rvalue_scope(expr.hir_id.local_id, lifetime);
41
42 match expr.kind {
43 hir::ExprKind::AddrOf(_, _, subexpr)
44 | hir::ExprKind::Unary(hir::UnOp::Deref, subexpr)
45 | hir::ExprKind::Field(subexpr, _)
46 | hir::ExprKind::Index(subexpr, _, _) => {
47 expr = subexpr;
48 }
49 _ => {
50 return;
51 }
52 }
53 }
54}
55fn record_rvalue_scope(
56 rvalue_scopes: &mut RvalueScopes,
57 expr: &hir::Expr<'_>,
58 candidate: &RvalueCandidateType,
59) {
60 debug!("resolve_rvalue_scope(expr={expr:?}, candidate={candidate:?})");
61 match candidate {
62 RvalueCandidateType::Borrow { lifetime, .. }
63 | RvalueCandidateType::Pattern { lifetime, .. } => {
64 record_rvalue_scope_rec(rvalue_scopes, expr, *lifetime)
65 } }
67}
68
69pub(crate) fn resolve_rvalue_scopes<'a, 'tcx>(
70 fcx: &'a FnCtxt<'a, 'tcx>,
71 scope_tree: &'a ScopeTree,
72 def_id: DefId,
73) -> RvalueScopes {
74 let tcx = &fcx.tcx;
75 let mut rvalue_scopes = RvalueScopes::new();
76 debug!("start resolving rvalue scopes, def_id={def_id:?}");
77 debug!("rvalue_scope: rvalue_candidates={:?}", scope_tree.rvalue_candidates);
78 for (&hir_id, candidate) in &scope_tree.rvalue_candidates {
79 let Node::Expr(expr) = tcx.hir_node(hir_id) else { bug!("hir node does not exist") };
80 record_rvalue_scope(&mut rvalue_scopes, expr, candidate);
81 }
82 rvalue_scopes
83}