Skip to content

Commit f7b3d29

Browse files
committed
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.
1 parent 68feb6c commit f7b3d29

File tree

4 files changed

+54
-52
lines changed

4 files changed

+54
-52
lines changed

compiler/rustc_hir_analysis/src/check/region.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -490,12 +490,8 @@ fn resolve_local<'tcx>(
490490
//
491491
// Iterate up to the enclosing destruction scope to find the same scope that will also
492492
// be used for the result of the block itself.
493-
while let Some(s) = visitor.cx.var_parent {
494-
let parent = visitor.scope_tree.parent_map.get(&s).cloned();
495-
if let Some(Scope { data: ScopeData::Destruction, .. }) = parent {
496-
break;
497-
}
498-
visitor.cx.var_parent = parent;
493+
if let Some(inner_scope) = visitor.cx.var_parent {
494+
(visitor.cx.var_parent, _) = visitor.scope_tree.default_temporary_scope(inner_scope)
499495
}
500496
}
501497
}

compiler/rustc_middle/src/middle/region.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,4 +299,43 @@ impl ScopeTree {
299299

300300
true
301301
}
302+
303+
/// Returns the scope of non-lifetime-extended temporaries within a given scope, as well as
304+
/// whether we've recorded a potential backwards-incompatible change to lint on.
305+
/// Returns `None` when no enclosing temporary scope is found, such as for static items.
306+
pub fn default_temporary_scope(&self, inner: Scope) -> (Option<Scope>, Option<Scope>) {
307+
let mut id = inner;
308+
let mut backwards_incompatible = None;
309+
310+
while let Some(&p) = self.parent_map.get(&id) {
311+
match p.data {
312+
ScopeData::Destruction => {
313+
debug!("temporary_scope({inner:?}) = {id:?} [enclosing]");
314+
return (Some(id), backwards_incompatible);
315+
}
316+
ScopeData::IfThenRescope | ScopeData::MatchGuard => {
317+
debug!("temporary_scope({inner:?}) = {p:?} [enclosing]");
318+
return (Some(p), backwards_incompatible);
319+
}
320+
ScopeData::Node
321+
| ScopeData::CallSite
322+
| ScopeData::Arguments
323+
| ScopeData::IfThen
324+
| ScopeData::Remainder(_) => {
325+
// If we haven't already passed through a backwards-incompatible node,
326+
// then check if we are passing through one now and record it if so.
327+
// This is for now only working for cases where a temporary lifetime is
328+
// *shortened*.
329+
if backwards_incompatible.is_none() {
330+
backwards_incompatible =
331+
self.backwards_incompatible_scope.get(&p.local_id).copied();
332+
}
333+
id = p
334+
}
335+
}
336+
}
337+
338+
debug!("temporary_scope({inner:?}) = None");
339+
(None, backwards_incompatible)
340+
}
302341
}

compiler/rustc_middle/src/ty/rvalue_scopes.rs

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -35,41 +35,8 @@ impl RvalueScopes {
3535
// if there's one. Static items, for instance, won't
3636
// have an enclosing scope, hence no scope will be
3737
// returned.
38-
let mut id = Scope { local_id: expr_id, data: ScopeData::Node };
39-
let mut backwards_incompatible = None;
40-
41-
while let Some(&p) = region_scope_tree.parent_map.get(&id) {
42-
match p.data {
43-
ScopeData::Destruction => {
44-
debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]");
45-
return (Some(id), backwards_incompatible);
46-
}
47-
ScopeData::IfThenRescope | ScopeData::MatchGuard => {
48-
debug!("temporary_scope({expr_id:?}) = {p:?} [enclosing]");
49-
return (Some(p), backwards_incompatible);
50-
}
51-
ScopeData::Node
52-
| ScopeData::CallSite
53-
| ScopeData::Arguments
54-
| ScopeData::IfThen
55-
| ScopeData::Remainder(_) => {
56-
// If we haven't already passed through a backwards-incompatible node,
57-
// then check if we are passing through one now and record it if so.
58-
// This is for now only working for cases where a temporary lifetime is
59-
// *shortened*.
60-
if backwards_incompatible.is_none() {
61-
backwards_incompatible = region_scope_tree
62-
.backwards_incompatible_scope
63-
.get(&p.local_id)
64-
.copied();
65-
}
66-
id = p
67-
}
68-
}
69-
}
70-
71-
debug!("temporary_scope({expr_id:?}) = None");
72-
(None, backwards_incompatible)
38+
region_scope_tree
39+
.default_temporary_scope(Scope { local_id: expr_id, data: ScopeData::Node })
7340
}
7441

7542
/// Make an association between a sub-expression and an extended lifetime

tests/ui/drop/if-let-super-let.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ fn main() {
2525
);
2626
#[cfg(e2024)]
2727
(
28-
if let _ = { super let _x = o.log(2); } { o.push(0) },
29-
o.push(1),
28+
if let _ = { super let _x = o.log(1); } { o.push(0) },
29+
o.push(2),
3030
);
3131
});
3232
assert_drop_order(0..=2, |o| {
@@ -37,15 +37,15 @@ fn main() {
3737
);
3838
#[cfg(e2024)]
3939
(
40-
if let true = { super let _x = o.log(2); false } {} else { o.push(0) },
41-
o.push(1),
40+
if let true = { super let _x = o.log(0); false } {} else { o.push(1) },
41+
o.push(2),
4242
);
4343
});
4444

4545
// `pin!` should behave likewise.
4646
assert_drop_order(0..=2, |o| {
4747
#[cfg(e2021)] (if let _ = pin!(o.log(2)) { o.push(0) }, o.push(1));
48-
#[cfg(e2024)] (if let _ = pin!(o.log(2)) { o.push(0) }, o.push(1));
48+
#[cfg(e2024)] (if let _ = pin!(o.log(1)) { o.push(0) }, o.push(2));
4949
});
5050
assert_drop_order(0..=2, |o| {
5151
#[cfg(e2021)]
@@ -55,8 +55,8 @@ fn main() {
5555
);
5656
#[cfg(e2024)]
5757
(
58-
if let None = Some(pin!(o.log(2))) {} else { o.push(0) },
59-
o.push(1),
58+
if let None = Some(pin!(o.log(0))) {} else { o.push(1) },
59+
o.push(2),
6060
);
6161
});
6262

@@ -65,15 +65,15 @@ fn main() {
6565
// dropped before the first operand's temporary. This is consistent across Editions.
6666
assert_drop_order(0..=1, |o| {
6767
match () {
68-
_ if let _ = o.log(0)
69-
&& let _ = { super let _x = o.log(1); } => {}
68+
_ if let _ = o.log(1)
69+
&& let _ = { super let _x = o.log(0); } => {}
7070
_ => unreachable!(),
7171
}
7272
});
7373
assert_drop_order(0..=1, |o| {
7474
match () {
75-
_ if let _ = o.log(0)
76-
&& let _ = pin!(o.log(1)) => {}
75+
_ if let _ = o.log(1)
76+
&& let _ = pin!(o.log(0)) => {}
7777
_ => unreachable!(),
7878
}
7979
});

0 commit comments

Comments
 (0)