@@ -589,12 +589,84 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
589589 // Check to see if this cast is a "coercion cast", where the cast is actually done
590590 // using a coercion (or is a no-op).
591591 if let Some ( & TyCastKind :: CoercionCast ) = cx. tables ( )
592- . cast_kinds ( )
593- . get ( source. hir_id ) {
592+ . cast_kinds ( )
593+ . get ( source. hir_id ) {
594594 // Convert the lexpr to a vexpr.
595595 ExprKind :: Use { source : source. to_ref ( ) }
596596 } else {
597- ExprKind :: Cast { source : source. to_ref ( ) }
597+ // check whether this is casting an enum variant discriminant
598+ // to prevent cycles, we refer to the discriminant initializer
599+ // which is always an integer and thus doesn't need to know the
600+ // enum's layout (or its tag type) to compute it during const eval
601+ // Example:
602+ // enum Foo {
603+ // A,
604+ // B = A as isize + 4,
605+ // }
606+ // The correct solution would be to add symbolic computations to miri,
607+ // so we wouldn't have to compute and store the actual value
608+ let var = if let hir:: ExprPath ( ref qpath) = source. node {
609+ let def = cx. tables ( ) . qpath_def ( qpath, source. hir_id ) ;
610+ cx
611+ . tables ( )
612+ . node_id_to_type ( source. hir_id )
613+ . ty_adt_def ( )
614+ . and_then ( |adt_def| {
615+ match def {
616+ Def :: VariantCtor ( variant_id, CtorKind :: Const ) => {
617+ let idx = adt_def. variant_index_with_id ( variant_id) ;
618+ let ( d, o) = adt_def. discriminant_def_for_variant ( idx) ;
619+ use rustc:: ty:: util:: IntTypeExt ;
620+ let ty = adt_def. repr . discr_type ( ) . to_ty ( cx. tcx ( ) ) ;
621+ Some ( ( d, o, ty) )
622+ }
623+ _ => None ,
624+ }
625+ } )
626+ } else {
627+ None
628+ } ;
629+ let source = if let Some ( ( did, offset, ty) ) = var {
630+ let mk_const = |val| Expr {
631+ temp_lifetime,
632+ ty,
633+ span : expr. span ,
634+ kind : ExprKind :: Literal {
635+ literal : Literal :: Value {
636+ value : cx. tcx ( ) . mk_const ( ty:: Const {
637+ val,
638+ ty,
639+ } ) ,
640+ } ,
641+ } ,
642+ } . to_ref ( ) ;
643+ let offset = mk_const (
644+ ConstVal :: Value ( Value :: ByVal ( PrimVal :: Bytes ( offset as u128 ) ) ) ,
645+ ) ;
646+ match did {
647+ Some ( did) => {
648+ // in case we are offsetting from a computed discriminant
649+ // and not the beginning of discriminants (which is always `0`)
650+ let substs = Substs :: identity_for_item ( cx. tcx ( ) , did) ;
651+ let lhs = mk_const ( ConstVal :: Unevaluated ( did, substs) ) ;
652+ let bin = ExprKind :: Binary {
653+ op : BinOp :: Add ,
654+ lhs,
655+ rhs : offset,
656+ } ;
657+ Expr {
658+ temp_lifetime,
659+ ty,
660+ span : expr. span ,
661+ kind : bin,
662+ } . to_ref ( )
663+ } ,
664+ None => offset,
665+ }
666+ } else {
667+ source. to_ref ( )
668+ } ;
669+ ExprKind :: Cast { source }
598670 }
599671 }
600672 hir:: ExprType ( ref source, _) => return source. make_mirror ( cx) ,
0 commit comments