about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-11-01 14:12:27 +0530
committerGitHub <noreply@github.com>2022-11-01 14:12:27 +0530
commit09f4f7c8f0b0e11c7bdf35e73bb22f90e58b1ca4 (patch)
tree1264259b24a4d004526b5c57b1330388d2d94933
parent20528baac4f676c8cbc969ab390e12d8039711aa (diff)
parentabc1ad71062dd8e2b7ae97ada736f2d0c0b2344e (diff)
downloadrust-09f4f7c8f0b0e11c7bdf35e73bb22f90e58b1ca4.tar.gz
rust-09f4f7c8f0b0e11c7bdf35e73bb22f90e58b1ca4.zip
Rollup merge of #103759 - cjgillot:adt-collect, r=davidtwco
Use `adt_def` during type collection.

This removes a wrapper which is close to what `adt_def` does.
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs121
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs107
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs43
-rw-r--r--src/test/ui/error-codes/E0081.stderr6
4 files changed, 113 insertions, 164 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index b70ac02058d..133bbd52b91 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -6,7 +6,7 @@ use super::*;
 use rustc_attr as attr;
 use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{ItemKind, Node, PathSegment};
@@ -75,7 +75,7 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         check_simd(tcx, span, def_id);
     }
 
-    check_transparent(tcx, span, def);
+    check_transparent(tcx, def);
     check_packed(tcx, span, def);
 }
 
@@ -83,7 +83,7 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let def = tcx.adt_def(def_id);
     let span = tcx.def_span(def_id);
     def.destructor(tcx); // force the destructor to be evaluated
-    check_transparent(tcx, span, def);
+    check_transparent(tcx, def);
     check_union_fields(tcx, span, def_id);
     check_packed(tcx, span, def);
 }
@@ -506,11 +506,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
             tcx.ensure().typeck(id.owner_id.def_id);
         }
         DefKind::Enum => {
-            let item = tcx.hir().item(id);
-            let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else {
-                return;
-            };
-            check_enum(tcx, &enum_definition.variants, item.owner_id.def_id);
+            check_enum(tcx, id.owner_id.def_id);
         }
         DefKind::Fn => {} // entirely within check_item_body
         DefKind::Impl => {
@@ -1026,7 +1022,7 @@ pub(super) fn check_packed_inner(
     None
 }
 
-pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtDef<'tcx>) {
+pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) {
     if !adt.repr().transparent() {
         return;
     }
@@ -1035,14 +1031,14 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
         feature_err(
             &tcx.sess.parse_sess,
             sym::transparent_unions,
-            sp,
+            tcx.def_span(adt.did()),
             "transparent unions are unstable",
         )
         .emit();
     }
 
     if adt.variants().len() != 1 {
-        bad_variant_count(tcx, adt, sp, adt.did());
+        bad_variant_count(tcx, adt, tcx.def_span(adt.did()), adt.did());
         if adt.variants().is_empty() {
             // Don't bother checking the fields. No variants (and thus no fields) exist.
             return;
@@ -1103,7 +1099,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
         .filter_map(|(span, zst, _align1, _non_exhaustive)| if !zst { Some(span) } else { None });
     let non_zst_count = non_zst_fields.clone().count();
     if non_zst_count >= 2 {
-        bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp);
+        bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, tcx.def_span(adt.did()));
     }
     let incompatible_zst_fields =
         field_infos.clone().filter(|(_, _, _, opt)| opt.is_some()).count();
@@ -1143,12 +1139,11 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
 }
 
 #[allow(trivial_numeric_casts)]
-fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: LocalDefId) {
+fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
     let def = tcx.adt_def(def_id);
-    let sp = tcx.def_span(def_id);
     def.destructor(tcx); // force the destructor to be evaluated
 
-    if vs.is_empty() {
+    if def.variants().is_empty() {
         if let Some(attr) = tcx.get_attrs(def_id.to_def_id(), sym::repr).next() {
             struct_span_err!(
                 tcx.sess,
@@ -1156,7 +1151,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
                 E0084,
                 "unsupported representation for zero-variant enum"
             )
-            .span_label(sp, "zero-variant enum")
+            .span_label(tcx.def_span(def_id), "zero-variant enum")
             .emit();
         }
     }
@@ -1167,88 +1162,96 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
             feature_err(
                 &tcx.sess.parse_sess,
                 sym::repr128,
-                sp,
+                tcx.def_span(def_id),
                 "repr with 128-bit type is unstable",
             )
             .emit();
         }
     }
 
-    for v in vs {
-        if let Some(ref e) = v.disr_expr {
-            tcx.ensure().typeck(tcx.hir().local_def_id(e.hir_id));
+    for v in def.variants() {
+        if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr {
+            tcx.ensure().typeck(discr_def_id.expect_local());
         }
     }
 
-    if tcx.adt_def(def_id).repr().int.is_none() {
-        let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
+    if def.repr().int.is_none() {
+        let is_unit = |var: &ty::VariantDef| matches!(var.ctor_kind, CtorKind::Const);
+        let has_disr = |var: &ty::VariantDef| matches!(var.discr, ty::VariantDiscr::Explicit(_));
 
-        let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
-        let has_non_units = vs.iter().any(|var| !is_unit(var));
-        let disr_units = vs.iter().any(|var| is_unit(&var) && has_disr(&var));
-        let disr_non_unit = vs.iter().any(|var| !is_unit(&var) && has_disr(&var));
+        let has_non_units = def.variants().iter().any(|var| !is_unit(var));
+        let disr_units = def.variants().iter().any(|var| is_unit(&var) && has_disr(&var));
+        let disr_non_unit = def.variants().iter().any(|var| !is_unit(&var) && has_disr(&var));
 
         if disr_non_unit || (disr_units && has_non_units) {
-            let mut err =
-                struct_span_err!(tcx.sess, sp, E0732, "`#[repr(inttype)]` must be specified");
+            let mut err = struct_span_err!(
+                tcx.sess,
+                tcx.def_span(def_id),
+                E0732,
+                "`#[repr(inttype)]` must be specified"
+            );
             err.emit();
         }
     }
 
-    detect_discriminant_duplicate(tcx, def.discriminants(tcx).collect(), vs, sp);
-
-    check_transparent(tcx, sp, def);
+    detect_discriminant_duplicate(tcx, def);
+    check_transparent(tcx, def);
 }
 
 /// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal
-fn detect_discriminant_duplicate<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    mut discrs: Vec<(VariantIdx, Discr<'tcx>)>,
-    vs: &'tcx [hir::Variant<'tcx>],
-    self_span: Span,
-) {
+fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) {
     // Helper closure to reduce duplicate code. This gets called everytime we detect a duplicate.
     // Here `idx` refers to the order of which the discriminant appears, and its index in `vs`
-    let report = |dis: Discr<'tcx>, idx: usize, err: &mut Diagnostic| {
-        let var = &vs[idx]; // HIR for the duplicate discriminant
-        let (span, display_discr) = match var.disr_expr {
-            Some(ref expr) => {
+    let report = |dis: Discr<'tcx>, idx, err: &mut Diagnostic| {
+        let var = adt.variant(idx); // HIR for the duplicate discriminant
+        let (span, display_discr) = match var.discr {
+            ty::VariantDiscr::Explicit(discr_def_id) => {
                 // In the case the discriminant is both a duplicate and overflowed, let the user know
-                if let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind
+                if let hir::Node::AnonConst(expr) = tcx.hir().get_by_def_id(discr_def_id.expect_local())
+                    && let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind
                     && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
                     && *lit_value != dis.val
                 {
-                    (tcx.hir().span(expr.hir_id), format!("`{dis}` (overflowed from `{lit_value}`)"))
-                // Otherwise, format the value as-is
+                    (tcx.def_span(discr_def_id), format!("`{dis}` (overflowed from `{lit_value}`)"))
                 } else {
-                    (tcx.hir().span(expr.hir_id), format!("`{dis}`"))
+                    // Otherwise, format the value as-is
+                    (tcx.def_span(discr_def_id), format!("`{dis}`"))
                 }
             }
-            None => {
+            // This should not happen.
+            ty::VariantDiscr::Relative(0) => (tcx.def_span(var.def_id), format!("`{dis}`")),
+            ty::VariantDiscr::Relative(distance_to_explicit) => {
                 // At this point we know this discriminant is a duplicate, and was not explicitly
                 // assigned by the user. Here we iterate backwards to fetch the HIR for the last
                 // explicitly assigned discriminant, and letting the user know that this was the
                 // increment startpoint, and how many steps from there leading to the duplicate
-                if let Some((n, hir::Variant { span, ident, .. })) =
-                    vs[..idx].iter().rev().enumerate().find(|v| v.1.disr_expr.is_some())
+                if let Some(explicit_idx) =
+                    idx.as_u32().checked_sub(distance_to_explicit).map(VariantIdx::from_u32)
                 {
-                    let ve_ident = var.ident;
-                    let n = n + 1;
-                    let sp = if n > 1 { "variants" } else { "variant" };
+                    let explicit_variant = adt.variant(explicit_idx);
+                    let ve_ident = var.name;
+                    let ex_ident = explicit_variant.name;
+                    let sp = if distance_to_explicit > 1 { "variants" } else { "variant" };
 
                     err.span_label(
-                        *span,
-                        format!("discriminant for `{ve_ident}` incremented from this startpoint (`{ident}` + {n} {sp} later => `{ve_ident}` = {dis})"),
+                        tcx.def_span(explicit_variant.def_id),
+                        format!(
+                            "discriminant for `{ve_ident}` incremented from this startpoint \
+                            (`{ex_ident}` + {distance_to_explicit} {sp} later \
+                             => `{ve_ident}` = {dis})"
+                        ),
                     );
                 }
 
-                (vs[idx].span, format!("`{dis}`"))
+                (tcx.def_span(var.def_id), format!("`{dis}`"))
             }
         };
 
         err.span_label(span, format!("{display_discr} assigned here"));
     };
 
+    let mut discrs = adt.discriminants(tcx).collect::<Vec<_>>();
+
     // Here we loop through the discriminants, comparing each discriminant to another.
     // When a duplicate is detected, we instantiate an error and point to both
     // initial and duplicate value. The duplicate discriminant is then discarded by swapping
@@ -1257,29 +1260,29 @@ fn detect_discriminant_duplicate<'tcx>(
     // style as we are mutating `discrs` on the fly).
     let mut i = 0;
     while i < discrs.len() {
-        let hir_var_i_idx = discrs[i].0.index();
+        let var_i_idx = discrs[i].0;
         let mut error: Option<DiagnosticBuilder<'_, _>> = None;
 
         let mut o = i + 1;
         while o < discrs.len() {
-            let hir_var_o_idx = discrs[o].0.index();
+            let var_o_idx = discrs[o].0;
 
             if discrs[i].1.val == discrs[o].1.val {
                 let err = error.get_or_insert_with(|| {
                     let mut ret = struct_span_err!(
                         tcx.sess,
-                        self_span,
+                        tcx.def_span(adt.did()),
                         E0081,
                         "discriminant value `{}` assigned more than once",
                         discrs[i].1,
                     );
 
-                    report(discrs[i].1, hir_var_i_idx, &mut ret);
+                    report(discrs[i].1, var_i_idx, &mut ret);
 
                     ret
                 });
 
-                report(discrs[o].1, hir_var_o_idx, err);
+                report(discrs[o].1, var_o_idx, err);
 
                 // Safe to unwrap here, as we wouldn't reach this point if `discrs` was empty
                 discrs[o] = *discrs.last().unwrap();
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index a2357500465..99d0beacfa0 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -218,19 +218,16 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
         hir::ItemKind::Const(ty, ..) => {
             check_item_type(tcx, def_id, ty.span, false);
         }
-        hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
-            check_type_defn(tcx, item, false, |wfcx| vec![wfcx.non_enum_variant(struct_def)]);
-
+        hir::ItemKind::Struct(_, ref ast_generics) => {
+            check_type_defn(tcx, item, false);
             check_variances_for_type_defn(tcx, item, ast_generics);
         }
-        hir::ItemKind::Union(ref struct_def, ref ast_generics) => {
-            check_type_defn(tcx, item, true, |wfcx| vec![wfcx.non_enum_variant(struct_def)]);
-
+        hir::ItemKind::Union(_, ref ast_generics) => {
+            check_type_defn(tcx, item, true);
             check_variances_for_type_defn(tcx, item, ast_generics);
         }
-        hir::ItemKind::Enum(ref enum_def, ref ast_generics) => {
-            check_type_defn(tcx, item, true, |wfcx| wfcx.enum_variants(enum_def));
-
+        hir::ItemKind::Enum(_, ref ast_generics) => {
+            check_type_defn(tcx, item, true);
             check_variances_for_type_defn(tcx, item, ast_generics);
         }
         hir::ItemKind::Trait(..) => {
@@ -1037,27 +1034,25 @@ fn item_adt_kind(kind: &ItemKind<'_>) -> Option<AdtKind> {
 }
 
 /// In a type definition, we check that to ensure that the types of the fields are well-formed.
-fn check_type_defn<'tcx, F>(
-    tcx: TyCtxt<'tcx>,
-    item: &hir::Item<'tcx>,
-    all_sized: bool,
-    mut lookup_fields: F,
-) where
-    F: FnMut(&WfCheckingCtxt<'_, 'tcx>) -> Vec<AdtVariant<'tcx>>,
-{
+fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: bool) {
     let _ = tcx.representability(item.owner_id.def_id);
+    let adt_def = tcx.adt_def(item.owner_id);
 
     enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
-        let variants = lookup_fields(wfcx);
-        let packed = tcx.adt_def(item.owner_id).repr().packed();
+        let variants = adt_def.variants();
+        let packed = adt_def.repr().packed();
 
-        for variant in &variants {
+        for variant in variants.iter() {
             // All field types must be well-formed.
             for field in &variant.fields {
+                let field_id = field.did.expect_local();
+                let hir::Node::Field(hir::FieldDef { ty: hir_ty, .. }) = tcx.hir().get_by_def_id(field_id)
+                else { bug!() };
+                let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did));
                 wfcx.register_wf_obligation(
-                    field.span,
-                    Some(WellFormedLoc::Ty(field.def_id)),
-                    field.ty.into(),
+                    hir_ty.span,
+                    Some(WellFormedLoc::Ty(field_id)),
+                    ty.into(),
                 )
             }
 
@@ -1065,7 +1060,7 @@ fn check_type_defn<'tcx, F>(
             // intermediate types must be sized.
             let needs_drop_copy = || {
                 packed && {
-                    let ty = variant.fields.last().unwrap().ty;
+                    let ty = tcx.type_of(variant.fields.last().unwrap().did);
                     let ty = tcx.erase_regions(ty);
                     if ty.needs_infer() {
                         tcx.sess
@@ -1084,27 +1079,31 @@ fn check_type_defn<'tcx, F>(
                 variant.fields[..variant.fields.len() - unsized_len].iter().enumerate()
             {
                 let last = idx == variant.fields.len() - 1;
+                let field_id = field.did.expect_local();
+                let hir::Node::Field(hir::FieldDef { ty: hir_ty, .. }) = tcx.hir().get_by_def_id(field_id)
+                else { bug!() };
+                let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did));
                 wfcx.register_bound(
                     traits::ObligationCause::new(
-                        field.span,
+                        hir_ty.span,
                         wfcx.body_id,
                         traits::FieldSized {
                             adt_kind: match item_adt_kind(&item.kind) {
                                 Some(i) => i,
                                 None => bug!(),
                             },
-                            span: field.span,
+                            span: hir_ty.span,
                             last,
                         },
                     ),
                     wfcx.param_env,
-                    field.ty,
+                    ty,
                     tcx.require_lang_item(LangItem::Sized, None),
                 );
             }
 
             // Explicit `enum` discriminant values must const-evaluate successfully.
-            if let Some(discr_def_id) = variant.explicit_discr {
+            if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {
                 let cause = traits::ObligationCause::new(
                     tcx.def_span(discr_def_id),
                     wfcx.body_id,
@@ -1114,7 +1113,7 @@ fn check_type_defn<'tcx, F>(
                     cause,
                     wfcx.param_env,
                     ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
-                        ty::Const::from_anon_const(tcx, discr_def_id),
+                        ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
                     ))
                     .to_predicate(tcx),
                 ));
@@ -1925,56 +1924,6 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) {
     items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id));
 }
 
-///////////////////////////////////////////////////////////////////////////
-// ADT
-
-// FIXME(eddyb) replace this with getting fields/discriminants through `ty::AdtDef`.
-struct AdtVariant<'tcx> {
-    /// Types of fields in the variant, that must be well-formed.
-    fields: Vec<AdtField<'tcx>>,
-
-    /// Explicit discriminant of this variant (e.g. `A = 123`),
-    /// that must evaluate to a constant value.
-    explicit_discr: Option<LocalDefId>,
-}
-
-struct AdtField<'tcx> {
-    ty: Ty<'tcx>,
-    def_id: LocalDefId,
-    span: Span,
-}
-
-impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> {
-    // FIXME(eddyb) replace this with getting fields through `ty::AdtDef`.
-    fn non_enum_variant(&self, struct_def: &hir::VariantData<'_>) -> AdtVariant<'tcx> {
-        let fields = struct_def
-            .fields()
-            .iter()
-            .map(|field| {
-                let def_id = self.tcx().hir().local_def_id(field.hir_id);
-                let field_ty = self.tcx().type_of(def_id);
-                let field_ty = self.normalize(field.ty.span, None, field_ty);
-                debug!("non_enum_variant: type of field {:?} is {:?}", field, field_ty);
-                AdtField { ty: field_ty, span: field.ty.span, def_id }
-            })
-            .collect();
-        AdtVariant { fields, explicit_discr: None }
-    }
-
-    fn enum_variants(&self, enum_def: &hir::EnumDef<'_>) -> Vec<AdtVariant<'tcx>> {
-        enum_def
-            .variants
-            .iter()
-            .map(|variant| AdtVariant {
-                fields: self.non_enum_variant(&variant.data).fields,
-                explicit_discr: variant
-                    .disr_expr
-                    .map(|explicit_discr| self.tcx().hir().local_def_id(explicit_discr.hir_id)),
-            })
-            .collect()
-    }
-}
-
 fn error_392(
     tcx: TyCtxt<'_>,
     span: Span,
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 65a1d61e87c..46db0f74d4d 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -604,11 +604,11 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
                 }
             }
         }
-        hir::ItemKind::Enum(ref enum_definition, _) => {
+        hir::ItemKind::Enum(..) => {
             tcx.ensure().generics_of(def_id);
             tcx.ensure().type_of(def_id);
             tcx.ensure().predicates_of(def_id);
-            convert_enum_variant_types(tcx, def_id.to_def_id(), enum_definition.variants);
+            convert_enum_variant_types(tcx, def_id.to_def_id());
         }
         hir::ItemKind::Impl { .. } => {
             tcx.ensure().generics_of(def_id);
@@ -640,7 +640,8 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
             }
 
             if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
-                convert_variant_ctor(tcx, ctor_hir_id);
+                let ctor_def_id = tcx.hir().local_def_id(ctor_hir_id);
+                convert_variant_ctor(tcx, ctor_def_id);
             }
         }
 
@@ -750,37 +751,34 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
     }
 }
 
-fn convert_variant_ctor(tcx: TyCtxt<'_>, ctor_id: hir::HirId) {
-    let def_id = tcx.hir().local_def_id(ctor_id);
+fn convert_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     tcx.ensure().generics_of(def_id);
     tcx.ensure().type_of(def_id);
     tcx.ensure().predicates_of(def_id);
 }
 
-fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId, variants: &[hir::Variant<'_>]) {
+fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
     let def = tcx.adt_def(def_id);
     let repr_type = def.repr().discr_type();
     let initial = repr_type.initial_discriminant(tcx);
     let mut prev_discr = None::<Discr<'_>>;
 
     // fill the discriminant values and field types
-    for variant in variants {
+    for variant in def.variants() {
         let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
         prev_discr = Some(
-            if let Some(ref e) = variant.disr_expr {
-                let expr_did = tcx.hir().local_def_id(e.hir_id);
-                def.eval_explicit_discr(tcx, expr_did.to_def_id())
+            if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
+                def.eval_explicit_discr(tcx, const_def_id)
             } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
                 Some(discr)
             } else {
-                struct_span_err!(tcx.sess, variant.span, E0370, "enum discriminant overflowed")
-                    .span_label(
-                        variant.span,
-                        format!("overflowed on value after {}", prev_discr.unwrap()),
-                    )
+                let span = tcx.def_span(variant.def_id);
+                struct_span_err!(tcx.sess, span, E0370, "enum discriminant overflowed")
+                    .span_label(span, format!("overflowed on value after {}", prev_discr.unwrap()))
                     .note(&format!(
                         "explicitly set `{} = {}` if that is desired outcome",
-                        variant.ident, wrapped_discr
+                        tcx.item_name(variant.def_id),
+                        wrapped_discr
                     ))
                     .emit();
                 None
@@ -788,17 +786,16 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId, variants: &[hir::V
             .unwrap_or(wrapped_discr),
         );
 
-        for f in variant.data.fields() {
-            let def_id = tcx.hir().local_def_id(f.hir_id);
-            tcx.ensure().generics_of(def_id);
-            tcx.ensure().type_of(def_id);
-            tcx.ensure().predicates_of(def_id);
+        for f in &variant.fields {
+            tcx.ensure().generics_of(f.did);
+            tcx.ensure().type_of(f.did);
+            tcx.ensure().predicates_of(f.did);
         }
 
         // Convert the ctor, if any. This also registers the variant as
         // an item.
-        if let Some(ctor_hir_id) = variant.data.ctor_hir_id() {
-            convert_variant_ctor(tcx, ctor_hir_id);
+        if let Some(ctor_def_id) = variant.ctor_def_id {
+            convert_variant_ctor(tcx, ctor_def_id.expect_local());
         }
     }
 }
diff --git a/src/test/ui/error-codes/E0081.stderr b/src/test/ui/error-codes/E0081.stderr
index 64562fefc86..d4b21f6893b 100644
--- a/src/test/ui/error-codes/E0081.stderr
+++ b/src/test/ui/error-codes/E0081.stderr
@@ -32,7 +32,7 @@ LL |     First = -1,
    |             -- `-1` assigned here
 LL |
 LL |     Second = -2,
-   |     ----------- discriminant for `Last` incremented from this startpoint (`Second` + 1 variant later => `Last` = -1)
+   |     ------ discriminant for `Last` incremented from this startpoint (`Second` + 1 variant later => `Last` = -1)
 LL |
 LL |     Last,
    |     ---- `-1` assigned here
@@ -53,7 +53,7 @@ LL |     V4 = 0,
    |          - `0` assigned here
 LL |
 LL |     V5 = -2,
-   |     ------- discriminant for `V7` incremented from this startpoint (`V5` + 2 variants later => `V7` = 0)
+   |     -- discriminant for `V7` incremented from this startpoint (`V5` + 2 variants later => `V7` = 0)
 ...
 LL |     V7,
    |     -- `0` assigned here
@@ -68,7 +68,7 @@ LL |     V5 = -2,
    |          -- `-2` assigned here
 ...
 LL |     V8 = -3,
-   |     ------- discriminant for `V9` incremented from this startpoint (`V8` + 1 variant later => `V9` = -2)
+   |     -- discriminant for `V9` incremented from this startpoint (`V8` + 1 variant later => `V9` = -2)
 LL |
 LL |     V9,
    |     -- `-2` assigned here