@@ -2092,10 +2092,6 @@ pub enum TyKind {
20922092 Never ,
20932093 /// A tuple (`(A, B, C, D,...)`).
20942094 Tup ( ThinVec < P < Ty > > ) ,
2095- /// An anonymous struct type i.e. `struct { foo: Type }`
2096- AnonStruct ( ThinVec < FieldDef > ) ,
2097- /// An anonymous union type i.e. `union { bar: Type }`
2098- AnonUnion ( ThinVec < FieldDef > ) ,
20992095 /// A path (`module::module::...::Type`), optionally
21002096 /// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
21012097 ///
@@ -2715,6 +2711,93 @@ impl VisibilityKind {
27152711 }
27162712}
27172713
2714+ #[ derive( Clone , Copy , Encodable , Decodable , Debug ) ]
2715+ pub enum AnonRecordKind {
2716+ Struct ,
2717+ Union ,
2718+ }
2719+
2720+ impl AnonRecordKind {
2721+ /// Returns the lowercase name.
2722+ pub fn name ( self ) -> & ' static str {
2723+ match self {
2724+ Self :: Struct => "struct" ,
2725+ Self :: Union => "union" ,
2726+ }
2727+ }
2728+ }
2729+
2730+ /// An anonymous struct or union, i.e. `struct { foo: Foo }` or `union { foo: Foo }`.
2731+ #[ derive( Clone , Encodable , Decodable , Debug ) ]
2732+ pub struct AnonRecord {
2733+ pub id : NodeId ,
2734+ pub span : Span ,
2735+ pub fields : ThinVec < FieldDef > ,
2736+ pub kind : AnonRecordKind ,
2737+ pub recovered : bool ,
2738+ }
2739+
2740+ impl AnonRecord {
2741+ pub fn is_union ( & self ) -> bool {
2742+ matches ! ( self . kind, AnonRecordKind :: Union )
2743+ }
2744+ pub fn is_struct ( & self ) -> bool {
2745+ matches ! ( self . kind, AnonRecordKind :: Struct )
2746+ }
2747+ }
2748+
2749+ /// Type of fields in a struct, variant or union.
2750+ #[ derive( Clone , Encodable , Decodable , Debug ) ]
2751+ pub enum FieldTy {
2752+ Ty ( P < Ty > ) ,
2753+ /// An anonymous struct or union, i.e. `struct { foo: Foo }` or `union { foo: Foo }`.
2754+ // AnonRecord(P<Item>),
2755+ AnonRecord ( P < AnonRecord > ) ,
2756+ }
2757+
2758+ impl From < P < Ty > > for FieldTy {
2759+ fn from ( ty : P < Ty > ) -> Self {
2760+ Self :: Ty ( ty)
2761+ }
2762+ }
2763+
2764+ impl From < AnonRecord > for FieldTy {
2765+ fn from ( anon_record : AnonRecord ) -> Self {
2766+ Self :: AnonRecord ( P ( anon_record) )
2767+ }
2768+ }
2769+
2770+ impl FieldTy {
2771+ pub fn id ( & self ) -> NodeId {
2772+ match self {
2773+ Self :: Ty ( ty) => ty. id ,
2774+ Self :: AnonRecord ( anon_record) => anon_record. id ,
2775+ }
2776+ }
2777+
2778+ pub fn span ( & self ) -> Span {
2779+ match self {
2780+ Self :: Ty ( ty) => ty. span ,
2781+ Self :: AnonRecord ( anon_record) => anon_record. span ,
2782+ }
2783+ }
2784+
2785+ pub fn as_ty ( & self ) -> Option < & P < Ty > > {
2786+ match self {
2787+ Self :: Ty ( ty) => Some ( ty) ,
2788+ _ => None ,
2789+ }
2790+ }
2791+
2792+ /// Expects a `Ty`, otherwise panics.
2793+ pub fn expect_ty ( & self ) -> & P < Ty > {
2794+ let FieldTy :: Ty ( ty) = & self else {
2795+ panic ! ( "expect a type, found {self:?}" ) ;
2796+ } ;
2797+ ty
2798+ }
2799+ }
2800+
27182801/// Field definition in a struct, variant or union.
27192802///
27202803/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
@@ -2726,7 +2809,7 @@ pub struct FieldDef {
27262809 pub vis : Visibility ,
27272810 pub ident : Option < Ident > ,
27282811
2729- pub ty : P < Ty > ,
2812+ pub ty : FieldTy ,
27302813 pub is_placeholder : bool ,
27312814}
27322815
@@ -2756,6 +2839,27 @@ impl VariantData {
27562839 }
27572840 }
27582841
2842+ /// Return all fields of this variant, with anonymous structs or unions flattened.
2843+ pub fn all_fields ( & self ) -> AllFields < ' _ > {
2844+ AllFields { iters : smallvec:: smallvec![ self . fields( ) . iter( ) ] }
2845+ }
2846+
2847+ /// Return whether this variant contains inner anonymous unions.
2848+ pub fn find_inner_union ( & self ) -> Option < Span > {
2849+ // We only check the record-like structs
2850+ let VariantData :: Struct ( fields, ..) = self else { return None } ;
2851+ fn find_union ( fields : & [ FieldDef ] ) -> Option < Span > {
2852+ fields. iter ( ) . find_map ( |field| {
2853+ let FieldTy :: AnonRecord ( anon_record) = & field. ty else { return None } ;
2854+ anon_record
2855+ . is_union ( )
2856+ . then ( || anon_record. span )
2857+ . or_else ( || find_union ( & anon_record. fields ) )
2858+ } )
2859+ }
2860+ find_union ( & fields)
2861+ }
2862+
27592863 /// Return the `NodeId` of this variant's constructor, if it has one.
27602864 pub fn ctor_node_id ( & self ) -> Option < NodeId > {
27612865 match * self {
@@ -2765,6 +2869,44 @@ impl VariantData {
27652869 }
27662870}
27672871
2872+ /// Iterator of all fields of a `VariantData`.
2873+ ///
2874+ /// It iterates on the field tree in preorder, where the unnamed fields with anonymous structs or unions
2875+ /// are flattened to their inner fields.
2876+ pub struct AllFields < ' a > {
2877+ iters : smallvec:: SmallVec < [ std:: slice:: Iter < ' a , FieldDef > ; 1 ] > ,
2878+ }
2879+
2880+ impl < ' a > Iterator for AllFields < ' a > {
2881+ type Item = & ' a FieldDef ;
2882+
2883+ fn next ( & mut self ) -> Option < Self :: Item > {
2884+ let mut top = self . iters . last_mut ( ) ?;
2885+ loop {
2886+ if let Some ( field) = top. next ( ) {
2887+ if let FieldTy :: AnonRecord ( anon_record) = & field. ty {
2888+ self . iters . push ( anon_record. fields . iter ( ) ) ;
2889+ top = self . iters . last_mut ( ) . unwrap ( ) ;
2890+ continue ;
2891+ }
2892+ return Some ( field) ;
2893+ }
2894+ self . iters . pop ( ) ;
2895+ top = self . iters . last_mut ( ) ?;
2896+ }
2897+ }
2898+
2899+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
2900+ match & self . iters [ ..] {
2901+ [ ] => ( 0 , Some ( 0 ) ) ,
2902+ [ single] => ( single. size_hint ( ) . 0 , None ) ,
2903+ [ first, .., last] => ( first. size_hint ( ) . 0 + last. size_hint ( ) . 0 , None ) ,
2904+ }
2905+ }
2906+ }
2907+
2908+ impl std:: iter:: FusedIterator for AllFields < ' _ > { }
2909+
27682910/// An item definition.
27692911#[ derive( Clone , Encodable , Decodable , Debug ) ]
27702912pub struct Item < K = ItemKind > {
0 commit comments