fix scope of super let bindings within if let
They now use the enclosing temporary scope as their scope, regardless of which `ScopeData` was used to mark it.
This commit is contained in:
parent
bbf08d87eb
commit
8fc3938d99
4 changed files with 54 additions and 52 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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!(),
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue