@@ -31,8 +31,8 @@ use rustc::util::common::ErrorReported;
31
31
use syntax:: ast:: Mutability ;
32
32
use syntax:: source_map:: { Span , DUMMY_SP } ;
33
33
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 ,
36
36
EvalResult , EvalError , EvalErrorKind , GlobalId , EvalContext , StackPopCleanup ,
37
37
Allocation , AllocId , MemoryKind ,
38
38
snapshot, RefTracking ,
@@ -94,11 +94,12 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
94
94
cid : GlobalId < ' tcx > ,
95
95
mir : & ' mir mir:: Mir < ' tcx > ,
96
96
param_env : ty:: ParamEnv < ' tcx > ,
97
- ) -> EvalResult < ' tcx , OpTy < ' tcx > > {
97
+ ) -> EvalResult < ' tcx , MPlaceTy < ' tcx > > {
98
98
let mut ecx = mk_borrowck_eval_cx ( tcx, cid. instance , mir, DUMMY_SP ) . unwrap ( ) ;
99
99
eval_body_using_ecx ( & mut ecx, cid, Some ( mir) , param_env)
100
100
}
101
101
102
+ // FIXME: These two conversion functions are bad hacks. We should just always use allocations.
102
103
pub fn op_to_const < ' tcx > (
103
104
ecx : & CompileTimeEvalContext < ' _ , ' _ , ' tcx > ,
104
105
op : OpTy < ' tcx > ,
@@ -144,13 +145,20 @@ pub fn op_to_const<'tcx>(
144
145
} ;
145
146
Ok ( ty:: Const :: from_const_value ( ecx. tcx . tcx , val, op. layout . ty ) )
146
147
}
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
+ }
147
155
148
156
fn eval_body_and_ecx < ' a , ' mir , ' tcx > (
149
157
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
150
158
cid : GlobalId < ' tcx > ,
151
159
mir : Option < & ' mir mir:: Mir < ' tcx > > ,
152
160
param_env : ty:: ParamEnv < ' tcx > ,
153
- ) -> ( EvalResult < ' tcx , OpTy < ' tcx > > , CompileTimeEvalContext < ' a , ' mir , ' tcx > ) {
161
+ ) -> ( EvalResult < ' tcx , MPlaceTy < ' tcx > > , CompileTimeEvalContext < ' a , ' mir , ' tcx > ) {
154
162
// we start out with the best span we have
155
163
// and try improving it down the road when more information is available
156
164
let span = tcx. def_span ( cid. instance . def_id ( ) ) ;
@@ -166,7 +174,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
166
174
cid : GlobalId < ' tcx > ,
167
175
mir : Option < & ' mir mir:: Mir < ' tcx > > ,
168
176
param_env : ty:: ParamEnv < ' tcx > ,
169
- ) -> EvalResult < ' tcx , OpTy < ' tcx > > {
177
+ ) -> EvalResult < ' tcx , MPlaceTy < ' tcx > > {
170
178
debug ! ( "eval_body_using_ecx: {:?}, {:?}" , cid, param_env) ;
171
179
let tcx = ecx. tcx . tcx ;
172
180
let mut mir = match mir {
@@ -206,7 +214,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
206
214
ecx. memory . intern_static ( ret. ptr . to_ptr ( ) ?. alloc_id , mutability) ?;
207
215
208
216
debug ! ( "eval_body_using_ecx done: {:?}" , * ret) ;
209
- Ok ( ret. into ( ) )
217
+ Ok ( ret)
210
218
}
211
219
212
220
impl < ' tcx > Into < EvalError < ' tcx > > for ConstEvalError {
@@ -494,7 +502,7 @@ pub fn const_field<'a, 'tcx>(
494
502
let ecx = mk_eval_cx ( tcx, instance, param_env) . unwrap ( ) ;
495
503
let result = ( || {
496
504
// get the operand again
497
- let op = ecx . const_to_op ( value) ?;
505
+ let op = const_to_op ( & ecx , value) ?;
498
506
// downcast
499
507
let down = match variant {
500
508
None => op,
@@ -521,7 +529,7 @@ pub fn const_variant_index<'a, 'tcx>(
521
529
) -> EvalResult < ' tcx , VariantIdx > {
522
530
trace ! ( "const_variant_index: {:?}, {:?}" , instance, val) ;
523
531
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) ?;
525
533
Ok ( ecx. read_discriminant ( op) ?. 1 )
526
534
}
527
535
@@ -534,15 +542,17 @@ pub fn error_to_const_error<'a, 'mir, 'tcx>(
534
542
ConstEvalErr { error : error. kind , stacktrace, span : ecx. tcx . span }
535
543
}
536
544
537
- fn validate_const < ' a , ' tcx > (
545
+ fn validate_and_turn_into_const < ' a , ' tcx > (
538
546
tcx : ty:: TyCtxt < ' a , ' tcx , ' tcx > ,
539
- constant : & ' tcx ty :: Const < ' tcx > ,
547
+ constant : RawConst < ' tcx > ,
540
548
key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
541
549
) -> :: rustc:: mir:: interpret:: ConstEvalResult < ' tcx > {
542
550
let cid = key. value ;
543
551
let ecx = mk_eval_cx ( tcx, cid. instance , key. param_env ) . unwrap ( ) ;
544
552
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`.
546
556
let mut ref_tracking = RefTracking :: new ( op) ;
547
557
while let Some ( ( op, path) ) = ref_tracking. todo . pop ( ) {
548
558
ecx. validate_operand (
@@ -552,7 +562,10 @@ fn validate_const<'a, 'tcx>(
552
562
/* const_mode */ true ,
553
563
) ?;
554
564
}
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)
556
569
} ) ( ) ;
557
570
558
571
val. map_err ( |error| {
@@ -591,14 +604,14 @@ pub fn const_eval_provider<'a, 'tcx>(
591
604
}
592
605
}
593
606
tcx. const_eval_raw ( key) . and_then ( |val| {
594
- validate_const ( tcx, val, key)
607
+ validate_and_turn_into_const ( tcx, val, key)
595
608
} )
596
609
}
597
610
598
611
pub fn const_eval_raw_provider < ' a , ' tcx > (
599
612
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
600
613
key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
601
- ) -> :: rustc:: mir:: interpret:: ConstEvalResult < ' tcx > {
614
+ ) -> :: rustc:: mir:: interpret:: ConstEvalRawResult < ' tcx > {
602
615
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
603
616
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
604
617
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was
@@ -648,16 +661,11 @@ pub fn const_eval_raw_provider<'a, 'tcx>(
648
661
} ;
649
662
650
663
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
+ } )
661
669
} ) . map_err ( |error| {
662
670
let err = error_to_const_error ( & ecx, error) ;
663
671
// errors in statics are always emitted as fatal errors
0 commit comments