@@ -1692,12 +1692,17 @@ bitflags! {
1692
1692
const IS_FUNDAMENTAL = 1 << 2 ;
1693
1693
const IS_UNION = 1 << 3 ;
1694
1694
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 ;
1701
1706
}
1702
1707
}
1703
1708
@@ -1710,8 +1715,56 @@ pub struct VariantDef {
1710
1715
pub discr : VariantDiscr ,
1711
1716
pub fields : Vec < FieldDef > ,
1712
1717
pub ctor_kind : CtorKind ,
1718
+ flags : VariantFlags ,
1713
1719
}
1714
1720
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
+
1715
1768
#[ derive( Copy , Clone , Debug , PartialEq , Eq , RustcEncodable , RustcDecodable ) ]
1716
1769
pub enum VariantDiscr {
1717
1770
/// Explicit value for this variant, i.e. `X = 123`.
@@ -1850,7 +1903,7 @@ impl_stable_hash_for!(struct ReprFlags {
1850
1903
1851
1904
1852
1905
/// 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 ) ]
1854
1907
pub struct ReprOptions {
1855
1908
pub int : Option < attr:: IntType > ,
1856
1909
pub align : u32 ,
@@ -1939,6 +1992,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
1939
1992
kind : AdtKind ,
1940
1993
variants : Vec < VariantDef > ,
1941
1994
repr : ReprOptions ) -> Self {
1995
+ debug ! ( "AdtDef::new({:?}, {:?}, {:?}, {:?})" , did, kind, variants, repr) ;
1942
1996
let mut flags = AdtFlags :: NO_ADT_FLAGS ;
1943
1997
let attrs = tcx. get_attrs ( did) ;
1944
1998
if attr:: contains_name ( & attrs, "fundamental" ) {
@@ -1950,8 +2004,9 @@ impl<'a, 'gcx, 'tcx> AdtDef {
1950
2004
if Some ( did) == tcx. lang_items ( ) . owned_box ( ) {
1951
2005
flags = flags | AdtFlags :: IS_BOX ;
1952
2006
}
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 ;
1955
2010
}
1956
2011
match kind {
1957
2012
AdtKind :: Enum => flags = flags | AdtFlags :: IS_ENUM ,
@@ -1982,8 +2037,8 @@ impl<'a, 'gcx, 'tcx> AdtDef {
1982
2037
}
1983
2038
1984
2039
#[ 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 )
1987
2042
}
1988
2043
1989
2044
/// Returns the kind of the ADT - Struct or Enum.
0 commit comments