@@ -7,11 +7,11 @@ use std::fmt::Write;
77use rustc_errors:: ErrorReported ;
88use rustc_hir:: def:: Namespace ;
99use rustc_macros:: HashStable ;
10- use rustc_middle:: ty:: layout:: { IntegerExt , PrimitiveExt , TyAndLayout } ;
10+ use rustc_middle:: ty:: layout:: { PrimitiveExt , TyAndLayout } ;
1111use rustc_middle:: ty:: print:: { FmtPrinter , PrettyPrinter , Printer } ;
1212use rustc_middle:: ty:: Ty ;
1313use 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 } ;
1515use rustc_target:: abi:: { VariantIdx , Variants } ;
1616
1717use super :: {
@@ -576,9 +576,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
576576 /// Read discriminant, return the runtime value as well as the variant index.
577577 pub fn read_discriminant (
578578 & self ,
579- rval : OpTy < ' tcx , M :: PointerTag > ,
579+ op : OpTy < ' tcx , M :: PointerTag > ,
580580 ) -> 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) ;
582586
583587 // We use "discriminant" to refer to the value associated with a particualr enum variant.
584588 // 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> {
587591 // straight-forward (`DiscriminantKind::Tag`) or with a niche (`DiscriminantKind::Niche`).
588592 // Unfortunately, the rest of the compiler calls the latter "discriminant", too, which makes things
589593 // 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 {
591595 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) {
593597 Some ( discr) => {
594598 // This type actually has discriminants.
595- let discr_layout = self . layout_of ( discr. ty ) ? ;
599+ assert_eq ! ( discr. ty, discr_layout . ty ) ;
596600 Scalar :: from_uint ( discr. val , discr_layout. size )
597601 }
598602 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.
600604 assert_eq ! ( index. as_u32( ) , 0 ) ;
601- let discr_layout = self . layout_of ( self . tcx . types . u8 ) ?;
602605 Scalar :: from_uint ( index. as_u32 ( ) , discr_layout. size )
603606 }
604607 } ;
@@ -609,53 +612,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
609612 }
610613 } ;
611614
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
614617 // 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.
621623
622624 // Get layout for tag.
623625 let tag_layout = self . layout_of ( tag_scalar_layout. value . to_int_ty ( * self . tcx ) ) ?;
624626
625627 // 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) ?) ?;
627629 assert_eq ! ( tag_layout. size, tag_val. layout. size) ;
628630 assert_eq ! ( tag_layout. abi. is_signed( ) , tag_val. layout. abi. is_signed( ) ) ;
629631 let tag_val = tag_val. to_scalar ( ) ?;
630632 trace ! ( "tag value: {:?}" , tag_val) ;
631633
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-
647634 // Figure out which discriminant and variant this corresponds to.
648635 Ok ( match * tag_kind {
649636 DiscriminantKind :: Tag => {
650637 let tag_bits = self
651638 . force_bits ( tag_val, tag_layout. size )
652639 . map_err ( |_| err_ub ! ( InvalidDiscriminant ( tag_val. erase_tag( ) ) ) ) ?;
653640 // 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 ) ;
656642 let discr_bits = discr_val_cast. assert_bits ( discr_layout. size ) ;
657643 // 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 {
659645 ty:: Adt ( adt, _) => {
660646 adt. discriminants ( self . tcx . tcx ) . find ( |( _, var) | var. val == discr_bits)
661647 }
@@ -705,7 +691,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
705691 let variant_index = variants_start
706692 . checked_add ( variant_index_relative)
707693 . expect ( "overflow computing absolute variant idx" ) ;
708- let variants_len = rval
694+ let variants_len = op
709695 . layout
710696 . ty
711697 . ty_adt_def ( )
@@ -722,8 +708,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
722708 // Compute the size of the scalar we need to return.
723709 // No need to cast, because the variant index directly serves as discriminant and is
724710 // 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)
727712 }
728713 } )
729714 }
0 commit comments