diff options
| author | bors <bors@rust-lang.org> | 2023-12-18 13:58:20 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-12-18 13:58:20 +0000 |
| commit | a7690a366ccb7c7fd6865241792e2199b23c2b5a (patch) | |
| tree | 8f9f4fc9983cfc7ad0686b74e6b50de208c2a14c | |
| parent | 3562c535fefe00174cc7fdcace387c9a7f50075e (diff) | |
| parent | c3a739e4c8a2bade976794211bbfbe4814fb4c5a (diff) | |
| download | rust-a7690a366ccb7c7fd6865241792e2199b23c2b5a.tar.gz rust-a7690a366ccb7c7fd6865241792e2199b23c2b5a.zip | |
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.
| -rw-r--r-- | compiler/rustc_hir_typeck/src/upvar.rs | 60 | ||||
| -rw-r--r-- | tests/ui/closures/2229_closure_analysis/issue-118144.rs | 16 | ||||
| -rw-r--r-- | tests/ui/closures/2229_closure_analysis/issue-118144.stderr | 11 |
3 files changed, 51 insertions, 36 deletions
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 69d6fb8e2ea..726ee02d75e 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -680,49 +680,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs`. for (_, captures) in &mut root_var_min_capture_list { captures.sort_by(|capture1, capture2| { - for (p1, p2) in capture1.place.projections.iter().zip(&capture2.place.projections) { + fn is_field<'a>(p: &&Projection<'a>) -> bool { + match p.kind { + ProjectionKind::Field(_, _) => true, + ProjectionKind::Deref | ProjectionKind::OpaqueCast => false, + p @ (ProjectionKind::Subslice | ProjectionKind::Index) => { + bug!("ProjectionKind {:?} was unexpected", p) + } + } + } + + // Need to sort only by Field projections, so filter away others. + // A previous implementation considered other projection types too + // but that caused ICE #118144 + let capture1_field_projections = capture1.place.projections.iter().filter(is_field); + let capture2_field_projections = capture2.place.projections.iter().filter(is_field); + + for (p1, p2) in capture1_field_projections.zip(capture2_field_projections) { // We do not need to look at the `Projection.ty` fields here because at each // step of the iteration, the projections will either be the same and therefore // the types must be as well or the current projection will be different and // we will return the result of comparing the field indexes. match (p1.kind, p2.kind) { - // Paths are the same, continue to next loop. - (ProjectionKind::Deref, ProjectionKind::Deref) => {} - (ProjectionKind::OpaqueCast, ProjectionKind::OpaqueCast) => {} - (ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _)) - if i1 == i2 => {} - - // Fields are different, compare them. (ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _)) => { - return i1.cmp(&i2); + // Compare only if paths are different. + // Otherwise continue to the next iteration + if i1 != i2 { + return i1.cmp(&i2); + } } - - // We should have either a pair of `Deref`s or a pair of `Field`s. - // Anything else is a bug. - ( - l @ (ProjectionKind::Deref | ProjectionKind::Field(..)), - r @ (ProjectionKind::Deref | ProjectionKind::Field(..)), - ) => bug!( - "ProjectionKinds Deref and Field were mismatched: ({:?}, {:?})", - l, - r - ), - ( - l @ (ProjectionKind::Index - | ProjectionKind::Subslice - | ProjectionKind::Deref - | ProjectionKind::OpaqueCast - | ProjectionKind::Field(..)), - r @ (ProjectionKind::Index - | ProjectionKind::Subslice - | ProjectionKind::Deref - | ProjectionKind::OpaqueCast - | ProjectionKind::Field(..)), - ) => bug!( - "ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})", - l, - r - ), + // Given the filter above, this arm should never be hit + (l, r) => bug!("ProjectionKinds {:?} or {:?} were unexpected", l, r), } } diff --git a/tests/ui/closures/2229_closure_analysis/issue-118144.rs b/tests/ui/closures/2229_closure_analysis/issue-118144.rs new file mode 100644 index 00000000000..3e5d9f9739a --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-118144.rs @@ -0,0 +1,16 @@ +// Regression test for ICE #118144 + +struct V(i32); + +fn func(func_arg: &mut V) { + || { + // Declaring `x` separately instead of using + // a destructuring binding like `let V(x) = ...` + // becaue only `V(x) = ...` triggers the ICE + let x; + V(x) = func_arg; //~ ERROR: mismatched types + func_arg.0 = 0; + }; +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/issue-118144.stderr b/tests/ui/closures/2229_closure_analysis/issue-118144.stderr new file mode 100644 index 00000000000..85cb5adc07e --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/issue-118144.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-118144.rs:11:9 + | +LL | V(x) = func_arg; + | ^^^^ -------- this expression has type `&mut V` + | | + | expected `&mut V`, found `V` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. |
