@@ -93,50 +93,69 @@ pub fn eval_body<'a, 'tcx>(
93
93
}
94
94
}
95
95
96
- pub fn value_to_const_value < ' a , ' tcx > (
97
- tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
98
- val : Value ,
96
+ pub fn value_to_const_value < ' tcx > (
97
+ ecx : & EvalContext < ' _ , ' _ , ' tcx , CompileTimeEvaluator > ,
98
+ mut val : Value ,
99
99
ty : Ty < ' tcx > ,
100
100
) -> & ' tcx ty:: Const < ' tcx > {
101
- let layout = tcx. layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) ) . unwrap ( ) ;
101
+ let result = ( || {
102
+ // Convert to ByVal or ByValPair if possible
103
+ if let Value :: ByRef ( ptr, align) = val {
104
+ if let Some ( read_val) = ecx. try_read_value ( ptr, align, ty) ? {
105
+ val = read_val;
106
+ }
107
+ }
102
108
103
- if layout. is_zst ( ) {
104
- return ty:: Const :: from_const_value (
105
- tcx,
106
- ConstValue :: ByVal ( PrimVal :: Undef ) ,
107
- ty) ;
108
- }
109
+ let layout = ecx. tcx . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) ) . unwrap ( ) ;
109
110
110
- let val = match layout. abi {
111
- layout:: Abi :: Scalar ( ..) => {
112
- if let Value :: ByVal ( val) = val {
113
- ConstValue :: ByVal ( val)
114
- } else {
115
- bug ! ( "expected ByVal value, got {:?}" , val) ;
116
- }
111
+ if layout. is_zst ( ) {
112
+ return Ok ( ty:: Const :: from_const_value (
113
+ ecx. tcx . tcx ,
114
+ ConstValue :: ByVal ( PrimVal :: Undef ) ,
115
+ ty) ) ;
117
116
}
118
- layout:: Abi :: ScalarPair ( ..) => {
119
- if let Value :: ByValPair ( a, b) = val {
120
- ConstValue :: ByValPair ( a, b)
121
- } else {
122
- bug ! ( "expected ByValPair value, got {:?}" , val) ;
117
+
118
+ let val = match layout. abi {
119
+ layout:: Abi :: Scalar ( ..) => {
120
+ if let Value :: ByVal ( val) = val {
121
+ ConstValue :: ByVal ( val)
122
+ } else {
123
+ bug ! ( "expected ByVal value, got {:?}" , val) ;
124
+ }
123
125
}
124
- }
125
- _ => {
126
- if let Value :: ByRef ( ptr, align) = val {
127
- let ptr = ptr. primval . to_ptr ( ) . unwrap ( ) ;
128
- assert_eq ! ( ptr. offset, 0 ) ;
129
- let alloc = tcx. interpret_interner
130
- . get_alloc ( ptr. alloc_id )
131
- . expect ( "miri allocation never successfully created" ) ;
132
- assert_eq ! ( align, alloc. align) ;
133
- ConstValue :: ByRef ( alloc)
134
- } else {
135
- bug ! ( "expected ByRef value, got {:?}" , val) ;
126
+ layout:: Abi :: ScalarPair ( ..) => {
127
+ if let Value :: ByValPair ( a, b) = val {
128
+ ConstValue :: ByValPair ( a, b)
129
+ } else {
130
+ bug ! ( "expected ByValPair value, got {:?}" , val) ;
131
+ }
136
132
}
137
- } ,
138
- } ;
139
- ty:: Const :: from_const_value ( tcx, val, ty)
133
+ _ => {
134
+ if let Value :: ByRef ( ptr, _) = val {
135
+ let ptr = ptr. primval . to_ptr ( ) . unwrap ( ) ;
136
+ assert_eq ! ( ptr. offset, 0 ) ;
137
+ let alloc = ecx. memory . get ( ptr. alloc_id ) ?;
138
+ assert ! ( alloc. align. abi( ) >= layout. align. abi( ) ) ;
139
+ assert ! ( alloc. bytes. len( ) as u64 == layout. size. bytes( ) ) ;
140
+ let mut alloc = alloc. clone ( ) ;
141
+ // The align field is meaningless for values, so just use the layout's align
142
+ alloc. align = layout. align ;
143
+ let alloc = ecx. tcx . intern_const_alloc ( alloc) ;
144
+ ConstValue :: ByRef ( alloc)
145
+ } else {
146
+ bug ! ( "expected ByRef value, got {:?}" , val) ;
147
+ }
148
+ } ,
149
+ } ;
150
+ Ok ( ty:: Const :: from_const_value ( ecx. tcx . tcx , val, ty) )
151
+ } ) ( ) ;
152
+ match result {
153
+ Ok ( v) => v,
154
+ Err ( mut err) => {
155
+ ecx. report ( & mut err, true , None ) ;
156
+ bug ! ( "miri error occured when converting Value to ConstValue" )
157
+ }
158
+ }
140
159
}
141
160
142
161
fn eval_body_and_ecx < ' a , ' mir , ' tcx > (
@@ -423,7 +442,7 @@ pub fn const_val_field<'a, 'tcx>(
423
442
let mut ecx = mk_eval_cx ( tcx, instance, param_env) . unwrap ( ) ;
424
443
let result = ( || {
425
444
let value = ecx. const_value_to_value ( value, ty) ?;
426
- let ( mut field, ty) = match value {
445
+ let ( field, ty) = match value {
427
446
Value :: ByValPair ( ..) | Value :: ByVal ( _) =>
428
447
ecx. read_field ( value, variant, field, ty) ?. expect ( "const_val_field on non-field" ) ,
429
448
Value :: ByRef ( ptr, align) => {
@@ -438,24 +457,16 @@ pub fn const_val_field<'a, 'tcx>(
438
457
( Value :: ByRef ( ptr, align) , layout. ty )
439
458
}
440
459
} ;
441
- if let Value :: ByRef ( ptr, align) = field {
442
- if let Some ( val) = ecx. try_read_value ( ptr, align, ty) ? {
443
- field = val;
444
- }
445
- }
446
- Ok ( ( field, ty) )
460
+ Ok ( value_to_const_value ( & ecx, field, ty) )
447
461
} ) ( ) ;
448
- match result {
449
- Ok ( ( field, ty) ) => Ok ( value_to_const_value ( tcx, field, ty) ) ,
450
- Err ( err) => {
451
- let ( trace, span) = ecx. generate_stacktrace ( None ) ;
452
- let err = ErrKind :: Miri ( err, trace) ;
453
- Err ( ConstEvalErr {
454
- kind : err. into ( ) ,
455
- span,
456
- } )
457
- } ,
458
- }
462
+ result. map_err ( |err| {
463
+ let ( trace, span) = ecx. generate_stacktrace ( None ) ;
464
+ let err = ErrKind :: Miri ( err, trace) ;
465
+ ConstEvalErr {
466
+ kind : err. into ( ) ,
467
+ span,
468
+ }
469
+ } )
459
470
}
460
471
461
472
pub fn const_variant_index < ' a , ' tcx > (
@@ -541,7 +552,7 @@ pub fn const_eval_provider<'a, 'tcx>(
541
552
542
553
let ( res, ecx) = eval_body_and_ecx ( tcx, cid, None , key. param_env ) ;
543
554
res. map ( |( val, _, miri_ty) | {
544
- value_to_const_value ( tcx , val, miri_ty)
555
+ value_to_const_value ( & ecx , val, miri_ty)
545
556
} ) . map_err ( |mut err| {
546
557
if tcx. is_static ( def_id) . is_some ( ) {
547
558
ecx. report ( & mut err, true , None ) ;
0 commit comments