@@ -589,12 +589,84 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
589
589
// Check to see if this cast is a "coercion cast", where the cast is actually done
590
590
// using a coercion (or is a no-op).
591
591
if let Some ( & TyCastKind :: CoercionCast ) = cx. tables ( )
592
- . cast_kinds ( )
593
- . get ( source. hir_id ) {
592
+ . cast_kinds ( )
593
+ . get ( source. hir_id ) {
594
594
// Convert the lexpr to a vexpr.
595
595
ExprKind :: Use { source : source. to_ref ( ) }
596
596
} 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 }
598
670
}
599
671
}
600
672
hir:: ExprType ( ref source, _) => return source. make_mirror ( cx) ,
0 commit comments