@@ -22,7 +22,7 @@ use tracing::{debug, instrument};
2222
2323use crate :: builder:: matches:: util:: Range ;
2424use crate :: builder:: matches:: { Candidate , MatchPairTree , Test , TestBranch , TestCase , TestKind } ;
25- use crate :: builder:: { Builder , PlaceBuilder } ;
25+ use crate :: builder:: { BlockAnd , BlockAndExtension , Builder , PlaceBuilder } ;
2626
2727impl < ' a , ' tcx > Builder < ' a , ' tcx > {
2828 /// Identifies what test is needed to decide if `match_pair` is applicable.
@@ -182,21 +182,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
182182 ref_str_ty,
183183 ) ;
184184 } else if !ty. is_scalar ( ) {
185- let ( place, block) = if let Some ( range) = range {
186- let target_block = self . cfg . start_new_block ( ) ;
187- let subslice = self . subslice (
188- block,
189- target_block,
190- place,
191- place_ty. ty ,
192- test. span ,
193- ty. sequence_element_type ( tcx) ,
194- range,
185+ let ( block, place) = if let Some ( range) = range {
186+ let mut block = block;
187+ let subslice = unpack ! (
188+ block = self . subslice(
189+ block,
190+ place,
191+ place_ty. ty,
192+ test. span,
193+ ty. sequence_element_type( tcx) ,
194+ range,
195+ )
195196 ) ;
196197
197- ( subslice , target_block )
198+ ( block , subslice )
198199 } else {
199- ( place , block )
200+ ( block , place )
200201 } ;
201202
202203 // Use `PartialEq::eq` instead of `BinOp::Eq`
@@ -310,20 +311,82 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
310311 }
311312 }
312313
313- fn subslice (
314+ fn offset (
314315 & mut self ,
315316 block : BasicBlock ,
316- target_block : BasicBlock ,
317+ ptr : Place < ' tcx > ,
318+ offset : Place < ' tcx > ,
319+ span : Span ,
320+ ) -> BlockAnd < Place < ' tcx > > {
321+ let ptr_ty = ptr. ty ( & self . local_decls , self . tcx ) . ty ;
322+ let offset_ty = offset. ty ( & self . local_decls , self . tcx ) . ty ;
323+
324+ let tcx = self . tcx ;
325+ let func = Operand :: function_handle (
326+ tcx,
327+ tcx. require_lang_item ( LangItem :: Offset , Some ( span) ) ,
328+ [ ptr_ty. into ( ) , offset_ty. into ( ) ] ,
329+ span,
330+ ) ;
331+
332+ let out = self . temp ( ptr_ty, span) ;
333+ let next_block = self . cfg . start_new_block ( ) ;
334+
335+ self . cfg . terminate ( block, self . source_info ( span) , TerminatorKind :: Call {
336+ func,
337+ args : [ Spanned { node : Operand :: Copy ( ptr) , span } , Spanned {
338+ node : Operand :: Copy ( offset) ,
339+ span,
340+ } ]
341+ . into ( ) ,
342+ destination : out,
343+ target : Some ( next_block) ,
344+ unwind : UnwindAction :: Continue ,
345+ call_source : CallSource :: Misc ,
346+ fn_span : span,
347+ } ) ;
348+
349+ next_block. and ( out)
350+ }
351+
352+ fn subslice (
353+ & mut self ,
354+ mut block : BasicBlock ,
317355 input : Place < ' tcx > ,
318356 input_ty : Ty < ' tcx > ,
319357 span : Span ,
320358 elem_ty : Ty < ' tcx > ,
321359 range : Range ,
322- ) -> Place < ' tcx > {
360+ ) -> BlockAnd < Place < ' tcx > > {
323361 let tcx = self . tcx ;
324362 let source_info = self . source_info ( span) ;
325363
326- // TODO: handle range.from_end == true
364+ let ( ptr_offset, slice_len) = {
365+ if !range. from_end {
366+ let start = self . push_usize ( block, source_info, range. start ) ;
367+ let len = self . push_usize ( block, source_info, range. len ( ) ) ;
368+ ( start, len)
369+ } else {
370+ let source_len = self . temp ( tcx. types . usize , span) ;
371+ self . cfg . push_assign ( block, source_info, source_len, Rvalue :: Len ( input) ) ;
372+
373+ let start = self . temp ( tcx. types . usize , span) ;
374+ let from_end = self . push_usize ( block, source_info, range. start ) ;
375+
376+ self . cfg . push_assign (
377+ block,
378+ source_info,
379+ start,
380+ Rvalue :: BinaryOp (
381+ BinOp :: Sub ,
382+ Box :: new ( ( Operand :: Copy ( source_len) , Operand :: Copy ( from_end) ) ) ,
383+ ) ,
384+ ) ;
385+ let len = self . push_usize ( block, source_info, range. len ( ) ) ;
386+
387+ ( start, len)
388+ }
389+ } ;
327390
328391 let temp_source_ptr = self . temp ( Ty :: new_ptr ( tcx, input_ty, Mutability :: Not ) , span) ;
329392 self . cfg . push_assign (
@@ -336,31 +399,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
336399 let elem_ptr_ty = Ty :: new_ptr ( tcx, elem_ty, Mutability :: Not ) ;
337400 let slice_ptr_ty = Ty :: new_ptr ( tcx, Ty :: new_slice ( tcx, elem_ty) , Mutability :: Not ) ;
338401
339- let mut temp_elem_ptr = self . temp ( elem_ptr_ty, span) ;
402+ let temp_elem_ptr = self . temp ( elem_ptr_ty, span) ;
340403 self . cfg . push_assign (
341404 block,
342405 source_info,
343406 temp_elem_ptr,
344407 Rvalue :: Cast ( CastKind :: PtrToPtr , Operand :: Copy ( temp_source_ptr) , elem_ptr_ty) ,
345408 ) ;
346409
347- if range. start != 0 {
348- let offset = self . temp ( elem_ptr_ty, span) ;
349- let offset_by = self . push_usize ( block, source_info, range. start ) ;
350- self . cfg . push_assign (
351- block,
352- source_info,
353- offset,
354- Rvalue :: BinaryOp (
355- BinOp :: Offset ,
356- Box :: new ( ( Operand :: Copy ( temp_elem_ptr) , Operand :: Move ( offset_by) ) ) ,
357- ) ,
358- ) ;
359-
360- temp_elem_ptr = offset;
361- }
362-
363- let temp_len = self . push_usize ( block, source_info, range. len ( ) ) ;
410+ let updated_ptr = unpack ! ( block = self . offset( block, temp_elem_ptr, ptr_offset, span) ) ;
364411
365412 let aggregate_raw_ptr = Operand :: function_handle (
366413 tcx,
@@ -371,21 +418,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
371418
372419 let subslice_ptr = self . temp ( slice_ptr_ty, span) ;
373420
421+ let next_block = self . cfg . start_new_block ( ) ;
422+
374423 self . cfg . terminate ( block, source_info, TerminatorKind :: Call {
375424 func : aggregate_raw_ptr,
376- args : [ Spanned { node : Operand :: Move ( temp_elem_ptr ) , span } , Spanned {
377- node : Operand :: Move ( temp_len ) ,
425+ args : [ Spanned { node : Operand :: Move ( updated_ptr ) , span } , Spanned {
426+ node : Operand :: Move ( slice_len ) ,
378427 span,
379428 } ]
380429 . into ( ) ,
381430 destination : subslice_ptr,
382- target : Some ( target_block ) ,
431+ target : Some ( next_block ) ,
383432 unwind : UnwindAction :: Continue ,
384433 call_source : CallSource :: Misc ,
385434 fn_span : source_info. span ,
386435 } ) ;
387436
388- PlaceBuilder :: from ( subslice_ptr) . deref ( ) . to_place ( self )
437+ let subslice = PlaceBuilder :: from ( subslice_ptr) . deref ( ) . to_place ( self ) ;
438+ next_block. and ( subslice)
389439 }
390440
391441 /// Perform `let temp = <ty as Deref>::deref(&place)`.
0 commit comments