@@ -52,8 +52,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5252 def_bm : ty:: BindingMode ,
5353 discrim_span : Option < Span > ,
5454 ) {
55- let tcx = self . tcx ;
56-
5755 debug ! ( "check_pat_walk(pat={:?},expected={:?},def_bm={:?})" , pat, expected, def_bm) ;
5856
5957 let path_resolution = match & pat. node {
@@ -114,77 +112,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
114112 self . check_pat_ref ( pat, inner, mutbl, expected, def_bm, discrim_span)
115113 }
116114 PatKind :: Slice ( ref before, ref slice, ref after) => {
117- let expected_ty = self . structurally_resolved_type ( pat. span , expected) ;
118- let ( inner_ty, slice_ty) = match expected_ty. sty {
119- ty:: Array ( inner_ty, size) => {
120- if let Some ( size) = size. try_eval_usize ( tcx, self . param_env ) {
121- let min_len = before. len ( ) as u64 + after. len ( ) as u64 ;
122- if slice. is_none ( ) {
123- if min_len != size {
124- struct_span_err ! (
125- tcx. sess, pat. span, E0527 ,
126- "pattern requires {} elements but array has {}" ,
127- min_len, size)
128- . span_label ( pat. span , format ! ( "expected {} elements" , size) )
129- . emit ( ) ;
130- }
131- ( inner_ty, tcx. types . err )
132- } else if let Some ( rest) = size. checked_sub ( min_len) {
133- ( inner_ty, tcx. mk_array ( inner_ty, rest) )
134- } else {
135- struct_span_err ! ( tcx. sess, pat. span, E0528 ,
136- "pattern requires at least {} elements but array has {}" ,
137- min_len, size)
138- . span_label ( pat. span ,
139- format ! ( "pattern cannot match array of {} elements" , size) )
140- . emit ( ) ;
141- ( inner_ty, tcx. types . err )
142- }
143- } else {
144- struct_span_err ! (
145- tcx. sess,
146- pat. span,
147- E0730 ,
148- "cannot pattern-match on an array without a fixed length" ,
149- ) . emit ( ) ;
150- ( inner_ty, tcx. types . err )
151- }
152- }
153- ty:: Slice ( inner_ty) => ( inner_ty, expected_ty) ,
154- _ => {
155- if !expected_ty. references_error ( ) {
156- let mut err = struct_span_err ! (
157- tcx. sess, pat. span, E0529 ,
158- "expected an array or slice, found `{}`" ,
159- expected_ty) ;
160- if let ty:: Ref ( _, ty, _) = expected_ty. sty {
161- match ty. sty {
162- ty:: Array ( ..) | ty:: Slice ( ..) => {
163- err. help ( "the semantics of slice patterns changed \
164- recently; see issue #62254") ;
165- }
166- _ => { }
167- }
168- }
169-
170- err. span_label ( pat. span ,
171- format ! ( "pattern cannot match with input type `{}`" , expected_ty)
172- ) . emit ( ) ;
173- }
174- ( tcx. types . err , tcx. types . err )
175- }
176- } ;
177-
178- for elt in before {
179- self . check_pat_walk ( & elt, inner_ty, def_bm, discrim_span) ;
180- }
181- if let Some ( ref slice) = * slice {
182- self . check_pat_walk ( & slice, slice_ty, def_bm, discrim_span) ;
183- }
184- for elt in after {
185- self . check_pat_walk ( & elt, inner_ty, def_bm, discrim_span) ;
186- }
187- expected_ty
115+ let slice = slice. as_deref ( ) ;
116+ self . check_pat_slice ( pat. span , before, slice, after, expected, def_bm, discrim_span)
188117 }
189118 } ;
190119
@@ -1070,4 +999,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1070999 tcx. types . err
10711000 }
10721001 }
1002+
1003+ fn check_pat_slice (
1004+ & self ,
1005+ span : Span ,
1006+ before : & ' tcx [ P < hir:: Pat > ] ,
1007+ slice : Option < & ' tcx hir:: Pat > ,
1008+ after : & ' tcx [ P < hir:: Pat > ] ,
1009+ expected : Ty < ' tcx > ,
1010+ def_bm : ty:: BindingMode ,
1011+ discrim_span : Option < Span > ,
1012+ ) -> Ty < ' tcx > {
1013+ let tcx = self . tcx ;
1014+ let expected_ty = self . structurally_resolved_type ( span, expected) ;
1015+ let ( inner_ty, slice_ty) = match expected_ty. sty {
1016+ ty:: Array ( inner_ty, size) => {
1017+ if let Some ( size) = size. try_eval_usize ( tcx, self . param_env ) {
1018+ let min_len = before. len ( ) as u64 + after. len ( ) as u64 ;
1019+ if slice. is_none ( ) {
1020+ if min_len != size {
1021+ struct_span_err ! (
1022+ tcx. sess, span, E0527 ,
1023+ "pattern requires {} elements but array has {}" ,
1024+ min_len, size
1025+ )
1026+ . span_label ( span, format ! ( "expected {} elements" , size) )
1027+ . emit ( ) ;
1028+ }
1029+ ( inner_ty, tcx. types . err )
1030+ } else if let Some ( rest) = size. checked_sub ( min_len) {
1031+ ( inner_ty, tcx. mk_array ( inner_ty, rest) )
1032+ } else {
1033+ let msg = format ! ( "pattern cannot match array of {} elements" , size) ;
1034+ struct_span_err ! (
1035+ tcx. sess, span, E0528 ,
1036+ "pattern requires at least {} elements but array has {}" ,
1037+ min_len, size
1038+ )
1039+ . span_label ( span, msg)
1040+ . emit ( ) ;
1041+ ( inner_ty, tcx. types . err )
1042+ }
1043+ } else {
1044+ struct_span_err ! (
1045+ tcx. sess, span, E0730 ,
1046+ "cannot pattern-match on an array without a fixed length" ,
1047+ )
1048+ . emit ( ) ;
1049+ ( inner_ty, tcx. types . err )
1050+ }
1051+ }
1052+ ty:: Slice ( inner_ty) => ( inner_ty, expected_ty) ,
1053+ _ => {
1054+ if !expected_ty. references_error ( ) {
1055+ let mut err = struct_span_err ! (
1056+ tcx. sess, span, E0529 ,
1057+ "expected an array or slice, found `{}`" ,
1058+ expected_ty
1059+ ) ;
1060+ if let ty:: Ref ( _, ty, _) = expected_ty. sty {
1061+ if let ty:: Array ( ..) | ty:: Slice ( ..) = ty. sty {
1062+ err. help ( "the semantics of slice patterns changed \
1063+ recently; see issue #62254") ;
1064+ }
1065+ }
1066+
1067+ let msg = format ! ( "pattern cannot match with input type `{}`" , expected_ty) ;
1068+ err. span_label ( span, msg) ;
1069+ err. emit ( ) ;
1070+ }
1071+ ( tcx. types . err , tcx. types . err )
1072+ }
1073+ } ;
1074+
1075+ for elt in before {
1076+ self . check_pat_walk ( & elt, inner_ty, def_bm, discrim_span) ;
1077+ }
1078+ if let Some ( slice) = slice {
1079+ self . check_pat_walk ( & slice, slice_ty, def_bm, discrim_span) ;
1080+ }
1081+ for elt in after {
1082+ self . check_pat_walk ( & elt, inner_ty, def_bm, discrim_span) ;
1083+ }
1084+ expected_ty
1085+ }
10731086}
0 commit comments