1#![warn(unused_crate_dependencies)]
9
10use either::Either;
11use lazy_regex::{lazy_regex, Lazy, Regex};
12use proc_macro::TokenStream;
13use proc_macro2::{Span, TokenStream as TokenStream2};
14use quote::{format_ident, quote, ToTokens};
15use std::borrow::Cow;
16use syn::{
17 braced,
18 parse::{self, Parse},
19 parse_macro_input, parse_quote,
20 punctuated::{self, Punctuated},
21 token::{self, Brace},
22 Attribute, DeriveInput, Error, Fields, Generics, Ident, LitStr, Result, Token, Type, Variant,
23 Visibility,
24};
25
26#[cfg(test)]
27mod tests;
28
29type Tuple4<T> = (T, T, T, T);
34
35fn split_fields_attrs(fields: &mut Fields) -> Result<Option<Ident>> {
36 let mut span_ident = None;
37 for (idx, field) in fields.iter_mut().enumerate() {
38 for attr in &field.attrs {
39 if attr.meta.path().is_ident("diag") {
40 attr.parse_nested_meta(|meta| {
41 if meta.path.is_ident("span") {
42 span_ident = Some(field.ident.clone().unwrap_or(format_ident!("_{idx}")))
43 }
44 Ok(())
45 })?
46 }
47 }
48 field.attrs.retain(|attr| !attr.path().is_ident("diag"));
49 }
50 Ok(span_ident)
51}
52
53enum ErrorTree {
55 Prefix {
57 span: Span,
58 attrs: Vec<Attribute>,
59 nodes: Punctuated<ErrorTree, Token![,]>,
60 },
61 Variant {
65 span: Span,
66 attrs: Vec<Attribute>,
67 span_ident: Option<Ident>,
68 ident: Ident,
69 fields: Fields,
70 },
71}
72
73impl ErrorTree {
74 fn attrs(&self) -> &[Attribute] {
75 match self {
76 ErrorTree::Prefix { attrs, .. } => attrs,
77 ErrorTree::Variant { attrs, .. } => attrs,
78 }
79 }
80 fn ident(&self) -> Option<&Ident> {
81 match self {
82 ErrorTree::Prefix { .. } => None,
83 ErrorTree::Variant { ident, .. } => Some(ident),
84 }
85 }
86 fn fields(&self) -> Option<&Fields> {
87 match self {
88 ErrorTree::Prefix { .. } => None,
89 ErrorTree::Variant { fields, .. } => Some(fields),
90 }
91 }
92 fn span_ident(&self) -> Option<Ident> {
93 match self {
94 ErrorTree::Prefix { .. } => None,
95 ErrorTree::Variant { span_ident, .. } => span_ident.clone(),
96 }
97 }
98 fn span(&self) -> Span {
99 match self {
100 ErrorTree::Prefix { span, .. } => *span,
101 ErrorTree::Variant { span, .. } => *span,
102 }
103 }
104}
105
106impl Parse for ErrorTree {
107 fn parse(input: parse::ParseStream) -> syn::Result<Self> {
109 let attrs = input.call(Attribute::parse_outer)?;
110
111 if input.peek(Ident) {
112 let ident: Ident = input.parse()?;
113 let mut fields = if input.peek(token::Brace) {
114 Fields::Named(input.parse()?)
115 } else if input.peek(token::Paren) {
116 Fields::Unnamed(input.parse()?)
117 } else {
118 Fields::Unit
119 };
120 let span_ident = split_fields_attrs(&mut fields)?;
121 Ok(ErrorTree::Variant {
122 span: ident.span(),
123 attrs,
124 span_ident,
125 ident,
126 fields,
127 })
128 } else {
129 let span = input.span();
130 let children;
131 braced!(children in input);
132 let nodes = Punctuated::parse_terminated(&children)?;
133 Ok(ErrorTree::Prefix { span, attrs, nodes })
134 }
135 }
136}
137
138#[derive(Clone, Copy, Default)]
139enum Kind {
140 #[default]
141 Error,
142 Warn,
143}
144
145impl Kind {
146 fn short_str(&self) -> &'static str {
147 match self {
148 Kind::Error => "E",
149 Kind::Warn => "W",
150 }
151 }
152}
153
154impl TryFrom<LitStr> for Kind {
155 type Error = Error;
156
157 fn try_from(value: LitStr) -> Result<Self> {
158 match value.value().as_str() {
159 "error" | "Error" => Ok(Kind::Error),
160 "warn" | "Warn" => Ok(Kind::Warn),
161 _ => Err(Error::new_spanned(
162 value,
163 "Kind must be either `Error` or `Warn`.",
164 )),
165 }
166 }
167}
168
169impl ToTokens for Kind {
170 fn to_tokens(&self, tokens: &mut TokenStream2) {
171 let kind = match self {
172 Kind::Error => quote! { ::error_enum::Kind::Error },
173 Kind::Warn => quote! { ::error_enum::Kind::Warn },
174 };
175 tokens.extend(kind);
176 }
177}
178
179#[derive(Clone)]
181struct Config {
182 kind: Option<Kind>,
183 number: String,
184 msg: Option<LitStr>,
185 attrs: Vec<Attribute>,
186 ident: Option<Ident>,
187 fields: Option<Fields>,
188 span_field: Option<Ident>,
189 span_type: Option<Type>,
191 label: Option<LitStr>,
192 depth: usize,
193 nested: bool,
194 #[expect(unused)]
195 span: Span,
196}
197
198impl Config {
199 const fn new(span: Span) -> Self {
200 Self {
201 kind: None,
202 number: String::new(),
203 msg: None,
204 attrs: Vec::new(),
205 ident: None,
206 fields: None,
207 span_field: None,
208 span_type: None,
209 label: None,
210 depth: 0,
211 nested: false,
212 span,
213 }
214 }
215 fn process(
216 &self,
217 attrs: &[Attribute],
218 ident: Option<&Ident>,
219 fields: Option<&Fields>,
220 span_field: Option<Ident>,
221 span: Span,
222 ) -> Result<Self> {
223 let mut kind = self.kind;
224 let mut number = self.number.clone();
225 let mut msg = self.msg.clone();
226 let mut label = self.label.clone();
227 let mut span_type = self.span_type.clone();
228 let depth = self.depth + 1;
229 let mut nested = self.nested;
230 let mut unused_attrs = Vec::new();
231
232 for attr in attrs {
233 if attr.path().is_ident("diag") {
234 attr.parse_nested_meta(|meta| {
235 if meta.path.is_ident("kind") {
236 let value: LitStr = meta.value()?.parse()?;
237 kind = Some(value.try_into()?);
238 } else if meta.path.is_ident("label") {
239 let value: LitStr = meta.value()?.parse()?;
240 label = Some(value);
241 } else if meta.path.is_ident("msg") {
242 let value: LitStr = meta.value()?.parse()?;
243 msg = Some(value);
244 } else if meta.path.is_ident("nested") {
245 nested = true;
246 } else if meta.path.is_ident("number") {
247 let value: LitStr = meta.value()?.parse()?;
248 number.push_str(value.value().as_str());
249 } else if meta.path.is_ident("span_type") {
250 let value: LitStr = meta.value()?.parse()?;
251 span_type = Some(value.parse()?);
252 } else {
253 return Err(Error::new_spanned(meta.path, "Unknown attribute key."));
254 }
255 Ok(())
256 })?
257 } else {
258 unused_attrs.push(attr.clone());
259 }
260 }
261
262 let ident = ident.cloned();
263 let fields = fields.cloned();
264 Ok(Self {
265 kind,
266 number,
267 msg,
268 attrs: unused_attrs,
269 ident,
270 fields,
271 span_field,
272 span_type,
273 label,
274 depth,
275 nested,
276 span,
277 })
278 }
279}
280
281struct ErrorTreeIter<'i> {
282 stack: Vec<(punctuated::Iter<'i, ErrorTree>, Config)>,
283}
284
285impl<'i> ErrorTreeIter<'i> {
286 fn new(tree: punctuated::Iter<'i, ErrorTree>, config: Config) -> Result<Self> {
287 Ok(Self {
288 stack: vec![(tree, config)],
289 })
290 }
291 fn process_next(node: &'i ErrorTree, config: &Config, span: Span) -> Result<Config> {
292 let new_config = config.process(
293 node.attrs(),
294 node.ident(),
295 node.fields(),
296 node.span_ident(),
297 span,
298 )?;
299 Ok(new_config)
300 }
301}
302
303impl<'i> Iterator for ErrorTreeIter<'i> {
304 type Item = Result<Config>;
305
306 fn next(&mut self) -> Option<Self::Item> {
307 while let Some((slice, config)) = self.stack.last_mut() {
308 if let Some(node) = slice.next() {
309 let config = Self::process_next(node, config, node.span())
310 .map(Some)
311 .transpose()?;
312 if let Ok(config) = &config {
313 if let ErrorTree::Prefix { nodes, .. } = node {
314 self.stack.push((nodes.iter(), config.clone()));
315 }
316 }
317 return Some(config);
318 } else {
319 self.stack.pop();
320 }
321 }
322 None
323 }
324}
325
326enum ErrorEnumInner {
327 Multiple {
328 brace: Brace,
329 roots: Punctuated<ErrorTree, Token![,]>,
330 body: bool,
331 },
332 Single {
333 node: ErrorTree,
334 },
335}
336
337impl ErrorEnumInner {
338 fn iter(&self, config: Config) -> Result<impl Iterator<Item = Result<Config>> + '_> {
339 match self {
340 ErrorEnumInner::Multiple { roots, .. } => {
341 Ok(Either::Left(ErrorTreeIter::new(roots.iter(), config)?))
342 }
343 ErrorEnumInner::Single { node } => {
344 let iter = Either::Right(std::iter::once(ErrorTreeIter::process_next(
345 node,
346 &config,
347 node.span(),
348 )));
349 Ok(iter)
350 }
351 }
352 }
353}
354
355struct ErrorEnum {
363 attrs: Vec<Attribute>,
364 vis: Visibility,
365 name: Ident,
366 generics: Generics,
367 inner: ErrorEnumInner,
368 config: Config,
369}
370
371impl ErrorEnum {
372 fn iter(&self) -> Result<impl Iterator<Item = Result<Config>> + '_> {
373 self.inner.iter(self.config.clone())
374 }
375 fn is_enum(&self) -> bool {
376 matches!(self.inner, ErrorEnumInner::Multiple { .. })
377 }
378}
379
380impl Parse for ErrorEnum {
381 fn parse(input: parse::ParseStream) -> syn::Result<Self> {
382 let mut attrs = input.call(Attribute::parse_outer)?;
383 let vis = input.parse()?;
384 let name: Ident = input.parse()?;
385 let generics = input.parse()?;
386 let children;
387 let brace = braced!(children in input);
388 let config = Config::new(name.span()).process(&attrs, None, None, None, name.span())?;
389 attrs.retain(|attr| !attr.path().is_ident("diag"));
390
391 let roots = Punctuated::parse_terminated(&children)?;
392 let inner = ErrorEnumInner::Multiple {
393 body: true,
394 brace,
395 roots,
396 };
397 Ok(Self {
398 attrs,
399 vis,
400 generics,
401 name,
402 inner,
403 config,
404 })
405 }
406}
407
408impl TryFrom<DeriveInput> for ErrorEnum {
409 type Error = Error;
410
411 fn try_from(value: DeriveInput) -> Result<Self> {
412 let DeriveInput {
413 mut attrs,
414 vis,
415 ident,
416 generics,
417 data,
418 } = value;
419 match data {
420 syn::Data::Enum(data_enum) => {
421 let mut roots = Punctuated::new();
422 for pair in data_enum.variants.into_pairs() {
423 let (mut variant, comma) = pair.into_tuple();
424 let span = variant.ident.span();
425 let span_ident = split_fields_attrs(&mut variant.fields)?;
426 let node = ErrorTree::Variant {
427 span,
428 attrs: variant.attrs,
429 ident: variant.ident,
430 fields: variant.fields,
431 span_ident,
432 };
433 roots.push_value(node);
434 if let Some(comma) = comma {
435 roots.push_punct(comma);
436 }
437 }
438 let config =
439 Config::new(ident.span()).process(&attrs, None, None, None, ident.span())?;
440 attrs.retain(|attr| !attr.path().is_ident("diag"));
441
442 let inner = ErrorEnumInner::Multiple {
443 body: false,
444 brace: data_enum.brace_token,
445 roots,
446 };
447 Ok(Self {
448 attrs,
449 vis,
450 name: ident,
451 generics,
452 inner,
453 config,
454 })
455 }
456 syn::Data::Struct(mut data_struct) => {
457 let span = ident.span();
458 let span_ident = split_fields_attrs(&mut data_struct.fields)?;
459 let config =
460 Config::new(ident.span()).process(&attrs, None, None, None, ident.span())?;
461 attrs.retain(|attr| !attr.path().is_ident("diag"));
462
463 let node = ErrorTree::Variant {
464 span,
465 attrs,
466 ident: ident.clone(),
467 fields: data_struct.fields,
468 span_ident,
469 };
470
471 let inner = ErrorEnumInner::Single { node };
472
473 Ok(Self {
474 attrs: Vec::new(),
475 vis,
476 name: ident,
477 generics,
478 inner,
479 config,
480 })
481 }
482 _ => Err(Error::new_spanned(
483 ident,
484 "ErrorEnum can only be derived for enums or structs.",
485 )),
486 }
487 }
488}
489
490impl ErrorEnum {
491 fn variant<'a>(&'a self, ident: &'a Ident) -> impl ToTokens + 'a {
492 struct VariantPrefix<'a> {
493 ident: &'a Ident,
494 is_enum: bool,
495 }
496 impl<'a> ToTokens for VariantPrefix<'a> {
497 fn to_tokens(&self, tokens: &mut TokenStream2) {
498 let ident = self.ident;
499 if self.is_enum {
500 tokens.extend(quote! { Self::#ident });
501 } else {
502 tokens.extend(quote! { Self });
503 }
504 }
505 }
506
507 VariantPrefix {
508 ident,
509 is_enum: self.is_enum(),
510 }
511 }
512 fn doc(&self) -> Result<Vec<String>> {
513 self.iter()?
514 .map(|config| {
515 let Config {
516 number,
517 depth,
518 ident,
519 msg,
520 kind,
521 ..
522 } = config?;
523 let indent = " ".repeat(depth - 2);
524 let msg = msg.as_ref().map(|s| s.value());
525 let kind = kind.unwrap_or_default().short_str();
526 Ok(match (ident, msg) {
527 (Some(ident), Some(msg)) => {
528 format!("{indent}- `{kind}{number}`(**{ident}**): {msg}")
529 }
530 (None, Some(msg)) => format!("{indent}- `{kind}{number}`: {msg}"),
531 (Some(ident), None) => format!("{indent}- `{kind}{number}`(**{ident}**)"),
532 (None, None) => format!("{indent}- `{kind}{number}`"),
533 })
534 })
535 .collect()
536 }
537 fn variants(&self) -> Result<Vec<Variant>> {
538 self.iter()?
539 .filter_map(|config| {
540 config
541 .map(
542 |Config {
543 kind,
544 msg,
545 number,
546 attrs,
547 ident,
548 fields,
549 ..
550 }| {
551 Some((kind, msg, number, attrs, ident?, fields?))
552 },
553 )
554 .transpose()
555 })
556 .map(|config| {
557 let (kind, msg, number, mut attrs, ident, fields) = config?;
558
559 let kind = kind.unwrap_or_default();
560 let code = format!("{}{}", kind.short_str(), number);
561
562 let doc = match msg {
563 Some(msg) => {
564 format!("`{code}`: {msg}", msg = msg.value())
565 }
566 None => format!("`{code}`"),
567 };
568
569 attrs.push(syn::parse_quote! {
570 #[doc = #doc]
571 });
572 attrs.push(syn::parse_quote! {
573 #[doc(alias = #code)]
574 });
575
576 Ok(Variant {
577 attrs,
578 ident,
579 fields,
580 discriminant: None,
581 })
582 })
583 .collect()
584 }
585 fn used_unnamed_fields(msg: &LitStr) -> Result<Vec<Ident>> {
586 static ARG: Lazy<Regex> = lazy_regex!(r#"(^|[^\{])(\{\{)*\{(?<index>\d+)(:[^\{\}]*)?\}"#);
587 ARG.captures_iter(msg.value().as_str())
588 .map(|cap| {
589 let index = cap
590 .name("index")
591 .ok_or_else(|| Error::new_spanned(msg, "Invalid argument index."))?
592 .as_str()
593 .parse::<usize>()
594 .map_err(|err| {
595 Error::new_spanned(msg, format!("Invalid argument index: {err}"))
596 })?;
597 Ok(format_ident!("_{}", index))
598 })
599 .collect()
600 }
601 fn display_branch(&self, ident: &Ident, fields: &Fields, msg: &LitStr) -> Result<TokenStream2> {
602 let prefix = self.variant(ident);
603 match fields {
604 Fields::Named(named) => {
605 let members = named.named.iter().map(|f| f.ident.as_ref());
606 Ok(quote! {
607 #[allow(unused_variables)]
608 #prefix { #(#members),* } => ::core::write!(f, #msg),
609 })
610 }
611 Fields::Unnamed(unnamed) => {
612 let params = (0..unnamed.unnamed.len()).map(|i| format_ident!("_{}", i));
613 let args = Self::used_unnamed_fields(msg)?;
614 Ok(quote! {
615 #prefix ( #(#params),* ) => ::core::write!(f, #msg #(, #args)* ),
616 })
617 }
618 Fields::Unit => Ok(quote! {
619 #prefix => ::core::write!(f, #msg),
620 }),
621 }
622 }
623 fn display(&self) -> Result<Vec<TokenStream2>> {
624 self.iter()?
625 .filter_map(|config| {
626 config
627 .map(
628 |Config {
629 msg, ident, fields, ..
630 }| { Some((msg, ident?, fields?)) },
631 )
632 .transpose()
633 })
634 .map(|config| {
635 let (msg, ident, fields) = config?;
636 let msg = msg.ok_or_else(|| {
637 Error::new_spanned(
638 &ident,
639 "Missing message. Consider using `#[diag(msg = \"...\")]`",
640 )
641 })?;
642 self.display_branch(&ident, &fields, &msg)
643 })
644 .collect()
645 }
646 fn primary_label_branch(
647 &self,
648 ident: &Ident,
649 fields: &Fields,
650 label: &LitStr,
651 ) -> Result<TokenStream2> {
652 let prefix = self.variant(ident);
653 match fields {
654 Fields::Named(named) => {
655 let members = named.named.iter().map(|f| f.ident.as_ref());
656 Ok(quote! {
657 #[allow(unused_variables)]
658 #prefix { #(#members),* } => ::std::format!(#label),
659 })
660 }
661 Fields::Unnamed(unnamed) => {
662 let params = (0..unnamed.unnamed.len()).map(|i| format_ident!("_{}", i));
663 let args = Self::used_unnamed_fields(label)?;
664 Ok(quote! {
665 #prefix ( #(#params),* ) => ::std::format!(#label #(, #args)* ),
666 })
667 }
668 Fields::Unit => Ok(quote! {
669 #prefix => ::std::format!(#label),
670 }),
671 }
672 }
673 fn primary_label(&self) -> Result<Vec<TokenStream2>> {
674 self.iter()?
675 .filter_map(|config| {
676 config
677 .map(
678 |Config {
679 msg,
680 ident,
681 fields,
682 label,
683 ..
684 }| { Some((msg, ident?, fields?, label)) },
685 )
686 .transpose()
687 })
688 .map(|config| {
689 let (msg, ident, fields, label) = config?;
690 let label = label.or(msg).ok_or_else(|| {
691 Error::new_spanned(
692 &ident,
693 "Missing label or message. Consider using `#[diag(label = \"...\")]`",
694 )
695 })?;
696 self.primary_label_branch(&ident, &fields, &label)
697 })
698 .collect()
699 }
700 fn impl_error_enum_branch(
701 &self,
702 ident: &Ident,
703 fields: &Fields,
704 span_field: Option<Ident>,
705 kind: &Kind,
706 number: &str,
707 ) -> Result<Tuple4<TokenStream2>> {
708 let branch_ignored = match fields {
709 Fields::Named(_) => quote! { { .. } },
710 Fields::Unnamed(_) => quote! { (..) },
711 Fields::Unit => quote! {},
712 };
713 let code = format!("{}{}", kind.short_str(), number);
714
715 let prefix = self.variant(ident);
716
717 let kind = quote! {
718 #prefix #branch_ignored => #kind,
719 };
720 let number = quote! {
721 #prefix #branch_ignored => #number,
722 };
723 let code = quote! {
724 #prefix #branch_ignored => #code,
725 };
726 let span_type = self.span_type();
727 let span = if let Some(span_field) = span_field {
728 quote! {<#span_type as ::core::convert::From<_>>::from(#span_field)}
729 } else {
730 quote! {<#span_type as ::core::default::Default>::default()}
731 };
732 let primary_span = match fields {
733 Fields::Named(named) => {
734 let members = named.named.iter().map(|f| f.ident.as_ref());
735 quote! {
736 #[allow(unused_variables)]
737 #prefix { #(#members),* } => #span,
738 }
739 }
740 Fields::Unnamed(unnamed) => {
741 let params = (0..unnamed.unnamed.len()).map(|i| format_ident!("_{}", i));
742 quote! {
743 #[allow(unused_variables)]
744 #prefix ( #(#params),* ) => #span,
745 }
746 }
747 Fields::Unit => quote! {
748 #prefix => #span,
749 },
750 };
751 Ok((kind, number, code, primary_span))
752 }
753 fn impl_error_enum(&self) -> Result<Tuple4<Vec<TokenStream2>>> {
754 self.iter()?
755 .filter_map(|config| {
756 config
757 .map(
758 |Config {
759 ident,
760 fields,
761 span_field,
762 kind,
763 number,
764 ..
765 }| {
766 Some((ident?, fields?, span_field, kind, number))
767 },
768 )
769 .transpose()
770 })
771 .map(|config| {
772 let (ident, fields, span_field, kind, number) = config?;
773 let kind = kind.unwrap_or_default();
774 self.impl_error_enum_branch(&ident, &fields, span_field, &kind, &number)
775 })
776 .collect()
777 }
778 fn span_type(&self) -> Cow<'_, Type> {
779 self.config.span_type.as_ref().map_or_else(
780 || {
781 Cow::Owned(parse_quote! {
782 ::error_enum::SimpleSpan
783 })
784 },
785 Cow::Borrowed,
786 )
787 }
788 fn try_to_tokens(&self, tokens: &mut TokenStream2) -> Result<()> {
789 let attrs = &self.attrs;
790 let vis = &self.vis;
791 let name = &self.name;
792 let generics = &self.generics;
793
794 let doc = self.doc()?;
795
796 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
797
798 let variants = self.variants()?;
799
800 if let ErrorEnumInner::Multiple {
801 body: true, brace, ..
802 } = self.inner
803 {
804 tokens.extend(quote! {
805 #(#attrs)*
806 #[doc = "List of error variants:"]
807 #(
808 #[doc = #doc]
809 )*
810 #vis enum #name #generics
811 });
812 brace.surround(tokens, |tokens| {
813 tokens.extend(quote! { #(#variants, )* });
814 });
815 }
816
817 let display = self.display()?;
818 tokens.extend(quote! {
819 impl #impl_generics ::core::fmt::Display for #name #ty_generics #where_clause {
820 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
821 match self {
822 #(#display)*
823 }
824 }
825 }
826 impl #impl_generics ::core::error::Error for #name #ty_generics #where_clause {}
827 });
828
829 let (kind, number, code, primary_span) = self.impl_error_enum()?;
830 let primary_label = self.primary_label()?;
831 let span_type = self.span_type();
832 tokens.extend(quote! {
833 impl #impl_generics ::error_enum::ErrorType for #name #ty_generics #where_clause {
834 type Span = #span_type;
835 type Message = ::std::string::String;
836
837 fn kind(&self) -> ::error_enum::Kind {
838 match self {
839 #(#kind)*
840 }
841 }
842 fn number(&self) -> &::core::primitive::str {
843 match self {
844 #(#number)*
845 }
846 }
847 fn code(&self) -> &::core::primitive::str {
848 match self {
849 #(#code)*
850 }
851 }
852 fn primary_span(&self) -> #span_type {
853 match self {
854 #(#primary_span)*
855 }
856 }
857 fn primary_message(&self) -> ::std::string::String {
858 ::std::format!("{self}")
859 }
860 fn primary_label(&self) -> ::std::string::String {
861 match self {
862 #(#primary_label)*
863 }
864 }
865 }
866 });
867
868 Ok(())
869 }
870}
871
872impl ToTokens for ErrorEnum {
873 fn to_tokens(&self, tokens: &mut TokenStream2) {
874 let mut buffer = TokenStream2::new();
875 self.try_to_tokens(&mut buffer)
876 .inspect(|()| tokens.extend(buffer))
877 .unwrap_or_else(|err| {
878 let diag = err.to_compile_error();
879 tokens.extend(diag);
880 });
881 }
882}
883
884#[proc_macro]
927pub fn error_type(token: TokenStream) -> TokenStream {
928 let error = parse_macro_input!(token as ErrorEnum);
929 error.to_token_stream().into()
930}
931
932#[proc_macro_derive(ErrorType, attributes(diag))]
936pub fn error_enum(token: TokenStream) -> TokenStream {
937 let input: DeriveInput = parse_macro_input!(token as DeriveInput);
938 let error = ErrorEnum::try_from(input)
939 .map_or_else(|err| err.to_compile_error(), |e| e.to_token_stream());
940 error.into()
941}