@@ -194,55 +194,48 @@ fn create_pointee_place<'tcx>(
194194) -> MPlaceTy < ' tcx > {
195195 let tcx = ecx. tcx . tcx ;
196196
197- match ty. kind ( ) {
198- ty:: Slice ( _) | ty:: Str => {
199- let slice_ty = match ty. kind ( ) {
200- ty:: Slice ( slice_ty) => * slice_ty,
201- ty:: Str => tcx. mk_ty ( ty:: Uint ( ty:: UintTy :: U8 ) ) ,
202- _ => bug ! ( "expected ty::Slice | ty::Str" ) ,
203- } ;
204-
205- // Create a place for the underlying array
206- let len = valtree. unwrap_branch ( ) . len ( ) as u64 ;
207- let arr_ty = tcx. mk_array ( slice_ty, len as u64 ) ;
208- let place = create_mplace_from_layout ( ecx, arr_ty) ;
209- debug ! ( ?place) ;
197+ if !ty. is_sized ( ecx. tcx , ty:: ParamEnv :: empty ( ) ) {
198+ // We need to create `Allocation`s for custom DSTs
199+
200+ let ( unsized_inner_ty, num_elems) = get_info_on_unsized_field ( ty, valtree, tcx) ;
201+ let unsized_inner_ty = match unsized_inner_ty. kind ( ) {
202+ ty:: Str => tcx. mk_ty ( ty:: Uint ( ty:: UintTy :: U8 ) ) ,
203+ _ => unsized_inner_ty,
204+ } ;
205+ let unsized_inner_ty_size =
206+ tcx. layout_of ( ty:: ParamEnv :: empty ( ) . and ( unsized_inner_ty) ) . unwrap ( ) . layout . size ( ) ;
207+ debug ! ( ?unsized_inner_ty, ?unsized_inner_ty_size, ?num_elems) ;
208+
209+ // for custom DSTs only the last field/element is unsized, but we need to also allocate
210+ // space for the other fields/elements
211+ let layout = tcx. layout_of ( ty:: ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
212+ let size_of_sized_part = layout. layout . size ( ) ;
213+
214+ // Get the size of the memory behind the DST
215+ let dst_size = unsized_inner_ty_size. checked_mul ( num_elems as u64 , & tcx) . unwrap ( ) ;
216+
217+ let ptr = ecx
218+ . allocate_ptr (
219+ size_of_sized_part. checked_add ( dst_size, & tcx) . unwrap ( ) ,
220+ Align :: from_bytes ( 1 ) . unwrap ( ) ,
221+ MemoryKind :: Stack ,
222+ )
223+ . unwrap ( ) ;
224+ debug ! ( ?ptr) ;
210225
211- place
212- }
213- ty:: Adt ( _, _) if !ty. is_sized ( ecx. tcx , ty:: ParamEnv :: empty ( ) ) => {
214- // We need to create `Allocation`s for custom DSTs
215-
216- let layout = tcx. layout_of ( ty:: ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
217- let sized_fields_size = layout. layout . size ( ) ;
218- let ( unsized_inner_ty, num_elems) = get_info_on_unsized_field ( ty, valtree, tcx) ;
219- let unsized_inner_ty_size =
220- tcx. layout_of ( ty:: ParamEnv :: empty ( ) . and ( unsized_inner_ty) ) . unwrap ( ) . layout . size ( ) ;
221- debug ! ( ?unsized_inner_ty, ?unsized_inner_ty_size, ?num_elems) ;
222-
223- // Get the size of the array behind the DST
224- let dst_size = unsized_inner_ty_size. checked_mul ( num_elems as u64 , & tcx) . unwrap ( ) ;
225-
226- let ptr = ecx
227- . allocate_ptr (
228- sized_fields_size. checked_add ( dst_size, & tcx) . unwrap ( ) ,
229- Align :: from_bytes ( 1 ) . unwrap ( ) ,
230- MemoryKind :: Stack ,
231- )
232- . unwrap ( ) ;
233- debug ! ( ?ptr) ;
234-
235- let place = MPlaceTy :: from_aligned_ptr ( ptr. into ( ) , layout) ;
236- debug ! ( ?place) ;
226+ let mut place = MPlaceTy :: from_aligned_ptr ( ptr. into ( ) , layout) ;
227+ place. meta = MemPlaceMeta :: Meta ( Scalar :: from_u64 ( num_elems as u64 ) ) ;
228+ debug ! ( ?place) ;
237229
238- place
239- }
240- _ => create_mplace_from_layout ( ecx, ty) ,
230+ place
231+ } else {
232+ create_mplace_from_layout ( ecx, ty)
241233 }
242234}
243235
244236/// Converts a `ValTree` to a `ConstValue`, which is needed after mir
245237/// construction has finished.
238+ // FIXME Merge `valtree_to_const_value` and `fill_place_recursively` into one function
246239#[ instrument( skip( tcx) , level = "debug" ) ]
247240pub fn valtree_to_const_value < ' tcx > (
248241 tcx : TyCtxt < ' tcx > ,
@@ -374,12 +367,9 @@ fn fill_place_recursively<'tcx>(
374367
375368 ecx. write_immediate ( imm, & ( * place) . into ( ) ) . unwrap ( ) ;
376369 }
377- ty:: Adt ( _, _) | ty:: Tuple ( _) | ty:: Array ( _, _) | ty:: Str => {
370+ ty:: Adt ( _, _) | ty:: Tuple ( _) | ty:: Array ( _, _) | ty:: Str | ty :: Slice ( _ ) => {
378371 let branches = valtree. unwrap_branch ( ) ;
379372
380- // Need to collect the length of the unsized field for meta info
381- let mut unsized_meta_info = None ;
382-
383373 // Need to downcast place for enums
384374 let ( place_adjusted, branches, variant_idx) = match ty. kind ( ) {
385375 ty:: Adt ( def, _) if def. is_enum ( ) => {
@@ -399,48 +389,52 @@ fn fill_place_recursively<'tcx>(
399389 } ;
400390 debug ! ( ?place_adjusted, ?branches) ;
401391
402- // Create the places for the fields and fill them recursively
392+ // Create the places (by indexing into `place`) for the fields and fill
393+ // them recursively
403394 for ( i, inner_valtree) in branches. iter ( ) . enumerate ( ) {
404395 debug ! ( ?i, ?inner_valtree) ;
405396
406- if !ty. is_sized ( ecx. tcx , ty:: ParamEnv :: empty ( ) ) && i == branches. len ( ) - 1 {
407- // Note: For custom DSTs we need to manually process the last unsized field.
408- // We created a `Pointer` for the `Allocation` of the complete sized version of
409- // the Adt in `create_pointee_place` and now we fill that `Allocation` with the
410- // values in the ValTree. For the unsized field we have to additionally add the meta
411- // data.
412-
413- let offset = place. layout . fields . offset ( i) ;
414- let ( unsized_inner_ty, num_elems) = get_info_on_unsized_field ( ty, valtree, tcx) ;
415- unsized_meta_info = Some ( num_elems) ;
416-
417- // We create an array type to allow the recursive call to fill the place
418- // corresponding to the array
419- let arr_ty = tcx. mk_array ( unsized_inner_ty, num_elems as u64 ) ;
420- debug ! ( ?arr_ty) ;
421- let arr_layout = tcx. layout_of ( ty:: ParamEnv :: empty ( ) . and ( arr_ty) ) . unwrap ( ) ;
422- let mut place_arr =
423- place. offset ( offset, MemPlaceMeta :: None , arr_layout, & tcx) . unwrap ( ) ;
424- debug ! ( ?place_arr) ;
425-
426- fill_place_recursively ( ecx, & mut place_arr, * inner_valtree) ;
427- dump_place ( & ecx, place_arr. into ( ) ) ;
428-
429- // Add the meta information for the unsized type
430- place_arr. meta = MemPlaceMeta :: Meta ( Scalar :: from_u64 ( num_elems as u64 ) ) ;
431-
432- break ;
433- }
434-
435- let mut place_inner = match * ty. kind ( ) {
436- ty:: Adt ( _, _) | ty:: Tuple ( _) => ecx. mplace_field ( & place_adjusted, i) . unwrap ( ) ,
437- ty:: Array ( _, _) | ty:: Str => {
438- ecx. mplace_index ( & place_adjusted, i as u64 ) . unwrap ( )
397+ let mut place_inner = match ty. kind ( ) {
398+ ty:: Str | ty:: Slice ( _) => ecx. mplace_index ( & place, i as u64 ) . unwrap ( ) ,
399+ _ if !ty. is_sized ( ecx. tcx , ty:: ParamEnv :: empty ( ) )
400+ && i == branches. len ( ) - 1 =>
401+ {
402+ // Note: For custom DSTs we need to manually process the last unsized field.
403+ // We created a `Pointer` for the `Allocation` of the complete sized version of
404+ // the Adt in `create_pointee_place` and now we fill that `Allocation` with the
405+ // values in the ValTree. For the unsized field we have to additionally add the meta
406+ // data.
407+
408+ let ( unsized_inner_ty, num_elems) =
409+ get_info_on_unsized_field ( ty, valtree, tcx) ;
410+ debug ! ( ?unsized_inner_ty) ;
411+
412+ let inner_ty = match ty. kind ( ) {
413+ ty:: Adt ( def, substs) => {
414+ def. variant ( VariantIdx :: from_u32 ( 0 ) ) . fields [ i] . ty ( tcx, substs)
415+ }
416+ ty:: Tuple ( inner_tys) => inner_tys[ i] ,
417+ _ => bug ! ( "unexpected unsized type {:?}" , ty) ,
418+ } ;
419+
420+ let inner_layout =
421+ tcx. layout_of ( ty:: ParamEnv :: empty ( ) . and ( inner_ty) ) . unwrap ( ) ;
422+ debug ! ( ?inner_layout) ;
423+
424+ let offset = place_adjusted. layout . fields . offset ( i) ;
425+ place
426+ . offset (
427+ offset,
428+ MemPlaceMeta :: Meta ( Scalar :: from_u64 ( num_elems as u64 ) ) ,
429+ inner_layout,
430+ & tcx,
431+ )
432+ . unwrap ( )
439433 }
440- _ => bug ! ( ) ,
434+ _ => ecx . mplace_field ( & place_adjusted , i ) . unwrap ( ) ,
441435 } ;
442- debug ! ( ?place_inner) ;
443436
437+ debug ! ( ?place_inner) ;
444438 fill_place_recursively ( ecx, & mut place_inner, * inner_valtree) ;
445439 dump_place ( & ecx, place_inner. into ( ) ) ;
446440 }
@@ -453,12 +447,7 @@ fn fill_place_recursively<'tcx>(
453447 ecx. write_discriminant ( variant_idx, & ( * place) . into ( ) ) . unwrap ( ) ;
454448 }
455449
456- // add meta information for unsized type
457- if !ty. is_sized ( ecx. tcx , ty:: ParamEnv :: empty ( ) ) {
458- place. meta =
459- MemPlaceMeta :: Meta ( Scalar :: from_u64 ( unsized_meta_info. unwrap ( ) as u64 ) ) ;
460- }
461-
450+ debug ! ( "dump of place after writing discriminant:" ) ;
462451 dump_place ( ecx, ( * place) . into ( ) ) ;
463452 }
464453 _ => bug ! ( "shouldn't have created a ValTree for {:?}" , ty) ,
0 commit comments