Skip to content

Commit 7cc8c44

Browse files
committed
Auto merge of #89648 - nbdd0121:issue-89606, r=nikomatsakis
Ignore type of projections for upvar capturing Fix #89606 Ignore type of projections for upvar capturing. Originally HashMap is used, and the hash/eq implementation of Place takes the type of projections into account. These types may differ by lifetime which causes #89606 to ICE. I originally considered erasing regions but `place.ty()` is used when creating upvar tuple type, more than just serving as a key type, so I switched to a linear comparison with custom eq (`compare_place_ignore_ty`) instead. r? `@wesleywiser` `@rustbot` label +T-compiler
2 parents 5b21064 + 7275cfa commit 7cc8c44

File tree

2 files changed

+49
-6
lines changed

2 files changed

+49
-6
lines changed

compiler/rustc_typeck/src/check/upvar.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ use std::iter;
6565
enum PlaceAncestryRelation {
6666
Ancestor,
6767
Descendant,
68+
SamePlace,
6869
Divergent,
6970
}
7071

@@ -564,7 +565,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
564565
for possible_ancestor in min_cap_list.iter_mut() {
565566
match determine_place_ancestry_relation(&place, &possible_ancestor.place) {
566567
// current place is descendant of possible_ancestor
567-
PlaceAncestryRelation::Descendant => {
568+
PlaceAncestryRelation::Descendant | PlaceAncestryRelation::SamePlace => {
568569
ancestor_found = true;
569570
let backup_path_expr_id = possible_ancestor.info.path_expr_id;
570571

@@ -2278,15 +2279,17 @@ fn determine_place_ancestry_relation(
22782279
let projections_b = &place_b.projections;
22792280

22802281
let same_initial_projections =
2281-
iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a == proj_b);
2282+
iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a.kind == proj_b.kind);
22822283

22832284
if same_initial_projections {
2285+
use std::cmp::Ordering;
2286+
22842287
// First min(n, m) projections are the same
22852288
// Select Ancestor/Descendant
2286-
if projections_b.len() >= projections_a.len() {
2287-
PlaceAncestryRelation::Ancestor
2288-
} else {
2289-
PlaceAncestryRelation::Descendant
2289+
match projections_b.len().cmp(&projections_a.len()) {
2290+
Ordering::Greater => PlaceAncestryRelation::Ancestor,
2291+
Ordering::Equal => PlaceAncestryRelation::SamePlace,
2292+
Ordering::Less => PlaceAncestryRelation::Descendant,
22902293
}
22912294
} else {
22922295
PlaceAncestryRelation::Divergent
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Regression test for #89606. Used to ICE.
2+
//
3+
// check-pass
4+
// revisions: twenty_eighteen twenty_twentyone
5+
// [twenty_eighteen]compile-flags: --edition 2018
6+
// [twenty_twentyone]compile-flags: --edition 2021
7+
8+
struct S<'a>(Option<&'a mut i32>);
9+
10+
fn by_ref(s: &mut S<'_>) {
11+
(|| {
12+
let S(_o) = s;
13+
s.0 = None;
14+
})();
15+
}
16+
17+
fn by_value(s: S<'_>) {
18+
(|| {
19+
let S(ref _o) = s;
20+
let _g = s.0;
21+
})();
22+
}
23+
24+
struct V<'a>((Option<&'a mut i32>,));
25+
26+
fn nested(v: &mut V<'_>) {
27+
(|| {
28+
let V((_o,)) = v;
29+
v.0 = (None, );
30+
})();
31+
}
32+
33+
fn main() {
34+
let mut s = S(None);
35+
by_ref(&mut s);
36+
by_value(s);
37+
38+
let mut v = V((None, ));
39+
nested(&mut v);
40+
}

0 commit comments

Comments
 (0)