@@ -21,7 +21,7 @@ use syntax::ast::Mutability;
2121use syntax:: source_map:: { Span , DUMMY_SP } ;
2222
2323use crate :: interpret:: { self ,
24- PlaceTy , MPlaceTy , MemPlace , OpTy , ImmTy , Operand , Immediate , Scalar , Pointer ,
24+ PlaceTy , MPlaceTy , MemPlace , OpTy , ImmTy , Immediate , Scalar , Pointer ,
2525 RawConst , ConstValue ,
2626 EvalResult , EvalError , EvalErrorKind , GlobalId , EvalContext , StackPopCleanup ,
2727 Allocation , AllocId , MemoryKind ,
@@ -62,45 +62,46 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
6262 eval_body_using_ecx ( & mut ecx, cid, Some ( mir) , param_env)
6363}
6464
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 > (
6786 ecx : & CompileTimeEvalContext < ' _ , ' _ , ' tcx > ,
6887 op : OpTy < ' tcx > ,
69- may_normalize : bool ,
7088) -> EvalResult < ' tcx , ty:: Const < ' tcx > > {
7189 // 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+ } ;
7895 let normalized_op = if normalize {
79- ecx. try_read_immediate ( op) ?
96+ Err ( * ecx. read_immediate ( op) . expect ( "normalization works on validated constants" ) )
8097 } else {
81- match * op {
82- Operand :: Indirect ( mplace) => Err ( mplace) ,
83- Operand :: Immediate ( val) => Ok ( val)
84- }
98+ op. try_as_mplace ( )
8599 } ;
86100 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) ) =>
102103 ConstValue :: Scalar ( x. not_undef ( ) ?) ,
103- Ok ( Immediate :: ScalarPair ( a, b) ) =>
104+ Err ( Immediate :: ScalarPair ( a, b) ) =>
104105 ConstValue :: Slice ( a. not_undef ( ) ?, b. to_usize ( ecx) ?) ,
105106 } ;
106107 Ok ( ty:: Const { val, ty : op. layout . ty } )
@@ -476,7 +477,7 @@ pub fn const_field<'a, 'tcx>(
476477 let ecx = mk_eval_cx ( tcx, DUMMY_SP , param_env) ;
477478 let result = ( || {
478479 // 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 ) ?;
480481 // downcast
481482 let down = match variant {
482483 None => op,
@@ -486,7 +487,7 @@ pub fn const_field<'a, 'tcx>(
486487 let field = ecx. operand_field ( down, field. index ( ) as u64 ) ?;
487488 // and finally move back to the const world, always normalizing because
488489 // this is not called for statics.
489- op_to_const ( & ecx, field, true )
490+ op_to_const ( & ecx, field)
490491 } ) ( ) ;
491492 result. map_err ( |error| {
492493 let err = error_to_const_error ( & ecx, error) ;
@@ -502,7 +503,7 @@ pub fn const_variant_index<'a, 'tcx>(
502503) -> EvalResult < ' tcx , VariantIdx > {
503504 trace ! ( "const_variant_index: {:?}" , val) ;
504505 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 ) ?;
506507 Ok ( ecx. read_discriminant ( op) ?. 1 )
507508}
508509
@@ -523,22 +524,23 @@ fn validate_and_turn_into_const<'a, 'tcx>(
523524 let cid = key. value ;
524525 let ecx = mk_eval_cx ( tcx, tcx. def_span ( key. value . instance . def_id ( ) ) , key. param_env ) ;
525526 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 ( ) {
531530 ecx. validate_operand (
532- op ,
531+ mplace . into ( ) ,
533532 path,
534533 Some ( & mut ref_tracking) ,
535534 true , // const mode
536535 ) ?;
537536 }
538537 // Now that we validated, turn this into a proper constant.
539538 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+ }
542544 } ) ( ) ;
543545
544546 val. map_err ( |error| {
0 commit comments