@@ -60,7 +60,8 @@ pub fn find_builtin_derive(ident: &name::Name) -> Option<BuiltinDeriveExpander>
60
60
61
61
struct BasicAdtInfo {
62
62
name : tt:: Ident ,
63
- type_or_const_params : usize ,
63
+ /// `Some(ty)` if it's a const param of type `ty`, `None` if it's a type param.
64
+ param_types : Vec < Option < tt:: Subtree > > ,
64
65
}
65
66
66
67
fn parse_adt ( tt : & tt:: Subtree ) -> Result < BasicAdtInfo , ExpandError > {
@@ -92,65 +93,50 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
92
93
let name_token_id =
93
94
token_map. token_by_range ( name. syntax ( ) . text_range ( ) ) . unwrap_or_else ( TokenId :: unspecified) ;
94
95
let name_token = tt:: Ident { id : name_token_id, text : name. text ( ) . into ( ) } ;
95
- let type_or_const_params =
96
- params. map_or ( 0 , |type_param_list| type_param_list. type_or_const_params ( ) . count ( ) ) ;
97
- Ok ( BasicAdtInfo { name : name_token, type_or_const_params } )
98
- }
99
-
100
- fn make_type_args ( n : usize , bound : Vec < tt:: TokenTree > ) -> Vec < tt:: TokenTree > {
101
- let mut result = Vec :: < tt:: TokenTree > :: with_capacity ( n * 2 ) ;
102
- result. push (
103
- tt:: Leaf :: Punct ( tt:: Punct {
104
- char : '<' ,
105
- spacing : tt:: Spacing :: Alone ,
106
- id : tt:: TokenId :: unspecified ( ) ,
107
- } )
108
- . into ( ) ,
109
- ) ;
110
- for i in 0 ..n {
111
- if i > 0 {
112
- result. push (
113
- tt:: Leaf :: Punct ( tt:: Punct {
114
- char : ',' ,
115
- spacing : tt:: Spacing :: Alone ,
116
- id : tt:: TokenId :: unspecified ( ) ,
117
- } )
118
- . into ( ) ,
119
- ) ;
120
- }
121
- result. push (
122
- tt:: Leaf :: Ident ( tt:: Ident {
123
- id : tt:: TokenId :: unspecified ( ) ,
124
- text : format ! ( "T{}" , i) . into ( ) ,
125
- } )
126
- . into ( ) ,
127
- ) ;
128
- result. extend ( bound. iter ( ) . cloned ( ) ) ;
129
- }
130
- result. push (
131
- tt:: Leaf :: Punct ( tt:: Punct {
132
- char : '>' ,
133
- spacing : tt:: Spacing :: Alone ,
134
- id : tt:: TokenId :: unspecified ( ) ,
96
+ let param_types = params
97
+ . into_iter ( )
98
+ . flat_map ( |param_list| param_list. type_or_const_params ( ) )
99
+ . map ( |param| {
100
+ if let ast:: TypeOrConstParam :: Const ( param) = param {
101
+ let ty = param
102
+ . ty ( )
103
+ . map ( |ty| mbe:: syntax_node_to_token_tree ( ty. syntax ( ) ) . 0 )
104
+ . unwrap_or_default ( ) ;
105
+ Some ( ty)
106
+ } else {
107
+ None
108
+ }
135
109
} )
136
- . into ( ) ,
137
- ) ;
138
- result
110
+ . collect ( ) ;
111
+ Ok ( BasicAdtInfo { name : name_token, param_types } )
139
112
}
140
113
141
114
fn expand_simple_derive ( tt : & tt:: Subtree , trait_path : tt:: Subtree ) -> ExpandResult < tt:: Subtree > {
142
115
let info = match parse_adt ( tt) {
143
116
Ok ( info) => info,
144
117
Err ( e) => return ExpandResult :: only_err ( e) ,
145
118
} ;
119
+ let ( params, args) : ( Vec < _ > , Vec < _ > ) = info
120
+ . param_types
121
+ . into_iter ( )
122
+ . enumerate ( )
123
+ . map ( |( idx, param_ty) | {
124
+ let ident = tt:: Leaf :: Ident ( tt:: Ident {
125
+ id : tt:: TokenId :: unspecified ( ) ,
126
+ text : format ! ( "T{idx}" ) . into ( ) ,
127
+ } ) ;
128
+ let ident_ = ident. clone ( ) ;
129
+ if let Some ( ty) = param_ty {
130
+ ( quote ! { const #ident : #ty , } , quote ! { #ident_ , } )
131
+ } else {
132
+ let bound = trait_path. clone ( ) ;
133
+ ( quote ! { #ident : #bound , } , quote ! { #ident_ , } )
134
+ }
135
+ } )
136
+ . unzip ( ) ;
146
137
let name = info. name ;
147
- let trait_path_clone = trait_path. token_trees . clone ( ) ;
148
- let bound = ( quote ! { : ##trait_path_clone } ) . token_trees ;
149
- let type_params = make_type_args ( info. type_or_const_params , bound) ;
150
- let type_args = make_type_args ( info. type_or_const_params , Vec :: new ( ) ) ;
151
- let trait_path = trait_path. token_trees ;
152
138
let expanded = quote ! {
153
- impl ##type_params ## trait_path for #name ##type_args { }
139
+ impl < ##params > # trait_path for #name < ##args > { }
154
140
} ;
155
141
ExpandResult :: ok ( expanded)
156
142
}
0 commit comments