1use proc_macro2::TokenStream;
2use std::collections::BTreeSet as Set;
3
4use quote::{format_ident, quote, quote_spanned, ToTokens};
5use syn::{
6 parse_quote, DeriveInput, Generics, Ident, ImplGenerics, Member, Result, Token, TypeGenerics,
7 Visibility, WhereClause,
8};
9
10use crate::ast::{DeriveType, Enum, Field, Input, Struct, Variant};
11use crate::attr::{Attrs, Trait};
12use crate::expand::display;
13use crate::generics::InferredBounds;
14use crate::span::MemberSpan;
15use crate::util::{fields_pat, from_initializer, type_is_option, unoptional_type, use_as_display};
16
17pub fn derive(input: &DeriveInput) -> TokenStream {
18 match try_expand(input) {
19 Ok(expanded) => expanded,
20 Err(error) => fallback(input, error),
27 }
28}
29
30fn try_expand(input: &DeriveInput) -> Result<TokenStream> {
31 let input = Input::from_syn(input, DeriveType::Error)?;
32 input.validate()?;
33 match input {
34 Input::Enum(input) => impl_enum(input),
35 Input::Struct(input) => impl_struct(input),
36 }
37}
38
39fn fallback(input: &DeriveInput, error: syn::Error) -> TokenStream {
40 let ty = &input.ident;
41 let vis = input.vis.to_token_stream();
42 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
43
44 let error = error.to_compile_error();
45 let static_lifetime = if input.generics.lifetimes().count() > 0 {
46 Some(quote! {<'static>})
47 } else {
48 Some(ty_generics.to_token_stream())
49 };
50
51 quote! {
52 #error
53
54 #[allow(unused_qualifications)]
55 #[automatically_derived]
56 impl #impl_generics ::core::error::Error for #ty #ty_generics #where_clause
57 where
58 for<'workaround> #ty #ty_generics: ::core::fmt::Debug,
61 {}
62
63 #[allow(unused_qualifications)]
64 #[automatically_derived]
65 impl #impl_generics ::core::fmt::Display for #ty #ty_generics #where_clause {
66 fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
67 ::core::unreachable!()
68 }
69 }
70
71 extern crate alloc;
72
73 #[allow(unused_qualifications)]
74 #[automatically_derived]
75 #[derive(Debug)]
76 #vis struct Ec #ty_generics (pub errore::span::Span<#ty #ty_generics>) #where_clause;
77
78 #[allow(unused_qualifications)]
79 #[automatically_derived]
80 impl #impl_generics errore::Metadata for #ty #ty_generics #where_clause {
81 fn name(&self) -> &'static str {
82 ::core::unreachable!()
83 }
84
85 fn id(&self) -> &'static errore::Id {
86 ::core::unreachable!()
87 }
88
89 fn target(&self) -> &'static str {
90 ::core::unreachable!()
91 }
92
93 fn target_id(&self) -> &'static errore::Id {
94 ::core::unreachable!()
95 }
96
97 fn display(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
98 ::core::unreachable!()
99 }
100
101 fn is_transparent(&self) -> bool {
102 ::core::unreachable!()
103 }
104 }
105
106 #[allow(unused_qualifications)]
107 #[automatically_derived]
108 impl #impl_generics ::core::convert::From<#ty #static_lifetime> for Ec #ty_generics #where_clause {
109 fn from(value: #ty #static_lifetime) -> Self {
110 ::core::unreachable!()
111 }
112 }
113 }
114}
115
116#[derive(Debug)]
117pub enum StaticVariable {
118 CtorName,
119 CtorId,
120 CtorTarget,
121 CtorTargetId,
122 LazyName,
123 LazyId,
124 LazyTarget,
125 LazyTargetId,
126}
127
128fn get_var(var_type: StaticVariable, ty: &Ident, ident: Option<&Ident>) -> TokenStream {
129 syn::parse_str::<TokenStream>(&format!(
130 "__{:?}{}{}",
131 var_type,
132 ty,
133 ident.map(|f| f.to_string()).unwrap_or(String::new())
134 ))
135 .unwrap()
136}
137
138fn access_static_var(
139 ctor: StaticVariable,
140 lazy: StaticVariable,
141 ty: &Ident,
142 ident: Option<&Ident>,
143) -> TokenStream {
144 let ctor_var = get_var(ctor, ty, ident);
145 let lazy_var = get_var(lazy, ty, ident);
146
147 quote! {{
149 errore::__private::access_static_var!(#ctor_var, #lazy_var)
150 }}
151}
152
153fn impl_static_var<'a>(ty: &'a Ident, mut field: Option<&'a Ident>) -> TokenStream {
154 let ctor_name = get_var(StaticVariable::CtorName, ty, field);
164 let ctor_id = get_var(StaticVariable::CtorId, ty, field);
165 let ctor_target = get_var(StaticVariable::CtorTarget, ty, field);
166 let ctor_target_id = get_var(StaticVariable::CtorTargetId, ty, field);
167 let lazy_name = get_var(StaticVariable::LazyName, ty, field);
168 let lazy_id = get_var(StaticVariable::LazyId, ty, field);
169 let lazy_target = get_var(StaticVariable::LazyTarget, ty, field);
170 let lazy_target_id = get_var(StaticVariable::LazyTargetId, ty, field);
171 if field.is_none() {
172 field = Some(ty);
173 }
174
175 let block_name = quote! {{
176 let mut module_path = module_path!();
177 let mut id = alloc::string::String::with_capacity(module_path.len() + 10);
178 alloc::format!(
179 "{}::{}::{}",
180 env!("CARGO_PKG_NAME").replace("-", "_"),
181 module_path.rsplit("::").next().unwrap(),
182 stringify!(#field)
183 )
184 }};
185
186 let block_id = quote! {{
187 errore::Id::from(
188 errore::__private::fnv1a_hash_64(
189 concat!(
190 env!("CARGO_PKG_NAME"),
191 module_path!(),
192 stringify!(#ty),
193 stringify!(#field)
194 ).as_bytes()
195 )
196 )
197 }};
198
199 let block_target = quote! {{
200 let mut module_path = module_path!();
201 alloc::format!(
202 "{}",
203 module_path.split("::").next().unwrap(),
204 )
205 }};
206
207 let block_target_id = quote! {{
208 let mut module_path = module_path!();
209 errore::Id::from(
210 errore::__private::fnv1a_hash_64(
211 alloc::format!(
212 "{}",
213 module_path.split("::").next().unwrap(),
214 ).as_bytes()
215 )
216 )
217 }};
218
219 quote! {
220 errore::__private::impl_static_var!(#ctor_name, #lazy_name, alloc::string::String, #block_name);
221 errore::__private::impl_static_var!(#ctor_id, #lazy_id, errore::Id, #block_id);
222 errore::__private::impl_static_var!(#ctor_target, #lazy_target, alloc::string::String, #block_target);
223 errore::__private::impl_static_var!(#ctor_target_id, #lazy_target_id, errore::Id, #block_target_id);
224 }
225}
226
227fn is_error_context(token: &TokenStream) -> bool {
228 let token_str = token.to_string();
234 token_str.ends_with(":: Ec") || token_str.contains(":: Ec <")
235}
236
237fn impl_from<'a>(
238 ty: &'a Ident,
239 ty_generics: &'a TypeGenerics,
240 where_clause: &'a Option<&WhereClause>,
241 impl_generics: &'a ImplGenerics,
242 from_field: &'a Field,
243 variant: Option<&Ident>,
244) -> TokenStream {
245 let from = unoptional_type(from_field.ty);
246 let body = from_initializer(from_field);
247 let error = match variant {
248 Some(v) => quote! { #ty::#v #body },
249 None => quote! { #ty #body },
250 };
251
252 let from_str = from.to_string();
253 let ty_str = ty.to_string();
254 quote! {
255 #[allow(unused_qualifications)]
256 #[automatically_derived]
257 impl #impl_generics ::core::convert::From<#from> for #ty #ty_generics #where_clause {
258 #[track_caller]
259 fn from(source: #from) -> Self {
260 errore::dlog!(
261 "From<{}> for {}::{}",
262 #from_str,
263 module_path!(),
264 #ty_str
265 );
266 #error
267 }
268 }
269 }
270}
271
272fn impl_enum(input: Enum) -> Result<TokenStream> {
273 let ty = &input.ident;
274 let mut error = Option::<TokenStream>::None;
275 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
276 let mut error_inferred_bounds = InferredBounds::new();
277
278 let lazy_vars_arms = input
279 .variants
280 .iter()
281 .map(|variant| impl_static_var(ty, Some(&variant.ident)));
282 let lazy_vars = quote! {
283 #(#lazy_vars_arms)*
284 };
285
286 for variant in &input.variants {
287 if let Some(display) = &variant.attrs.display {
288 error = display.recursing();
289 }
290 }
291
292 let source_method = if input.has_source() {
293 let arms = input.variants.iter().map(|variant| {
294 let ident = &variant.ident;
295 if let Some(transparent_attr) = &variant.attrs.transparent {
296 let only_field = &variant.fields[0];
297 if only_field.contains_generic {
298 error_inferred_bounds.insert(only_field.ty, quote!(::core::error::Error));
299 }
300 let member = &only_field.member;
301 let source = quote_spanned! {transparent_attr.span=>
302 ::core::error::Error::source(transparent.as_dyn_error())
303 };
304 quote! {
305 #ty::#ident {#member: transparent} => #source,
306 }
307 } else if let Some(source_field) = variant.source_field() {
308 let source = &source_field.member;
309 if source_field.contains_generic {
310 let ty = unoptional_type(source_field.ty);
311 error_inferred_bounds.insert(ty, quote!(::core::error::Error + 'static));
312 }
313 let asref = if type_is_option(source_field.ty) {
314 Some(quote_spanned!(source.member_span()=> .as_ref()?))
315 } else {
316 None
317 };
318 let varsource = quote!(source);
319 let dyn_error = quote_spanned! {source_field.source_span()=>
320 #varsource #asref.as_dyn_error()
321 };
322 quote! {
323 #ty::#ident {#source: #varsource, ..} => ::core::option::Option::Some(#dyn_error),
324 }
325 } else {
326 quote! {
327 #ty::#ident {..} => ::core::option::Option::None,
328 }
329 }
330 });
331 Some(quote! {
332 fn source(&self) -> ::core::option::Option<&(dyn ::core::error::Error + 'static)> {
333 use errore::__private::AsDynError as _;
334 #[allow(deprecated)]
335 match self {
336 #(#arms)*
337 }
338 }
339 })
340 } else {
341 None
342 };
343
344 let display_impl = if input.has_display() {
345 let mut display_inferred_bounds = InferredBounds::new();
346 let has_bonus_display = input.variants.iter().any(|v| {
347 v.attrs
348 .display
349 .as_ref()
350 .map_or(false, |display| display.has_bonus_display)
351 });
352 let use_as_display = use_as_display(has_bonus_display);
353 let void_deref = if input.variants.is_empty() {
354 Some(quote!(*))
355 } else {
356 None
357 };
358
359 let arms = input.variants.iter().map(|variant| {
360 let mut display_implied_bounds = Set::new();
361 let display = match &variant.attrs.display {
362 Some(display) => {
363 display_implied_bounds.clone_from(&display.implied_bounds);
364 display.to_token_stream()
365 }
366 None => {
367 let only_field = match &variant.fields[0].member {
368 Member::Named(ident) => ident.clone(),
369 Member::Unnamed(index) => format_ident!("_{}", index),
370 };
371 display_implied_bounds.insert((0, Trait::Display));
372 quote!(::core::fmt::Display::fmt(#only_field, __formatter))
373 }
374 };
375 for (field, bound) in display_implied_bounds {
376 let field = &variant.fields[field];
377 if field.contains_generic {
378 display_inferred_bounds.insert(field.ty, bound);
379 }
380 }
381 let ident = &variant.ident;
382 let pat = fields_pat(&variant.fields);
383 quote! {
384 #ty::#ident #pat => #display
385 }
386 });
387
388 let arms = arms.collect::<Vec<_>>();
389 let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics);
390 Some(quote! {
391 #[allow(unused_qualifications)]
392 #[automatically_derived]
393 impl #impl_generics ::core::fmt::Display for #ty #ty_generics #display_where_clause {
394 fn fmt(&self, __formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
395 #use_as_display
396 #[allow(unused_variables, deprecated, clippy::used_underscore_binding)]
397 match #void_deref self {
398 #(#arms,)*
399 }
400 }
401 }
402 })
403 } else {
404 None
405 };
406
407 let from_impls = input.variants.iter().filter_map(|variant| {
408 let from_field = variant.from_field()?;
409 let variant = &variant.ident;
410 Some(impl_from(
411 ty,
412 &ty_generics,
413 &where_clause,
414 &impl_generics,
415 from_field,
416 Some(variant),
417 ))
418 });
419
420 let metadata_impl = {
421 let name_arms = input.variants.iter().map(|variant| {
422 let ident = &variant.ident;
423 let var = access_static_var(
424 StaticVariable::CtorName,
425 StaticVariable::LazyName,
426 ty,
427 Some(ident),
428 );
429 quote! {
430 #ty::#ident {..} => #var,
431 }
432 });
433
434 let id_arms = input.variants.iter().map(|variant| {
435 let ident = &variant.ident;
436 let var = access_static_var(
437 StaticVariable::CtorId,
438 StaticVariable::LazyId,
439 ty,
440 Some(ident),
441 );
442 quote! {
443 #ty::#ident {..} => #var,
444 }
445 });
446
447 let target_arms = input.variants.iter().map(|variant| {
448 let ident = &variant.ident;
449 let var = access_static_var(
450 StaticVariable::CtorTarget,
451 StaticVariable::LazyTarget,
452 ty,
453 Some(ident),
454 );
455 quote! {
456 #ty::#ident {..} => #var,
457 }
458 });
459
460 let target_id_arms = input.variants.iter().map(|variant| {
461 let ident = &variant.ident;
462 let var = access_static_var(
463 StaticVariable::CtorTargetId,
464 StaticVariable::LazyTargetId,
465 ty,
466 Some(ident),
467 );
468 quote! {
469 #ty::#ident {..} => #var,
470 }
471 });
472
473 let transparent_arms = input.variants.iter().map(|variant| {
474 let ident = &variant.ident;
475 let is_transparent = variant.attrs.transparent.is_some();
476 quote! {
477 #ty::#ident {..} => #is_transparent,
478 }
479 });
480
481 Some(quote! {
482 #[allow(unused_qualifications)]
483 #[automatically_derived]
484 impl #impl_generics errore::Metadata for #ty #ty_generics #where_clause {
485 fn name(&self) -> &'static str {
486 match self {
487 #(#name_arms)*
488 }
489 }
490
491 fn id(&self) -> &'static errore::Id {
492 match self {
493 #(#id_arms)*
494 }
495 }
496
497 fn target(&self) -> &'static str {
498 match self {
499 #(#target_arms)*
500 }
501 }
502
503 fn target_id(&self) -> &'static errore::Id {
504 match self {
505 #(#target_id_arms)*
506 }
507 }
508
509 #[inline]
510 fn display(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
511 ::core::fmt::Display::fmt(self, f)
512 }
513
514 fn is_transparent(&self) -> bool {
515 match self {
516 #(#transparent_arms)*
517 }
518 }
519 }
520 })
521 };
522
523 let impl_extractable = quote! {
524 #[allow(unused_qualifications)]
525 #[automatically_derived]
526 impl #impl_generics errore::Extractable for #ty #ty_generics #where_clause {}
527 };
528
529 if input.generics.type_params().next().is_some() {
530 let self_token = <Token![Self]>::default();
531 error_inferred_bounds.insert(self_token, Trait::Debug);
532 error_inferred_bounds.insert(self_token, Trait::Display);
533 }
534 let error_where_clause = error_inferred_bounds.augment_where_clause(input.generics);
535 let impl_error = {
536 quote! {
537 #[allow(unused_qualifications)]
538 #[automatically_derived]
539 impl #impl_generics ::core::error::Error for #ty #ty_generics #error_where_clause {
540 #source_method
541 }
542 }
543 };
544
545 let from_fields = input
546 .variants
547 .iter()
548 .filter_map(|variant| Some(variant.from_field()?))
549 .collect::<Vec<&Field>>();
550 let impl_error_context = impl_error_context(
551 &input.ident,
552 &input.vis,
553 input.generics,
554 &input.attrs,
555 Some(&input.variants),
556 from_fields,
557 );
558
559 Ok(quote! {
560 #error
561
562 #lazy_vars
563 #display_impl
564 #metadata_impl
565 #(#from_impls)*
566 #impl_extractable
567 #impl_error
568 #impl_error_context
569 })
570}
571
572fn impl_struct(input: Struct) -> Result<TokenStream> {
573 let ty = &input.ident;
574 let mut error = Option::<TokenStream>::None;
575 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
576 let mut error_inferred_bounds = InferredBounds::new();
577
578 let lazy_vars = impl_static_var(ty, None);
579
580 if let Some(display) = &input.attrs.display {
581 error = display.recursing();
582 }
583
584 let source_body = if let Some(transparent_attr) = &input.attrs.transparent {
585 let only_field = &input.fields[0];
586 if only_field.contains_generic {
587 error_inferred_bounds.insert(only_field.ty, quote!(::core::error::Error));
588 }
589 let member = &only_field.member;
590 Some(quote_spanned! {transparent_attr.span=>
591 ::core::error::Error::source(self.#member.as_dyn_error())
592 })
593 } else if let Some(source_field) = input.source_field() {
594 let source = &source_field.member;
595 if source_field.contains_generic {
596 let ty = unoptional_type(source_field.ty);
597 error_inferred_bounds.insert(ty, quote!(::core::error::Error + 'static));
598 }
599 let asref = if type_is_option(source_field.ty) {
600 Some(quote_spanned!(source.member_span()=> .as_ref()?))
601 } else {
602 None
603 };
604 let dyn_error = quote_spanned! {source_field.source_span()=>
605 self.#source #asref.as_dyn_error()
606 };
607 Some(quote! {
608 ::core::option::Option::Some(#dyn_error)
609 })
610 } else {
611 None
612 };
613 let source_method = source_body.map(|body| {
614 quote! {
615 fn source(&self) -> ::core::option::Option<&(dyn ::core::error::Error + 'static)> {
616 use errore::__private::AsDynError as _;
617 #body
618 }
619 }
620 });
621
622 let mut display_implied_bounds = Set::new();
624 let display_body = display::impl_struct_display_body(&input, &mut display_implied_bounds);
625
626 let mut display_inferred_bounds = InferredBounds::new();
628 let display_impl = display::impl_struct_display(
629 &input,
630 ty,
631 &ty_generics,
632 &mut display_inferred_bounds,
633 display_implied_bounds,
634 display_body,
635 &impl_generics,
636 );
637
638 let metadata_impl = {
639 let var_name =
640 access_static_var(StaticVariable::CtorName, StaticVariable::LazyName, ty, None);
641 let var_id = access_static_var(StaticVariable::CtorId, StaticVariable::LazyId, ty, None);
642 let var_target = access_static_var(
643 StaticVariable::CtorTarget,
644 StaticVariable::LazyTarget,
645 ty,
646 None,
647 );
648 let var_target_id = access_static_var(
649 StaticVariable::CtorTargetId,
650 StaticVariable::LazyTargetId,
651 ty,
652 None,
653 );
654 let is_transparent = input.attrs.transparent.is_some();
655 quote! {
656 #[allow(unused_qualifications)]
657 #[automatically_derived]
658 impl #impl_generics errore::Metadata for #ty #ty_generics #where_clause {
659 #[inline]
660 fn name(&self) -> &'static str {
661 #var_name
662 }
663
664 #[inline]
665 fn id(&self) -> &'static errore::Id {
666 #var_id
667 }
668
669 #[inline]
670 fn target(&self) -> &'static str {
671 #var_target
672 }
673
674 #[inline]
675 fn target_id(&self) -> &'static errore::Id {
676 #var_target_id
677 }
678
679 #[inline]
680 fn display(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
681 ::core::fmt::Display::fmt(self, f)
682 }
683
684 #[inline]
685 fn is_transparent(&self) -> bool {
686 #is_transparent
687 }
688 }
689 }
690 };
691
692 let from_impl = input.from_field().map(|from_field| {
693 Some(impl_from(
694 ty,
695 &ty_generics,
696 &where_clause,
697 &impl_generics,
698 from_field,
699 None,
700 ))
701 });
702
703 let impl_extractable = quote! {
704 #[allow(unused_qualifications)]
705 #[automatically_derived]
706 impl #impl_generics errore::Extractable for #ty #ty_generics #where_clause {}
707 };
708
709 if input.generics.type_params().next().is_some() {
710 let self_token = <Token![Self]>::default();
711 error_inferred_bounds.insert(self_token, Trait::Debug);
712 error_inferred_bounds.insert(self_token, Trait::Display);
713 }
714 let error_where_clause = error_inferred_bounds.augment_where_clause(input.generics);
715 let impl_error = quote! {
716 #[allow(unused_qualifications)]
717 #[automatically_derived]
718 impl #impl_generics ::core::error::Error for #ty #ty_generics #error_where_clause {
719 #source_method
720 }
721 };
722
723 let mut from_fields = Vec::<&Field>::new();
724 if let Some(from_field) = input.from_field() {
725 from_fields.push(from_field);
726 }
727 let impl_error_context = impl_error_context(
728 &input.ident,
729 &input.vis,
730 input.generics,
731 &input.attrs,
732 None,
733 from_fields,
734 );
735
736 Ok(quote! {
737 #error
738
739 #lazy_vars
740 #display_impl
741 #metadata_impl
742 #from_impl
743 #impl_extractable
744 #impl_error
745 #impl_error_context
746 })
747}
748
749fn impl_error_context(
750 ty: &Ident,
751 vis: &Visibility,
752 generics: &Generics,
753 attrs: &Attrs,
754 variants: Option<&Vec<Variant>>,
755 from_fields: Vec<&Field>,
756) -> TokenStream {
757 let vis = vis.to_token_stream();
758 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
759 let mut iter_generics = generics.clone();
760 iter_generics.params.push(parse_quote!('iter));
761 let (iter_impl_generics, _iter_ty_generics, iter_where_clause) = iter_generics.split_for_impl();
762 let ty_str = ty.to_string();
763
764 let static_lifetime = if generics.lifetimes().count() > 0 {
765 Some(quote! {<'static>})
766 } else {
767 Some(ty_generics.to_token_stream())
768 };
769
770 let doc = if attrs.doc.is_some() {
771 let mut from_doc = String::with_capacity(128);
772 for from_field in &from_fields {
773 let from = unoptional_type(from_field.ty).to_string().replace(" ", "");
774 from_doc.push_str(&format!("- [{}]\n\n", from));
775 }
776 if !from_doc.is_empty() {
777 from_doc = format!(
778 "\n\nThe [`From`](std::convert::From) trait is implemented for:\n{}",
779 from_doc
780 )
781 }
782
783 let doc_str = if variants.is_some() {
784 format!("Context for [`{}`](enum.{}.html).{}", ty, ty, from_doc)
785 } else {
786 format!("Context for [`{}`](struct.{}.html).{}", ty, ty, from_doc)
787 };
788
789 Some(quote! {
790 #[doc = #doc_str]
791 })
792 } else {
793 None
794 };
795
796 let from_impls = from_fields.iter().map(|from_field| {
797 let from = unoptional_type(from_field.ty);
798 let from_str = from.to_string();
799
800 if is_error_context(&from) {
802 Some(quote! {
803 #[allow(unused_qualifications)]
804 #[automatically_derived]
805 impl ::core::convert::From<#from> for Ec {
806 #[track_caller]
807 fn from(mut value: #from) -> Self {
808 errore::dlog!(
809 "From<{}> for {}::Ec",
810 #from_str,
811 module_path!()
812 );
813 let ctx = value.take_trace();
814 Self(errore::span::Span::new(ctx, #ty::from(value)))
815 }
816 }
817 })
818 } else {
819 Some(quote! {
820 #[allow(unused_qualifications)]
821 #[automatically_derived]
822 impl ::core::convert::From<#from> for Ec {
823 #[track_caller]
824 fn from(value: #from) -> Self {
825 errore::dlog!(
826 "From<{}> for {}::Ec",
827 #from_str,
828 module_path!()
829 );
830 let ctx = None;
831 Self(errore::span::Span::new(ctx, #ty::from(value)))
832 }
833 }
834 })
835 }
836 });
837
838 quote! {
839 extern crate alloc;
840
841 #doc
842 #[allow(unused_qualifications)]
843 #[automatically_derived]
844 #[derive(Debug)]
845 #vis struct Ec #ty_generics (#[doc(hidden)] pub errore::span::Span<#ty #ty_generics>) #where_clause;
846
847 #[allow(unused_qualifications)]
848 #[automatically_derived]
849 impl #impl_generics Ec #ty_generics #where_clause {
850 #[track_caller]
851 pub fn new(kind: #ty #static_lifetime) -> Self {
852 Self(errore::span::Span::new(None, kind))
853 }
854
855 #[inline]
857 pub fn error(&self) -> &#ty #ty_generics {
858 self.0.inner.as_ref()
859 }
860 }
861
862 #[allow(unused_qualifications)]
863 #[automatically_derived]
864 impl #impl_generics ::core::fmt::Display for Ec #ty_generics #where_clause {
865 #[inline]
866 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
867 self.0.fmt(f)
868 }
869 }
870
871 #[allow(unused_qualifications)]
872 #[automatically_derived]
873 impl #impl_generics ::core::error::Error for Ec #static_lifetime #where_clause {
874 #[inline]
875 fn source(&self) -> Option<&(dyn ::core::error::Error + 'static)> {
876 Some(&self.0 as &dyn ::core::error::Error)
877 }
878 }
879
880 #[allow(unused_qualifications)]
881 #[automatically_derived]
882 impl #iter_impl_generics IntoIterator for &'iter Ec #static_lifetime #iter_where_clause {
883 type Item = &'iter errore::TraceRecord;
884
885 type IntoIter = errore::__private::TraceRecordIterator<'iter>;
886
887 #[inline]
888 fn into_iter(self) -> Self::IntoIter {
889 self.0.into_iter()
890 }
891 }
892
893 #[allow(unused_qualifications)]
895 #[automatically_derived]
896 impl #impl_generics errore::Metadata for Ec #static_lifetime #where_clause {
897 #[inline]
898 fn name(&self) -> &'static str {
899 self.0.inner.name()
900 }
901
902 #[inline]
903 fn id(&self) -> &'static errore::Id {
904 self.0.inner.id()
905 }
906
907 #[inline]
908 fn target(&self) -> &'static str {
909 self.0.inner.target()
910 }
911
912 #[inline]
913 fn target_id(&self) -> &'static errore::Id {
914 self.0.inner.target_id()
915 }
916
917 #[inline]
918 fn display(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
919 ::core::fmt::Display::fmt(self, f)
920 }
921
922 #[inline]
923 fn is_transparent(&self) -> bool {
924 self.0.inner.is_transparent()
925 }
926 }
927
928 #[allow(unused_qualifications)]
929 #[automatically_derived]
930 impl #impl_generics errore::Extract for Ec #ty_generics #where_clause {
931 #[inline]
932 fn get<'a, E>(&'a self) -> Option<errore::Downcasted<'a, E>>
933 where
934 E: ::core::error::Error + errore::Extractable + 'static,
935 {
936 self.0.get::<E>()
937 }
938
939 #[inline]
940 fn has<'a, E>(&'a self) -> bool
941 where
942 E: ::core::error::Error + errore::Extractable + 'static,
943 {
944 self.0.has::<E>()
945 }
946 }
947
948 #[allow(unused_qualifications)]
949 #[automatically_derived]
950 impl #impl_generics errore::Traceable for Ec #ty_generics #where_clause {
951 #[inline]
952 fn trace(&self) -> &errore::TraceContext {
953 self.0.ctx.as_ref().expect("Trace should be available in 'Traceable::trace'")
954 }
955
956 #[inline]
957 fn trace_ref(&self) -> Option<&errore::TraceContext> {
958 self.0.ctx.as_ref()
959 }
960
961 #[inline]
962 fn take_trace(&mut self) -> Option<errore::TraceContext> {
963 self.0.ctx.take()
964 }
965
966 #[inline]
967 fn inner(&self) -> alloc::sync::Arc<dyn ::core::error::Error + ::core::marker::Send + ::core::marker::Sync> {
968 return self.0.inner.clone();
969 }
970
971 fn insert(&mut self, mut record: errore::TraceRecord) -> bool {
972 let ctx = self.0.ctx.as_mut().expect("Trace should be available in 'Traceable::insert'");
973
974 errore::__private::for_each_subscriber(|s| s.on_try_record(&mut errore::span::SpanContext::new(
975 ctx,
976 &record,
977 )));
978
979 if ctx.insert(record) {
981 errore::__private::for_each_subscriber(|s| s.on_record(ctx));
982 return true;
983 }
984
985 return false;
986 }
987 }
988
989 #[allow(unused_qualifications)]
990 #[automatically_derived]
991 impl #impl_generics ::core::convert::From<#ty #static_lifetime> for Ec #ty_generics #where_clause {
993 #[track_caller]
994 fn from(value: #ty #static_lifetime) -> Self {
995 errore::dlog!(
996 "From<{}::{}> for {}::Ec",
997 module_path!(),
998 #ty_str,
999 module_path!()
1000 );
1001 Self(errore::span::Span::new(None, value))
1002 }
1003 }
1004
1005 #(#from_impls)*
1006 }
1007}