@@ -7,11 +7,11 @@ use std::fmt::Write;
7
7
use rustc_errors:: ErrorReported ;
8
8
use rustc_hir:: def:: Namespace ;
9
9
use rustc_macros:: HashStable ;
10
- use rustc_middle:: ty:: layout:: { IntegerExt , PrimitiveExt , TyAndLayout } ;
10
+ use rustc_middle:: ty:: layout:: { PrimitiveExt , TyAndLayout } ;
11
11
use rustc_middle:: ty:: print:: { FmtPrinter , PrettyPrinter , Printer } ;
12
12
use rustc_middle:: ty:: Ty ;
13
13
use rustc_middle:: { mir, ty} ;
14
- use rustc_target:: abi:: { Abi , DiscriminantKind , HasDataLayout , Integer , LayoutOf , Size } ;
14
+ use rustc_target:: abi:: { Abi , DiscriminantKind , HasDataLayout , LayoutOf , Size } ;
15
15
use rustc_target:: abi:: { VariantIdx , Variants } ;
16
16
17
17
use super :: {
@@ -576,9 +576,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
576
576
/// Read discriminant, return the runtime value as well as the variant index.
577
577
pub fn read_discriminant (
578
578
& self ,
579
- rval : OpTy < ' tcx , M :: PointerTag > ,
579
+ op : OpTy < ' tcx , M :: PointerTag > ,
580
580
) -> InterpResult < ' tcx , ( Scalar < M :: PointerTag > , VariantIdx ) > {
581
- trace ! ( "read_discriminant_value {:#?}" , rval. layout) ;
581
+ trace ! ( "read_discriminant_value {:#?}" , op. layout) ;
582
+
583
+ // Get type and layout of the discriminant.
584
+ let discr_layout = self . layout_of ( op. layout . ty . discriminant_type ( * self . tcx ) ) ?;
585
+ trace ! ( "discriminant type: {:?}" , discr_layout. ty) ;
582
586
583
587
// We use "discriminant" to refer to the value associated with a particualr enum variant.
584
588
// This is not to be confused with its "variant index", which is just determining its position in the
@@ -587,18 +591,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
587
591
// straight-forward (`DiscriminantKind::Tag`) or with a niche (`DiscriminantKind::Niche`).
588
592
// Unfortunately, the rest of the compiler calls the latter "discriminant", too, which makes things
589
593
// rather confusing.
590
- let ( tag_scalar_layout, tag_kind, tag_index) = match rval . layout . variants {
594
+ let ( tag_scalar_layout, tag_kind, tag_index) = match op . layout . variants {
591
595
Variants :: Single { index } => {
592
- let discr = match rval . layout . ty . discriminant_for_variant ( * self . tcx , index) {
596
+ let discr = match op . layout . ty . discriminant_for_variant ( * self . tcx , index) {
593
597
Some ( discr) => {
594
598
// This type actually has discriminants.
595
- let discr_layout = self . layout_of ( discr. ty ) ? ;
599
+ assert_eq ! ( discr. ty, discr_layout . ty ) ;
596
600
Scalar :: from_uint ( discr. val , discr_layout. size )
597
601
}
598
602
None => {
599
- // On a type without actual discriminants, variant is 0. Return variant idx as `u8`.
603
+ // On a type without actual discriminants, variant is 0.
600
604
assert_eq ! ( index. as_u32( ) , 0 ) ;
601
- let discr_layout = self . layout_of ( self . tcx . types . u8 ) ?;
602
605
Scalar :: from_uint ( index. as_u32 ( ) , discr_layout. size )
603
606
}
604
607
} ;
@@ -609,53 +612,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
609
612
}
610
613
} ;
611
614
612
- // There are *three* types/ layouts that come into play here:
613
- // - The discriminant has a type for typechecking. This is `discr_ty `, and is used for
615
+ // There are *three* layouts that come into play here:
616
+ // - The discriminant has a type for typechecking. This is `discr_layout `, and is used for
614
617
// the `Scalar` we return.
615
- // - The discriminant gets encoded as a tag/niche, with layout `tag_layout`.
616
- // This is always an integer, and used to interpret the value we read from the
617
- // tag field. For the return value, a cast to `discr_ty` is performed.
618
- // - The field storing the tag has a layout, which is very similar to
619
- // `tag_layout` but may be a pointer. This is `tag_val.layout`;
620
- // we just use it for sanity checks.
618
+ // - The tag (encoded discriminant) has layout `tag_layout`. This is always an integer type,
619
+ // and used to interpret the value we read from the tag field.
620
+ // For the return value, a cast to `discr_layout` is performed.
621
+ // - The field storing the tag has a layout, which is very similar to `tag_layout` but
622
+ // may be a pointer. This is `tag_val.layout`; we just use it for sanity checks.
621
623
622
624
// Get layout for tag.
623
625
let tag_layout = self . layout_of ( tag_scalar_layout. value . to_int_ty ( * self . tcx ) ) ?;
624
626
625
627
// Read tag and sanity-check `tag_layout`.
626
- let tag_val = self . read_immediate ( self . operand_field ( rval , tag_index) ?) ?;
628
+ let tag_val = self . read_immediate ( self . operand_field ( op , tag_index) ?) ?;
627
629
assert_eq ! ( tag_layout. size, tag_val. layout. size) ;
628
630
assert_eq ! ( tag_layout. abi. is_signed( ) , tag_val. layout. abi. is_signed( ) ) ;
629
631
let tag_val = tag_val. to_scalar ( ) ?;
630
632
trace ! ( "tag value: {:?}" , tag_val) ;
631
633
632
- // Get type used by typechecking.
633
- let discr_ty = match rval. layout . ty . kind {
634
- ty:: Adt ( adt, _) => {
635
- let discr_int_ty = Integer :: from_attr ( self , adt. repr . discr_type ( ) ) ;
636
- // The signedness of tag and discriminant is the same.
637
- discr_int_ty. to_ty ( * self . tcx , tag_layout. abi . is_signed ( ) )
638
- }
639
- ty:: Generator ( _, substs, _) => {
640
- let substs = substs. as_generator ( ) ;
641
- substs. discr_ty ( * self . tcx )
642
- }
643
- _ => bug ! ( "multiple variants for non-adt non-generator" ) ,
644
- } ;
645
- trace ! ( "discriminant type: {:?}" , discr_ty) ;
646
-
647
634
// Figure out which discriminant and variant this corresponds to.
648
635
Ok ( match * tag_kind {
649
636
DiscriminantKind :: Tag => {
650
637
let tag_bits = self
651
638
. force_bits ( tag_val, tag_layout. size )
652
639
. map_err ( |_| err_ub ! ( InvalidDiscriminant ( tag_val. erase_tag( ) ) ) ) ?;
653
640
// Cast bits from tag layout to discriminant layout.
654
- let discr_layout = self . layout_of ( discr_ty) ?;
655
- let discr_val_cast = self . cast_from_scalar ( tag_bits, tag_layout, discr_ty) ;
641
+ let discr_val_cast = self . cast_from_scalar ( tag_bits, tag_layout, discr_layout. ty ) ;
656
642
let discr_bits = discr_val_cast. assert_bits ( discr_layout. size ) ;
657
643
// Convert discriminant to variant index, and catch invalid discriminants.
658
- let index = match rval . layout . ty . kind {
644
+ let index = match op . layout . ty . kind {
659
645
ty:: Adt ( adt, _) => {
660
646
adt. discriminants ( self . tcx . tcx ) . find ( |( _, var) | var. val == discr_bits)
661
647
}
@@ -705,7 +691,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
705
691
let variant_index = variants_start
706
692
. checked_add ( variant_index_relative)
707
693
. expect ( "overflow computing absolute variant idx" ) ;
708
- let variants_len = rval
694
+ let variants_len = op
709
695
. layout
710
696
. ty
711
697
. ty_adt_def ( )
@@ -722,8 +708,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
722
708
// Compute the size of the scalar we need to return.
723
709
// No need to cast, because the variant index directly serves as discriminant and is
724
710
// encoded in the tag.
725
- let size = self . layout_of ( discr_ty) ?. size ;
726
- ( Scalar :: from_uint ( variant. as_u32 ( ) , size) , variant)
711
+ ( Scalar :: from_uint ( variant. as_u32 ( ) , discr_layout. size ) , variant)
727
712
}
728
713
} )
729
714
}
0 commit comments