summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:13:23 +0000
commit20431706a863f92cb37dc512fef6e48d192aaf2c (patch)
tree2867f13f5fd5437ba628c67d7f87309ccadcd286 /compiler/rustc_hir_typeck/src/rvalue_scopes.rs
parentReleasing progress-linux version 1.65.0+dfsg1-2~progress7.99u1. (diff)
downloadrustc-20431706a863f92cb37dc512fef6e48d192aaf2c.tar.xz
rustc-20431706a863f92cb37dc512fef6e48d192aaf2c.zip
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_typeck/src/rvalue_scopes.rs')
-rw-r--r--compiler/rustc_hir_typeck/src/rvalue_scopes.rs83
1 files changed, 83 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
new file mode 100644
index 000000000..22c9e7961
--- /dev/null
+++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
@@ -0,0 +1,83 @@
+use super::FnCtxt;
+use hir::def_id::DefId;
+use hir::Node;
+use rustc_hir as hir;
+use rustc_middle::middle::region::{RvalueCandidateType, Scope, ScopeTree};
+use rustc_middle::ty::RvalueScopes;
+
+/// Applied to an expression `expr` if `expr` -- or something owned or partially owned by
+/// `expr` -- is going to be indirectly referenced by a variable in a let statement. In that
+/// case, the "temporary lifetime" or `expr` is extended to be the block enclosing the `let`
+/// statement.
+///
+/// More formally, if `expr` matches the grammar `ET`, record the rvalue scope of the matching
+/// `<rvalue>` as `blk_id`:
+///
+/// ```text
+/// ET = *ET
+/// | ET[...]
+/// | ET.f
+/// | (ET)
+/// | <rvalue>
+/// ```
+///
+/// Note: ET is intended to match "rvalues or places based on rvalues".
+fn record_rvalue_scope_rec(
+ rvalue_scopes: &mut RvalueScopes,
+ mut expr: &hir::Expr<'_>,
+ lifetime: Option<Scope>,
+) {
+ loop {
+ // Note: give all the expressions matching `ET` with the
+ // extended temporary lifetime, not just the innermost rvalue,
+ // because in codegen if we must compile e.g., `*rvalue()`
+ // into a temporary, we request the temporary scope of the
+ // outer expression.
+
+ rvalue_scopes.record_rvalue_scope(expr.hir_id.local_id, lifetime);
+
+ match expr.kind {
+ hir::ExprKind::AddrOf(_, _, subexpr)
+ | hir::ExprKind::Unary(hir::UnOp::Deref, subexpr)
+ | hir::ExprKind::Field(subexpr, _)
+ | hir::ExprKind::Index(subexpr, _) => {
+ expr = subexpr;
+ }
+ _ => {
+ return;
+ }
+ }
+ }
+}
+fn record_rvalue_scope(
+ rvalue_scopes: &mut RvalueScopes,
+ expr: &hir::Expr<'_>,
+ candidate: &RvalueCandidateType,
+) {
+ debug!("resolve_rvalue_scope(expr={expr:?}, candidate={candidate:?})");
+ match candidate {
+ RvalueCandidateType::Borrow { lifetime, .. }
+ | RvalueCandidateType::Pattern { lifetime, .. } => {
+ record_rvalue_scope_rec(rvalue_scopes, expr, *lifetime)
+ } // FIXME(@dingxiangfei2009): handle the candidates in the function call arguments
+ }
+}
+
+pub fn resolve_rvalue_scopes<'a, 'tcx>(
+ fcx: &'a FnCtxt<'a, 'tcx>,
+ scope_tree: &'a ScopeTree,
+ def_id: DefId,
+) -> RvalueScopes {
+ let tcx = &fcx.tcx;
+ let hir_map = tcx.hir();
+ let mut rvalue_scopes = RvalueScopes::new();
+ debug!("start resolving rvalue scopes, def_id={def_id:?}");
+ debug!("rvalue_scope: rvalue_candidates={:?}", scope_tree.rvalue_candidates);
+ for (&hir_id, candidate) in &scope_tree.rvalue_candidates {
+ let Some(Node::Expr(expr)) = hir_map.find(hir_id) else {
+ bug!("hir node does not exist")
+ };
+ record_rvalue_scope(&mut rvalue_scopes, expr, candidate);
+ }
+ rvalue_scopes
+}