From 444eb4cc12ad94935ba8047c3e79da789b9e7d94 Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 8 Oct 2025 03:03:55 -0700 Subject: [PATCH] assert that non-extended temporaries have scopes --- compiler/rustc_hir_analysis/src/check/region.rs | 11 ++++++----- compiler/rustc_middle/src/middle/region.rs | 13 ++++++------- compiler/rustc_middle/src/ty/rvalue_scopes.rs | 10 ++++------ 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 43e6f5fe10471..f99fefcf56ace 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -498,7 +498,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. if let Some(inner_scope) = visitor.cx.var_parent { - (visitor.cx.var_parent, _) = visitor.scope_tree.default_temporary_scope(inner_scope) + visitor.cx.var_parent = + Some(visitor.scope_tree.default_temporary_scope(inner_scope).0) } // Don't lifetime-extend child `super let`s or block tail expressions' temporaries in // the initializer when this `super let` is not itself extended by a parent `let` @@ -752,10 +753,10 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { // The body of the every fn is a root scope. resolve_expr(this, body.value, true); } else { - // Only functions have an outer terminating (drop) scope, while - // temporaries in constant initializers may be 'static, but only - // according to rvalue lifetime semantics, using the same - // syntactical rules used for let initializers. + // All bodies have an outer temporary drop scope, but temporaries + // and `super let` bindings in constant initializers may be extended + // to have 'static lifetimes, using the same syntactical rules used + // for `let` initializers. // // e.g., in `let x = &f();`, the temporary holding the result from // the `f()` call lives for the entirety of the surrounding block. diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 5367e5edd496a..3ed8d9a36e101 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -16,7 +16,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::{DUMMY_SP, Span}; use tracing::debug; -use crate::ty::TyCtxt; +use crate::ty::{self, TyCtxt}; /// Represents a statically-describable scope that can be used to /// bound the lifetime/region for values. @@ -302,8 +302,8 @@ impl ScopeTree { /// 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, Option) { + /// Panics if no enclosing temporary scope is found. + pub fn default_temporary_scope(&self, inner: Scope) -> (Scope, Option) { let mut id = inner; let mut backwards_incompatible = None; @@ -311,11 +311,11 @@ impl ScopeTree { match p.data { ScopeData::Destruction => { debug!("temporary_scope({inner:?}) = {id:?} [enclosing]"); - return (Some(id), backwards_incompatible); + return (id, backwards_incompatible); } ScopeData::IfThenRescope | ScopeData::MatchGuard => { debug!("temporary_scope({inner:?}) = {p:?} [enclosing]"); - return (Some(p), backwards_incompatible); + return (p, backwards_incompatible); } ScopeData::Node | ScopeData::CallSite @@ -335,7 +335,6 @@ impl ScopeTree { } } - debug!("temporary_scope({inner:?}) = None"); - (None, backwards_incompatible) + span_bug!(ty::tls::with(|tcx| inner.span(tcx, self)), "no enclosing temporary scope") } } diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index 8b92e48ed1a07..df4e29d457548 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -31,12 +31,10 @@ impl RvalueScopes { return (s, None); } - // Otherwise, locate the innermost terminating scope - // if there's one. Static items, for instance, won't - // have an enclosing scope, hence no scope will be - // returned. - region_scope_tree - .default_temporary_scope(Scope { local_id: expr_id, data: ScopeData::Node }) + // Otherwise, locate the innermost terminating scope. + let (scope, backward_incompatible) = region_scope_tree + .default_temporary_scope(Scope { local_id: expr_id, data: ScopeData::Node }); + (Some(scope), backward_incompatible) } /// Make an association between a sub-expression and an extended lifetime