@@ -2074,10 +2074,6 @@ pub enum TyKind {
20742074 Never ,
20752075 /// A tuple (`(A, B, C, D,...)`).
20762076 Tup ( ThinVec < P < Ty > > ) ,
2077- /// An anonymous struct type i.e. `struct { foo: Type }`
2078- AnonStruct ( ThinVec < FieldDef > ) ,
2079- /// An anonymous union type i.e. `union { bar: Type }`
2080- AnonUnion ( ThinVec < FieldDef > ) ,
20812077 /// A path (`module::module::...::Type`), optionally
20822078 /// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
20832079 ///
@@ -2721,6 +2717,93 @@ impl VisibilityKind {
27212717 }
27222718}
27232719
2720+ #[ derive( Clone , Copy , Encodable , Decodable , Debug ) ]
2721+ pub enum AnonRecordKind {
2722+ Struct ,
2723+ Union ,
2724+ }
2725+
2726+ impl AnonRecordKind {
2727+ /// Returns the lowercase name.
2728+ pub fn name ( self ) -> & ' static str {
2729+ match self {
2730+ Self :: Struct => "struct" ,
2731+ Self :: Union => "union" ,
2732+ }
2733+ }
2734+ }
2735+
2736+ /// An anonymous struct or union, i.e. `struct { foo: Foo }` or `union { foo: Foo }`.
2737+ #[ derive( Clone , Encodable , Decodable , Debug ) ]
2738+ pub struct AnonRecord {
2739+ pub id : NodeId ,
2740+ pub span : Span ,
2741+ pub fields : ThinVec < FieldDef > ,
2742+ pub kind : AnonRecordKind ,
2743+ pub recovered : bool ,
2744+ }
2745+
2746+ impl AnonRecord {
2747+ pub fn is_union ( & self ) -> bool {
2748+ matches ! ( self . kind, AnonRecordKind :: Union )
2749+ }
2750+ pub fn is_struct ( & self ) -> bool {
2751+ matches ! ( self . kind, AnonRecordKind :: Struct )
2752+ }
2753+ }
2754+
2755+ /// Type of fields in a struct, variant or union.
2756+ #[ derive( Clone , Encodable , Decodable , Debug ) ]
2757+ pub enum FieldTy {
2758+ Ty ( P < Ty > ) ,
2759+ /// An anonymous struct or union, i.e. `struct { foo: Foo }` or `union { foo: Foo }`.
2760+ // AnonRecord(P<Item>),
2761+ AnonRecord ( P < AnonRecord > ) ,
2762+ }
2763+
2764+ impl From < P < Ty > > for FieldTy {
2765+ fn from ( ty : P < Ty > ) -> Self {
2766+ Self :: Ty ( ty)
2767+ }
2768+ }
2769+
2770+ impl From < AnonRecord > for FieldTy {
2771+ fn from ( anon_record : AnonRecord ) -> Self {
2772+ Self :: AnonRecord ( P ( anon_record) )
2773+ }
2774+ }
2775+
2776+ impl FieldTy {
2777+ pub fn id ( & self ) -> NodeId {
2778+ match self {
2779+ Self :: Ty ( ty) => ty. id ,
2780+ Self :: AnonRecord ( anon_record) => anon_record. id ,
2781+ }
2782+ }
2783+
2784+ pub fn span ( & self ) -> Span {
2785+ match self {
2786+ Self :: Ty ( ty) => ty. span ,
2787+ Self :: AnonRecord ( anon_record) => anon_record. span ,
2788+ }
2789+ }
2790+
2791+ pub fn as_ty ( & self ) -> Option < & P < Ty > > {
2792+ match self {
2793+ Self :: Ty ( ty) => Some ( ty) ,
2794+ _ => None ,
2795+ }
2796+ }
2797+
2798+ /// Expects a `Ty`, otherwise panics.
2799+ pub fn expect_ty ( & self ) -> & P < Ty > {
2800+ let FieldTy :: Ty ( ty) = & self else {
2801+ panic ! ( "expect a type, found {self:?}" ) ;
2802+ } ;
2803+ ty
2804+ }
2805+ }
2806+
27242807/// Field definition in a struct, variant or union.
27252808///
27262809/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
@@ -2732,7 +2815,7 @@ pub struct FieldDef {
27322815 pub vis : Visibility ,
27332816 pub ident : Option < Ident > ,
27342817
2735- pub ty : P < Ty > ,
2818+ pub ty : FieldTy ,
27362819 pub is_placeholder : bool ,
27372820}
27382821
@@ -2762,6 +2845,27 @@ impl VariantData {
27622845 }
27632846 }
27642847
2848+ /// Return all fields of this variant, with anonymous structs or unions flattened.
2849+ pub fn all_fields ( & self ) -> AllFields < ' _ > {
2850+ AllFields { iters : smallvec:: smallvec![ self . fields( ) . iter( ) ] }
2851+ }
2852+
2853+ /// Return whether this variant contains inner anonymous unions.
2854+ pub fn find_inner_union ( & self ) -> Option < Span > {
2855+ // We only check the record-like structs
2856+ let VariantData :: Struct ( fields, ..) = self else { return None } ;
2857+ fn find_union ( fields : & [ FieldDef ] ) -> Option < Span > {
2858+ fields. iter ( ) . find_map ( |field| {
2859+ let FieldTy :: AnonRecord ( anon_record) = & field. ty else { return None } ;
2860+ anon_record
2861+ . is_union ( )
2862+ . then ( || anon_record. span )
2863+ . or_else ( || find_union ( & anon_record. fields ) )
2864+ } )
2865+ }
2866+ find_union ( & fields)
2867+ }
2868+
27652869 /// Return the `NodeId` of this variant's constructor, if it has one.
27662870 pub fn ctor_node_id ( & self ) -> Option < NodeId > {
27672871 match * self {
@@ -2771,6 +2875,44 @@ impl VariantData {
27712875 }
27722876}
27732877
2878+ /// Iterator of all fields of a `VariantData`.
2879+ ///
2880+ /// It iterates on the field tree in preorder, where the unnamed fields with anonymous structs or unions
2881+ /// are flattened to their inner fields.
2882+ pub struct AllFields < ' a > {
2883+ iters : smallvec:: SmallVec < [ std:: slice:: Iter < ' a , FieldDef > ; 1 ] > ,
2884+ }
2885+
2886+ impl < ' a > Iterator for AllFields < ' a > {
2887+ type Item = & ' a FieldDef ;
2888+
2889+ fn next ( & mut self ) -> Option < Self :: Item > {
2890+ let mut top = self . iters . last_mut ( ) ?;
2891+ loop {
2892+ if let Some ( field) = top. next ( ) {
2893+ if let FieldTy :: AnonRecord ( anon_record) = & field. ty {
2894+ self . iters . push ( anon_record. fields . iter ( ) ) ;
2895+ top = self . iters . last_mut ( ) . unwrap ( ) ;
2896+ continue ;
2897+ }
2898+ return Some ( field) ;
2899+ }
2900+ self . iters . pop ( ) ;
2901+ top = self . iters . last_mut ( ) ?;
2902+ }
2903+ }
2904+
2905+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
2906+ match & self . iters [ ..] {
2907+ [ ] => ( 0 , Some ( 0 ) ) ,
2908+ [ single] => ( single. size_hint ( ) . 0 , None ) ,
2909+ [ first, .., last] => ( first. size_hint ( ) . 0 + last. size_hint ( ) . 0 , None ) ,
2910+ }
2911+ }
2912+ }
2913+
2914+ impl std:: iter:: FusedIterator for AllFields < ' _ > { }
2915+
27742916/// An item definition.
27752917#[ derive( Clone , Encodable , Decodable , Debug ) ]
27762918pub struct Item < K = ItemKind > {
0 commit comments