/home/runner/work/bare_err_tree/bare_err_tree/bare_err_tree_proc/src/lib.rs
Line | Count | Source |
1 | | /* |
2 | | * This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at https://mozilla.org/MPL/2.0/. |
5 | | */ |
6 | | |
7 | | //! Derive macros for `bare_err_tree`. |
8 | | |
9 | | #![cfg_attr(docsrs, feature(doc_auto_cfg))] |
10 | | #![cfg_attr(coverage, feature(coverage_attribute))] |
11 | | |
12 | | extern crate proc_macro; |
13 | | use core::panic; |
14 | | |
15 | | use proc_macro::{Span, TokenStream}; |
16 | | use quote::{quote, ToTokens}; |
17 | | use syn::{ |
18 | | parse::Parser, parse_macro_input, punctuated::Punctuated, token::Brace, Attribute, Data, |
19 | | DataStruct, DeriveInput, Error, Field, Fields, FieldsNamed, Generics, Ident, Meta, Visibility, |
20 | | }; |
21 | | |
22 | | mod errtype; |
23 | | use errtype::*; |
24 | | mod boiler; |
25 | | use boiler::*; |
26 | | mod fields; |
27 | | use fields::*; |
28 | | |
29 | | /// Implements a type as an error tree. |
30 | | /// |
31 | | /// The struct must define [`Error`](`core::error::Error`) and be annotated with `#[err_tree]` above |
32 | | /// any attributes relying on a full field definition. The type must then be |
33 | | /// internally constructed with `Self::_tree` to capture extra error |
34 | | /// information in a hidden field. |
35 | | /// |
36 | | /// Any derive such as [`Clone`] that relies on all fields being present must |
37 | | /// occur after the `#[err_tree]` macro. The `_err_tree_pkg` field will |
38 | | /// otherwise be added late and break the derivation. |
39 | | /// |
40 | | /// # `Self::_tree` |
41 | | /// This is an internal-use constructor that takes all struct fields in order. |
42 | | /// Use `#[track_caller]` on any functions calling `Self::_tree` to store the |
43 | | /// callsite correctly. |
44 | | /// [Open an issue or PR](<https://github.com/Bennett-Petzold/bare_err_tree>) |
45 | | /// if this hidden field degrades a struct's API (aside from requiring a |
46 | | /// constructor method). |
47 | | /// |
48 | | /// #### Example |
49 | | /// ``` |
50 | 1 | /// # #![cfg_attr(coverage, feature(coverage_attribute))] |
51 | | /// # use std::{error::Error, fmt::{self, Debug, Display, Formatter}}; |
52 | | /// use bare_err_tree::{err_tree, tree_unwrap}; |
53 | | /// |
54 | | /// #[err_tree] |
55 | | /// #[derive(Debug)] |
56 | | /// struct Foo { |
57 | | /// num: i32, |
58 | | /// } |
59 | | /// |
60 | | /// impl Foo { |
61 | | /// # #[cfg_attr(coverage, coverage(off))] |
62 | | /// #[track_caller] |
63 | | /// pub fn new(num: i32) -> Self { |
64 | | /// Foo::_tree(num) |
65 | | /// } |
66 | | /// } |
67 | | /// |
68 | | /// impl Error for Foo { |
69 | | /// # #[cfg_attr(coverage, coverage(off))] |
70 | | /// fn source(&self) -> Option<&(dyn Error + 'static)> { |
71 | | /// # /* |
72 | | /// ... |
73 | | /// # */ |
74 | | /// # unimplemented!() |
75 | | /// } |
76 | | /// } |
77 | | /// impl Display for Foo { |
78 | | /// # #[cfg_attr(coverage, coverage(off))] |
79 | | /// fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
80 | | /// # /* |
81 | | /// ... |
82 | | /// # */ |
83 | | /// # unimplemented!() |
84 | | /// } |
85 | | /// } |
86 | 1 | /// ``` |
87 | | /// |
88 | | /// # Field Annotations |
89 | | /// The macro needs annotations for underlying source fields. |
90 | | /// |
91 | | /// #### Single Item |
92 | | /// * `tree_err`: Mark a field as a `ErrTree` implementing [`Error`](`core::error::Error`). |
93 | | /// * `dyn_err`: Mark a field as a generic [`Error`](`core::error::Error`). |
94 | | /// |
95 | | /// #### Collection |
96 | | /// `*_iter_err` works on any type with a `.iter()` method returning its items. |
97 | | /// |
98 | | /// * `tree_iter_err`: Mark a field as a collection of `ErrTree` implementing [`Error`](`core::error::Error`)s. |
99 | | /// * `dyn_iter_err`: Mark a field as a collection of generic [`Error`](`core::error::Error`)s. |
100 | | /// |
101 | | /// `*_iter_err` does not allocate for arrays with a known length. |
102 | | /// The `derive_alloc` feature enables generation of allocating code to support |
103 | | /// dynamically sized collections. |
104 | | /// |
105 | | /// #### Example |
106 | | /// ``` |
107 | | /// # #![cfg_attr(coverage, feature(coverage_attribute))] |
108 | | /// # use std::{any::Any, error::Error, fmt::{self, Debug, Display, Formatter}}; |
109 | | /// use bare_err_tree::{err_tree, tree_unwrap, AsErrTree, ErrTree}; |
110 | | /// |
111 | | /// #[err_tree] |
112 | | /// #[derive(Debug)] |
113 | | /// struct Foo { |
114 | | /// #[dyn_err] |
115 | | /// io_err: std::io::Error, |
116 | | /// #[dyn_iter_err] |
117 | | /// extra_io_errs: [std::io::Error; 5], |
118 | | /// } |
119 | | /// |
120 | | /// impl Foo { |
121 | | /// # #[cfg_attr(coverage, coverage(off))] |
122 | | /// #[track_caller] |
123 | | /// pub fn new(io_err: std::io::Error, extra_io_errs: [std::io::Error; 5]) -> Self { |
124 | | /// Foo::_tree(io_err, extra_io_errs) |
125 | | /// } |
126 | | /// } |
127 | | /// |
128 | | /// impl Error for Foo { |
129 | | /// # #[cfg_attr(coverage, coverage(off))] |
130 | | /// fn source(&self) -> Option<&(dyn Error + 'static)> { |
131 | | /// # /* |
132 | | /// ... |
133 | | /// # */ |
134 | | /// # unimplemented!() |
135 | | /// } |
136 | | /// } |
137 | | /// impl Display for Foo { |
138 | | /// # #[cfg_attr(coverage, coverage(off))] |
139 | | /// fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
140 | | /// # /* |
141 | | /// ... |
142 | | /// # */ |
143 | | /// # unimplemented!() |
144 | | /// } |
145 | | /// } |
146 | | /// |
147 | 1 | /// fn main() { |
148 | 1 | /// // Make a Foo of all EOF errors |
149 | 6 | /// let eof_gen = || std::io::Error::from(std::io::ErrorKind::UnexpectedEof); |
150 | 5 | /// let err = Foo::new(eof_gen(), std::array::from1 _fn(|_| eof_gen())); |
151 | 1 | /// |
152 | 1 | /// // Confirm exactly six sources from annotation |
153 | 1 | /// err.as_err_tree(&mut |tree| { |
154 | 1 | /// let sources = tree.sources(); |
155 | 1 | /// assert_eq!(sources.count(), 6); |
156 | 1 | /// }); |
157 | 1 | /// } |
158 | | /// ``` |
159 | | /// |
160 | | /// # Generating a Wrapper |
161 | | /// `#[err_tree(WRAPPER)]` will generate a wrapper struct for storing metadata. |
162 | | /// Enums need this form, as a hidden field cannot be added to the enum. |
163 | | /// `WRAPPER` provides [`From`](`core::convert::From`) both ways and |
164 | | /// [`Deref`](`core::ops::Deref`)/[`DerefMut`](`core::ops::DerefMut`) to be |
165 | | /// maximally transparent. |
166 | | /// Some derives are automatically re-derived for the wrapper; any other traits |
167 | | /// that need to be implemented for the wrapper can be written manually. |
168 | | /// |
169 | | /// #### Wrapper automatic re-derives |
170 | | // https://doc.rust-lang.org/rust-by-example/trait/derive.html |
171 | | /// [`Eq`](`core::cmp::Eq`), [`PartialEq`](`core::cmp::PartialEq`), |
172 | | /// [`Ord`](`core::cmp::Ord`), [`PartialOrd`](`core::cmp::PartialOrd`), |
173 | | /// [`Clone`](`core::clone::Clone`), [`Hash`](`core::hash::Hash`), |
174 | | /// [`Default`](`core::default::Default). |
175 | | /// |
176 | | /// #### Enum Example |
177 | | /// ``` |
178 | | /// # #![cfg_attr(coverage, feature(coverage_attribute))] |
179 | | /// # use std::{error::Error, fmt::{self, Debug, Display, Formatter}}; |
180 | | /// use bare_err_tree::{err_tree, tree_unwrap}; |
181 | | /// |
182 | | /// // Generates `FooWrap<T: Debug>` |
183 | | /// #[err_tree(FooWrap)] |
184 | | /// #[derive(Debug)] |
185 | | /// enum Foo<T: Debug> { |
186 | | /// Val(T), |
187 | | /// #[dyn_err] |
188 | | /// Single(std::io::Error), |
189 | | /// #[dyn_iter_err] |
190 | | /// Many([std::io::Error; 5]), |
191 | | /// } |
192 | | /// |
193 | | /// impl<T: Debug> Error for Foo<T> { |
194 | | /// # #[cfg_attr(coverage, coverage(off))] |
195 | | /// fn source(&self) -> Option<&(dyn Error + 'static)> { |
196 | | /// # /* |
197 | | /// ... |
198 | | /// # */ |
199 | | /// # unimplemented!() |
200 | | /// } |
201 | | /// } |
202 | | /// impl<T: Debug> Display for Foo<T> { |
203 | | /// # #[cfg_attr(coverage, coverage(off))] |
204 | | /// fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
205 | | /// # /* |
206 | | /// ... |
207 | | /// # */ |
208 | | /// # unimplemented!() |
209 | | /// } |
210 | | /// } |
211 | | /// |
212 | | /// fn main() { |
213 | | /// let wrapped = FooWrap::from(Foo::Val(8_i32)); |
214 | | /// assert!(matches!(*wrapped, Foo::Val(8_i32))); |
215 | | /// } |
216 | | /// |
217 | | /// ``` |
218 | | /// |
219 | | /// # Full Usage Example: |
220 | | /// ``` |
221 | | /// # use std::{error::Error, fmt::{self, Debug, Display, Formatter}}; |
222 | | /// use bare_err_tree::{err_tree, tree_unwrap}; |
223 | | /// |
224 | | /// #[err_tree] |
225 | | /// #[derive(Debug)] |
226 | | /// struct Foo { |
227 | | /// #[dyn_err] |
228 | | /// io_err: std::io::Error, |
229 | | /// #[dyn_iter_err] |
230 | | /// extra_io_errs: [std::io::Error; 5], |
231 | | /// } |
232 | | /// |
233 | | /// impl Foo { |
234 | 1 | /// #[track_caller] |
235 | 1 | /// pub fn new(io_err: std::io::Error, extra_io_errs: [std::io::Error; 5]) -> Self { |
236 | 1 | /// Foo::_tree(io_err, extra_io_errs) |
237 | | /// } |
238 | | /// } |
239 | | /// |
240 | 0 | /// impl Error for Foo { |
241 | 0 | /// fn source(&self) -> Option<&(dyn Error + 'static)> { |
242 | 0 | /// Some(&self.io_err) |
243 | | /// } |
244 | | /// } |
245 | 1 | /// impl Display for Foo { |
246 | 1 | /// fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
247 | 1 | /// # /* |
248 | 1 | /// ... |
249 | 1 | /// # */ |
250 | 1 | /// # Display::fmt(&self.io_err, f) |
251 | | /// } |
252 | | /// } |
253 | | /// |
254 | 1 | /// /// Always return the error with tree formatting support |
255 | 6 | /// pub fn always_fail() -> Result<(), Foo> { |
256 | 1 | /// # let get_err = || std::io::Error::from(std::io::ErrorKind::UnexpectedEof); |
257 | 1 | /// Err(Foo::new( |
258 | 1 | /// # /* |
259 | 1 | /// ... |
260 | 5 | /// # */ |
261 | 1 | /// # get_err(), std::array::from_fn(|_| get_err()), |
262 | 1 | /// )) |
263 | | /// } |
264 | | /// |
265 | | /// const MAX_DEPTH: usize = 10; |
266 | | /// const MAX_CHARS: usize = MAX_DEPTH * 6; |
267 | | /// |
268 | | /// pub fn main() { |
269 | | /// # let _ = std::panic::catch_unwind(|| { |
270 | | /// let result = always_fail(); |
271 | | /// |
272 | | /// /// Fancy display panic with a maximum tree depth of 10 errors |
273 | | /// tree_unwrap::<MAX_CHARS, _, _>(result); |
274 | | /// # }); |
275 | | /// } |
276 | | /// ``` |
277 | | #[proc_macro_attribute] |
278 | 4 | pub fn err_tree(args: TokenStream, input: TokenStream) -> TokenStream { |
279 | 4 | let args = parse_macro_input!(args with Punctuated::<Meta, syn::Token![,]>::parse_terminated); |
280 | | |
281 | 4 | let name_attribute = name_attribute(&args); |
282 | | |
283 | | let DeriveInput { |
284 | 4 | attrs, |
285 | 4 | vis, |
286 | 4 | ident, |
287 | 4 | generics, |
288 | 4 | mut data, |
289 | 4 | } = parse_macro_input!(input as DeriveInput); |
290 | | |
291 | 4 | let generated = match data { |
292 | | // Only structs are directly valid for injecting the hidden field |
293 | 3 | Data::Struct(ref mut data) => { |
294 | 3 | let errs: Vec<_> = get_struct_macros(data).collect(); |
295 | | |
296 | 3 | if let Some(name_attribute0 ) = name_attribute { |
297 | 0 | foreign_err_tree( |
298 | 0 | &ident, |
299 | 0 | &vis, |
300 | 0 | &attrs, |
301 | 0 | name_attribute, |
302 | 0 | &generics, |
303 | 0 | &errs, |
304 | 0 | Foreign::Struct, |
305 | 0 | ) |
306 | | } else { |
307 | 3 | clean_struct_macros(data); |
308 | 3 | err_tree_struct(&ident, &vis, &generics, data, &errs, Foreign::Not) |
309 | | } |
310 | | } |
311 | | // Enums can be handled by a generated wrapping struct |
312 | 1 | Data::Enum(ref mut data) => { |
313 | 1 | let errs: Vec<_> = get_enum_macros(data).collect(); |
314 | 1 | clean_enum_macros(data); |
315 | | |
316 | 1 | if let Some(name_attribute) = name_attribute { |
317 | 1 | foreign_err_tree( |
318 | 1 | &ident, |
319 | 1 | &vis, |
320 | 1 | &attrs, |
321 | 1 | name_attribute, |
322 | 1 | &generics, |
323 | 1 | &errs, |
324 | 1 | Foreign::Enum(&ident), |
325 | 1 | ) |
326 | | } else { |
327 | 0 | TokenStream::from( |
328 | 0 | Error::new( |
329 | 0 | Span::call_site().into(), |
330 | 0 | "err_tree cannot implement directly on an enum type. Use '#[err_tree(WRAPPER)]'", |
331 | 0 | ) |
332 | 0 | .into_compile_error(), |
333 | 0 | ) |
334 | | } |
335 | | } |
336 | | // This datatype is barely used -- mostly C interop -- so the lack of |
337 | | // functionality doesn't really matter. I've never seen a Union Error. |
338 | 0 | Data::Union(_) => TokenStream::from( |
339 | 0 | Error::new( |
340 | 0 | Span::call_site().into(), |
341 | 0 | "err_tree cannot be annotated on union types", |
342 | 0 | ) |
343 | 0 | .into_compile_error(), |
344 | 0 | ), |
345 | | }; |
346 | | |
347 | 4 | TokenStream::from_iter([ |
348 | 4 | DeriveInput { |
349 | 4 | attrs, |
350 | 4 | vis, |
351 | 4 | ident, |
352 | 4 | generics, |
353 | 4 | data, |
354 | 4 | } |
355 | 4 | .into_token_stream() |
356 | 4 | .into(), |
357 | 4 | generated, |
358 | 4 | ]) |
359 | 4 | } |
360 | | |
361 | | #[derive(Debug)] |
362 | | enum Foreign<'a> { |
363 | | /// Direct struct generation |
364 | | Not, |
365 | | /// Wrapper around a struct, doesn't need a defined ident |
366 | | Struct, |
367 | | /// Wrapper around an enum, needs an enum ident for pattern matching |
368 | | Enum(&'a Ident), |
369 | | } |
370 | | |
371 | | /// Generate a foreign wrapper. |
372 | | /// |
373 | | /// Boilerplates a wrapper notice into docs, copies all struct docs, creates |
374 | | /// automatic Deref and From impls, and re-derives known trivial methods. |
375 | | /// |
376 | | /// Concludes with a call to [`err_tree_struct`]. |
377 | 1 | fn foreign_err_tree( |
378 | 1 | ident: &Ident, |
379 | 1 | vis: &Visibility, |
380 | 1 | attrs: &[Attribute], |
381 | 1 | name_attribute: &Ident, |
382 | 1 | generics: &Generics, |
383 | 1 | errs: &[TreeErr], |
384 | 1 | foreign_type: Foreign, |
385 | 1 | ) -> TokenStream { |
386 | 1 | let (_, ty_generics, _) = generics.split_for_impl(); |
387 | 1 | |
388 | 1 | let doc_attrs = attrs.iter().filter(|x| { |
389 | 1 | if let Ok(x0 ) = x.meta.require_name_value() { |
390 | 0 | if let Some(x) = x.path.get_ident() { |
391 | 0 | x == "doc" |
392 | | } else { |
393 | 0 | false |
394 | | } |
395 | | } else { |
396 | 1 | false |
397 | | } |
398 | 1 | }); |
399 | 1 | |
400 | 1 | let ident_link = format!("Wrapper for [`{ident}`] generated by [`bare_err_tree`]."); |
401 | 1 | let wrapper_struct: TokenStream = quote! { |
402 | 1 | #[doc = #ident_link] |
403 | 1 | /// |
404 | 1 | #(#doc_attrs)* |
405 | 1 | #vis struct #name_attribute #generics { |
406 | 1 | inner: #ident #ty_generics, |
407 | 1 | } |
408 | 1 | } |
409 | 1 | .into(); |
410 | | |
411 | 1 | let mut wrapper_struct = parse_macro_input!(wrapper_struct as DeriveInput); |
412 | | |
413 | 1 | if let Data::Struct(ref mut wrapper_struct_data) = &mut wrapper_struct.data { |
414 | 1 | let boilerplate = wrapper_boilerplate(ident, generics, attrs, name_attribute); |
415 | 1 | let generated_impl = err_tree_struct( |
416 | 1 | name_attribute, |
417 | 1 | vis, |
418 | 1 | &wrapper_struct.generics, |
419 | 1 | wrapper_struct_data, |
420 | 1 | errs, |
421 | 1 | foreign_type, |
422 | 1 | ); |
423 | 1 | TokenStream::from_iter([ |
424 | 1 | wrapper_struct.to_token_stream().into(), |
425 | 1 | boilerplate, |
426 | 1 | generated_impl, |
427 | 1 | ]) |
428 | | } else { |
429 | 0 | panic!("The wrapper is always a struct!") |
430 | | } |
431 | 1 | } |
432 | | |
433 | | /// Injects `_err_tree_pkg`, the `_tree` constructor, and the `_as_err_tree` |
434 | | /// impl. |
435 | 4 | fn err_tree_struct( |
436 | 4 | ident: &Ident, |
437 | 4 | vis: &Visibility, |
438 | 4 | generics: &Generics, |
439 | 4 | data: &mut DataStruct, |
440 | 4 | errs: &[TreeErr], |
441 | 4 | foreign: Foreign<'_>, |
442 | 4 | ) -> TokenStream { |
443 | 4 | let FieldsStrip { |
444 | 4 | bounds: field_bounds, |
445 | 4 | idents: field_names, |
446 | 4 | } = strip_fields(&data.fields); |
447 | | |
448 | | // Generate the with_pkg call on all notated sources |
449 | 4 | let sources = match foreign { |
450 | 3 | Foreign::Not => gen_sources_struct(errs, false), |
451 | 0 | Foreign::Struct => gen_sources_struct(errs, true), |
452 | 1 | Foreign::Enum(ident) => gen_sources_enum(errs, ident), |
453 | | }; |
454 | 4 | let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); |
455 | 4 | |
456 | 4 | match &mut data.fields { |
457 | | // Struct with fields like { a: usize, b: usize } |
458 | 4 | Fields::Named(fields) => { |
459 | 4 | // Insert the pkg field |
460 | 4 | let field_ident = proc_macro2::Ident::new("_err_tree_pkg", Span::call_site().into()); |
461 | 4 | fields.named.push( |
462 | 4 | Field::parse_named |
463 | 4 | .parse2(quote! { #field_ident: ::bare_err_tree::ErrTreePkg }) |
464 | 4 | .unwrap(), |
465 | 4 | ); |
466 | 4 | let field_ident = field_ident.into_token_stream(); |
467 | 4 | |
468 | 4 | quote! { |
469 | 4 | #[automatically_derived] |
470 | 4 | impl #impl_generics ::bare_err_tree::AsErrTree for #ident #ty_generics #where_clause { |
471 | 4 | #[track_caller] |
472 | 4 | fn as_err_tree(&self, func: &mut dyn FnMut(::bare_err_tree::ErrTree<'_>)) { |
473 | 4 | let _err_tree_pkg = &self.#field_ident; |
474 | 4 | #sources |
475 | 4 | } |
476 | 4 | } |
477 | 4 | |
478 | 4 | #[automatically_derived] |
479 | 4 | impl #impl_generics #ident #ty_generics #where_clause { |
480 | 4 | #[track_caller] |
481 | 4 | #[allow(clippy::too_many_arguments)] |
482 | 4 | fn _tree(#field_bounds) -> Self { |
483 | 4 | let #field_ident = ::bare_err_tree::ErrTreePkg::new(); |
484 | 4 | Self { |
485 | 4 | #(#field_names,)* |
486 | 4 | #field_ident |
487 | 4 | } |
488 | 4 | } |
489 | 4 | } |
490 | 4 | } |
491 | 4 | .into() |
492 | | } |
493 | | // Struct with fields like ( usize, usize ) |
494 | 0 | Fields::Unnamed(fields) => { |
495 | 0 | // Insert the pkg field |
496 | 0 | let prev_len = syn::Index::from(fields.unnamed.len()); |
497 | 0 | fields.unnamed.push( |
498 | 0 | Field::parse_unnamed |
499 | 0 | .parse2(quote! { ::bare_err_tree::ErrTreePkg }) |
500 | 0 | .unwrap(), |
501 | 0 | ); |
502 | 0 |
|
503 | 0 | quote! { |
504 | 0 | #[automatically_derived] |
505 | 0 | impl #impl_generics ::bare_err_tree::AsErrTree for #ident #ty_generics #where_clause { |
506 | 0 | #[track_caller] |
507 | 0 | fn as_err_tree(&self, func: &mut dyn FnMut(::bare_err_tree::ErrTree<'_>)) { |
508 | 0 | let _err_tree_pkg = &self.#prev_len; |
509 | 0 | #sources |
510 | 0 | } |
511 | 0 | } |
512 | 0 |
|
513 | 0 | #[automatically_derived] |
514 | 0 | impl #impl_generics #ident #ty_generics #where_clause { |
515 | 0 | #[track_caller] |
516 | 0 | #[allow(clippy::too_many_arguments)] |
517 | 0 | fn _tree(#field_bounds) -> Self { |
518 | 0 | let _err_tree_pkg = ::bare_err_tree::ErrTreePkg::new(); |
519 | 0 | Self ( |
520 | 0 | #(#field_names,)* |
521 | 0 | _err_tree_pkg |
522 | 0 | ) |
523 | 0 | } |
524 | 0 | } |
525 | 0 | } |
526 | 0 | .into() |
527 | | } |
528 | | // Transmutes a unit struct into a named struct for pkg injection |
529 | | // Adds new and default methods for easy construction |
530 | | Fields::Unit => { |
531 | | // Insert the pkg field |
532 | 0 | let field_ident = proc_macro2::Ident::new("_err_tree_pkg", Span::call_site().into()); |
533 | 0 | let mut named = Punctuated::default(); |
534 | 0 | named.push( |
535 | 0 | Field::parse_named |
536 | 0 | .parse2(quote! { #field_ident: ::bare_err_tree::ErrTreePkg }) |
537 | 0 | .unwrap(), |
538 | 0 | ); |
539 | 0 | let field_ident = field_ident.into_token_stream(); |
540 | 0 | data.fields = Fields::Named(FieldsNamed { |
541 | 0 | brace_token: Brace::default(), |
542 | 0 | named, |
543 | 0 | }); |
544 | 0 |
|
545 | 0 | quote! { |
546 | 0 | #[automatically_derived] |
547 | 0 | impl #impl_generics ::bare_err_tree::AsErrTree for #ident #ty_generics #where_clause { |
548 | 0 | #[track_caller] |
549 | 0 | fn as_err_tree(&self, func: &mut dyn FnMut(::bare_err_tree::ErrTree<'_>)) { |
550 | 0 | let _err_tree_pkg = &self.#field_ident; |
551 | 0 | #sources |
552 | 0 | } |
553 | 0 | } |
554 | 0 |
|
555 | 0 | #[automatically_derived] |
556 | 0 | impl #impl_generics #ident #ty_generics #where_clause { |
557 | 0 | #[track_caller] |
558 | 0 | fn _tree() -> Self { |
559 | 0 | let #field_ident = ::bare_err_tree::ErrTreePkg::new(); |
560 | 0 | Self { |
561 | 0 | #field_ident |
562 | 0 | } |
563 | 0 | } |
564 | 0 | } |
565 | 0 |
|
566 | 0 | #[automatically_derived] |
567 | 0 | impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause { |
568 | 0 | #[track_caller] |
569 | 0 | fn default() -> Self { |
570 | 0 | Self::_tree() |
571 | 0 | } |
572 | 0 | } |
573 | 0 |
|
574 | 0 | #[automatically_derived] |
575 | 0 | impl #impl_generics #ident #ty_generics #where_clause { |
576 | 0 | #[track_caller] |
577 | 0 | #vis fn new() -> Self { |
578 | 0 | Self::_tree() |
579 | 0 | } |
580 | 0 | } |
581 | 0 | } |
582 | 0 | .into() |
583 | | } |
584 | | } |
585 | 4 | } |