@@ -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 , MemPlace , OpTy , ImmTy , Immediate , Scalar , Pointer ,
25
25
RawConst , ConstValue ,
26
26
EvalResult , EvalError , EvalErrorKind , GlobalId , EvalContext , StackPopCleanup ,
27
27
Allocation , AllocId , MemoryKind ,
@@ -62,45 +62,46 @@ 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
- pub fn op_to_const < ' tcx > (
65
+ fn mplace_to_const < ' tcx > (
66
+ ecx : & CompileTimeEvalContext < ' _ , ' _ , ' tcx > ,
67
+ mplace : MPlaceTy < ' tcx > ,
68
+ ) -> EvalResult < ' tcx , ty:: Const < ' tcx > > {
69
+ let MemPlace { ptr, align, meta } = * mplace;
70
+ // extract alloc-offset pair
71
+ assert ! ( meta. is_none( ) ) ;
72
+ let ptr = ptr. to_ptr ( ) ?;
73
+ let alloc = ecx. memory . get ( ptr. alloc_id ) ?;
74
+ assert ! ( alloc. align >= align) ;
75
+ assert ! ( alloc. bytes. len( ) as u64 - ptr. offset. bytes( ) >= mplace. layout. size. bytes( ) ) ;
76
+ let mut alloc = alloc. clone ( ) ;
77
+ alloc. align = align;
78
+ // FIXME shouldn't it be the case that `mark_static_initialized` has already
79
+ // interned this? I thought that is the entire point of that `FinishStatic` stuff?
80
+ let alloc = ecx. tcx . intern_const_alloc ( alloc) ;
81
+ let val = ConstValue :: ByRef ( ptr, alloc) ;
82
+ Ok ( ty:: Const { val, ty : mplace. layout . ty } )
83
+ }
84
+
85
+ fn op_to_const < ' tcx > (
67
86
ecx : & CompileTimeEvalContext < ' _ , ' _ , ' tcx > ,
68
87
op : OpTy < ' tcx > ,
69
- may_normalize : bool ,
70
88
) -> EvalResult < ' tcx , ty:: Const < ' tcx > > {
71
89
// We do not normalize just any data. Only scalar layout and slices.
72
- let normalize = may_normalize
73
- && match op. layout . abi {
74
- layout:: Abi :: Scalar ( ..) => true ,
75
- layout:: Abi :: ScalarPair ( ..) => op. layout . ty . is_slice ( ) ,
76
- _ => false ,
77
- } ;
90
+ let normalize = match op. layout . abi {
91
+ layout:: Abi :: Scalar ( ..) => true ,
92
+ layout:: Abi :: ScalarPair ( ..) => op. layout . ty . is_slice ( ) ,
93
+ _ => false ,
94
+ } ;
78
95
let normalized_op = if normalize {
79
- ecx. try_read_immediate ( op) ?
96
+ Err ( * ecx. read_immediate ( op) . expect ( "normalization works on validated constants" ) )
80
97
} else {
81
- match * op {
82
- Operand :: Indirect ( mplace) => Err ( mplace) ,
83
- Operand :: Immediate ( val) => Ok ( val)
84
- }
98
+ op. try_as_mplace ( )
85
99
} ;
86
100
let val = match normalized_op {
87
- Err ( MemPlace { ptr, align, meta } ) => {
88
- // extract alloc-offset pair
89
- assert ! ( meta. is_none( ) ) ;
90
- let ptr = ptr. to_ptr ( ) ?;
91
- let alloc = ecx. memory . get ( ptr. alloc_id ) ?;
92
- assert ! ( alloc. align >= align) ;
93
- assert ! ( alloc. bytes. len( ) as u64 - ptr. offset. bytes( ) >= op. layout. size. bytes( ) ) ;
94
- let mut alloc = alloc. clone ( ) ;
95
- alloc. align = align;
96
- // FIXME shouldn't it be the case that `mark_static_initialized` has already
97
- // interned this? I thought that is the entire point of that `FinishStatic` stuff?
98
- let alloc = ecx. tcx . intern_const_alloc ( alloc) ;
99
- ConstValue :: ByRef ( ptr. alloc_id , alloc, ptr. offset )
100
- } ,
101
- Ok ( Immediate :: Scalar ( x) ) =>
101
+ Ok ( mplace) => return mplace_to_const ( ecx, mplace) ,
102
+ Err ( Immediate :: Scalar ( x) ) =>
102
103
ConstValue :: Scalar ( x. not_undef ( ) ?) ,
103
- Ok ( Immediate :: ScalarPair ( a, b) ) =>
104
+ Err ( Immediate :: ScalarPair ( a, b) ) =>
104
105
ConstValue :: Slice ( a. not_undef ( ) ?, b. to_usize ( ecx) ?) ,
105
106
} ;
106
107
Ok ( ty:: Const { val, ty : op. layout . ty } )
@@ -476,7 +477,7 @@ pub fn const_field<'a, 'tcx>(
476
477
let ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env) ;
477
478
let result = ( || {
478
479
// get the operand again
479
- let op = ecx. lazy_const_to_op ( ty :: LazyConst :: Evaluated ( value) , value . ty ) ?;
480
+ let op = ecx. const_to_op ( value, None ) ?;
480
481
// downcast
481
482
let down = match variant {
482
483
None => op,
@@ -486,7 +487,7 @@ pub fn const_field<'a, 'tcx>(
486
487
let field = ecx. operand_field ( down, field. index ( ) as u64 ) ?;
487
488
// and finally move back to the const world, always normalizing because
488
489
// this is not called for statics.
489
- op_to_const ( & ecx, field, true )
490
+ op_to_const ( & ecx, field)
490
491
} ) ( ) ;
491
492
result. map_err ( |error| {
492
493
let err = error_to_const_error ( & ecx, error) ;
@@ -502,7 +503,7 @@ pub fn const_variant_index<'a, 'tcx>(
502
503
) -> EvalResult < ' tcx , VariantIdx > {
503
504
trace ! ( "const_variant_index: {:?}" , val) ;
504
505
let ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env) ;
505
- let op = ecx. lazy_const_to_op ( ty :: LazyConst :: Evaluated ( val) , val . ty ) ?;
506
+ let op = ecx. const_to_op ( val, None ) ?;
506
507
Ok ( ecx. read_discriminant ( op) ?. 1 )
507
508
}
508
509
@@ -523,22 +524,23 @@ fn validate_and_turn_into_const<'a, 'tcx>(
523
524
let cid = key. value ;
524
525
let ecx = mk_eval_cx ( tcx, tcx. def_span ( key. value . instance . def_id ( ) ) , key. param_env ) ;
525
526
let val = ( || {
526
- let op = ecx. raw_const_to_mplace ( constant) ?. into ( ) ;
527
- // FIXME: Once the visitor infrastructure landed, change validation to
528
- // work directly on `MPlaceTy`.
529
- let mut ref_tracking = RefTracking :: new ( op) ;
530
- while let Some ( ( op, path) ) = ref_tracking. todo . pop ( ) {
527
+ let mplace = ecx. raw_const_to_mplace ( constant) ?;
528
+ let mut ref_tracking = RefTracking :: new ( mplace) ;
529
+ while let Some ( ( mplace, path) ) = ref_tracking. todo . pop ( ) {
531
530
ecx. validate_operand (
532
- op ,
531
+ mplace . into ( ) ,
533
532
path,
534
533
Some ( & mut ref_tracking) ,
535
534
true , // const mode
536
535
) ?;
537
536
}
538
537
// Now that we validated, turn this into a proper constant.
539
538
let def_id = cid. instance . def . def_id ( ) ;
540
- let normalize = tcx. is_static ( def_id) . is_none ( ) && cid. promoted . is_none ( ) ;
541
- op_to_const ( & ecx, op, normalize)
539
+ if tcx. is_static ( def_id) . is_some ( ) || cid. promoted . is_some ( ) {
540
+ mplace_to_const ( & ecx, mplace)
541
+ } else {
542
+ op_to_const ( & ecx, mplace. into ( ) )
543
+ }
542
544
} ) ( ) ;
543
545
544
546
val. map_err ( |error| {
0 commit comments