@@ -2074,10 +2074,6 @@ pub enum TyKind {
2074
2074
Never ,
2075
2075
/// A tuple (`(A, B, C, D,...)`).
2076
2076
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 > ) ,
2081
2077
/// A path (`module::module::...::Type`), optionally
2082
2078
/// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
2083
2079
///
@@ -2721,6 +2717,93 @@ impl VisibilityKind {
2721
2717
}
2722
2718
}
2723
2719
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
+
2724
2807
/// Field definition in a struct, variant or union.
2725
2808
///
2726
2809
/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
@@ -2732,7 +2815,7 @@ pub struct FieldDef {
2732
2815
pub vis : Visibility ,
2733
2816
pub ident : Option < Ident > ,
2734
2817
2735
- pub ty : P < Ty > ,
2818
+ pub ty : FieldTy ,
2736
2819
pub is_placeholder : bool ,
2737
2820
}
2738
2821
@@ -2762,6 +2845,27 @@ impl VariantData {
2762
2845
}
2763
2846
}
2764
2847
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
+
2765
2869
/// Return the `NodeId` of this variant's constructor, if it has one.
2766
2870
pub fn ctor_node_id ( & self ) -> Option < NodeId > {
2767
2871
match * self {
@@ -2771,6 +2875,44 @@ impl VariantData {
2771
2875
}
2772
2876
}
2773
2877
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
+
2774
2916
/// An item definition.
2775
2917
#[ derive( Clone , Encodable , Decodable , Debug ) ]
2776
2918
pub struct Item < K = ItemKind > {
0 commit comments