From ad7179d2a409faaf45465862f44efe7f989cd71e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 23 May 2020 17:24:33 +0200 Subject: [PATCH] fix discriminant_ty for non-enums --- src/librustc_middle/mir/tcx.rs | 4 +--- src/librustc_middle/ty/mod.rs | 5 +++++ src/librustc_middle/ty/sty.rs | 13 +++++++++---- src/librustc_mir/interpret/operand.rs | 4 ++-- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/librustc_middle/mir/tcx.rs b/src/librustc_middle/mir/tcx.rs index 174da7db1753d..3e172bd8d2a76 100644 --- a/src/librustc_middle/mir/tcx.rs +++ b/src/librustc_middle/mir/tcx.rs @@ -173,9 +173,7 @@ impl<'tcx> Rvalue<'tcx> { tcx.intern_tup(&[ty, tcx.types.bool]) } Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx), - Rvalue::Discriminant(ref place) => { - place.ty(local_decls, tcx).ty.discriminant_type(tcx) - } + Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t), Rvalue::NullaryOp(NullOp::SizeOf, _) => tcx.types.usize, Rvalue::Aggregate(ref ak, ref ops) => match **ak { diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index aad3c6889c3ce..4d050a7b48eac 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -2040,6 +2040,8 @@ impl ReprOptions { self.flags.contains(ReprFlags::HIDE_NICHE) } + /// Returns the discriminant type, given these `repr` options. + /// This must only be called on enums! pub fn discr_type(&self) -> attr::IntType { self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize)) } @@ -2272,6 +2274,7 @@ impl<'tcx> AdtDef { #[inline] pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option> { + assert!(self.is_enum()); let param_env = tcx.param_env(expr_did); let repr_type = self.repr.discr_type(); match tcx.const_eval_poly(expr_did) { @@ -2308,6 +2311,7 @@ impl<'tcx> AdtDef { &'tcx self, tcx: TyCtxt<'tcx>, ) -> impl Iterator)> + Captures<'tcx> { + assert!(self.is_enum()); let repr_type = self.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx); let mut prev_discr = None::>; @@ -2340,6 +2344,7 @@ impl<'tcx> AdtDef { tcx: TyCtxt<'tcx>, variant_index: VariantIdx, ) -> Discr<'tcx> { + assert!(self.is_enum()); let (val, offset) = self.discriminant_def_for_variant(variant_index); let explicit_value = val .and_then(|expr_did| self.eval_explicit_discr(tcx, expr_did)) diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 6cee224219b63..aacca710dd037 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -2097,7 +2097,9 @@ impl<'tcx> TyS<'tcx> { variant_index: VariantIdx, ) -> Option> { match self.kind { - TyKind::Adt(adt, _) => Some(adt.discriminant_for_variant(tcx, variant_index)), + TyKind::Adt(adt, _) if adt.is_enum() => { + Some(adt.discriminant_for_variant(tcx, variant_index)) + } TyKind::Generator(def_id, substs, _) => { Some(substs.as_generator().discriminant_for_variant(def_id, tcx, variant_index)) } @@ -2106,11 +2108,14 @@ impl<'tcx> TyS<'tcx> { } /// Returns the type of the discriminant of this type. - pub fn discriminant_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + pub fn discriminant_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self.kind { - ty::Adt(adt_def, _) => adt_def.repr.discr_type().to_ty(tcx), + ty::Adt(adt, _) if adt.is_enum() => adt.repr.discr_type().to_ty(tcx), ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx), - _ => bug!("{:?} does not have a discriminant", self), + _ => { + // This can only be `0`, for now, so `u8` will suffice. + tcx.types.u8 + } } } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 139871310fbf3..f546f6236d777 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -581,10 +581,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("read_discriminant_value {:#?}", op.layout); // Get type and layout of the discriminant. - let discr_layout = self.layout_of(op.layout.ty.discriminant_type(*self.tcx))?; + let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?; trace!("discriminant type: {:?}", discr_layout.ty); - // We use "discriminant" to refer to the value associated with a particualr enum variant. + // We use "discriminant" to refer to the value associated with a particular enum variant. // This is not to be confused with its "variant index", which is just determining its position in the // declared list of variants -- they can differ with explicitly assigned discriminants. // We use "tag" to refer to how the discriminant is encoded in memory, which can be either