about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-03-31 19:19:50 +0200
committerGitHub <noreply@github.com>2019-03-31 19:19:50 +0200
commit0171fe55986abd7e9ac33839db1676fd3ed6c03a (patch)
tree55e75e3988fd19867ef0b73c980add642145605b
parent245a0afb52d18e906c1f042165559c57261e754a (diff)
parent5b7f4e9e2106f5e83fc650e8185d59a57e27ad09 (diff)
downloadrust-0171fe55986abd7e9ac33839db1676fd3ed6c03a.tar.gz
rust-0171fe55986abd7e9ac33839db1676fd3ed6c03a.zip
Rollup merge of #59519 - eddyb:layout-variants-refactor, r=oli-obk
rustc_target: factor out common fields of non-Single Variants.

@tmandry and I were discussing ways to generalize the current variants/discriminant layout to allow more fields in the "`enum`" (or another multi-variant types, such as potentially generator state, in the future), shared by all variants, than just the tag/niche discriminant.

This refactor should make it easier to extend multi-variant layouts, as nothing is duplicating anymore between "tagged enums" and "niche-filling enums".

r? @oli-obk
-rw-r--r--src/librustc/ty/layout.rs57
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs68
-rw-r--r--src/librustc_codegen_llvm/type_of.rs8
-rw-r--r--src/librustc_codegen_ssa/mir/place.rs36
-rw-r--r--src/librustc_codegen_ssa/mir/rvalue.rs3
-rw-r--r--src/librustc_lint/types.rs87
-rw-r--r--src/librustc_mir/interpret/cast.rs3
-rw-r--r--src/librustc_mir/interpret/operand.rs16
-rw-r--r--src/librustc_mir/interpret/place.rs18
-rw-r--r--src/librustc_mir/interpret/visitor.rs3
-rw-r--r--src/librustc_target/abi/call/x86_64.rs3
-rw-r--r--src/librustc_target/abi/mod.rs25
12 files changed, 193 insertions, 134 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 7d2b21b9aec..e01b50113b9 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -913,11 +913,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                             }
 
                             return Ok(tcx.intern_layout(LayoutDetails {
-                                variants: Variants::NicheFilling {
-                                    dataful_variant: i,
-                                    niche_variants,
-                                    niche: niche_scalar,
-                                    niche_start,
+                                variants: Variants::Multiple {
+                                    discr: niche_scalar,
+                                    discr_kind: DiscriminantKind::Niche {
+                                        dataful_variant: i,
+                                        niche_variants,
+                                        niche_start,
+                                    },
                                     variants: st,
                                 },
                                 fields: FieldPlacement::Arbitrary {
@@ -1137,8 +1139,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 }
 
                 tcx.intern_layout(LayoutDetails {
-                    variants: Variants::Tagged {
-                        tag,
+                    variants: Variants::Multiple {
+                        discr: tag,
+                        discr_kind: DiscriminantKind::Tag,
                         variants: layout_variants,
                     },
                     fields: FieldPlacement::Arbitrary {
@@ -1293,8 +1296,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                 }
             }
 
-            Variants::NicheFilling { .. } |
-            Variants::Tagged { .. } => {
+            Variants::Multiple { ref discr, ref discr_kind, .. } => {
                 debug!("print-type-size `{:#?}` adt general variants def {}",
                        layout.ty, adt_def.variants.len());
                 let variant_infos: Vec<_> =
@@ -1306,8 +1308,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                                            layout.for_variant(self, i))
                     })
                     .collect();
-                record(adt_kind.into(), adt_packed, match layout.variants {
-                    Variants::Tagged { ref tag, .. } => Some(tag.value.size(self)),
+                record(adt_kind.into(), adt_packed, match discr_kind {
+                    DiscriminantKind::Tag => Some(discr.value.size(self)),
                     _ => None
                 }, variant_infos);
             }
@@ -1627,8 +1629,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
                 })
             }
 
-            Variants::NicheFilling { ref variants, .. } |
-            Variants::Tagged { ref variants, .. } => {
+            Variants::Multiple { ref variants, .. } => {
                 &variants[variant_index]
             }
         };
@@ -1735,8 +1736,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
                     }
 
                     // Discriminant field for enums (where applicable).
-                    Variants::Tagged { tag: ref discr, .. } |
-                    Variants::NicheFilling { niche: ref discr, .. } => {
+                    Variants::Multiple { ref discr, .. } => {
                         assert_eq!(i, 0);
                         let layout = LayoutDetails::scalar(cx, discr.clone());
                         return MaybeResult::from_ok(TyLayout {
@@ -1881,26 +1881,37 @@ impl<'a> HashStable<StableHashingContext<'a>> for Variants {
             Single { index } => {
                 index.hash_stable(hcx, hasher);
             }
-            Tagged {
-                ref tag,
+            Multiple {
+                ref discr,
+                ref discr_kind,
                 ref variants,
             } => {
-                tag.hash_stable(hcx, hasher);
+                discr.hash_stable(hcx, hasher);
+                discr_kind.hash_stable(hcx, hasher);
                 variants.hash_stable(hcx, hasher);
             }
-            NicheFilling {
+        }
+    }
+}
+
+impl<'a> HashStable<StableHashingContext<'a>> for DiscriminantKind {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        use crate::ty::layout::DiscriminantKind::*;
+        mem::discriminant(self).hash_stable(hcx, hasher);
+
+        match *self {
+            Tag => {}
+            Niche {
                 dataful_variant,
                 ref niche_variants,
-                ref niche,
                 niche_start,
-                ref variants,
             } => {
                 dataful_variant.hash_stable(hcx, hasher);
                 niche_variants.start().hash_stable(hcx, hasher);
                 niche_variants.end().hash_stable(hcx, hasher);
-                niche.hash_stable(hcx, hasher);
                 niche_start.hash_stable(hcx, hasher);
-                variants.hash_stable(hcx, hasher);
             }
         }
     }
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index e50839cd598..e549b120da9 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -1246,7 +1246,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                     }
                 ]
             }
-            layout::Variants::Tagged { ref variants, .. } => {
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Tag,
+                ref variants,
+                ..
+            } => {
                 let discriminant_info = if fallback {
                     RegularDiscriminant(self.discriminant_type_metadata
                                         .expect(""))
@@ -1288,12 +1292,14 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                     }
                 }).collect()
             }
-            layout::Variants::NicheFilling {
-                ref niche_variants,
-                niche_start,
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Niche {
+                    ref niche_variants,
+                    niche_start,
+                    dataful_variant,
+                },
+                ref discr,
                 ref variants,
-                dataful_variant,
-                ref niche,
             } => {
                 if fallback {
                     let variant = self.layout.for_variant(cx, dataful_variant);
@@ -1380,7 +1386,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                             let value = (i.as_u32() as u128)
                                 .wrapping_sub(niche_variants.start().as_u32() as u128)
                                 .wrapping_add(niche_start);
-                            let value = truncate(value, niche.value.size(cx));
+                            let value = truncate(value, discr.value.size(cx));
+                            // NOTE(eddyb) do *NOT* remove this assert, until
+                            // we pass the full 128-bit value to LLVM, otherwise
+                            // truncation will be silent and remain undetected.
+                            assert_eq!(value as u64 as u128, value);
                             Some(value as u64)
                         };
 
@@ -1597,8 +1607,11 @@ fn prepare_enum_metadata(
     let layout = cx.layout_of(enum_type);
 
     match (&layout.abi, &layout.variants) {
-        (&layout::Abi::Scalar(_), &layout::Variants::Tagged {ref tag, .. }) =>
-            return FinalMetadata(discriminant_type_metadata(tag.value)),
+        (&layout::Abi::Scalar(_), &layout::Variants::Multiple {
+            discr_kind: layout::DiscriminantKind::Tag,
+            ref discr,
+            ..
+        }) => return FinalMetadata(discriminant_type_metadata(discr.value)),
         _ => {}
     }
 
@@ -1610,9 +1623,16 @@ fn prepare_enum_metadata(
     if use_enum_fallback(cx) {
         let discriminant_type_metadata = match layout.variants {
             layout::Variants::Single { .. } |
-            layout::Variants::NicheFilling { .. } => None,
-            layout::Variants::Tagged { ref tag, .. } => {
-                Some(discriminant_type_metadata(tag.value))
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Niche { .. },
+                ..
+            } => None,
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Tag,
+                ref discr,
+                ..
+            } => {
+                Some(discriminant_type_metadata(discr.value))
             }
         };
 
@@ -1647,16 +1667,20 @@ fn prepare_enum_metadata(
         );
     }
 
-    let discriminator_metadata = match &layout.variants {
+    let discriminator_metadata = match layout.variants {
         // A single-variant enum has no discriminant.
-        &layout::Variants::Single { .. } => None,
+        layout::Variants::Single { .. } => None,
 
-        &layout::Variants::NicheFilling { ref niche, .. } => {
+        layout::Variants::Multiple {
+            discr_kind: layout::DiscriminantKind::Niche { .. },
+            ref discr,
+            ..
+        } => {
             // Find the integer type of the correct size.
-            let size = niche.value.size(cx);
-            let align = niche.value.align(cx);
+            let size = discr.value.size(cx);
+            let align = discr.value.align(cx);
 
-            let discr_type = match niche.value {
+            let discr_type = match discr.value {
                 layout::Int(t, _) => t,
                 layout::Float(layout::FloatTy::F32) => Integer::I32,
                 layout::Float(layout::FloatTy::F64) => Integer::I64,
@@ -1679,8 +1703,12 @@ fn prepare_enum_metadata(
             }
         },
 
-        &layout::Variants::Tagged { ref tag, .. } => {
-            let discr_type = tag.value.to_ty(cx.tcx);
+        layout::Variants::Multiple {
+            discr_kind: layout::DiscriminantKind::Tag,
+            ref discr,
+            ..
+        } => {
+            let discr_type = discr.value.to_ty(cx.tcx);
             let (size, align) = cx.size_and_align_of(discr_type);
 
             let discr_metadata = basic_type_metadata(cx, discr_type);
diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs
index fb5624d5607..020447608ee 100644
--- a/src/librustc_codegen_llvm/type_of.rs
+++ b/src/librustc_codegen_llvm/type_of.rs
@@ -452,7 +452,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
 
             _ => {
                 let mut data_variant = match self.variants {
-                    layout::Variants::NicheFilling { dataful_variant, .. } => {
+                    layout::Variants::Multiple {
+                        discr_kind: layout::DiscriminantKind::Niche {
+                            dataful_variant,
+                            ..
+                        },
+                        ..
+                    } => {
                         // Only the niche itself is always initialized,
                         // so only check for a pointer at its offset.
                         //
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index bf2afbbabab..9ed7e26729f 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -216,37 +216,36 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
         if self.layout.abi.is_uninhabited() {
             return bx.cx().const_undef(cast_to);
         }
-        match self.layout.variants {
+        let (discr_scalar, discr_kind) = match self.layout.variants {
             layout::Variants::Single { index } => {
                 let discr_val = self.layout.ty.ty_adt_def().map_or(
                     index.as_u32() as u128,
                     |def| def.discriminant_for_variant(bx.cx().tcx(), index).val);
                 return bx.cx().const_uint_big(cast_to, discr_val);
             }
-            layout::Variants::Tagged { .. } |
-            layout::Variants::NicheFilling { .. } => {},
-        }
+            layout::Variants::Multiple { ref discr, ref discr_kind, .. } => {
+                (discr, discr_kind)
+            }
+        };
 
         let discr = self.project_field(bx, 0);
         let lldiscr = bx.load_operand(discr).immediate();
-        match self.layout.variants {
-            layout::Variants::Single { .. } => bug!(),
-            layout::Variants::Tagged { ref tag, .. } => {
-                let signed = match tag.value {
+        match *discr_kind {
+            layout::DiscriminantKind::Tag => {
+                let signed = match discr_scalar.value {
                     // We use `i1` for bytes that are always `0` or `1`,
                     // e.g., `#[repr(i8)] enum E { A, B }`, but we can't
                     // let LLVM interpret the `i1` as signed, because
                     // then `i1 1` (i.e., E::B) is effectively `i8 -1`.
-                    layout::Int(_, signed) => !tag.is_bool() && signed,
+                    layout::Int(_, signed) => !discr_scalar.is_bool() && signed,
                     _ => false
                 };
                 bx.intcast(lldiscr, cast_to, signed)
             }
-            layout::Variants::NicheFilling {
+            layout::DiscriminantKind::Niche {
                 dataful_variant,
                 ref niche_variants,
                 niche_start,
-                ..
             } => {
                 let niche_llty = bx.cx().immediate_backend_type(discr.layout);
                 if niche_variants.start() == niche_variants.end() {
@@ -291,7 +290,10 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
             layout::Variants::Single { index } => {
                 assert_eq!(index, variant_index);
             }
-            layout::Variants::Tagged { .. } => {
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Tag,
+                ..
+            } => {
                 let ptr = self.project_field(bx, 0);
                 let to = self.layout.ty.ty_adt_def().unwrap()
                     .discriminant_for_variant(bx.tcx(), variant_index)
@@ -301,10 +303,12 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
                     ptr.llval,
                     ptr.align);
             }
-            layout::Variants::NicheFilling {
-                dataful_variant,
-                ref niche_variants,
-                niche_start,
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Niche {
+                    dataful_variant,
+                    ref niche_variants,
+                    niche_start,
+                },
                 ..
             } => {
                 if variant_index != dataful_variant {
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index fc4f6b83247..dfb7f37eb4c 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -282,8 +282,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                     });
                                 }
                             }
-                            layout::Variants::Tagged { .. } |
-                            layout::Variants::NicheFilling { .. } => {},
+                            layout::Variants::Multiple { .. } => {},
                         }
                         let llval = operand.immediate();
 
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 4ad1a00afe9..494a9bb73ed 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -842,51 +842,56 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
             let item_def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
             let t = cx.tcx.type_of(item_def_id);
             let ty = cx.tcx.erase_regions(&t);
-            match cx.layout_of(ty) {
-                Ok(layout) => {
-                    let variants = &layout.variants;
-                    if let layout::Variants::Tagged { ref variants, ref tag, .. } = variants {
-                        let discr_size = tag.value.size(&cx.tcx).bytes();
-
-                        debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
-                               t, layout.size.bytes(), layout);
-
-                        let (largest, slargest, largest_index) = enum_definition.variants
-                            .iter()
-                            .zip(variants)
-                            .map(|(variant, variant_layout)| {
-                                // Subtract the size of the enum discriminant.
-                                let bytes = variant_layout.size.bytes().saturating_sub(discr_size);
-
-                                debug!("- variant `{}` is {} bytes large",
-                                       variant.node.ident,
-                                       bytes);
-                                bytes
-                            })
-                            .enumerate()
-                            .fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l {
-                                (size, l, idx)
-                            } else if size > s {
-                                (l, size, li)
-                            } else {
-                                (l, s, li)
-                            });
-
-                        // We only warn if the largest variant is at least thrice as large as
-                        // the second-largest.
-                        if largest > slargest * 3 && slargest > 0 {
-                            cx.span_lint(VARIANT_SIZE_DIFFERENCES,
-                                            enum_definition.variants[largest_index].span,
-                                            &format!("enum variant is more than three times \
-                                                      larger ({} bytes) than the next largest",
-                                                     largest));
-                        }
-                    }
-                }
+            let layout = match cx.layout_of(ty) {
+                Ok(layout) => layout,
                 Err(ty::layout::LayoutError::Unknown(_)) => return,
                 Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => {
                     bug!("failed to get layout for `{}`: {}", t, err);
                 }
+            };
+            let (variants, tag) = match layout.variants {
+                layout::Variants::Multiple {
+                    discr_kind: layout::DiscriminantKind::Tag,
+                    ref discr,
+                    ref variants,
+                } => (variants, discr),
+                _ => return,
+            };
+
+            let discr_size = tag.value.size(&cx.tcx).bytes();
+
+            debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
+                   t, layout.size.bytes(), layout);
+
+            let (largest, slargest, largest_index) = enum_definition.variants
+                .iter()
+                .zip(variants)
+                .map(|(variant, variant_layout)| {
+                    // Subtract the size of the enum discriminant.
+                    let bytes = variant_layout.size.bytes().saturating_sub(discr_size);
+
+                    debug!("- variant `{}` is {} bytes large",
+                           variant.node.ident,
+                           bytes);
+                    bytes
+                })
+                .enumerate()
+                .fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l {
+                    (size, l, idx)
+                } else if size > s {
+                    (l, size, li)
+                } else {
+                    (l, s, li)
+                });
+
+            // We only warn if the largest variant is at least thrice as large as
+            // the second-largest.
+            if largest > slargest * 3 && slargest > 0 {
+                cx.span_lint(VARIANT_SIZE_DIFFERENCES,
+                                enum_definition.variants[largest_index].span,
+                                &format!("enum variant is more than three times \
+                                          larger ({} bytes) than the next largest",
+                                         largest));
             }
         }
     }
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 003c2182d0b..ba61b03ea67 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -64,8 +64,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                                     dest);
                             }
                         }
-                        layout::Variants::Tagged { .. } |
-                        layout::Variants::NicheFilling { .. } => {},
+                        layout::Variants::Multiple { .. } => {},
                     }
 
                     let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 15b6d5c914d..38a9371b927 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -610,25 +610,24 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
     ) -> EvalResult<'tcx, (u128, VariantIdx)> {
         trace!("read_discriminant_value {:#?}", rval.layout);
 
-        match rval.layout.variants {
+        let discr_kind = match rval.layout.variants {
             layout::Variants::Single { index } => {
                 let discr_val = rval.layout.ty.ty_adt_def().map_or(
                     index.as_u32() as u128,
                     |def| def.discriminant_for_variant(*self.tcx, index).val);
                 return Ok((discr_val, index));
             }
-            layout::Variants::Tagged { .. } |
-            layout::Variants::NicheFilling { .. } => {},
-        }
+            layout::Variants::Multiple { ref discr_kind, .. } => discr_kind,
+        };
+
         // read raw discriminant value
         let discr_op = self.operand_field(rval, 0)?;
         let discr_val = self.read_immediate(discr_op)?;
         let raw_discr = discr_val.to_scalar_or_undef();
         trace!("discr value: {:?}", raw_discr);
         // post-process
-        Ok(match rval.layout.variants {
-            layout::Variants::Single { .. } => bug!(),
-            layout::Variants::Tagged { .. } => {
+        Ok(match *discr_kind {
+            layout::DiscriminantKind::Tag => {
                 let bits_discr = match raw_discr.to_bits(discr_val.layout.size) {
                     Ok(raw_discr) => raw_discr,
                     Err(_) => return err!(InvalidDiscriminant(raw_discr.erase_tag())),
@@ -657,11 +656,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
                     .ok_or_else(|| EvalErrorKind::InvalidDiscriminant(raw_discr.erase_tag()))?;
                 (real_discr, index.0)
             },
-            layout::Variants::NicheFilling {
+            layout::DiscriminantKind::Niche {
                 dataful_variant,
                 ref niche_variants,
                 niche_start,
-                ..
             } => {
                 let variants_start = niche_variants.start().as_u32() as u128;
                 let variants_end = niche_variants.end().as_u32() as u128;
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 82b92acdb76..4d51772d5ea 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -958,7 +958,11 @@ where
             layout::Variants::Single { index } => {
                 assert_eq!(index, variant_index);
             }
-            layout::Variants::Tagged { ref tag, .. } => {
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Tag,
+                ref discr,
+                ..
+            } => {
                 let adt_def = dest.layout.ty.ty_adt_def().unwrap();
                 assert!(variant_index.as_usize() < adt_def.variants.len());
                 let discr_val = adt_def
@@ -968,16 +972,18 @@ where
                 // raw discriminants for enums are isize or bigger during
                 // their computation, but the in-memory tag is the smallest possible
                 // representation
-                let size = tag.value.size(self);
+                let size = discr.value.size(self);
                 let discr_val = truncate(discr_val, size);
 
                 let discr_dest = self.place_field(dest, 0)?;
                 self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?;
             }
-            layout::Variants::NicheFilling {
-                dataful_variant,
-                ref niche_variants,
-                niche_start,
+            layout::Variants::Multiple {
+                discr_kind: layout::DiscriminantKind::Niche {
+                    dataful_variant,
+                    ref niche_variants,
+                    niche_start,
+                },
                 ..
             } => {
                 assert!(
diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs
index 90d4fff4218..05343ac66d9 100644
--- a/src/librustc_mir/interpret/visitor.rs
+++ b/src/librustc_mir/interpret/visitor.rs
@@ -241,8 +241,7 @@ macro_rules! make_value_visitor {
                 // If this is a multi-variant layout, we have find the right one and proceed with
                 // that.
                 match v.layout().variants {
-                    layout::Variants::NicheFilling { .. } |
-                    layout::Variants::Tagged { .. } => {
+                    layout::Variants::Multiple { .. } => {
                         let op = v.to_op(self.ecx())?;
                         let idx = self.ecx().read_discriminant(op)?.1;
                         let inner = v.project_downcast(self.ecx(), idx)?;
diff --git a/src/librustc_target/abi/call/x86_64.rs b/src/librustc_target/abi/call/x86_64.rs
index 680e529b108..b68c70224c9 100644
--- a/src/librustc_target/abi/call/x86_64.rs
+++ b/src/librustc_target/abi/call/x86_64.rs
@@ -61,8 +61,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &ArgType<'a, Ty>)
                         }
                         return Ok(());
                     }
-                    abi::Variants::Tagged { .. } |
-                    abi::Variants::NicheFilling { .. } => return Err(Memory),
+                    abi::Variants::Multiple { .. } => return Err(Memory),
                 }
             }
 
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 8b96a8c1658..235b530a7ef 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -828,15 +828,22 @@ pub enum Variants {
         index: VariantIdx,
     },
 
-    /// General-case enums: for each case there is a struct, and they all have
-    /// all space reserved for the tag, and their first field starts
-    /// at a non-0 offset, after where the tag would go.
-    Tagged {
-        tag: Scalar,
+    /// Enums with more than one inhabited variant: for each case there is
+    /// a struct, and they all have space reserved for the discriminant,
+    /// which is the sole field of the enum layout.
+    Multiple {
+        discr: Scalar,
+        discr_kind: DiscriminantKind,
         variants: IndexVec<VariantIdx, LayoutDetails>,
     },
+}
+
+#[derive(PartialEq, Eq, Hash, Debug)]
+pub enum DiscriminantKind {
+    /// Integer tag holding the discriminant value itself.
+    Tag,
 
-    /// Multiple cases distinguished by a niche (values invalid for a type):
+    /// Niche (values invalid for a type) encoding the discriminant:
     /// the variant `dataful_variant` contains a niche at an arbitrary
     /// offset (field 0 of the enum), which for a variant with discriminant
     /// `d` is set to `(d - niche_variants.start).wrapping_add(niche_start)`.
@@ -844,13 +851,11 @@ pub enum Variants {
     /// For example, `Option<(usize, &T)>`  is represented such that
     /// `None` has a null pointer for the second tuple field, and
     /// `Some` is the identity function (with a non-null reference).
-    NicheFilling {
+    Niche {
         dataful_variant: VariantIdx,
         niche_variants: RangeInclusive<VariantIdx>,
-        niche: Scalar,
         niche_start: u128,
-        variants: IndexVec<VariantIdx, LayoutDetails>,
-    }
+    },
 }
 
 #[derive(PartialEq, Eq, Hash, Debug)]