Skip to content

Commit ae2ad30

Browse files
committed
move the is_field_list_non_exhaustive flag to VariantDef
This completely splits the IS_NON_EXHAUSTIVE flag. No functional changes intended.
1 parent 993e7e2 commit ae2ad30

File tree

9 files changed

+108
-73
lines changed

9 files changed

+108
-73
lines changed

src/librustc/ich/impls_ty.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -344,13 +344,13 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::AdtFlags {
344344
}
345345
}
346346

347-
impl_stable_hash_for!(struct ty::VariantDef {
348-
did,
349-
name,
350-
discr,
351-
fields,
352-
ctor_kind
353-
});
347+
impl<'a> HashStable<StableHashingContext<'a>> for ty::VariantFlags {
348+
fn hash_stable<W: StableHasherResult>(&self,
349+
_: &mut StableHashingContext<'a>,
350+
hasher: &mut StableHasher<W>) {
351+
std_hash::Hash::hash(self, hasher);
352+
}
353+
}
354354

355355
impl_stable_hash_for!(enum ty::VariantDiscr {
356356
Explicit(def_id),

src/librustc/ty/mod.rs

+66-44
Original file line numberDiff line numberDiff line change
@@ -1691,12 +1691,17 @@ bitflags! {
16911691
const IS_FUNDAMENTAL = 1 << 2;
16921692
const IS_UNION = 1 << 3;
16931693
const IS_BOX = 1 << 4;
1694-
/// Indicates whether this abstract data type will be expanded on in future (new
1695-
/// fields/variants) and as such, whether downstream crates must match exhaustively on the
1696-
/// fields/variants of this data type.
1697-
///
1698-
/// See RFC 2008 (<https://github.com/rust-lang/rfcs/pull/2008>).
1699-
const IS_NON_EXHAUSTIVE = 1 << 5;
1694+
/// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
1695+
/// (i.e., this flag is never set unless this ADT is an enum).
1696+
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 5;
1697+
}
1698+
}
1699+
1700+
bitflags! {
1701+
pub struct VariantFlags: u32 {
1702+
const NO_VARIANT_FLAGS = 0;
1703+
/// Indicates whether the field list of this variant is `#[non_exhaustive]`.
1704+
const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
17001705
}
17011706
}
17021707

@@ -1709,8 +1714,56 @@ pub struct VariantDef {
17091714
pub discr: VariantDiscr,
17101715
pub fields: Vec<FieldDef>,
17111716
pub ctor_kind: CtorKind,
1717+
flags: VariantFlags,
17121718
}
17131719

1720+
impl<'a, 'gcx, 'tcx> VariantDef {
1721+
/// Create a new `VariantDef`.
1722+
///
1723+
/// - `did` is the DefId used for the variant - for tuple-structs, it is the constructor DefId,
1724+
/// and for everything else, it is the variant DefId.
1725+
/// - `attribute_def_id` is the DefId that has the variant's attributes.
1726+
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
1727+
did: DefId,
1728+
name: Name,
1729+
discr: VariantDiscr,
1730+
fields: Vec<FieldDef>,
1731+
adt_kind: AdtKind,
1732+
ctor_kind: CtorKind)
1733+
-> Self
1734+
{
1735+
debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, name, discr, fields,
1736+
adt_kind, ctor_kind);
1737+
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
1738+
if adt_kind == AdtKind::Struct && tcx.has_attr(did, "non_exhaustive") {
1739+
debug!("found non-exhaustive field list for {:?}", did);
1740+
flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
1741+
}
1742+
VariantDef {
1743+
did,
1744+
name,
1745+
discr,
1746+
fields,
1747+
ctor_kind,
1748+
flags
1749+
}
1750+
}
1751+
1752+
#[inline]
1753+
pub fn is_field_list_non_exhaustive(&self) -> bool {
1754+
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
1755+
}
1756+
}
1757+
1758+
impl_stable_hash_for!(struct VariantDef {
1759+
did,
1760+
name,
1761+
discr,
1762+
fields,
1763+
ctor_kind,
1764+
flags
1765+
});
1766+
17141767
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
17151768
pub enum VariantDiscr {
17161769
/// Explicit value for this variant, i.e. `X = 123`.
@@ -1849,7 +1902,7 @@ impl_stable_hash_for!(struct ReprFlags {
18491902

18501903

18511904
/// Represents the repr options provided by the user,
1852-
#[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)]
1905+
#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)]
18531906
pub struct ReprOptions {
18541907
pub int: Option<attr::IntType>,
18551908
pub align: u32,
@@ -1938,6 +1991,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
19381991
kind: AdtKind,
19391992
variants: Vec<VariantDef>,
19401993
repr: ReprOptions) -> Self {
1994+
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
19411995
let mut flags = AdtFlags::NO_ADT_FLAGS;
19421996
let attrs = tcx.get_attrs(did);
19431997
if attr::contains_name(&attrs, "fundamental") {
@@ -1949,8 +2003,9 @@ impl<'a, 'gcx, 'tcx> AdtDef {
19492003
if Some(did) == tcx.lang_items().owned_box() {
19502004
flags = flags | AdtFlags::IS_BOX;
19512005
}
1952-
if tcx.has_attr(did, "non_exhaustive") {
1953-
flags = flags | AdtFlags::IS_NON_EXHAUSTIVE;
2006+
if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
2007+
debug!("found non-exhaustive variant list for {:?}", did);
2008+
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
19542009
}
19552010
match kind {
19562011
AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
@@ -1981,28 +2036,8 @@ impl<'a, 'gcx, 'tcx> AdtDef {
19812036
}
19822037

19832038
#[inline]
1984-
fn is_non_exhaustive(&self) -> bool {
1985-
self.flags.intersects(AdtFlags::IS_NON_EXHAUSTIVE)
1986-
}
1987-
1988-
#[inline]
1989-
pub fn is_enum_non_exhaustive(&self) -> bool {
1990-
match self.adt_kind() {
1991-
AdtKind::Enum => self.is_non_exhaustive(),
1992-
AdtKind::Struct | AdtKind::Union => {
1993-
bug!("is_non_exhaustive_enum called on non-enum `{:?}`", self);
1994-
}
1995-
}
1996-
}
1997-
1998-
#[inline]
1999-
pub fn is_univariant_non_exhaustive(&self) -> bool {
2000-
match self.adt_kind() {
2001-
AdtKind::Struct | AdtKind::Union => self.is_non_exhaustive(),
2002-
AdtKind::Enum => {
2003-
bug!("is_non_exhaustive_enum called on non-enum `{:?}`", self);
2004-
}
2005-
}
2039+
pub fn is_variant_list_non_exhaustive(&self) -> bool {
2040+
self.flags.intersects(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
20062041
}
20072042

20082043
/// Returns the kind of the ADT - Struct or Enum.
@@ -2017,19 +2052,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
20172052
}
20182053
}
20192054

2020-
/// Return whether `variant` is non-exhaustive as a *struct* (i.e., whether
2021-
/// it can have additional fields).
2022-
pub fn is_variant_non_exhaustive(&self, _variant: &ty::VariantDef) -> bool {
2023-
match self.adt_kind() {
2024-
// A struct is non-exhaustive if it has a `#[non_exhaustive]` attribute.
2025-
AdtKind::Struct => self.is_non_exhaustive(),
2026-
// At this moment, all enum variants are exhaustive.
2027-
AdtKind::Enum => false,
2028-
// All unions are "exhaustive", as far as that makes sense.
2029-
AdtKind::Union => false,
2030-
}
2031-
}
2032-
20332055
pub fn descr(&self) -> &'static str {
20342056
match self.adt_kind() {
20352057
AdtKind::Struct => "struct",

src/librustc_metadata/decoder.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -507,28 +507,36 @@ impl<'a, 'tcx> CrateMetadata {
507507
self.def_path_table.def_path_hash(item_id))
508508
}
509509

510-
fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef {
510+
fn get_variant(&self,
511+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
512+
item: &Entry,
513+
index: DefIndex,
514+
adt_kind: ty::AdtKind)
515+
-> ty::VariantDef
516+
{
511517
let data = match item.kind {
512518
EntryKind::Variant(data) |
513519
EntryKind::Struct(data, _) |
514520
EntryKind::Union(data, _) => data.decode(self),
515521
_ => bug!(),
516522
};
517523

518-
ty::VariantDef {
519-
did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
520-
name: self.item_name(index).as_symbol(),
521-
fields: item.children.decode(self).map(|index| {
524+
ty::VariantDef::new(
525+
tcx,
526+
self.local_def_id(data.struct_ctor.unwrap_or(index)),
527+
self.item_name(index).as_symbol(),
528+
data.discr,
529+
item.children.decode(self).map(|index| {
522530
let f = self.entry(index);
523531
ty::FieldDef {
524532
did: self.local_def_id(index),
525533
ident: Ident::from_interned_str(self.item_name(index)),
526534
vis: f.visibility.decode(self)
527535
}
528536
}).collect(),
529-
discr: data.discr,
530-
ctor_kind: data.ctor_kind,
531-
}
537+
adt_kind,
538+
data.ctor_kind
539+
)
532540
}
533541

534542
pub fn get_adt_def(&self,
@@ -549,11 +557,11 @@ impl<'a, 'tcx> CrateMetadata {
549557
item.children
550558
.decode(self)
551559
.map(|index| {
552-
self.get_variant(&self.entry(index), index)
560+
self.get_variant(tcx, &self.entry(index), index, kind)
553561
})
554562
.collect()
555563
} else {
556-
vec![self.get_variant(&item, item_id)]
564+
vec![self.get_variant(tcx, &item, item_id, kind)]
557565
};
558566

559567
tcx.alloc_adt_def(did, kind, variants, repr)

src/librustc_metadata/encoder.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
740740

741741
// If the structure is marked as non_exhaustive then lower the visibility
742742
// to within the crate.
743-
if adt_def.is_univariant_non_exhaustive() && ctor_vis == ty::Visibility::Public {
743+
if adt_def.non_enum_variant().is_field_list_non_exhaustive() &&
744+
ctor_vis == ty::Visibility::Public
745+
{
744746
ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
745747
}
746748

src/librustc_mir/hair/pattern/_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
381381

382382
fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
383383
match ty.sty {
384-
ty::Adt(adt_def, ..) => adt_def.is_enum() && adt_def.is_enum_non_exhaustive(),
384+
ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(),
385385
_ => false,
386386
}
387387
}

src/librustc_privacy/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
684684
// visibility to within the crate.
685685
let struct_def_id = self.tcx.hir.get_parent_did(node_id);
686686
let adt_def = self.tcx.adt_def(struct_def_id);
687-
if adt_def.is_univariant_non_exhaustive()
687+
if adt_def.non_enum_variant().is_field_list_non_exhaustive()
688688
&& ctor_vis == ty::Visibility::Public
689689
{
690690
ctor_vis = ty::Visibility::Restricted(

src/librustc_typeck/check/_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
948948
}
949949

950950
// Require `..` if struct has non_exhaustive attribute.
951-
if adt.is_variant_non_exhaustive(variant) && !adt.did.is_local() && !etc {
951+
if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
952952
span_err!(tcx.sess, span, E0638,
953953
"`..` required with {} marked as non-exhaustive",
954954
kind_name);

src/librustc_typeck/check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3654,7 +3654,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
36543654

36553655
// Prohibit struct expressions when non exhaustive flag is set.
36563656
let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type");
3657-
if !adt.did.is_local() && adt.is_variant_non_exhaustive(variant) {
3657+
if !adt.did.is_local() && variant.is_field_list_non_exhaustive() {
36583658
span_err!(self.tcx.sess, expr.span, E0639,
36593659
"cannot create non-exhaustive {} using struct expression",
36603660
adt.variant_descr());

src/librustc_typeck/collect.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -548,12 +548,13 @@ fn convert_enum_variant_types<'a, 'tcx>(
548548
}
549549
}
550550

551-
fn convert_struct_variant<'a, 'tcx>(
551+
fn convert_variant<'a, 'tcx>(
552552
tcx: TyCtxt<'a, 'tcx, 'tcx>,
553553
did: DefId,
554554
name: ast::Name,
555555
discr: ty::VariantDiscr,
556556
def: &hir::VariantData,
557+
adt_kind: ty::AdtKind
557558
) -> ty::VariantDef {
558559
let mut seen_fields: FxHashMap<ast::Ident, Span> = FxHashMap();
559560
let node_id = tcx.hir.as_local_node_id(did).unwrap();
@@ -584,13 +585,13 @@ fn convert_struct_variant<'a, 'tcx>(
584585
}
585586
})
586587
.collect();
587-
ty::VariantDef {
588+
ty::VariantDef::new(tcx,
588589
did,
589590
name,
590591
discr,
591592
fields,
592-
ctor_kind: CtorKind::from_hir(def),
593-
}
593+
adt_kind,
594+
CtorKind::from_hir(def))
594595
}
595596

596597
fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::AdtDef {
@@ -621,7 +622,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
621622
};
622623
distance_from_explicit += 1;
623624

624-
convert_struct_variant(tcx, did, v.node.name, discr, &v.node.data)
625+
convert_variant(tcx, did, v.node.name, discr, &v.node.data, AdtKind::Enum)
625626
})
626627
.collect(),
627628
)
@@ -635,23 +636,25 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
635636
};
636637
(
637638
AdtKind::Struct,
638-
vec![convert_struct_variant(
639+
vec![convert_variant(
639640
tcx,
640641
ctor_id.unwrap_or(def_id),
641642
item.name,
642643
ty::VariantDiscr::Relative(0),
643644
def,
645+
AdtKind::Struct
644646
)],
645647
)
646648
}
647649
ItemKind::Union(ref def, _) => (
648650
AdtKind::Union,
649-
vec![convert_struct_variant(
651+
vec![convert_variant(
650652
tcx,
651653
def_id,
652654
item.name,
653655
ty::VariantDiscr::Relative(0),
654656
def,
657+
AdtKind::Union
655658
)],
656659
),
657660
_ => bug!(),

0 commit comments

Comments
 (0)