@@ -32,20 +32,33 @@ impl Parse for Attrs {
32
32
}
33
33
}
34
34
35
- struct MakeVariant {
36
- name : Ident ,
37
- #[ allow( unused) ]
38
- colon : Token ! [ : ] ,
39
- bounds : Punctuated < TraitBound , Plus > ,
35
+ enum MakeVariant {
36
+ // Creates a variant of a trait under a new name with additional bounds while preserving the original trait.
37
+ Create {
38
+ name : Ident ,
39
+ _colon : Token ! [ : ] ,
40
+ bounds : Punctuated < TraitBound , Plus > ,
41
+ } ,
42
+ // Rewrites the original trait into a new trait with additional bounds.
43
+ Rewrite {
44
+ bounds : Punctuated < TraitBound , Plus > ,
45
+ } ,
40
46
}
41
47
42
48
impl Parse for MakeVariant {
43
49
fn parse ( input : ParseStream ) -> Result < Self > {
44
- Ok ( Self {
45
- name : input. parse ( ) ?,
46
- colon : input. parse ( ) ?,
47
- bounds : input. parse_terminated ( TraitBound :: parse, Token ! [ +] ) ?,
48
- } )
50
+ let variant = if input. peek ( Ident ) && input. peek2 ( Token ! [ : ] ) {
51
+ MakeVariant :: Create {
52
+ name : input. parse ( ) ?,
53
+ _colon : input. parse ( ) ?,
54
+ bounds : input. parse_terminated ( TraitBound :: parse, Token ! [ +] ) ?,
55
+ }
56
+ } else {
57
+ MakeVariant :: Rewrite {
58
+ bounds : input. parse_terminated ( TraitBound :: parse, Token ! [ +] ) ?,
59
+ }
60
+ } ;
61
+ Ok ( variant)
49
62
}
50
63
}
51
64
@@ -56,43 +69,51 @@ pub fn make(
56
69
let attrs = parse_macro_input ! ( attr as Attrs ) ;
57
70
let item = parse_macro_input ! ( item as ItemTrait ) ;
58
71
59
- let maybe_allow_async_lint = if attrs
60
- . variant
61
- . bounds
62
- . iter ( )
63
- . any ( |b| b. path . segments . last ( ) . unwrap ( ) . ident == "Send" )
64
- {
65
- quote ! { #[ allow( async_fn_in_trait) ] }
66
- } else {
67
- quote ! { }
68
- } ;
72
+ match attrs. variant {
73
+ MakeVariant :: Create { name , bounds , .. } => {
74
+ let maybe_allow_async_lint = if bounds
75
+ . iter ( )
76
+ . any ( |b| b. path . segments . last ( ) . unwrap ( ) . ident == "Send" )
77
+ {
78
+ quote ! { #[ allow( async_fn_in_trait) ] }
79
+ } else {
80
+ quote ! { }
81
+ } ;
69
82
70
- let variant = mk_variant ( & attrs , & item) ;
71
- let blanket_impl = mk_blanket_impl ( & attrs , & item) ;
83
+ let variant = mk_variant ( & name , bounds , & item) ;
84
+ let blanket_impl = mk_blanket_impl ( & name , & item) ;
72
85
73
- quote ! {
74
- #maybe_allow_async_lint
75
- #item
86
+ quote ! {
87
+ #maybe_allow_async_lint
88
+ #item
76
89
77
- #variant
90
+ #variant
78
91
79
- #blanket_impl
92
+ #blanket_impl
93
+ }
94
+ . into ( )
95
+ }
96
+ MakeVariant :: Rewrite { bounds, .. } => {
97
+ let variant = mk_variant ( & item. ident , bounds, & item) ;
98
+ quote ! {
99
+ #variant
100
+ }
101
+ . into ( )
102
+ }
80
103
}
81
- . into ( )
82
104
}
83
105
84
- fn mk_variant ( attrs : & Attrs , tr : & ItemTrait ) -> TokenStream {
85
- let MakeVariant {
86
- ref name,
87
- colon : _,
88
- ref bounds,
89
- } = attrs. variant ;
90
- let bounds: Vec < _ > = bounds
106
+ fn mk_variant (
107
+ variant : & Ident ,
108
+ with_bounds : Punctuated < TraitBound , Plus > ,
109
+ tr : & ItemTrait ,
110
+ ) -> TokenStream {
111
+ let bounds: Vec < _ > = with_bounds
91
112
. into_iter ( )
92
113
. map ( |b| TypeParamBound :: Trait ( b. clone ( ) ) )
93
114
. collect ( ) ;
94
115
let variant = ItemTrait {
95
- ident : name . clone ( ) ,
116
+ ident : variant . clone ( ) ,
96
117
supertraits : tr. supertraits . iter ( ) . chain ( & bounds) . cloned ( ) . collect ( ) ,
97
118
items : tr
98
119
. items
@@ -104,21 +125,8 @@ fn mk_variant(attrs: &Attrs, tr: &ItemTrait) -> TokenStream {
104
125
quote ! { #variant }
105
126
}
106
127
128
+ // Transforms a one item declaration within the definition if it has `async fn` and/or `-> impl Trait` return types by adding new bounds.
107
129
fn transform_item ( item : & TraitItem , bounds : & Vec < TypeParamBound > ) -> TraitItem {
108
- // #[make_variant(SendIntFactory: Send)]
109
- // trait IntFactory {
110
- // async fn make(&self, x: u32, y: &str) -> i32;
111
- // fn stream(&self) -> impl Iterator<Item = i32>;
112
- // fn call(&self) -> u32;
113
- // }
114
- //
115
- // becomes:
116
- //
117
- // trait SendIntFactory: Send {
118
- // fn make(&self, x: u32, y: &str) -> impl ::core::future::Future<Output = i32> + Send;
119
- // fn stream(&self) -> impl Iterator<Item = i32> + Send;
120
- // fn call(&self) -> u32;
121
- // }
122
130
let TraitItem :: Fn ( fn_item @ TraitItemFn { sig, .. } ) = item else {
123
131
return item. clone ( ) ;
124
132
} ;
@@ -160,9 +168,8 @@ fn transform_item(item: &TraitItem, bounds: &Vec<TypeParamBound>) -> TraitItem {
160
168
} )
161
169
}
162
170
163
- fn mk_blanket_impl ( attrs : & Attrs , tr : & ItemTrait ) -> TokenStream {
171
+ fn mk_blanket_impl ( variant : & Ident , tr : & ItemTrait ) -> TokenStream {
164
172
let orig = & tr. ident ;
165
- let variant = & attrs. variant . name ;
166
173
let ( _impl, orig_ty_generics, _where) = & tr. generics . split_for_impl ( ) ;
167
174
let items = tr
168
175
. items
0 commit comments