@@ -1692,12 +1692,17 @@ bitflags! {
16921692 const IS_FUNDAMENTAL = 1 << 2 ;
16931693 const IS_UNION = 1 << 3 ;
16941694 const IS_BOX = 1 << 4 ;
1695- /// Indicates whether this abstract data type will be expanded on in future (new
1696- /// fields/variants) and as such, whether downstream crates must match exhaustively on the
1697- /// fields/variants of this data type.
1698- ///
1699- /// See RFC 2008 (<https://github.com/rust-lang/rfcs/pull/2008>).
1700- const IS_NON_EXHAUSTIVE = 1 << 5 ;
1695+ /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
1696+ /// (i.e., this flag is never set unless this ADT is an enum).
1697+ const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 5 ;
1698+ }
1699+ }
1700+
1701+ bitflags ! {
1702+ pub struct VariantFlags : u32 {
1703+ const NO_VARIANT_FLAGS = 0 ;
1704+ /// Indicates whether the field list of this variant is `#[non_exhaustive]`.
1705+ const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0 ;
17011706 }
17021707}
17031708
@@ -1710,8 +1715,56 @@ pub struct VariantDef {
17101715 pub discr : VariantDiscr ,
17111716 pub fields : Vec < FieldDef > ,
17121717 pub ctor_kind : CtorKind ,
1718+ flags : VariantFlags ,
17131719}
17141720
1721+ impl < ' a , ' gcx , ' tcx > VariantDef {
1722+ /// Create a new `VariantDef`.
1723+ ///
1724+ /// - `did` is the DefId used for the variant - for tuple-structs, it is the constructor DefId,
1725+ /// and for everything else, it is the variant DefId.
1726+ /// - `attribute_def_id` is the DefId that has the variant's attributes.
1727+ pub fn new ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
1728+ did : DefId ,
1729+ name : Name ,
1730+ discr : VariantDiscr ,
1731+ fields : Vec < FieldDef > ,
1732+ adt_kind : AdtKind ,
1733+ ctor_kind : CtorKind )
1734+ -> Self
1735+ {
1736+ debug ! ( "VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?})" , did, name, discr, fields,
1737+ adt_kind, ctor_kind) ;
1738+ let mut flags = VariantFlags :: NO_VARIANT_FLAGS ;
1739+ if adt_kind == AdtKind :: Struct && tcx. has_attr ( did, "non_exhaustive" ) {
1740+ debug ! ( "found non-exhaustive field list for {:?}" , did) ;
1741+ flags = flags | VariantFlags :: IS_FIELD_LIST_NON_EXHAUSTIVE ;
1742+ }
1743+ VariantDef {
1744+ did,
1745+ name,
1746+ discr,
1747+ fields,
1748+ ctor_kind,
1749+ flags
1750+ }
1751+ }
1752+
1753+ #[ inline]
1754+ pub fn is_field_list_non_exhaustive ( & self ) -> bool {
1755+ self . flags . intersects ( VariantFlags :: IS_FIELD_LIST_NON_EXHAUSTIVE )
1756+ }
1757+ }
1758+
1759+ impl_stable_hash_for ! ( struct VariantDef {
1760+ did,
1761+ name,
1762+ discr,
1763+ fields,
1764+ ctor_kind,
1765+ flags
1766+ } ) ;
1767+
17151768#[ derive( Copy , Clone , Debug , PartialEq , Eq , RustcEncodable , RustcDecodable ) ]
17161769pub enum VariantDiscr {
17171770 /// Explicit value for this variant, i.e. `X = 123`.
@@ -1850,7 +1903,7 @@ impl_stable_hash_for!(struct ReprFlags {
18501903
18511904
18521905/// Represents the repr options provided by the user,
1853- #[ derive( Copy , Clone , Eq , PartialEq , RustcEncodable , RustcDecodable , Default ) ]
1906+ #[ derive( Copy , Clone , Debug , Eq , PartialEq , RustcEncodable , RustcDecodable , Default ) ]
18541907pub struct ReprOptions {
18551908 pub int : Option < attr:: IntType > ,
18561909 pub align : u32 ,
@@ -1939,6 +1992,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
19391992 kind : AdtKind ,
19401993 variants : Vec < VariantDef > ,
19411994 repr : ReprOptions ) -> Self {
1995+ debug ! ( "AdtDef::new({:?}, {:?}, {:?}, {:?})" , did, kind, variants, repr) ;
19421996 let mut flags = AdtFlags :: NO_ADT_FLAGS ;
19431997 let attrs = tcx. get_attrs ( did) ;
19441998 if attr:: contains_name ( & attrs, "fundamental" ) {
@@ -1950,8 +2004,9 @@ impl<'a, 'gcx, 'tcx> AdtDef {
19502004 if Some ( did) == tcx. lang_items ( ) . owned_box ( ) {
19512005 flags = flags | AdtFlags :: IS_BOX ;
19522006 }
1953- if tcx. has_attr ( did, "non_exhaustive" ) {
1954- flags = flags | AdtFlags :: IS_NON_EXHAUSTIVE ;
2007+ if kind == AdtKind :: Enum && tcx. has_attr ( did, "non_exhaustive" ) {
2008+ debug ! ( "found non-exhaustive variant list for {:?}" , did) ;
2009+ flags = flags | AdtFlags :: IS_VARIANT_LIST_NON_EXHAUSTIVE ;
19552010 }
19562011 match kind {
19572012 AdtKind :: Enum => flags = flags | AdtFlags :: IS_ENUM ,
@@ -1982,8 +2037,8 @@ impl<'a, 'gcx, 'tcx> AdtDef {
19822037 }
19832038
19842039 #[ inline]
1985- pub fn is_non_exhaustive ( & self ) -> bool {
1986- self . flags . intersects ( AdtFlags :: IS_NON_EXHAUSTIVE )
2040+ pub fn is_variant_list_non_exhaustive ( & self ) -> bool {
2041+ self . flags . intersects ( AdtFlags :: IS_VARIANT_LIST_NON_EXHAUSTIVE )
19872042 }
19882043
19892044 /// Returns the kind of the ADT - Struct or Enum.
0 commit comments