@@ -21,7 +21,7 @@ use syntax::ast::Mutability;
21
21
use syntax:: source_map:: { Span , DUMMY_SP } ;
22
22
23
23
use crate :: interpret:: { self ,
24
- PlaceTy , MPlaceTy , MemPlace , OpTy , ImmTy , Operand , Immediate , Scalar , Pointer ,
24
+ PlaceTy , MPlaceTy , OpTy , ImmTy , Scalar , Pointer ,
25
25
RawConst , ConstValue ,
26
26
EvalResult , EvalError , EvalErrorKind , GlobalId , EvalContext , StackPopCleanup ,
27
27
Allocation , AllocId , MemoryKind ,
@@ -62,43 +62,6 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
62
62
eval_body_using_ecx ( & mut ecx, cid, Some ( mir) , param_env)
63
63
}
64
64
65
- // FIXME: These two conversion functions are bad hacks. We should just always use allocations.
66
- fn op_to_const < ' tcx > (
67
- ecx : & CompileTimeEvalContext < ' _ , ' _ , ' tcx > ,
68
- op : OpTy < ' tcx > ,
69
- ) -> EvalResult < ' tcx , ty:: Const < ' tcx > > {
70
- // We do not normalize just any data. Only scalar layout and slices.
71
- let normalized_op = match op. layout . abi {
72
- layout:: Abi :: Scalar ( ..) => ecx. try_read_immediate ( op) ?,
73
- layout:: Abi :: ScalarPair ( ..) if op. layout . ty . is_slice ( ) => ecx. try_read_immediate ( op) ?,
74
- _ => match * op {
75
- Operand :: Indirect ( mplace) => Err ( mplace) ,
76
- Operand :: Immediate ( val) => Ok ( val)
77
- } ,
78
- } ;
79
- let ( val, alloc) = match normalized_op {
80
- Err ( MemPlace { ptr, align, meta } ) => {
81
- // extract alloc-offset pair
82
- assert ! ( meta. is_none( ) ) ;
83
- let ptr = ptr. to_ptr ( ) ?;
84
- let alloc = ecx. memory . get ( ptr. alloc_id ) ?;
85
- assert ! ( alloc. align >= align) ;
86
- assert ! ( alloc. bytes. len( ) as u64 - ptr. offset. bytes( ) >= op. layout. size. bytes( ) ) ;
87
- let mut alloc = alloc. clone ( ) ;
88
- alloc. align = align;
89
- // FIXME shouldn't it be the case that `mark_static_initialized` has already
90
- // interned this? I thought that is the entire point of that `FinishStatic` stuff?
91
- let alloc = ecx. tcx . intern_const_alloc ( alloc) ;
92
- ( ConstValue :: ByRef , Some ( ( alloc, ptr) ) )
93
- } ,
94
- Ok ( Immediate :: Scalar ( x) ) =>
95
- ( ConstValue :: Scalar ( x. not_undef ( ) ?) , None ) ,
96
- Ok ( Immediate :: ScalarPair ( a, b) ) =>
97
- ( ConstValue :: Slice ( a. not_undef ( ) ?, b. to_usize ( ecx) ?) , None ) ,
98
- } ;
99
- Ok ( ty:: Const { val, ty : op. layout . ty , alloc } )
100
- }
101
-
102
65
fn eval_body_and_ecx < ' a , ' mir , ' tcx > (
103
66
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
104
67
cid : GlobalId < ' tcx > ,
@@ -471,18 +434,43 @@ pub fn const_field<'a, 'tcx>(
471
434
trace ! ( "const_field: {:?}, {:?}" , field, value) ;
472
435
let ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env) ;
473
436
let result = ( || {
474
- // get the operand again
475
- let op = ecx. lazy_const_to_op ( ty:: LazyConst :: Evaluated ( value) , value. ty ) ?;
437
+ let ( alloc, ptr) = value. alloc . expect (
438
+ "const_field can only be called on aggregates, which should never be created without
439
+ a corresponding allocation" ,
440
+ ) ;
441
+ let mplace = MPlaceTy :: from_aligned_ptr ( ptr, ecx. layout_of ( value. ty ) ?) ;
476
442
// downcast
477
443
let down = match variant {
478
- None => op ,
479
- Some ( variant) => ecx. operand_downcast ( op , variant) ?
444
+ None => mplace ,
445
+ Some ( variant) => ecx. mplace_downcast ( mplace , variant) ?,
480
446
} ;
481
447
// then project
482
- let field = ecx. operand_field ( down, field. index ( ) as u64 ) ?;
483
- // and finally move back to the const world, always normalizing because
484
- // this is not called for statics.
485
- op_to_const ( & ecx, field)
448
+ let field = ecx. mplace_field ( down, field. index ( ) as u64 ) ?;
449
+ let val = match field. layout . abi {
450
+ layout:: Abi :: Scalar ( ..) => {
451
+ let scalar = ecx. try_read_immediate_from_mplace ( field) ?. unwrap ( ) . to_scalar ( ) ?;
452
+ ConstValue :: Scalar ( scalar)
453
+ }
454
+ layout:: Abi :: ScalarPair ( ..) if field. layout . ty . is_slice ( ) => {
455
+ let ( a, b) = ecx. try_read_immediate_from_mplace ( field) ?. unwrap ( ) . to_scalar_pair ( ) ?;
456
+ ConstValue :: Slice ( a, b. to_usize ( & ecx) ?)
457
+ } ,
458
+ _ => ConstValue :: ByRef ,
459
+ } ;
460
+ let field_ptr = field. to_ptr ( ) . unwrap ( ) ;
461
+ assert_eq ! (
462
+ ptr. alloc_id,
463
+ field_ptr. alloc_id,
464
+ "field access of aggregate moved to different allocation" ,
465
+ ) ;
466
+ Ok ( ty:: Const {
467
+ val,
468
+ ty : field. layout . ty ,
469
+ alloc : Some ( (
470
+ alloc,
471
+ field_ptr,
472
+ ) ) ,
473
+ } )
486
474
} ) ( ) ;
487
475
result. map_err ( |error| {
488
476
let err = error_to_const_error ( & ecx, error) ;
0 commit comments