From 54812011600a2c19f7076c438e6eabe6a8063774 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 8 Oct 2021 03:59:56 +0100 Subject: [PATCH 1/3] Ignore projection type when determining upvar ancestory --- compiler/rustc_typeck/src/check/upvar.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index b7c042a08cf1c..9b94fda515363 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -2278,7 +2278,7 @@ fn determine_place_ancestry_relation( let projections_b = &place_b.projections; let same_initial_projections = - iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a == proj_b); + iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a.kind == proj_b.kind); if same_initial_projections { // First min(n, m) projections are the same From d7f8a0678012f8a0fa24609345b777af4a6a4c04 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 7 Oct 2021 22:04:13 +0100 Subject: [PATCH 2/3] Add regression test --- .../2229_closure_analysis/issue-89606.rs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/test/ui/closures/2229_closure_analysis/issue-89606.rs diff --git a/src/test/ui/closures/2229_closure_analysis/issue-89606.rs b/src/test/ui/closures/2229_closure_analysis/issue-89606.rs new file mode 100644 index 0000000000000..1bb6aa40f06fa --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-89606.rs @@ -0,0 +1,40 @@ +// Regression test for #89606. Used to ICE. +// +// check-pass +// revisions: twenty_eighteen twenty_twentyone +// [twenty_eighteen]compile-flags: --edition 2018 +// [twenty_twentyone]compile-flags: --edition 2021 + +struct S<'a>(Option<&'a mut i32>); + +fn by_ref(s: &mut S<'_>) { + (|| { + let S(_o) = s; + s.0 = None; + })(); +} + +fn by_value(s: S<'_>) { + (|| { + let S(ref _o) = s; + let _g = s.0; + })(); +} + +struct V<'a>((Option<&'a mut i32>,)); + +fn nested(v: &mut V<'_>) { + (|| { + let V((_o,)) = v; + v.0 = (None, ); + })(); +} + +fn main() { + let mut s = S(None); + by_ref(&mut s); + by_value(s); + + let mut v = V((None, )); + nested(&mut v); +} From 7275cfa47cf3fdbf41c2ad859ac937bffe5923a4 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 9 Oct 2021 06:41:05 +0100 Subject: [PATCH 3/3] Explicit `PlaceAncestryRelation::SamePlace` and handle like `Descendant` --- compiler/rustc_typeck/src/check/upvar.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 9b94fda515363..3a10988bba0b9 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -65,6 +65,7 @@ use std::iter; enum PlaceAncestryRelation { Ancestor, Descendant, + SamePlace, Divergent, } @@ -564,7 +565,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for possible_ancestor in min_cap_list.iter_mut() { match determine_place_ancestry_relation(&place, &possible_ancestor.place) { // current place is descendant of possible_ancestor - PlaceAncestryRelation::Descendant => { + PlaceAncestryRelation::Descendant | PlaceAncestryRelation::SamePlace => { ancestor_found = true; let backup_path_expr_id = possible_ancestor.info.path_expr_id; @@ -2281,12 +2282,14 @@ fn determine_place_ancestry_relation( iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a.kind == proj_b.kind); if same_initial_projections { + use std::cmp::Ordering; + // First min(n, m) projections are the same // Select Ancestor/Descendant - if projections_b.len() >= projections_a.len() { - PlaceAncestryRelation::Ancestor - } else { - PlaceAncestryRelation::Descendant + match projections_b.len().cmp(&projections_a.len()) { + Ordering::Greater => PlaceAncestryRelation::Ancestor, + Ordering::Equal => PlaceAncestryRelation::SamePlace, + Ordering::Less => PlaceAncestryRelation::Descendant, } } else { PlaceAncestryRelation::Divergent