@@ -93,50 +93,69 @@ pub fn eval_body<'a, 'tcx>(
9393 }
9494}
9595
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 ,
9999 ty : Ty < ' tcx > ,
100100) -> & ' 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+ }
102108
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 ( ) ;
109110
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) ) ;
117116 }
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+ }
123125 }
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+ }
136132 }
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+ }
140159}
141160
142161fn eval_body_and_ecx < ' a , ' mir , ' tcx > (
@@ -423,7 +442,7 @@ pub fn const_val_field<'a, 'tcx>(
423442 let mut ecx = mk_eval_cx ( tcx, instance, param_env) . unwrap ( ) ;
424443 let result = ( || {
425444 let value = ecx. const_value_to_value ( value, ty) ?;
426- let ( mut field, ty) = match value {
445+ let ( field, ty) = match value {
427446 Value :: ByValPair ( ..) | Value :: ByVal ( _) =>
428447 ecx. read_field ( value, variant, field, ty) ?. expect ( "const_val_field on non-field" ) ,
429448 Value :: ByRef ( ptr, align) => {
@@ -438,24 +457,16 @@ pub fn const_val_field<'a, 'tcx>(
438457 ( Value :: ByRef ( ptr, align) , layout. ty )
439458 }
440459 } ;
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) )
447461 } ) ( ) ;
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+ } )
459470}
460471
461472pub fn const_variant_index < ' a , ' tcx > (
@@ -541,7 +552,7 @@ pub fn const_eval_provider<'a, 'tcx>(
541552
542553 let ( res, ecx) = eval_body_and_ecx ( tcx, cid, None , key. param_env ) ;
543554 res. map ( |( val, _, miri_ty) | {
544- value_to_const_value ( tcx , val, miri_ty)
555+ value_to_const_value ( & ecx , val, miri_ty)
545556 } ) . map_err ( |mut err| {
546557 if tcx. is_static ( def_id) . is_some ( ) {
547558 ecx. report ( & mut err, true , None ) ;
0 commit comments