diff options
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/region.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/middle/region.rs | 39 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/rvalue_scopes.rs | 37 | ||||
| -rw-r--r-- | tests/ui/drop/if-let-super-let.rs | 22 |
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!(), } }); |
