@@ -7,7 +7,7 @@ use crate::interpret::{
77 intern_const_alloc_recursive, ConstValue , ImmTy , Immediate , InternKind , MemPlaceMeta ,
88 MemoryKind , PlaceTy , Projectable , Scalar ,
99} ;
10- use rustc_middle:: ty:: layout:: { LayoutOf , TyAndLayout } ;
10+ use rustc_middle:: ty:: layout:: { LayoutCx , LayoutOf , TyAndLayout } ;
1111use rustc_middle:: ty:: { self , ScalarInt , Ty , TyCtxt } ;
1212use rustc_span:: source_map:: DUMMY_SP ;
1313use rustc_target:: abi:: VariantIdx ;
@@ -189,12 +189,11 @@ fn reconstruct_place_meta<'tcx>(
189189}
190190
191191#[ instrument( skip( ecx) , level = "debug" , ret) ]
192- fn create_pointee_place < ' tcx > (
192+ fn create_valtree_place < ' tcx > (
193193 ecx : & mut CompileTimeEvalContext < ' tcx , ' tcx > ,
194- ty : Ty < ' tcx > ,
194+ layout : TyAndLayout < ' tcx > ,
195195 valtree : ty:: ValTree < ' tcx > ,
196196) -> MPlaceTy < ' tcx > {
197- let layout = ecx. layout_of ( ty) . unwrap ( ) ;
198197 let meta = reconstruct_place_meta ( layout, valtree, ecx. tcx . tcx ) ;
199198 ecx. allocate_dyn ( layout, MemoryKind :: Stack , meta) . unwrap ( )
200199}
@@ -216,11 +215,6 @@ pub fn valtree_to_const_value<'tcx>(
216215 // FIXME Does this need an example?
217216
218217 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 ) ;
224218
225219 match ty. kind ( ) {
226220 ty:: FnDef ( ..) => {
@@ -233,33 +227,44 @@ pub fn valtree_to_const_value<'tcx>(
233227 "ValTrees for Bool, Int, Uint, Float or Char should have the form ValTree::Leaf"
234228 ) ,
235229 } ,
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+ }
245254 }
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) ;
248262
249263 valtree_into_mplace ( & mut ecx, & place, valtree) ;
250264 dump_place ( & ecx, & place) ;
251265 intern_const_alloc_recursive ( & mut ecx, InternKind :: Constant , & place) . unwrap ( ) ;
252266
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 ( ) )
263268 }
264269 ty:: Never
265270 | ty:: Error ( _)
@@ -283,6 +288,22 @@ pub fn valtree_to_const_value<'tcx>(
283288 }
284289}
285290
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+
286307#[ instrument( skip( ecx) , level = "debug" ) ]
287308fn valtree_into_mplace < ' tcx > (
288309 ecx : & mut CompileTimeEvalContext < ' tcx , ' tcx > ,
@@ -292,7 +313,6 @@ fn valtree_into_mplace<'tcx>(
292313 // This will match on valtree and write the value(s) corresponding to the ValTree
293314 // inside the place recursively.
294315
295- let tcx = ecx. tcx . tcx ;
296316 let ty = place. layout . ty ;
297317
298318 match ty. kind ( ) {
@@ -305,27 +325,8 @@ fn valtree_into_mplace<'tcx>(
305325 ecx. write_immediate ( Immediate :: Scalar ( scalar_int. into ( ) ) , place) . unwrap ( ) ;
306326 }
307327 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) ;
327329 debug ! ( ?imm) ;
328-
329330 ecx. write_immediate ( imm, place) . unwrap ( ) ;
330331 }
331332 ty:: Adt ( _, _) | ty:: Tuple ( _) | ty:: Array ( _, _) | ty:: Str | ty:: Slice ( _) => {
0 commit comments