Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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)

AltStyle によって変換されたページ (->オリジナル) /