@@ -20,8 +20,8 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym};
20
20
use rustc_trait_selection:: infer:: InferCtxtExt ;
21
21
use tracing:: { debug, instrument} ;
22
22
23
- use crate :: builder:: Builder ;
24
23
use crate :: builder:: matches:: { Candidate , MatchPairTree , Test , TestBranch , TestCase , TestKind } ;
24
+ use crate :: builder:: { Builder , PlaceBuilder } ;
25
25
26
26
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
27
27
/// Identifies what test is needed to decide if `match_pair` is applicable.
@@ -36,7 +36,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
36
36
37
37
TestCase :: Constant { .. } if match_pair. pattern . ty . is_bool ( ) => TestKind :: If ,
38
38
TestCase :: Constant { .. } if is_switch_ty ( match_pair. pattern . ty ) => TestKind :: SwitchInt ,
39
- TestCase :: Constant { value } => TestKind :: Eq { value, ty : match_pair. pattern . ty } ,
39
+ TestCase :: Constant { value, ref range } => {
40
+ TestKind :: Eq { value, ty : match_pair. pattern . ty , range : range. clone ( ) }
41
+ }
40
42
41
43
TestCase :: Range ( range) => {
42
44
assert_eq ! ( range. ty, match_pair. pattern. ty) ;
@@ -142,7 +144,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
142
144
self . cfg . terminate ( block, self . source_info ( match_start_span) , terminator) ;
143
145
}
144
146
145
- TestKind :: Eq { value, ty } => {
147
+ TestKind :: Eq { value, ref range , ty } => {
146
148
let tcx = self . tcx ;
147
149
let success_block = target_block ( TestBranch :: Success ) ;
148
150
let fail_block = target_block ( TestBranch :: Failure ) ;
@@ -179,15 +181,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
179
181
ref_str_ty,
180
182
) ;
181
183
} else if !ty. is_scalar ( ) {
184
+ let new_place;
185
+ let cmp_block;
186
+ if let Some ( range) = range {
187
+ assert_eq ! ( range. start, 0 ) ;
188
+ let elem_ty = ty. sequence_element_type ( tcx) ;
189
+ cmp_block = self . cfg . start_new_block ( ) ;
190
+ let subslice_ptr = self . subslice (
191
+ block,
192
+ cmp_block,
193
+ place,
194
+ place_ty. ty ,
195
+ test. span ,
196
+ elem_ty,
197
+ range. end ,
198
+ ) ;
199
+
200
+ new_place = PlaceBuilder :: from ( subslice_ptr) . deref ( ) . to_place ( self ) ;
201
+ } else {
202
+ cmp_block = block;
203
+ new_place = place;
204
+ }
205
+
182
206
// Use `PartialEq::eq` instead of `BinOp::Eq`
183
207
// (the binop can only handle primitives)
184
208
self . non_scalar_compare (
185
- block ,
209
+ cmp_block ,
186
210
success_block,
187
211
fail_block,
188
212
source_info,
189
213
value,
190
- place ,
214
+ new_place ,
191
215
ty,
192
216
) ;
193
217
} else {
@@ -290,6 +314,66 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
290
314
}
291
315
}
292
316
317
+ fn subslice (
318
+ & mut self ,
319
+ block : BasicBlock ,
320
+ target_block : BasicBlock ,
321
+ input : Place < ' tcx > ,
322
+ input_ty : Ty < ' tcx > ,
323
+ span : Span ,
324
+ elem_ty : Ty < ' tcx > ,
325
+ new_len : u64 ,
326
+ ) -> Place < ' tcx > {
327
+ let tcx = self . tcx ;
328
+ let source_info = self . source_info ( span) ;
329
+
330
+ let temp_source_ptr = self . temp ( Ty :: new_ptr ( tcx, input_ty, Mutability :: Not ) , span) ;
331
+ self . cfg . push_assign (
332
+ block,
333
+ source_info,
334
+ temp_source_ptr,
335
+ Rvalue :: RawPtr ( Mutability :: Not , input) ,
336
+ ) ;
337
+
338
+ let elem_ptr_ty = Ty :: new_ptr ( tcx, elem_ty, Mutability :: Not ) ;
339
+ let slice_ptr_ty = Ty :: new_ptr ( tcx, Ty :: new_slice ( tcx, elem_ty) , Mutability :: Not ) ;
340
+
341
+ let temp_elem_ptr = self . temp ( elem_ptr_ty, span) ;
342
+ self . cfg . push_assign (
343
+ block,
344
+ source_info,
345
+ temp_elem_ptr,
346
+ Rvalue :: Cast ( CastKind :: PtrToPtr , Operand :: Copy ( temp_source_ptr) , elem_ptr_ty) ,
347
+ ) ;
348
+
349
+ let temp_len = self . push_usize ( block, source_info, new_len) ;
350
+
351
+ let aggregate_raw_ptr = Operand :: function_handle (
352
+ tcx,
353
+ tcx. require_lang_item ( LangItem :: AggregateRawPtr , Some ( span) ) ,
354
+ [ slice_ptr_ty. into ( ) , elem_ptr_ty. into ( ) , tcx. types . usize . into ( ) ] ,
355
+ span,
356
+ ) ;
357
+
358
+ let subslice_ptr = self . temp ( slice_ptr_ty, span) ;
359
+
360
+ self . cfg . terminate ( block, source_info, TerminatorKind :: Call {
361
+ func : aggregate_raw_ptr,
362
+ args : [ Spanned { node : Operand :: Move ( temp_elem_ptr) , span } , Spanned {
363
+ node : Operand :: Move ( temp_len) ,
364
+ span,
365
+ } ]
366
+ . into ( ) ,
367
+ destination : subslice_ptr,
368
+ target : Some ( target_block) ,
369
+ unwind : UnwindAction :: Continue ,
370
+ call_source : CallSource :: Misc ,
371
+ fn_span : source_info. span ,
372
+ } ) ;
373
+
374
+ subslice_ptr
375
+ }
376
+
293
377
/// Perform `let temp = <ty as Deref>::deref(&place)`.
294
378
/// or `let temp = <ty as DerefMut>::deref_mut(&mut place)`.
295
379
pub ( super ) fn call_deref (
@@ -582,7 +666,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
582
666
//
583
667
// FIXME(#29623) we could use PatKind::Range to rule
584
668
// things out here, in some cases.
585
- ( TestKind :: SwitchInt , & TestCase :: Constant { value } )
669
+ ( TestKind :: SwitchInt , & TestCase :: Constant { value, .. } )
586
670
if is_switch_ty ( match_pair. pattern . ty ) =>
587
671
{
588
672
// An important invariant of candidate sorting is that a candidate
@@ -636,7 +720,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
636
720
} )
637
721
}
638
722
639
- ( TestKind :: If , TestCase :: Constant { value } ) => {
723
+ ( TestKind :: If , TestCase :: Constant { value, .. } ) => {
640
724
fully_matched = true ;
641
725
let value = value. try_eval_bool ( self . tcx , self . typing_env ( ) ) . unwrap_or_else ( || {
642
726
span_bug ! ( test. span, "expected boolean value but got {value:?}" )
@@ -725,7 +809,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
725
809
}
726
810
}
727
811
}
728
- ( TestKind :: Range ( range) , & TestCase :: Constant { value } ) => {
812
+ ( TestKind :: Range ( range) , & TestCase :: Constant { value, .. } ) => {
729
813
fully_matched = false ;
730
814
if !range. contains ( value, self . tcx , self . typing_env ( ) ) ? {
731
815
// `value` is not contained in the testing range,
@@ -736,7 +820,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
736
820
}
737
821
}
738
822
739
- ( TestKind :: Eq { value : test_val, .. } , TestCase :: Constant { value : case_val } ) => {
823
+ ( TestKind :: Eq { value : test_val, .. } , TestCase :: Constant { value : case_val, .. } ) => {
740
824
if test_val == case_val {
741
825
fully_matched = true ;
742
826
Some ( TestBranch :: Success )
0 commit comments