@@ -1691,12 +1691,17 @@ bitflags! {
1691
1691
const IS_FUNDAMENTAL = 1 << 2 ;
1692
1692
const IS_UNION = 1 << 3 ;
1693
1693
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 ;
1700
1705
}
1701
1706
}
1702
1707
@@ -1709,8 +1714,56 @@ pub struct VariantDef {
1709
1714
pub discr : VariantDiscr ,
1710
1715
pub fields : Vec < FieldDef > ,
1711
1716
pub ctor_kind : CtorKind ,
1717
+ flags : VariantFlags ,
1712
1718
}
1713
1719
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
+
1714
1767
#[ derive( Copy , Clone , Debug , PartialEq , Eq , RustcEncodable , RustcDecodable ) ]
1715
1768
pub enum VariantDiscr {
1716
1769
/// Explicit value for this variant, i.e. `X = 123`.
@@ -1849,7 +1902,7 @@ impl_stable_hash_for!(struct ReprFlags {
1849
1902
1850
1903
1851
1904
/// 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 ) ]
1853
1906
pub struct ReprOptions {
1854
1907
pub int : Option < attr:: IntType > ,
1855
1908
pub align : u32 ,
@@ -1938,6 +1991,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
1938
1991
kind : AdtKind ,
1939
1992
variants : Vec < VariantDef > ,
1940
1993
repr : ReprOptions ) -> Self {
1994
+ debug ! ( "AdtDef::new({:?}, {:?}, {:?}, {:?})" , did, kind, variants, repr) ;
1941
1995
let mut flags = AdtFlags :: NO_ADT_FLAGS ;
1942
1996
let attrs = tcx. get_attrs ( did) ;
1943
1997
if attr:: contains_name ( & attrs, "fundamental" ) {
@@ -1949,8 +2003,9 @@ impl<'a, 'gcx, 'tcx> AdtDef {
1949
2003
if Some ( did) == tcx. lang_items ( ) . owned_box ( ) {
1950
2004
flags = flags | AdtFlags :: IS_BOX ;
1951
2005
}
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 ;
1954
2009
}
1955
2010
match kind {
1956
2011
AdtKind :: Enum => flags = flags | AdtFlags :: IS_ENUM ,
@@ -1981,28 +2036,8 @@ impl<'a, 'gcx, 'tcx> AdtDef {
1981
2036
}
1982
2037
1983
2038
#[ 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 )
2006
2041
}
2007
2042
2008
2043
/// Returns the kind of the ADT - Struct or Enum.
@@ -2017,19 +2052,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
2017
2052
}
2018
2053
}
2019
2054
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
-
2033
2055
pub fn descr ( & self ) -> & ' static str {
2034
2056
match self . adt_kind ( ) {
2035
2057
AdtKind :: Struct => "struct" ,
0 commit comments