Skip to content

Commit a7690a3

Browse files
committedDec 18, 2023
Auto merge of #118584 - gurry:118144-projection-kind-mismatched, r=WaffleLapkin
Fix ICE `ProjectionKinds Deref and Field were mismatched` Fix #118144 Removed the check that ICEd if the sequence of projection kinds were different across captures. Instead we now sort based only on `Field` projection kinds.
2 parents 3562c53 + c3a739e commit a7690a3

File tree

3 files changed

+51
-36
lines changed

3 files changed

+51
-36
lines changed
 

‎compiler/rustc_hir_typeck/src/upvar.rs

+24-36
Original file line numberDiff line numberDiff line change
@@ -680,49 +680,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
680680
// `tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs`.
681681
for (_, captures) in &mut root_var_min_capture_list {
682682
captures.sort_by(|capture1, capture2| {
683-
for (p1, p2) in capture1.place.projections.iter().zip(&capture2.place.projections) {
683+
fn is_field<'a>(p: &&Projection<'a>) -> bool {
684+
match p.kind {
685+
ProjectionKind::Field(_, _) => true,
686+
ProjectionKind::Deref | ProjectionKind::OpaqueCast => false,
687+
p @ (ProjectionKind::Subslice | ProjectionKind::Index) => {
688+
bug!("ProjectionKind {:?} was unexpected", p)
689+
}
690+
}
691+
}
692+
693+
// Need to sort only by Field projections, so filter away others.
694+
// A previous implementation considered other projection types too
695+
// but that caused ICE #118144
696+
let capture1_field_projections = capture1.place.projections.iter().filter(is_field);
697+
let capture2_field_projections = capture2.place.projections.iter().filter(is_field);
698+
699+
for (p1, p2) in capture1_field_projections.zip(capture2_field_projections) {
684700
// We do not need to look at the `Projection.ty` fields here because at each
685701
// step of the iteration, the projections will either be the same and therefore
686702
// the types must be as well or the current projection will be different and
687703
// we will return the result of comparing the field indexes.
688704
match (p1.kind, p2.kind) {
689-
// Paths are the same, continue to next loop.
690-
(ProjectionKind::Deref, ProjectionKind::Deref) => {}
691-
(ProjectionKind::OpaqueCast, ProjectionKind::OpaqueCast) => {}
692-
(ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _))
693-
if i1 == i2 => {}
694-
695-
// Fields are different, compare them.
696705
(ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _)) => {
697-
return i1.cmp(&i2);
706+
// Compare only if paths are different.
707+
// Otherwise continue to the next iteration
708+
if i1 != i2 {
709+
return i1.cmp(&i2);
710+
}
698711
}
699-
700-
// We should have either a pair of `Deref`s or a pair of `Field`s.
701-
// Anything else is a bug.
702-
(
703-
l @ (ProjectionKind::Deref | ProjectionKind::Field(..)),
704-
r @ (ProjectionKind::Deref | ProjectionKind::Field(..)),
705-
) => bug!(
706-
"ProjectionKinds Deref and Field were mismatched: ({:?}, {:?})",
707-
l,
708-
r
709-
),
710-
(
711-
l @ (ProjectionKind::Index
712-
| ProjectionKind::Subslice
713-
| ProjectionKind::Deref
714-
| ProjectionKind::OpaqueCast
715-
| ProjectionKind::Field(..)),
716-
r @ (ProjectionKind::Index
717-
| ProjectionKind::Subslice
718-
| ProjectionKind::Deref
719-
| ProjectionKind::OpaqueCast
720-
| ProjectionKind::Field(..)),
721-
) => bug!(
722-
"ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})",
723-
l,
724-
r
725-
),
712+
// Given the filter above, this arm should never be hit
713+
(l, r) => bug!("ProjectionKinds {:?} or {:?} were unexpected", l, r),
726714
}
727715
}
728716

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Regression test for ICE #118144
2+
3+
struct V(i32);
4+
5+
fn func(func_arg: &mut V) {
6+
|| {
7+
// Declaring `x` separately instead of using
8+
// a destructuring binding like `let V(x) = ...`
9+
// becaue only `V(x) = ...` triggers the ICE
10+
let x;
11+
V(x) = func_arg; //~ ERROR: mismatched types
12+
func_arg.0 = 0;
13+
};
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-118144.rs:11:9
3+
|
4+
LL | V(x) = func_arg;
5+
| ^^^^ -------- this expression has type `&mut V`
6+
| |
7+
| expected `&mut V`, found `V`
8+
9+
error: aborting due to 1 previous error
10+
11+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)