@@ -827,7 +827,6 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
827
827
fn hoist_witness_pat ( & self , pat : & WitnessPat < ' p , ' tcx > ) -> print:: Pat < ' tcx > {
828
828
use print:: { FieldPat , Pat , PatKind } ;
829
829
let cx = self ;
830
- let is_wildcard = |pat : & Pat < ' _ > | matches ! ( pat. kind, PatKind :: Wild ) ;
831
830
let hoist = |p| Box :: new ( cx. hoist_witness_pat ( p) ) ;
832
831
let mut subpatterns = pat. iter_fields ( ) . map ( hoist) ;
833
832
let kind = match pat. ctor ( ) {
@@ -862,37 +861,35 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
862
861
// ignore this issue.
863
862
Ref => PatKind :: Deref { subpattern : subpatterns. next ( ) . unwrap ( ) } ,
864
863
Slice ( slice) => {
865
- match slice. kind {
866
- SliceKind :: FixedLen ( _) => PatKind :: Slice {
867
- prefix : subpatterns. collect ( ) ,
868
- has_dot_dot : false ,
869
- suffix : Box :: new ( [ ] ) ,
870
- } ,
871
- SliceKind :: VarLen ( prefix, _) => {
872
- let mut subpatterns = subpatterns. peekable ( ) ;
873
- let mut prefix: Vec < _ > = subpatterns. by_ref ( ) . take ( prefix) . collect ( ) ;
874
- if slice. array_len . is_some ( ) {
875
- // Improves diagnostics a bit: if the type is a known-size array, instead
876
- // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`.
877
- // This is incorrect if the size is not known, since `[_, ..]` captures
878
- // arrays of lengths `>= 1` whereas `[..]` captures any length.
879
- while !prefix. is_empty ( ) && is_wildcard ( prefix. last ( ) . unwrap ( ) ) {
880
- prefix. pop ( ) ;
881
- }
882
- while subpatterns. peek ( ) . is_some ( )
883
- && is_wildcard ( subpatterns. peek ( ) . unwrap ( ) )
884
- {
885
- subpatterns. next ( ) ;
886
- }
887
- }
888
- let suffix: Box < [ _ ] > = subpatterns. collect ( ) ;
889
- PatKind :: Slice {
890
- prefix : prefix. into_boxed_slice ( ) ,
891
- has_dot_dot : true ,
892
- suffix,
893
- }
864
+ let ( prefix_len, has_dot_dot) = match slice. kind {
865
+ SliceKind :: FixedLen ( len) => ( len, false ) ,
866
+ SliceKind :: VarLen ( prefix_len, _) => ( prefix_len, true ) ,
867
+ } ;
868
+
869
+ let ( mut prefix, mut suffix) = pat. fields . split_at ( prefix_len) ;
870
+
871
+ // If the pattern contains a `..`, but is applied to values of statically-known
872
+ // length (arrays), then we can slightly simplify diagnostics by merging any
873
+ // adjacent wildcard patterns into the `..`: `[x, _, .., _, y]` => `[x, .., y]`.
874
+ // (This simplification isn't allowed for slice values, because in that case
875
+ // `[x, .., y]` would match some slices that `[x, _, .., _, y]` would not.)
876
+ if has_dot_dot && slice. array_len . is_some ( ) {
877
+ while let [ rest @ .., last] = prefix
878
+ && would_print_as_wildcard ( cx. tcx , last)
879
+ {
880
+ prefix = rest;
881
+ }
882
+ while let [ first, rest @ ..] = suffix
883
+ && would_print_as_wildcard ( cx. tcx , first)
884
+ {
885
+ suffix = rest;
894
886
}
895
887
}
888
+
889
+ let prefix = prefix. iter ( ) . map ( hoist) . collect ( ) ;
890
+ let suffix = suffix. iter ( ) . map ( hoist) . collect ( ) ;
891
+
892
+ PatKind :: Slice { prefix, has_dot_dot, suffix }
896
893
}
897
894
& Str ( value) => PatKind :: Constant { value } ,
898
895
Never if self . tcx . features ( ) . never_patterns => PatKind :: Never ,
@@ -910,6 +907,22 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
910
907
}
911
908
}
912
909
910
+ /// Returns `true` if the given pattern would be printed as a wildcard (`_`).
911
+ fn would_print_as_wildcard ( tcx : TyCtxt < ' _ > , p : & WitnessPat < ' _ , ' _ > ) -> bool {
912
+ match p. ctor ( ) {
913
+ Constructor :: IntRange ( IntRange {
914
+ lo : MaybeInfiniteInt :: NegInfinity ,
915
+ hi : MaybeInfiniteInt :: PosInfinity ,
916
+ } )
917
+ | Constructor :: Wildcard
918
+ | Constructor :: NonExhaustive
919
+ | Constructor :: Hidden
920
+ | Constructor :: PrivateUninhabited => true ,
921
+ Constructor :: Never if !tcx. features ( ) . never_patterns => true ,
922
+ _ => false ,
923
+ }
924
+ }
925
+
913
926
impl < ' p , ' tcx : ' p > PatCx for RustcPatCtxt < ' p , ' tcx > {
914
927
type Ty = RevealedTy < ' tcx > ;
915
928
type Error = ErrorGuaranteed ;
0 commit comments