@@ -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 ) ]
17151768pub 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 ) ]
18531906pub 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" ,
0 commit comments