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