about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs8
-rw-r--r--compiler/rustc_middle/src/middle/region.rs39
-rw-r--r--compiler/rustc_middle/src/ty/rvalue_scopes.rs37
-rw-r--r--tests/ui/drop/if-let-super-let.rs22
4 files changed, 54 insertions, 52 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index f5770b7312d..2ba7ed46f92 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -490,12 +490,8 @@ fn resolve_local<'tcx>(
             //
             // Iterate up to the enclosing destruction scope to find the same scope that will also
             // be used for the result of the block itself.
-            while let Some(s) = visitor.cx.var_parent {
-                let parent = visitor.scope_tree.parent_map.get(&s).cloned();
-                if let Some(Scope { data: ScopeData::Destruction, .. }) = parent {
-                    break;
-                }
-                visitor.cx.var_parent = parent;
+            if let Some(inner_scope) = visitor.cx.var_parent {
+                (visitor.cx.var_parent, _) = visitor.scope_tree.default_temporary_scope(inner_scope)
             }
         }
     }
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 857d041224f..5367e5edd49 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -299,4 +299,43 @@ impl ScopeTree {
 
         true
     }
+
+    /// Returns the scope of non-lifetime-extended temporaries within a given scope, as well as
+    /// whether we've recorded a potential backwards-incompatible change to lint on.
+    /// Returns `None` when no enclosing temporary scope is found, such as for static items.
+    pub fn default_temporary_scope(&self, inner: Scope) -> (Option<Scope>, Option<Scope>) {
+        let mut id = inner;
+        let mut backwards_incompatible = None;
+
+        while let Some(&p) = self.parent_map.get(&id) {
+            match p.data {
+                ScopeData::Destruction => {
+                    debug!("temporary_scope({inner:?}) = {id:?} [enclosing]");
+                    return (Some(id), backwards_incompatible);
+                }
+                ScopeData::IfThenRescope | ScopeData::MatchGuard => {
+                    debug!("temporary_scope({inner:?}) = {p:?} [enclosing]");
+                    return (Some(p), backwards_incompatible);
+                }
+                ScopeData::Node
+                | ScopeData::CallSite
+                | ScopeData::Arguments
+                | ScopeData::IfThen
+                | ScopeData::Remainder(_) => {
+                    // If we haven't already passed through a backwards-incompatible node,
+                    // then check if we are passing through one now and record it if so.
+                    // This is for now only working for cases where a temporary lifetime is
+                    // *shortened*.
+                    if backwards_incompatible.is_none() {
+                        backwards_incompatible =
+                            self.backwards_incompatible_scope.get(&p.local_id).copied();
+                    }
+                    id = p
+                }
+            }
+        }
+
+        debug!("temporary_scope({inner:?}) = None");
+        (None, backwards_incompatible)
+    }
 }
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index 7dfe2d28051..8b92e48ed1a 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -35,41 +35,8 @@ impl RvalueScopes {
         // if there's one. Static items, for instance, won't
         // have an enclosing scope, hence no scope will be
         // returned.
-        let mut id = Scope { local_id: expr_id, data: ScopeData::Node };
-        let mut backwards_incompatible = None;
-
-        while let Some(&p) = region_scope_tree.parent_map.get(&id) {
-            match p.data {
-                ScopeData::Destruction => {
-                    debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]");
-                    return (Some(id), backwards_incompatible);
-                }
-                ScopeData::IfThenRescope | ScopeData::MatchGuard => {
-                    debug!("temporary_scope({expr_id:?}) = {p:?} [enclosing]");
-                    return (Some(p), backwards_incompatible);
-                }
-                ScopeData::Node
-                | ScopeData::CallSite
-                | ScopeData::Arguments
-                | ScopeData::IfThen
-                | ScopeData::Remainder(_) => {
-                    // If we haven't already passed through a backwards-incompatible node,
-                    // then check if we are passing through one now and record it if so.
-                    // This is for now only working for cases where a temporary lifetime is
-                    // *shortened*.
-                    if backwards_incompatible.is_none() {
-                        backwards_incompatible = region_scope_tree
-                            .backwards_incompatible_scope
-                            .get(&p.local_id)
-                            .copied();
-                    }
-                    id = p
-                }
-            }
-        }
-
-        debug!("temporary_scope({expr_id:?}) = None");
-        (None, backwards_incompatible)
+        region_scope_tree
+            .default_temporary_scope(Scope { local_id: expr_id, data: ScopeData::Node })
     }
 
     /// Make an association between a sub-expression and an extended lifetime
diff --git a/tests/ui/drop/if-let-super-let.rs b/tests/ui/drop/if-let-super-let.rs
index 0f966e793a3..c6543e6d3dc 100644
--- a/tests/ui/drop/if-let-super-let.rs
+++ b/tests/ui/drop/if-let-super-let.rs
@@ -25,8 +25,8 @@ fn main() {
         );
         #[cfg(e2024)]
         (
-            if let _ = { super let _x = o.log(2); } { o.push(0) },
-            o.push(1),
+            if let _ = { super let _x = o.log(1); } { o.push(0) },
+            o.push(2),
         );
     });
     assert_drop_order(0..=2, |o| {
@@ -37,15 +37,15 @@ fn main() {
         );
         #[cfg(e2024)]
         (
-            if let true = { super let _x = o.log(2); false } {} else { o.push(0) },
-            o.push(1),
+            if let true = { super let _x = o.log(0); false } {} else { o.push(1) },
+            o.push(2),
         );
     });
 
     // `pin!` should behave likewise.
     assert_drop_order(0..=2, |o| {
         #[cfg(e2021)] (if let _ = pin!(o.log(2)) { o.push(0) }, o.push(1));
-        #[cfg(e2024)] (if let _ = pin!(o.log(2)) { o.push(0) }, o.push(1));
+        #[cfg(e2024)] (if let _ = pin!(o.log(1)) { o.push(0) }, o.push(2));
     });
     assert_drop_order(0..=2, |o| {
         #[cfg(e2021)]
@@ -55,8 +55,8 @@ fn main() {
         );
         #[cfg(e2024)]
         (
-            if let None = Some(pin!(o.log(2))) {} else { o.push(0) },
-            o.push(1),
+            if let None = Some(pin!(o.log(0))) {} else { o.push(1) },
+            o.push(2),
         );
     });
 
@@ -65,15 +65,15 @@ fn main() {
     // dropped before the first operand's temporary. This is consistent across Editions.
     assert_drop_order(0..=1, |o| {
         match () {
-            _ if let _ = o.log(0)
-                && let _ = { super let _x = o.log(1); } => {}
+            _ if let _ = o.log(1)
+                && let _ = { super let _x = o.log(0); } => {}
             _ => unreachable!(),
         }
     });
     assert_drop_order(0..=1, |o| {
         match () {
-            _ if let _ = o.log(0)
-                && let _ = pin!(o.log(1)) => {}
+            _ if let _ = o.log(1)
+                && let _ = pin!(o.log(0)) => {}
             _ => unreachable!(),
         }
     });