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