@@ -7,7 +7,7 @@ use crate::interpret::{
7
7
intern_const_alloc_recursive, ConstValue , ImmTy , Immediate , InternKind , MemPlaceMeta ,
8
8
MemoryKind , PlaceTy , Projectable , Scalar ,
9
9
} ;
10
- use rustc_middle:: ty:: layout:: { LayoutOf , TyAndLayout } ;
10
+ use rustc_middle:: ty:: layout:: { LayoutCx , LayoutOf , TyAndLayout } ;
11
11
use rustc_middle:: ty:: { self , ScalarInt , Ty , TyCtxt } ;
12
12
use rustc_span:: source_map:: DUMMY_SP ;
13
13
use rustc_target:: abi:: VariantIdx ;
@@ -189,12 +189,11 @@ fn reconstruct_place_meta<'tcx>(
189
189
}
190
190
191
191
#[ instrument( skip( ecx) , level = "debug" , ret) ]
192
- fn create_pointee_place < ' tcx > (
192
+ fn create_valtree_place < ' tcx > (
193
193
ecx : & mut CompileTimeEvalContext < ' tcx , ' tcx > ,
194
- ty : Ty < ' tcx > ,
194
+ layout : TyAndLayout < ' tcx > ,
195
195
valtree : ty:: ValTree < ' tcx > ,
196
196
) -> MPlaceTy < ' tcx > {
197
- let layout = ecx. layout_of ( ty) . unwrap ( ) ;
198
197
let meta = reconstruct_place_meta ( layout, valtree, ecx. tcx . tcx ) ;
199
198
ecx. allocate_dyn ( layout, MemoryKind :: Stack , meta) . unwrap ( )
200
199
}
@@ -216,11 +215,6 @@ pub fn valtree_to_const_value<'tcx>(
216
215
// FIXME Does this need an example?
217
216
218
217
let ( param_env, ty) = param_env_ty. into_parts ( ) ;
219
- let mut ecx: crate :: interpret:: InterpCx <
220
- ' _ ,
221
- ' _ ,
222
- crate :: const_eval:: CompileTimeInterpreter < ' _ , ' _ > ,
223
- > = mk_eval_cx ( tcx, DUMMY_SP , param_env, CanAccessStatics :: No ) ;
224
218
225
219
match ty. kind ( ) {
226
220
ty:: FnDef ( ..) => {
@@ -233,33 +227,44 @@ pub fn valtree_to_const_value<'tcx>(
233
227
"ValTrees for Bool, Int, Uint, Float or Char should have the form ValTree::Leaf"
234
228
) ,
235
229
} ,
236
- ty:: Ref ( _, _, _) | ty:: Tuple ( _) | ty:: Array ( _, _) | ty:: Adt ( ..) => {
237
- let place = match ty. kind ( ) {
238
- ty:: Ref ( _, inner_ty, _) => {
239
- // Need to create a place for the pointee (the reference itself will be an immediate)
240
- create_pointee_place ( & mut ecx, * inner_ty, valtree)
241
- }
242
- _ => {
243
- // Need to create a place for this valtree.
244
- create_pointee_place ( & mut ecx, ty, valtree)
230
+ ty:: Ref ( _, inner_ty, _) => {
231
+ let mut ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env, CanAccessStatics :: No ) ;
232
+ let imm = valtree_to_ref ( & mut ecx, valtree, * inner_ty) ;
233
+ let imm = ImmTy :: from_immediate ( imm, tcx. layout_of ( param_env_ty) . unwrap ( ) ) ;
234
+ op_to_const ( & ecx, & imm. into ( ) )
235
+ }
236
+ ty:: Tuple ( _) | ty:: Array ( _, _) | ty:: Adt ( ..) => {
237
+ let layout = tcx. layout_of ( param_env_ty) . unwrap ( ) ;
238
+ if layout. is_zst ( ) {
239
+ // Fast path to avoid some allocations.
240
+ return ConstValue :: ZeroSized ;
241
+ }
242
+ if layout. abi . is_scalar ( )
243
+ && ( matches ! ( ty. kind( ) , ty:: Tuple ( _) )
244
+ || matches ! ( ty. kind( ) , ty:: Adt ( def, _) if def. is_struct( ) ) )
245
+ {
246
+ // A Scalar tuple/struct; we can avoid creating an allocation.
247
+ let branches = valtree. unwrap_branch ( ) ;
248
+ // Find the non-ZST field. (There can be aligned ZST!)
249
+ for ( i, & inner_valtree) in branches. iter ( ) . enumerate ( ) {
250
+ let field = layout. field ( & LayoutCx { tcx, param_env } , i) ;
251
+ if !field. is_zst ( ) {
252
+ return valtree_to_const_value ( tcx, param_env. and ( field. ty ) , inner_valtree) ;
253
+ }
245
254
}
246
- } ;
247
- debug ! ( ?place) ;
255
+ bug ! ( "could not find non-ZST field during in {layout:#?}" ) ;
256
+ }
257
+
258
+ let mut ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env, CanAccessStatics :: No ) ;
259
+
260
+ // Need to create a place for this valtree.
261
+ let place = create_valtree_place ( & mut ecx, layout, valtree) ;
248
262
249
263
valtree_into_mplace ( & mut ecx, & place, valtree) ;
250
264
dump_place ( & ecx, & place) ;
251
265
intern_const_alloc_recursive ( & mut ecx, InternKind :: Constant , & place) . unwrap ( ) ;
252
266
253
- match ty. kind ( ) {
254
- ty:: Ref ( _, _, _) => {
255
- let ref_place = place. to_ref ( & tcx) ;
256
- let imm =
257
- ImmTy :: from_immediate ( ref_place, tcx. layout_of ( param_env_ty) . unwrap ( ) ) ;
258
-
259
- op_to_const ( & ecx, & imm. into ( ) )
260
- }
261
- _ => op_to_const ( & ecx, & place. into ( ) ) ,
262
- }
267
+ op_to_const ( & ecx, & place. into ( ) )
263
268
}
264
269
ty:: Never
265
270
| ty:: Error ( _)
@@ -283,6 +288,22 @@ pub fn valtree_to_const_value<'tcx>(
283
288
}
284
289
}
285
290
291
+ /// Put a valtree into memory and return a reference to that.
292
+ fn valtree_to_ref < ' tcx > (
293
+ ecx : & mut CompileTimeEvalContext < ' tcx , ' tcx > ,
294
+ valtree : ty:: ValTree < ' tcx > ,
295
+ pointee_ty : Ty < ' tcx > ,
296
+ ) -> Immediate {
297
+ let pointee_place = create_valtree_place ( ecx, ecx. layout_of ( pointee_ty) . unwrap ( ) , valtree) ;
298
+ debug ! ( ?pointee_place) ;
299
+
300
+ valtree_into_mplace ( ecx, & pointee_place, valtree) ;
301
+ dump_place ( ecx, & pointee_place) ;
302
+ intern_const_alloc_recursive ( ecx, InternKind :: Constant , & pointee_place) . unwrap ( ) ;
303
+
304
+ pointee_place. to_ref ( & ecx. tcx )
305
+ }
306
+
286
307
#[ instrument( skip( ecx) , level = "debug" ) ]
287
308
fn valtree_into_mplace < ' tcx > (
288
309
ecx : & mut CompileTimeEvalContext < ' tcx , ' tcx > ,
@@ -292,7 +313,6 @@ fn valtree_into_mplace<'tcx>(
292
313
// This will match on valtree and write the value(s) corresponding to the ValTree
293
314
// inside the place recursively.
294
315
295
- let tcx = ecx. tcx . tcx ;
296
316
let ty = place. layout . ty ;
297
317
298
318
match ty. kind ( ) {
@@ -305,27 +325,8 @@ fn valtree_into_mplace<'tcx>(
305
325
ecx. write_immediate ( Immediate :: Scalar ( scalar_int. into ( ) ) , place) . unwrap ( ) ;
306
326
}
307
327
ty:: Ref ( _, inner_ty, _) => {
308
- let pointee_place = create_pointee_place ( ecx, * inner_ty, valtree) ;
309
- debug ! ( ?pointee_place) ;
310
-
311
- valtree_into_mplace ( ecx, & pointee_place, valtree) ;
312
- dump_place ( ecx, & pointee_place) ;
313
- intern_const_alloc_recursive ( ecx, InternKind :: Constant , & pointee_place) . unwrap ( ) ;
314
-
315
- let imm = match inner_ty. kind ( ) {
316
- ty:: Slice ( _) | ty:: Str => {
317
- let len = valtree. unwrap_branch ( ) . len ( ) ;
318
- let len_scalar = Scalar :: from_target_usize ( len as u64 , & tcx) ;
319
-
320
- Immediate :: ScalarPair (
321
- Scalar :: from_maybe_pointer ( pointee_place. ptr ( ) , & tcx) ,
322
- len_scalar,
323
- )
324
- }
325
- _ => pointee_place. to_ref ( & tcx) ,
326
- } ;
328
+ let imm = valtree_to_ref ( ecx, valtree, * inner_ty) ;
327
329
debug ! ( ?imm) ;
328
-
329
330
ecx. write_immediate ( imm, place) . unwrap ( ) ;
330
331
}
331
332
ty:: Adt ( _, _) | ty:: Tuple ( _) | ty:: Array ( _, _) | ty:: Str | ty:: Slice ( _) => {
0 commit comments