@@ -2,6 +2,7 @@ use either::Either;
22use rustc_middle:: mir:: * ;
33use rustc_middle:: thir:: { self , * } ;
44use rustc_middle:: ty:: { self , Ty , TypeVisitableExt } ;
5+ use std:: ops;
56
67use crate :: builder:: Builder ;
78use crate :: builder:: expr:: as_place:: { PlaceBase , PlaceBuilder } ;
@@ -35,7 +36,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3536 /// Used internally by [`MatchPairTree::for_pattern`].
3637 fn prefix_slice_suffix < ' pat > (
3738 & mut self ,
38- src_path : & ' pat Pat < ' tcx > ,
39+ top_pattern : & ' pat Pat < ' tcx > ,
3940 match_pairs : & mut Vec < MatchPairTree < ' pat , ' tcx > > ,
4041 place : & PlaceBuilder < ' tcx > ,
4142 prefix : & ' pat [ Box < Pat < ' tcx > > ] ,
@@ -57,28 +58,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5758 ( ( prefix. len ( ) + suffix. len ( ) ) . try_into ( ) . unwrap ( ) , false )
5859 } ;
5960
60- if self . should_optimize_subslice ( prefix) {
61- let elem_ty = prefix[ 0 ] . ty ;
62- let prefix_valtree = self . simplify_const_pattern_slice_into_valtree ( prefix) ;
63- let match_pair = self . valtree_to_match_pair (
64- src_path,
65- prefix_valtree,
66- place. clone ( ) ,
67- elem_ty,
68- Range :: from_start ( 0 ..prefix. len ( ) as u64 ) ,
69- opt_slice. is_some ( ) || !suffix. is_empty ( ) ,
70- ) ;
71-
72- match_pairs. push ( match_pair) ;
73- } else {
74- match_pairs. extend ( prefix. iter ( ) . enumerate ( ) . map ( |( idx, subpattern) | {
75- let elem = ProjectionElem :: ConstantIndex {
76- offset : idx as u64 ,
77- min_length,
78- from_end : false ,
79- } ;
80- MatchPairTree :: for_pattern ( place. clone_project ( elem) , subpattern, self )
81- } ) ) ;
61+ tracing:: warn!( "Builder::prefix_slice_suffix: min_length: {}, exact_size: {} -> {:?}" , min_length, exact_size, top_pattern) ;
62+ tracing:: warn!( "prefix: {:?}, suffix: {:?}" , prefix. len( ) , suffix. len( ) ) ;
63+
64+ if !prefix. is_empty ( ) {
65+ let bounds = Range :: from_start ( 0 ..prefix. len ( ) as u64 ) ;
66+ let subpattern = bounds. apply ( prefix) ;
67+ for pair in self . build_slice_branch ( bounds, place, top_pattern, subpattern) {
68+ match_pairs. push ( pair) ;
69+ }
8270 }
8371
8472 if let Some ( subslice_pat) = opt_slice {
@@ -91,61 +79,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9179 match_pairs. push ( MatchPairTree :: for_pattern ( subslice, subslice_pat, self ) ) ;
9280 }
9381
94- if self . should_optimize_subslice ( suffix) {
95- let elem_ty = suffix[ 0 ] . ty ;
96- let suffix_valtree = self . simplify_const_pattern_slice_into_valtree ( suffix) ;
97- let match_pair = self . valtree_to_match_pair (
98- src_path,
99- suffix_valtree,
100- place. clone ( ) ,
101- elem_ty,
102- Range :: from_end ( 0 ..suffix. len ( ) as u64 ) ,
103- true ,
104- ) ;
105-
106- match_pairs. push ( match_pair) ;
107- } else {
108- match_pairs. extend ( suffix. iter ( ) . rev ( ) . enumerate ( ) . map ( |( idx, subpattern) | {
109- let end_offset = ( idx + 1 ) as u64 ;
110- let elem = ProjectionElem :: ConstantIndex {
111- offset : if exact_size { min_length - end_offset } else { end_offset } ,
112- min_length,
113- from_end : !exact_size,
114- } ;
115- let place = place. clone_project ( elem) ;
116- MatchPairTree :: for_pattern ( place, subpattern, self )
117- } ) ) ;
82+ if !suffix. is_empty ( ) {
83+ let bounds = Range :: from_end ( 0 ..suffix. len ( ) as u64 ) ;
84+ let subpattern = bounds. apply ( suffix) ;
85+ for pair in self . build_slice_branch ( bounds, place, top_pattern, subpattern) {
86+ match_pairs. push ( pair) ;
87+ }
11888 }
11989 }
12090
121- fn build_slice_branch < ' pat > (
122- & ' pat mut self ,
123- place : & ' pat PlaceBuilder < ' tcx > ,
91+ fn build_slice_branch < ' pat , ' b > (
92+ & ' b mut self ,
93+ bounds : Range ,
94+ place : & ' b PlaceBuilder < ' tcx > ,
12495 top_pattern : & ' pat Pat < ' tcx > ,
12596 pattern : & ' pat [ Box < Pat < ' tcx > > ] ,
126- ) -> impl Iterator < Item = MatchPairTree < ' pat , ' tcx > > + use < ' pat , ' tcx , ' a > {
97+ ) -> impl Iterator < Item = MatchPairTree < ' pat , ' tcx > > + use < ' a , ' tcx , ' pat , ' b > {
12798 let entries = self . find_const_groups ( pattern) ;
128- let solo = entries. len ( ) == 1 ;
129-
130- let maybe_project = move |base : & PlaceBuilder < ' tcx > , elem| {
131- if solo { base. clone_project ( elem) } else { base. clone ( ) }
132- } ;
13399
134100 entries. into_iter ( ) . map ( move |entry| {
135- let pattern_len = pattern. len ( ) as u64 ;
136101 let mut build_single = |idx| {
137102 let subpattern = & pattern[ idx as usize ] ;
138- let place = maybe_project ( place, ProjectionElem :: ConstantIndex {
139- offset : idx,
140- min_length : pattern_len ,
141- from_end : false ,
103+ let place = place. clone_project ( ProjectionElem :: ConstantIndex {
104+ offset : bounds . shift_idx ( idx) ,
105+ min_length : pattern . len ( ) as u64 ,
106+ from_end : bounds . from_end ,
142107 } ) ;
143108
144109 MatchPairTree :: for_pattern ( place, subpattern, self )
145110 } ;
146111
147112 match entry {
148- Either :: Right ( range) if range. len ( ) > 1 => {
113+ Either :: Right ( range) if range. end -range . start > 1 => {
149114 assert ! (
150115 ( range. start..range. end)
151116 . all( |idx| self . is_constant_pattern( & pattern[ idx as usize ] ) )
@@ -154,14 +119,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
154119 let subpattern = & pattern[ range. start as usize ..range. end as usize ] ;
155120 let elem_ty = subpattern[ 0 ] . ty ;
156121
157- let place = maybe_project ( place, PlaceElem :: Subslice {
158- from : range. start ,
159- to : pattern. len ( ) as u64 - range. end ,
160- from_end : true ,
161- } ) ;
162-
163122 let valtree = self . simplify_const_pattern_slice_into_valtree ( subpattern) ;
164- self . valtree_to_match_pair ( top_pattern, valtree, place, elem_ty, range, false )
123+ self . valtree_to_match_pair (
124+ top_pattern,
125+ valtree,
126+ place. clone ( ) ,
127+ elem_ty,
128+ bounds. shift_range ( range) ,
129+ true , // TODO: set false if only branch and only entry
130+ )
165131 }
166132 Either :: Right ( range) => {
167133 let tree = build_single ( range. start ) ;
@@ -173,15 +139,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
173139 } )
174140 }
175141
176- fn find_const_groups ( & self , pattern : & [ Box < Pat < ' tcx > > ] ) -> Vec < Either < u64 , Range > > {
142+ fn find_const_groups ( & self , pattern : & [ Box < Pat < ' tcx > > ] ) -> Vec < Either < u64 , ops :: Range < u64 > > > {
177143 let mut entries = Vec :: new ( ) ;
178144 let mut current_seq_start = None ;
179145
180- let mut apply = |state : & mut _ , idx| {
146+ let mut apply = |state : & mut _ , idx, b : bool | {
181147 if let Some ( start) = * state {
182148 * state = None ;
183- entries. push ( Either :: Right ( Range :: from_start ( start..idx) ) ) ;
184- } else {
149+ entries. push ( Either :: Right ( start..idx) ) ;
150+ } else if !b {
185151 entries. push ( Either :: Left ( idx) ) ;
186152 }
187153 } ;
@@ -192,18 +158,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
192158 current_seq_start = Some ( idx as u64 ) ;
193159 }
194160 } else {
195- apply ( & mut current_seq_start, idx as u64 ) ;
161+ apply ( & mut current_seq_start, idx as u64 , false ) ;
196162 }
197163 }
198164
199- apply ( & mut current_seq_start, pattern. len ( ) as u64 ) ;
165+ apply ( & mut current_seq_start, pattern. len ( ) as u64 , true ) ;
200166 entries
201167 }
202168
203- fn should_optimize_subslice ( & self , subslice : & [ Box < Pat < ' tcx > > ] ) -> bool {
204- subslice. len ( ) > 1 && subslice. iter ( ) . all ( |p| self . is_constant_pattern ( p) )
205- }
206-
207169 fn is_constant_pattern ( & self , pat : & Pat < ' tcx > ) -> bool {
208170 if let PatKind :: Constant { value } = pat. kind
209171 && let Const :: Ty ( _, const_) = value
@@ -244,16 +206,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
244206 place : PlaceBuilder < ' tcx > ,
245207 elem_ty : Ty < ' tcx > ,
246208 range : Range ,
247- do_own_slice : bool ,
209+ do_slice : bool ,
248210 ) -> MatchPairTree < ' pat , ' tcx > {
249211 let tcx = self . tcx ;
250212 let const_ty =
251213 Ty :: new_imm_ref ( tcx, tcx. lifetimes . re_erased , Ty :: new_array ( tcx, elem_ty, range. len ( ) ) ) ;
252214
253- let pat_ty = if do_own_slice { Ty :: new_slice ( tcx, elem_ty) } else { source_pattern. ty } ;
215+ let pat_ty = if do_slice { Ty :: new_slice ( tcx, elem_ty) } else { source_pattern. ty } ;
254216 let ty_const = ty:: Const :: new ( tcx, ty:: ConstKind :: Value ( const_ty, valtree) ) ;
255217 let value = Const :: Ty ( const_ty, ty_const) ;
256- let test_case = TestCase :: Constant { value, range : do_own_slice . then_some ( range) } ;
218+ let test_case = TestCase :: Constant { value, range : do_slice . then_some ( range) } ;
257219 let pattern = tcx. arena . alloc ( Pat {
258220 ty : pat_ty,
259221 span : source_pattern. span ,
0 commit comments