Change:
<!-- Thank you for finding an Internal Compiler Error! If possible, try to provide a minimal verifiable example. You can read "Rust Bug Minimization Patterns" for how to create smaller examples. --This bug popped up in CI on a project of ours. This does not reproduce on stable, but does reproduce on nightly and the latest beta (). Bisection shows that was the first build with the regression. Further bisection points to being the commit that introduced the regression. If I had to guess from the PRs in the rollup I'd say seems the most likely, since it touched the code around the error source. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</details
label: +regression-from-stable-to-beta
Reduced:
This assertion is indeed introduced in . The two captures have the same place but different CaptureInfo. cc
Interesting. It's a bit hard to imagine how could have introduced this, since that just sorts a list. Fascinating! Maybe somebody from has a clue?
Actually, it's not at all hard to imagine, because introduced the following: The projections are actually the same, but the types differ in regions, which probably means that this comment is wrong:
Yeah, I just checked and the region of the match is an inferenced variable and gives an concrete ReFree instead.
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-critical
Did some analysis: We cannot just replace the with . This will create two mutable references in edition 2021 and fail borrowck. Pre-2018 the places do get merged later so the issue isn't exposed. None of the upvar code makes use of the region info, and writeback will erase it anyway. So I think the fix should just be have the region erased when inserting/looking up from capture_information. I can submit a PR if you haven't started
I just started looking at it but if you have a solution, go for it! Happy to review your PR
I'm not sure about region code that much but regionchk uses the regions created: I think at one point mentioned getting rid of the region field entirely in UpvarBorrow, but since it wasn't required the discussion didn't proceed. Also it's more like this is a bug of the capture analysis than the sorting. We should never have two same places going into min capture in the list.
I was thinking about erasing the region from s (i.e. the key of captureinformation). But it turns out that's used later to create upvar tuple... So I switched captureinformation from HashMap to a linear vec looked up with custom eq fn instead.

Discussion:
enum PlaceAncestryRelation { Ancestor, Descendant, <ins> SamePlace, </ins> Divergent, }

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 <del> PlaceAncestryRelation::Descendant => { </del> <ins> PlaceAncestryRelation::Descendant | PlaceAncestryRelation::SamePlace => { </ins> ancestor_found = true; let backup_path_expr_id = possible_ancestor.info.path_expr_id;

let projections_b = &place_b.projections; let same_initial_projections = <del> iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a == proj_b); </del> <ins> iter::zip(projections_a, projections_b).all(|(proj_a, proj_b)| proj_a.kind == proj_b.kind); </ins> if same_initial_projections { <ins> use std::cmp::Ordering; </ins> // First min(n, m) projections are the same // Select Ancestor/Descendant <del> if projections_b.len() >= projections_a.len() { PlaceAncestryRelation::Ancestor } else { PlaceAncestryRelation::Descendant </del> <ins> match projections_b.len().cmp(&projections_a.len()) { Ordering::Greater => PlaceAncestryRelation::Ancestor, Ordering::Equal => PlaceAncestryRelation::SamePlace, Ordering::Less => PlaceAncestryRelation::Descendant, </ins> } } else { PlaceAncestryRelation::Divergent

<ins> // 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); } </ins>