@@ -31,8 +31,8 @@ use rustc::util::common::ErrorReported;
3131use syntax:: ast:: Mutability ;
3232use syntax:: source_map:: { Span , DUMMY_SP } ;
3333
34- use interpret:: { self ,
35- PlaceTy , MemPlace , OpTy , Operand , Immediate , Scalar , ConstValue , Pointer ,
34+ use crate :: interpret:: { self ,
35+ PlaceTy , MPlaceTy , MemPlace , OpTy , Operand , Immediate , Scalar , RawConst , ConstValue , Pointer ,
3636 EvalResult , EvalError , EvalErrorKind , GlobalId , EvalContext , StackPopCleanup ,
3737 Allocation , AllocId , MemoryKind ,
3838 snapshot, RefTracking ,
@@ -94,11 +94,12 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
9494 cid : GlobalId < ' tcx > ,
9595 mir : & ' mir mir:: Mir < ' tcx > ,
9696 param_env : ty:: ParamEnv < ' tcx > ,
97- ) -> EvalResult < ' tcx , OpTy < ' tcx > > {
97+ ) -> EvalResult < ' tcx , MPlaceTy < ' tcx > > {
9898 let mut ecx = mk_borrowck_eval_cx ( tcx, cid. instance , mir, DUMMY_SP ) . unwrap ( ) ;
9999 eval_body_using_ecx ( & mut ecx, cid, Some ( mir) , param_env)
100100}
101101
102+ // FIXME: These two conversion functions are bad hacks. We should just always use allocations.
102103pub fn op_to_const < ' tcx > (
103104 ecx : & CompileTimeEvalContext < ' _ , ' _ , ' tcx > ,
104105 op : OpTy < ' tcx > ,
@@ -144,13 +145,20 @@ pub fn op_to_const<'tcx>(
144145 } ;
145146 Ok ( ty:: Const :: from_const_value ( ecx. tcx . tcx , val, op. layout . ty ) )
146147}
148+ pub fn const_to_op < ' tcx > (
149+ ecx : & CompileTimeEvalContext < ' _ , ' _ , ' tcx > ,
150+ cnst : & ty:: Const < ' tcx > ,
151+ ) -> EvalResult < ' tcx , OpTy < ' tcx > > {
152+ let op = ecx. const_value_to_op ( cnst. val ) ?;
153+ Ok ( OpTy { op, layout : ecx. layout_of ( cnst. ty ) ? } )
154+ }
147155
148156fn eval_body_and_ecx < ' a , ' mir , ' tcx > (
149157 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
150158 cid : GlobalId < ' tcx > ,
151159 mir : Option < & ' mir mir:: Mir < ' tcx > > ,
152160 param_env : ty:: ParamEnv < ' tcx > ,
153- ) -> ( EvalResult < ' tcx , OpTy < ' tcx > > , CompileTimeEvalContext < ' a , ' mir , ' tcx > ) {
161+ ) -> ( EvalResult < ' tcx , MPlaceTy < ' tcx > > , CompileTimeEvalContext < ' a , ' mir , ' tcx > ) {
154162 // we start out with the best span we have
155163 // and try improving it down the road when more information is available
156164 let span = tcx. def_span ( cid. instance . def_id ( ) ) ;
@@ -166,7 +174,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
166174 cid : GlobalId < ' tcx > ,
167175 mir : Option < & ' mir mir:: Mir < ' tcx > > ,
168176 param_env : ty:: ParamEnv < ' tcx > ,
169- ) -> EvalResult < ' tcx , OpTy < ' tcx > > {
177+ ) -> EvalResult < ' tcx , MPlaceTy < ' tcx > > {
170178 debug ! ( "eval_body_using_ecx: {:?}, {:?}" , cid, param_env) ;
171179 let tcx = ecx. tcx . tcx ;
172180 let mut mir = match mir {
@@ -206,7 +214,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
206214 ecx. memory . intern_static ( ret. ptr . to_ptr ( ) ?. alloc_id , mutability) ?;
207215
208216 debug ! ( "eval_body_using_ecx done: {:?}" , * ret) ;
209- Ok ( ret. into ( ) )
217+ Ok ( ret)
210218}
211219
212220impl < ' tcx > Into < EvalError < ' tcx > > for ConstEvalError {
@@ -494,7 +502,7 @@ pub fn const_field<'a, 'tcx>(
494502 let ecx = mk_eval_cx ( tcx, instance, param_env) . unwrap ( ) ;
495503 let result = ( || {
496504 // get the operand again
497- let op = ecx . const_to_op ( value) ?;
505+ let op = const_to_op ( & ecx , value) ?;
498506 // downcast
499507 let down = match variant {
500508 None => op,
@@ -521,7 +529,7 @@ pub fn const_variant_index<'a, 'tcx>(
521529) -> EvalResult < ' tcx , VariantIdx > {
522530 trace ! ( "const_variant_index: {:?}, {:?}" , instance, val) ;
523531 let ecx = mk_eval_cx ( tcx, instance, param_env) . unwrap ( ) ;
524- let op = ecx . const_to_op ( val) ?;
532+ let op = const_to_op ( & ecx , val) ?;
525533 Ok ( ecx. read_discriminant ( op) ?. 1 )
526534}
527535
@@ -534,15 +542,17 @@ pub fn error_to_const_error<'a, 'mir, 'tcx>(
534542 ConstEvalErr { error : error. kind , stacktrace, span : ecx. tcx . span }
535543}
536544
537- fn validate_const < ' a , ' tcx > (
545+ fn validate_and_turn_into_const < ' a , ' tcx > (
538546 tcx : ty:: TyCtxt < ' a , ' tcx , ' tcx > ,
539- constant : & ' tcx ty :: Const < ' tcx > ,
547+ constant : RawConst < ' tcx > ,
540548 key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
541549) -> :: rustc:: mir:: interpret:: ConstEvalResult < ' tcx > {
542550 let cid = key. value ;
543551 let ecx = mk_eval_cx ( tcx, cid. instance , key. param_env ) . unwrap ( ) ;
544552 let val = ( || {
545- let op = ecx. const_to_op ( constant) ?;
553+ let op = ecx. raw_const_to_mplace ( constant) ?. into ( ) ;
554+ // FIXME: Once the visitor infrastructure landed, change validation to
555+ // work directly on `MPlaceTy`.
546556 let mut ref_tracking = RefTracking :: new ( op) ;
547557 while let Some ( ( op, path) ) = ref_tracking. todo . pop ( ) {
548558 ecx. validate_operand (
@@ -552,7 +562,10 @@ fn validate_const<'a, 'tcx>(
552562 /* const_mode */ true ,
553563 ) ?;
554564 }
555- Ok ( constant)
565+ // Now that we validated, turn this into a proper constant
566+ let def_id = cid. instance . def . def_id ( ) ;
567+ let normalize = tcx. is_static ( def_id) . is_none ( ) && cid. promoted . is_none ( ) ;
568+ op_to_const ( & ecx, op, normalize)
556569 } ) ( ) ;
557570
558571 val. map_err ( |error| {
@@ -591,14 +604,14 @@ pub fn const_eval_provider<'a, 'tcx>(
591604 }
592605 }
593606 tcx. const_eval_raw ( key) . and_then ( |val| {
594- validate_const ( tcx, val, key)
607+ validate_and_turn_into_const ( tcx, val, key)
595608 } )
596609}
597610
598611pub fn const_eval_raw_provider < ' a , ' tcx > (
599612 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
600613 key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
601- ) -> :: rustc:: mir:: interpret:: ConstEvalResult < ' tcx > {
614+ ) -> :: rustc:: mir:: interpret:: ConstEvalRawResult < ' tcx > {
602615 // Because the constant is computed twice (once per value of `Reveal`), we are at risk of
603616 // reporting the same error twice here. To resolve this, we check whether we can evaluate the
604617 // constant in the more restrictive `Reveal::UserFacing`, which most likely already was
@@ -648,16 +661,11 @@ pub fn const_eval_raw_provider<'a, 'tcx>(
648661 } ;
649662
650663 let ( res, ecx) = eval_body_and_ecx ( tcx, cid, None , key. param_env ) ;
651- res. and_then ( |op| {
652- let normalize = tcx. is_static ( def_id) . is_none ( ) && cid. promoted . is_none ( ) ;
653- if !normalize {
654- // Sanity check: These must always be a MemPlace
655- match op. op {
656- Operand :: Indirect ( _) => { /* all is good */ } ,
657- Operand :: Immediate ( _) => bug ! ( "const eval gave us an Immediate" ) ,
658- }
659- }
660- op_to_const ( & ecx, op, normalize)
664+ res. and_then ( |place| {
665+ Ok ( RawConst {
666+ alloc_id : place. to_ptr ( ) . expect ( "we allocated this ptr!" ) . alloc_id ,
667+ ty : place. layout . ty
668+ } )
661669 } ) . map_err ( |error| {
662670 let err = error_to_const_error ( & ecx, error) ;
663671 // errors in statics are always emitted as fatal errors
0 commit comments