@@ -40,33 +40,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4040 match_pairs : & mut Vec < MatchPairTree < ' tcx > > ,
4141 extra_data : & mut PatternExtraData < ' tcx > ,
4242 place : & PlaceBuilder < ' tcx > ,
43+ array_len : Option < u64 > ,
4344 prefix : & [ Pat < ' tcx > ] ,
4445 opt_slice : & Option < Box < Pat < ' tcx > > > ,
4546 suffix : & [ Pat < ' tcx > ] ,
4647 ) {
47- let tcx = self . tcx ;
48- let ( min_length, exact_size) = if let Some ( place_resolved) = place. try_to_place ( self ) {
49- let place_ty = place_resolved. ty ( & self . local_decls , tcx) . ty ;
50- match place_ty. kind ( ) {
51- ty:: Array ( _, length) => {
52- if let Some ( length) = length. try_to_target_usize ( tcx) {
53- ( length, true )
54- } else {
55- // This can happen when the array length is a generic const
56- // expression that couldn't be evaluated (e.g., due to an error).
57- // Since there's already a compilation error, we use a fallback
58- // to avoid an ICE.
59- tcx. dcx ( ) . span_delayed_bug (
60- tcx. def_span ( self . def_id ) ,
61- "array length in pattern couldn't be evaluated" ,
62- ) ;
63- ( ( prefix. len ( ) + suffix. len ( ) ) . try_into ( ) . unwrap ( ) , false )
64- }
65- }
66- _ => ( ( prefix. len ( ) + suffix. len ( ) ) . try_into ( ) . unwrap ( ) , false ) ,
67- }
68- } else {
69- ( ( prefix. len ( ) + suffix. len ( ) ) . try_into ( ) . unwrap ( ) , false )
48+ let prefix_len = u64:: try_from ( prefix. len ( ) ) . unwrap ( ) ;
49+ let suffix_len = u64:: try_from ( suffix. len ( ) ) . unwrap ( ) ;
50+
51+ // For slice patterns with a `..` followed by 0 or more suffix subpatterns,
52+ // the actual slice index of those subpatterns isn't statically known, so
53+ // we have to index them relative to the end of the slice.
54+ //
55+ // For array patterns, all subpatterns are indexed relative to the start.
56+ let ( min_length, is_array) = match array_len {
57+ Some ( len) => ( len, true ) ,
58+ None => ( prefix_len + suffix_len, false ) ,
7059 } ;
7160
7261 for ( idx, subpattern) in prefix. iter ( ) . enumerate ( ) {
@@ -77,21 +66,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
7766 }
7867
7968 if let Some ( subslice_pat) = opt_slice {
80- let suffix_len = suffix. len ( ) as u64 ;
8169 let subslice = place. clone_project ( PlaceElem :: Subslice {
82- from : prefix . len ( ) as u64 ,
83- to : if exact_size { min_length - suffix_len } else { suffix_len } ,
84- from_end : !exact_size ,
70+ from : prefix_len ,
71+ to : if is_array { min_length - suffix_len } else { suffix_len } ,
72+ from_end : !is_array ,
8573 } ) ;
8674 MatchPairTree :: for_pattern ( subslice, subslice_pat, self , match_pairs, extra_data) ;
8775 }
8876
8977 for ( idx, subpattern) in suffix. iter ( ) . rev ( ) . enumerate ( ) {
9078 let end_offset = ( idx + 1 ) as u64 ;
9179 let elem = ProjectionElem :: ConstantIndex {
92- offset : if exact_size { min_length - end_offset } else { end_offset } ,
80+ offset : if is_array { min_length - end_offset } else { end_offset } ,
9381 min_length,
94- from_end : !exact_size ,
82+ from_end : !is_array ,
9583 } ;
9684 let place = place. clone_project ( elem) ;
9785 MatchPairTree :: for_pattern ( place, subpattern, self , match_pairs, extra_data)
@@ -256,21 +244,44 @@ impl<'tcx> MatchPairTree<'tcx> {
256244 }
257245
258246 PatKind :: Array { ref prefix, ref slice, ref suffix } => {
259- cx. prefix_slice_suffix (
260- & mut subpairs,
261- extra_data,
262- & place_builder,
263- prefix,
264- slice,
265- suffix,
266- ) ;
247+ // Determine the statically-known length of the array type being matched.
248+ // This should always succeed for legal programs, but could fail for
249+ // erroneous programs (e.g. the type is `[u8; const { panic!() }]`),
250+ // so take care not to ICE if this fails.
251+ let array_len = match pattern. ty . kind ( ) {
252+ ty:: Array ( _, len) => len. try_to_target_usize ( cx. tcx ) ,
253+ _ => None ,
254+ } ;
255+ if let Some ( array_len) = array_len {
256+ cx. prefix_slice_suffix (
257+ & mut subpairs,
258+ extra_data,
259+ & place_builder,
260+ Some ( array_len) ,
261+ prefix,
262+ slice,
263+ suffix,
264+ ) ;
265+ } else {
266+ // If the array length couldn't be determined, ignore the
267+ // subpatterns and delayed-assert that compilation will fail.
268+ cx. tcx . dcx ( ) . span_delayed_bug (
269+ pattern. span ,
270+ format ! (
271+ "array length in pattern couldn't be determined for ty={:?}" ,
272+ pattern. ty
273+ ) ,
274+ ) ;
275+ }
276+
267277 None
268278 }
269279 PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
270280 cx. prefix_slice_suffix (
271281 & mut subpairs,
272282 extra_data,
273283 & place_builder,
284+ None ,
274285 prefix,
275286 slice,
276287 suffix,
0 commit comments