@@ -2060,10 +2060,6 @@ pub enum TyKind {
20602060 Never ,
20612061 /// A tuple (`(A, B, C, D,...)`).
20622062 Tup ( ThinVec < P < Ty > > ) ,
2063- /// An anonymous struct type i.e. `struct { foo: Type }`
2064- AnonStruct ( ThinVec < FieldDef > ) ,
2065- /// An anonymous union type i.e. `union { bar: Type }`
2066- AnonUnion ( ThinVec < FieldDef > ) ,
20672063 /// A path (`module::module::...::Type`), optionally
20682064 /// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
20692065 ///
@@ -2689,6 +2685,93 @@ impl VisibilityKind {
26892685 }
26902686}
26912687
2688+ #[ derive( Clone , Copy , Encodable , Decodable , Debug ) ]
2689+ pub enum AnonRecordKind {
2690+ Struct ,
2691+ Union ,
2692+ }
2693+
2694+ impl AnonRecordKind {
2695+ /// Returns the lowercase name.
2696+ pub fn name ( self ) -> & ' static str {
2697+ match self {
2698+ Self :: Struct => "struct" ,
2699+ Self :: Union => "union" ,
2700+ }
2701+ }
2702+ }
2703+
2704+ /// An anonymous struct or union, i.e. `struct { foo: Foo }` or `union { foo: Foo }`.
2705+ #[ derive( Clone , Encodable , Decodable , Debug ) ]
2706+ pub struct AnonRecord {
2707+ pub id : NodeId ,
2708+ pub span : Span ,
2709+ pub fields : ThinVec < FieldDef > ,
2710+ pub kind : AnonRecordKind ,
2711+ pub recovered : bool ,
2712+ }
2713+
2714+ impl AnonRecord {
2715+ pub fn is_union ( & self ) -> bool {
2716+ matches ! ( self . kind, AnonRecordKind :: Union )
2717+ }
2718+ pub fn is_struct ( & self ) -> bool {
2719+ matches ! ( self . kind, AnonRecordKind :: Struct )
2720+ }
2721+ }
2722+
2723+ /// Type of fields in a struct, variant or union.
2724+ #[ derive( Clone , Encodable , Decodable , Debug ) ]
2725+ pub enum FieldTy {
2726+ Ty ( P < Ty > ) ,
2727+ /// An anonymous struct or union, i.e. `struct { foo: Foo }` or `union { foo: Foo }`.
2728+ // AnonRecord(P<Item>),
2729+ AnonRecord ( P < AnonRecord > ) ,
2730+ }
2731+
2732+ impl From < P < Ty > > for FieldTy {
2733+ fn from ( ty : P < Ty > ) -> Self {
2734+ Self :: Ty ( ty)
2735+ }
2736+ }
2737+
2738+ impl From < AnonRecord > for FieldTy {
2739+ fn from ( anon_record : AnonRecord ) -> Self {
2740+ Self :: AnonRecord ( P ( anon_record) )
2741+ }
2742+ }
2743+
2744+ impl FieldTy {
2745+ pub fn id ( & self ) -> NodeId {
2746+ match self {
2747+ Self :: Ty ( ty) => ty. id ,
2748+ Self :: AnonRecord ( anon_record) => anon_record. id ,
2749+ }
2750+ }
2751+
2752+ pub fn span ( & self ) -> Span {
2753+ match self {
2754+ Self :: Ty ( ty) => ty. span ,
2755+ Self :: AnonRecord ( anon_record) => anon_record. span ,
2756+ }
2757+ }
2758+
2759+ pub fn as_ty ( & self ) -> Option < & P < Ty > > {
2760+ match self {
2761+ Self :: Ty ( ty) => Some ( ty) ,
2762+ _ => None ,
2763+ }
2764+ }
2765+
2766+ /// Expects a `Ty`, otherwise panics.
2767+ pub fn expect_ty ( & self ) -> & P < Ty > {
2768+ let FieldTy :: Ty ( ty) = & self else {
2769+ panic ! ( "expect a type, found {self:?}" ) ;
2770+ } ;
2771+ ty
2772+ }
2773+ }
2774+
26922775/// Field definition in a struct, variant or union.
26932776///
26942777/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
@@ -2700,7 +2783,7 @@ pub struct FieldDef {
27002783 pub vis : Visibility ,
27012784 pub ident : Option < Ident > ,
27022785
2703- pub ty : P < Ty > ,
2786+ pub ty : FieldTy ,
27042787 pub is_placeholder : bool ,
27052788}
27062789
@@ -2730,6 +2813,27 @@ impl VariantData {
27302813 }
27312814 }
27322815
2816+ /// Return all fields of this variant, with anonymous structs or unions flattened.
2817+ pub fn all_fields ( & self ) -> AllFields < ' _ > {
2818+ AllFields { iters : smallvec:: smallvec![ self . fields( ) . iter( ) ] }
2819+ }
2820+
2821+ /// Return whether this variant contains inner anonymous unions.
2822+ pub fn find_inner_union ( & self ) -> Option < Span > {
2823+ // We only check the record-like structs
2824+ let VariantData :: Struct ( fields, ..) = self else { return None } ;
2825+ fn find_union ( fields : & [ FieldDef ] ) -> Option < Span > {
2826+ fields. iter ( ) . find_map ( |field| {
2827+ let FieldTy :: AnonRecord ( anon_record) = & field. ty else { return None } ;
2828+ anon_record
2829+ . is_union ( )
2830+ . then ( || anon_record. span )
2831+ . or_else ( || find_union ( & anon_record. fields ) )
2832+ } )
2833+ }
2834+ find_union ( & fields)
2835+ }
2836+
27332837 /// Return the `NodeId` of this variant's constructor, if it has one.
27342838 pub fn ctor_node_id ( & self ) -> Option < NodeId > {
27352839 match * self {
@@ -2739,6 +2843,44 @@ impl VariantData {
27392843 }
27402844}
27412845
2846+ /// Iterator of all fields of a `VariantData`.
2847+ ///
2848+ /// It iterates on the field tree in preorder, where the unnamed fields with anonymous structs or unions
2849+ /// are flattened to their inner fields.
2850+ pub struct AllFields < ' a > {
2851+ iters : smallvec:: SmallVec < [ std:: slice:: Iter < ' a , FieldDef > ; 1 ] > ,
2852+ }
2853+
2854+ impl < ' a > Iterator for AllFields < ' a > {
2855+ type Item = & ' a FieldDef ;
2856+
2857+ fn next ( & mut self ) -> Option < Self :: Item > {
2858+ let mut top = self . iters . last_mut ( ) ?;
2859+ loop {
2860+ if let Some ( field) = top. next ( ) {
2861+ if let FieldTy :: AnonRecord ( anon_record) = & field. ty {
2862+ self . iters . push ( anon_record. fields . iter ( ) ) ;
2863+ top = self . iters . last_mut ( ) . unwrap ( ) ;
2864+ continue ;
2865+ }
2866+ return Some ( field) ;
2867+ }
2868+ self . iters . pop ( ) ;
2869+ top = self . iters . last_mut ( ) ?;
2870+ }
2871+ }
2872+
2873+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
2874+ match & self . iters [ ..] {
2875+ [ ] => ( 0 , Some ( 0 ) ) ,
2876+ [ single] => ( single. size_hint ( ) . 0 , None ) ,
2877+ [ first, .., last] => ( first. size_hint ( ) . 0 + last. size_hint ( ) . 0 , None ) ,
2878+ }
2879+ }
2880+ }
2881+
2882+ impl std:: iter:: FusedIterator for AllFields < ' _ > { }
2883+
27422884/// An item definition.
27432885#[ derive( Clone , Encodable , Decodable , Debug ) ]
27442886pub struct Item < K = ItemKind > {
0 commit comments