@@ -7,9 +7,10 @@ use crate::interpret::{
77 intern_const_alloc_recursive, ConstValue , ImmTy , Immediate , InternKind , MemPlaceMeta ,
88 MemoryKind , Place , Projectable , Scalar ,
99} ;
10+ use rustc_middle:: ty:: layout:: { LayoutOf , TyAndLayout } ;
1011use rustc_middle:: ty:: { self , ScalarInt , Ty , TyCtxt } ;
1112use rustc_span:: source_map:: DUMMY_SP ;
12- use rustc_target:: abi:: { Align , FieldIdx , VariantIdx , FIRST_VARIANT } ;
13+ use rustc_target:: abi:: VariantIdx ;
1314
1415#[ instrument( skip( ecx) , level = "debug" ) ]
1516fn branches < ' tcx > (
@@ -154,52 +155,37 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
154155 }
155156}
156157
157- #[ instrument( skip( ecx) , level = "debug" ) ]
158- fn create_mplace_from_layout < ' tcx > (
159- ecx : & mut CompileTimeEvalContext < ' tcx , ' tcx > ,
160- ty : Ty < ' tcx > ,
161- ) -> MPlaceTy < ' tcx > {
162- let tcx = ecx. tcx ;
163- let param_env = ecx. param_env ;
164- let layout = tcx. layout_of ( param_env. and ( ty) ) . unwrap ( ) ;
165- debug ! ( ?layout) ;
166-
167- ecx. allocate ( layout, MemoryKind :: Stack ) . unwrap ( )
168- }
169-
170- // Walks custom DSTs and gets the type of the unsized field and the number of elements
171- // in the unsized field.
172- fn get_info_on_unsized_field < ' tcx > (
173- ty : Ty < ' tcx > ,
158+ /// Valtrees don't store the `MemPlaceMeta` that all dynamically sized values have in the interpreter.
159+ /// This function reconstructs it.
160+ fn reconstruct_place_meta < ' tcx > (
161+ layout : TyAndLayout < ' tcx > ,
174162 valtree : ty:: ValTree < ' tcx > ,
175163 tcx : TyCtxt < ' tcx > ,
176- ) -> ( Ty < ' tcx > , usize ) {
164+ ) -> MemPlaceMeta {
165+ if layout. is_sized ( ) {
166+ return MemPlaceMeta :: None ;
167+ }
168+
177169 let mut last_valtree = valtree;
170+ // Traverse the type, and update `last_valtree` as we go.
178171 let tail = tcx. struct_tail_with_normalize (
179- ty,
172+ layout . ty ,
180173 |ty| ty,
181174 || {
182175 let branches = last_valtree. unwrap_branch ( ) ;
183- last_valtree = branches[ branches . len ( ) - 1 ] ;
176+ last_valtree = * branches. last ( ) . unwrap ( ) ;
184177 debug ! ( ?branches, ?last_valtree) ;
185178 } ,
186179 ) ;
187- let unsized_inner_ty = match tail. kind ( ) {
188- ty:: Slice ( t) => * t,
189- ty:: Str => tail,
190- _ => bug ! ( "expected Slice or Str" ) ,
191- } ;
192-
193- // Have to adjust type for ty::Str
194- let unsized_inner_ty = match unsized_inner_ty. kind ( ) {
195- ty:: Str => tcx. types . u8 ,
196- _ => unsized_inner_ty,
180+ // Sanity-check that we got a tail we support.
181+ match tail. kind ( ) {
182+ ty:: Slice ( ..) | ty:: Str => { }
183+ _ => bug ! ( "unsized tail of a valtree must be Slice or Str" ) ,
197184 } ;
198185
199- // Get the number of elements in the unsized field
186+ // Get the number of elements in the unsized field.
200187 let num_elems = last_valtree. unwrap_branch ( ) . len ( ) ;
201-
202- ( unsized_inner_ty, num_elems)
188+ MemPlaceMeta :: Meta ( Scalar :: from_target_usize ( num_elems as u64 , & tcx) )
203189}
204190
205191#[ instrument( skip( ecx) , level = "debug" , ret) ]
@@ -208,41 +194,9 @@ fn create_pointee_place<'tcx>(
208194 ty : Ty < ' tcx > ,
209195 valtree : ty:: ValTree < ' tcx > ,
210196) -> MPlaceTy < ' tcx > {
211- let tcx = ecx. tcx . tcx ;
212-
213- if !ty. is_sized ( * ecx. tcx , ty:: ParamEnv :: empty ( ) ) {
214- // We need to create `Allocation`s for custom DSTs
215-
216- let ( unsized_inner_ty, num_elems) = get_info_on_unsized_field ( ty, valtree, tcx) ;
217- let unsized_inner_ty = match unsized_inner_ty. kind ( ) {
218- ty:: Str => tcx. types . u8 ,
219- _ => unsized_inner_ty,
220- } ;
221- let unsized_inner_ty_size =
222- tcx. layout_of ( ty:: ParamEnv :: empty ( ) . and ( unsized_inner_ty) ) . unwrap ( ) . layout . size ( ) ;
223- debug ! ( ?unsized_inner_ty, ?unsized_inner_ty_size, ?num_elems) ;
224-
225- // for custom DSTs only the last field/element is unsized, but we need to also allocate
226- // space for the other fields/elements
227- let layout = tcx. layout_of ( ty:: ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
228- let size_of_sized_part = layout. layout . size ( ) ;
229-
230- // Get the size of the memory behind the DST
231- let dst_size = unsized_inner_ty_size. checked_mul ( num_elems as u64 , & tcx) . unwrap ( ) ;
232-
233- let size = size_of_sized_part. checked_add ( dst_size, & tcx) . unwrap ( ) ;
234- let align = Align :: from_bytes ( size. bytes ( ) . next_power_of_two ( ) ) . unwrap ( ) ;
235- let ptr = ecx. allocate_ptr ( size, align, MemoryKind :: Stack ) . unwrap ( ) ;
236- debug ! ( ?ptr) ;
237-
238- MPlaceTy :: from_aligned_ptr_with_meta (
239- ptr. into ( ) ,
240- layout,
241- MemPlaceMeta :: Meta ( Scalar :: from_target_usize ( num_elems as u64 , & tcx) ) ,
242- )
243- } else {
244- create_mplace_from_layout ( ecx, ty)
245- }
197+ let layout = ecx. layout_of ( ty) . unwrap ( ) ;
198+ let meta = reconstruct_place_meta ( layout, valtree, ecx. tcx . tcx ) ;
199+ ecx. allocate_dyn ( layout, MemoryKind :: Stack , meta) . unwrap ( )
246200}
247201
248202/// Converts a `ValTree` to a `ConstValue`, which is needed after mir
@@ -282,10 +236,13 @@ pub fn valtree_to_const_value<'tcx>(
282236 ty:: Ref ( _, _, _) | ty:: Tuple ( _) | ty:: Array ( _, _) | ty:: Adt ( ..) => {
283237 let place = match ty. kind ( ) {
284238 ty:: Ref ( _, inner_ty, _) => {
285- // Need to create a place for the pointee to fill for Refs
239+ // Need to create a place for the pointee (the reference itself will be an immediate)
286240 create_pointee_place ( & mut ecx, * inner_ty, valtree)
287241 }
288- _ => create_mplace_from_layout ( & mut ecx, ty) ,
242+ _ => {
243+ // Need to create a place for this valtree.
244+ create_pointee_place ( & mut ecx, ty, valtree)
245+ }
289246 } ;
290247 debug ! ( ?place) ;
291248
@@ -399,45 +356,8 @@ fn valtree_into_mplace<'tcx>(
399356 debug ! ( ?i, ?inner_valtree) ;
400357
401358 let place_inner = match ty. kind ( ) {
402- ty:: Str | ty:: Slice ( _) => ecx. project_index ( place, i as u64 ) . unwrap ( ) ,
403- _ if !ty. is_sized ( * ecx. tcx , ty:: ParamEnv :: empty ( ) )
404- && i == branches. len ( ) - 1 =>
405- {
406- // Note: For custom DSTs we need to manually process the last unsized field.
407- // We created a `Pointer` for the `Allocation` of the complete sized version of
408- // the Adt in `create_pointee_place` and now we fill that `Allocation` with the
409- // values in the ValTree. For the unsized field we have to additionally add the meta
410- // data.
411-
412- let ( unsized_inner_ty, num_elems) =
413- get_info_on_unsized_field ( ty, valtree, tcx) ;
414- debug ! ( ?unsized_inner_ty) ;
415-
416- let inner_ty = match ty. kind ( ) {
417- ty:: Adt ( def, args) => {
418- let i = FieldIdx :: from_usize ( i) ;
419- def. variant ( FIRST_VARIANT ) . fields [ i] . ty ( tcx, args)
420- }
421- ty:: Tuple ( inner_tys) => inner_tys[ i] ,
422- _ => bug ! ( "unexpected unsized type {:?}" , ty) ,
423- } ;
424-
425- let inner_layout =
426- tcx. layout_of ( ty:: ParamEnv :: empty ( ) . and ( inner_ty) ) . unwrap ( ) ;
427- debug ! ( ?inner_layout) ;
428-
429- let offset = place_adjusted. layout . fields . offset ( i) ;
430- place
431- . offset_with_meta (
432- offset,
433- MemPlaceMeta :: Meta ( Scalar :: from_target_usize (
434- num_elems as u64 ,
435- & tcx,
436- ) ) ,
437- inner_layout,
438- & tcx,
439- )
440- . unwrap ( )
359+ ty:: Str | ty:: Slice ( _) | ty:: Array ( ..) => {
360+ ecx. project_index ( place, i as u64 ) . unwrap ( )
441361 }
442362 _ => ecx. project_field ( & place_adjusted, i) . unwrap ( ) ,
443363 } ;
0 commit comments