@@ -40,58 +40,44 @@ 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
72- for ( idx, subpattern) in prefix. iter ( ) . enumerate ( ) {
73- let elem =
74- ProjectionElem :: ConstantIndex { offset : idx as u64 , min_length, from_end : false } ;
61+ for ( offset, subpattern) in ( 0u64 ..) . zip ( prefix) {
62+ let elem = ProjectionElem :: ConstantIndex { offset, min_length, from_end : false } ;
7563 let place = place. clone_project ( elem) ;
7664 MatchPairTree :: for_pattern ( place, subpattern, self , match_pairs, extra_data)
7765 }
7866
7967 if let Some ( subslice_pat) = opt_slice {
80- let suffix_len = suffix. len ( ) as u64 ;
8168 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 ,
69+ from : prefix_len ,
70+ to : if is_array { min_length - suffix_len } else { suffix_len } ,
71+ from_end : !is_array ,
8572 } ) ;
8673 MatchPairTree :: for_pattern ( subslice, subslice_pat, self , match_pairs, extra_data) ;
8774 }
8875
89- for ( idx, subpattern) in suffix. iter ( ) . rev ( ) . enumerate ( ) {
90- let end_offset = ( idx + 1 ) as u64 ;
76+ for ( end_offset, subpattern) in ( 1u64 ..) . zip ( suffix. iter ( ) . rev ( ) ) {
9177 let elem = ProjectionElem :: ConstantIndex {
92- offset : if exact_size { min_length - end_offset } else { end_offset } ,
78+ offset : if is_array { min_length - end_offset } else { end_offset } ,
9379 min_length,
94- from_end : !exact_size ,
80+ from_end : !is_array ,
9581 } ;
9682 let place = place. clone_project ( elem) ;
9783 MatchPairTree :: for_pattern ( place, subpattern, self , match_pairs, extra_data)
@@ -256,21 +242,44 @@ impl<'tcx> MatchPairTree<'tcx> {
256242 }
257243
258244 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- ) ;
245+ // Determine the statically-known length of the array type being matched.
246+ // This should always succeed for legal programs, but could fail for
247+ // erroneous programs (e.g. the type is `[u8; const { panic!() }]`),
248+ // so take care not to ICE if this fails.
249+ let array_len = match pattern. ty . kind ( ) {
250+ ty:: Array ( _, len) => len. try_to_target_usize ( cx. tcx ) ,
251+ _ => None ,
252+ } ;
253+ if let Some ( array_len) = array_len {
254+ cx. prefix_slice_suffix (
255+ & mut subpairs,
256+ extra_data,
257+ & place_builder,
258+ Some ( array_len) ,
259+ prefix,
260+ slice,
261+ suffix,
262+ ) ;
263+ } else {
264+ // If the array length couldn't be determined, ignore the
265+ // subpatterns and delayed-assert that compilation will fail.
266+ cx. tcx . dcx ( ) . span_delayed_bug (
267+ pattern. span ,
268+ format ! (
269+ "array length in pattern couldn't be determined for ty={:?}" ,
270+ pattern. ty
271+ ) ,
272+ ) ;
273+ }
274+
267275 None
268276 }
269277 PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
270278 cx. prefix_slice_suffix (
271279 & mut subpairs,
272280 extra_data,
273281 & place_builder,
282+ None ,
274283 prefix,
275284 slice,
276285 suffix,
0 commit comments