@@ -32,7 +32,7 @@ pub fn expand(
32
32
} )
33
33
. collect ( ) ;
34
34
35
- let ( bounds, source, backtrace ) = match state. derive_type {
35
+ let ( bounds, source, provide ) = match state. derive_type {
36
36
DeriveType :: Named | DeriveType :: Unnamed => render_struct ( & type_params, & state) ?,
37
37
DeriveType :: Enum => render_enum ( & type_params, & state) ?,
38
38
} ;
@@ -45,11 +45,11 @@ pub fn expand(
45
45
}
46
46
} ) ;
47
47
48
- let backtrace = backtrace . map ( |backtrace | {
48
+ let provide = provide . map ( |provide | {
49
49
quote ! {
50
- fn backtrace ( & self ) -> Option < & :: std:: backtrace :: Backtrace > {
51
- #backtrace
52
- }
50
+ fn provide< ' _demand> ( & ' _demand self , demand : & mut :: std:: any :: Demand < ' _demand> ) {
51
+ #provide
52
+ }
53
53
}
54
54
} ) ;
55
55
@@ -82,7 +82,7 @@ pub fn expand(
82
82
let render = quote ! {
83
83
impl #impl_generics :: std:: error:: Error for #ident#ty_generics #where_clause {
84
84
#source
85
- #backtrace
85
+ #provide
86
86
}
87
87
} ;
88
88
@@ -96,9 +96,9 @@ fn render_struct(
96
96
let parsed_fields = parse_fields ( type_params, state) ?;
97
97
98
98
let source = parsed_fields. render_source_as_struct ( ) ;
99
- let backtrace = parsed_fields. render_backtrace_as_struct ( ) ;
99
+ let provide = parsed_fields. render_provide_as_struct ( ) ;
100
100
101
- Ok ( ( parsed_fields. bounds , source, backtrace ) )
101
+ Ok ( ( parsed_fields. bounds , source, provide ) )
102
102
}
103
103
104
104
fn render_enum (
@@ -107,7 +107,7 @@ fn render_enum(
107
107
) -> Result < ( HashSet < syn:: Type > , Option < TokenStream > , Option < TokenStream > ) > {
108
108
let mut bounds = HashSet :: default ( ) ;
109
109
let mut source_match_arms = Vec :: new ( ) ;
110
- let mut backtrace_match_arms = Vec :: new ( ) ;
110
+ let mut provide_match_arms = Vec :: new ( ) ;
111
111
112
112
for variant in state. enabled_variant_data ( ) . variants {
113
113
let default_info = FullMetaInfo {
@@ -131,35 +131,31 @@ fn render_enum(
131
131
source_match_arms. push ( expr) ;
132
132
}
133
133
134
- if let Some ( expr) = parsed_fields. render_backtrace_as_enum_variant_match_arm ( ) {
135
- backtrace_match_arms . push ( expr) ;
134
+ if let Some ( expr) = parsed_fields. render_provide_as_enum_variant_match_arm ( ) {
135
+ provide_match_arms . push ( expr) ;
136
136
}
137
137
138
138
bounds. extend ( parsed_fields. bounds . into_iter ( ) ) ;
139
139
}
140
140
141
- let render = |match_arms : & mut Vec < TokenStream > | {
141
+ let render = |match_arms : & mut Vec < TokenStream > , unmatched | {
142
142
if !match_arms. is_empty ( ) && match_arms. len ( ) < state. variants . len ( ) {
143
- match_arms. push ( quote ! ( _ => None ) ) ;
143
+ match_arms. push ( quote ! ( _ => #unmatched ) ) ;
144
144
}
145
145
146
- if !match_arms. is_empty ( ) {
147
- let expr = quote ! {
146
+ ( !match_arms. is_empty ( ) ) . then ( || {
147
+ quote ! {
148
148
match self {
149
149
#( #match_arms) , *
150
150
}
151
- } ;
152
-
153
- Some ( expr)
154
- } else {
155
- None
156
- }
151
+ }
152
+ } )
157
153
} ;
158
154
159
- let source = render ( & mut source_match_arms) ;
160
- let backtrace = render ( & mut backtrace_match_arms ) ;
155
+ let source = render ( & mut source_match_arms, quote ! ( None ) ) ;
156
+ let provide = render ( & mut provide_match_arms , quote ! ( ( ) ) ) ;
161
157
162
- Ok ( ( bounds, source, backtrace ) )
158
+ Ok ( ( bounds, source, provide ) )
163
159
}
164
160
165
161
fn allowed_attr_params ( ) -> AttrParams {
@@ -203,16 +199,67 @@ impl<'input, 'state> ParsedFields<'input, 'state> {
203
199
Some ( quote ! ( #pattern => #expr) )
204
200
}
205
201
206
- fn render_backtrace_as_struct ( & self ) -> Option < TokenStream > {
202
+ fn render_provide_as_struct ( & self ) -> Option < TokenStream > {
207
203
let backtrace = self . backtrace ?;
208
- let backtrace_expr = & self . data . members [ backtrace] ;
209
- Some ( quote ! ( Some ( & #backtrace_expr) ) )
204
+
205
+ let source_provider = self . source . map ( |source| {
206
+ let source_expr = & self . data . members [ source] ;
207
+ quote ! {
208
+ :: std:: error:: Error :: provide( & #source_expr, demand) ;
209
+ }
210
+ } ) ;
211
+ let backtrace_provider = self
212
+ . source
213
+ . filter ( |source| * source == backtrace)
214
+ . is_none ( )
215
+ . then ( || {
216
+ let backtrace_expr = & self . data . members [ backtrace] ;
217
+ quote ! {
218
+ demand. provide_ref:: <std:: backtrace:: Backtrace >( & #backtrace_expr) ;
219
+ }
220
+ } ) ;
221
+
222
+ ( source_provider. is_some ( ) || backtrace_provider. is_some ( ) ) . then ( || {
223
+ quote ! {
224
+ #backtrace_provider
225
+ #source_provider
226
+ }
227
+ } )
210
228
}
211
229
212
- fn render_backtrace_as_enum_variant_match_arm ( & self ) -> Option < TokenStream > {
230
+ fn render_provide_as_enum_variant_match_arm ( & self ) -> Option < TokenStream > {
213
231
let backtrace = self . backtrace ?;
214
- let pattern = self . data . matcher ( & [ backtrace] , & [ quote ! ( backtrace) ] ) ;
215
- Some ( quote ! ( #pattern => Some ( backtrace) ) )
232
+
233
+ match self . source {
234
+ Some ( source) if source == backtrace => {
235
+ let pattern = self . data . matcher ( & [ source] , & [ quote ! ( source) ] ) ;
236
+ Some ( quote ! {
237
+ #pattern => {
238
+ :: std:: error:: Error :: provide( source, demand) ;
239
+ }
240
+ } )
241
+ }
242
+ Some ( source) => {
243
+ let pattern = self . data . matcher (
244
+ & [ source, backtrace] ,
245
+ & [ quote ! ( source) , quote ! ( backtrace) ] ,
246
+ ) ;
247
+ Some ( quote ! {
248
+ #pattern => {
249
+ demand. provide_ref:: <std:: backtrace:: Backtrace >( backtrace) ;
250
+ :: std:: error:: Error :: provide( source, demand) ;
251
+ }
252
+ } )
253
+ }
254
+ None => {
255
+ let pattern = self . data . matcher ( & [ backtrace] , & [ quote ! ( backtrace) ] ) ;
256
+ Some ( quote ! {
257
+ #pattern => {
258
+ demand. provide_ref:: <std:: backtrace:: Backtrace >( backtrace) ;
259
+ }
260
+ } )
261
+ }
262
+ }
216
263
}
217
264
}
218
265
0 commit comments