thiserror_impl/
attr.rs

1use proc_macro2::{Delimiter, Group, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
2use quote::{format_ident, quote, quote_spanned, ToTokens};
3use std::collections::BTreeSet as Set;
4use syn::parse::discouraged::Speculative;
5use syn::parse::{End, ParseStream};
6use syn::{
7    braced, bracketed, parenthesized, token, Attribute, Error, ExprPath, Ident, Index, LitFloat,
8    LitInt, LitStr, Meta, Result, Token,
9};
10
11pub struct Attrs<'a> {
12    pub display: Option<Display<'a>>,
13    pub source: Option<Source<'a>>,
14    pub backtrace: Option<&'a Attribute>,
15    pub from: Option<From<'a>>,
16    pub transparent: Option<Transparent<'a>>,
17    pub fmt: Option<Fmt<'a>>,
18}
19
20#[derive(#[automatically_derived]
impl<'a> ::core::clone::Clone for Display<'a> {
    #[inline]
    fn clone(&self) -> Display<'a> {
        Display {
            original: ::core::clone::Clone::clone(&self.original),
            fmt: ::core::clone::Clone::clone(&self.fmt),
            args: ::core::clone::Clone::clone(&self.args),
            requires_fmt_machinery: ::core::clone::Clone::clone(&self.requires_fmt_machinery),
            has_bonus_display: ::core::clone::Clone::clone(&self.has_bonus_display),
            infinite_recursive: ::core::clone::Clone::clone(&self.infinite_recursive),
            implied_bounds: ::core::clone::Clone::clone(&self.implied_bounds),
            bindings: ::core::clone::Clone::clone(&self.bindings),
        }
    }
}Clone)]
21pub struct Display<'a> {
22    pub original: &'a Attribute,
23    pub fmt: LitStr,
24    pub args: TokenStream,
25    pub requires_fmt_machinery: bool,
26    pub has_bonus_display: bool,
27    pub infinite_recursive: bool,
28    pub implied_bounds: Set<(usize, Trait)>,
29    pub bindings: Vec<(Ident, TokenStream)>,
30}
31
32#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for Source<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for Source<'a> {
    #[inline]
    fn clone(&self) -> Source<'a> {
        let _: ::core::clone::AssertParamIsClone<&'a Attribute>;
        let _: ::core::clone::AssertParamIsClone<Span>;
        *self
    }
}Clone)]
33pub struct Source<'a> {
34    pub original: &'a Attribute,
35    pub span: Span,
36}
37
38#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for From<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for From<'a> {
    #[inline]
    fn clone(&self) -> From<'a> {
        let _: ::core::clone::AssertParamIsClone<&'a Attribute>;
        let _: ::core::clone::AssertParamIsClone<Span>;
        *self
    }
}Clone)]
39pub struct From<'a> {
40    pub original: &'a Attribute,
41    pub span: Span,
42}
43
44#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for Transparent<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for Transparent<'a> {
    #[inline]
    fn clone(&self) -> Transparent<'a> {
        let _: ::core::clone::AssertParamIsClone<&'a Attribute>;
        let _: ::core::clone::AssertParamIsClone<Span>;
        *self
    }
}Clone)]
45pub struct Transparent<'a> {
46    pub original: &'a Attribute,
47    pub span: Span,
48}
49
50#[derive(#[automatically_derived]
impl<'a> ::core::clone::Clone for Fmt<'a> {
    #[inline]
    fn clone(&self) -> Fmt<'a> {
        Fmt {
            original: ::core::clone::Clone::clone(&self.original),
            path: ::core::clone::Clone::clone(&self.path),
        }
    }
}Clone)]
51pub struct Fmt<'a> {
52    pub original: &'a Attribute,
53    pub path: ExprPath,
54}
55
56#[derive(#[automatically_derived]
impl ::core::marker::Copy for Trait { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Trait {
    #[inline]
    fn clone(&self) -> Trait { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for Trait {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for Trait {
    #[inline]
    fn eq(&self, other: &Trait) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Ord for Trait {
    #[inline]
    fn cmp(&self, other: &Trait) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for Trait {
    #[inline]
    fn partial_cmp(&self, other: &Trait)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}PartialOrd, #[automatically_derived]
impl ::core::fmt::Debug for Trait {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                Trait::Debug => "Debug",
                Trait::Display => "Display",
                Trait::Octal => "Octal",
                Trait::LowerHex => "LowerHex",
                Trait::UpperHex => "UpperHex",
                Trait::Pointer => "Pointer",
                Trait::Binary => "Binary",
                Trait::LowerExp => "LowerExp",
                Trait::UpperExp => "UpperExp",
            })
    }
}Debug)]
57pub enum Trait {
58    Debug,
59    Display,
60    Octal,
61    LowerHex,
62    UpperHex,
63    Pointer,
64    Binary,
65    LowerExp,
66    UpperExp,
67}
68
69pub fn get(input: &[Attribute]) -> Result<Attrs> {
70    let mut attrs = Attrs {
71        display: None,
72        source: None,
73        backtrace: None,
74        from: None,
75        transparent: None,
76        fmt: None,
77    };
78
79    for attr in input {
80        if attr.path().is_ident("error") {
81            parse_error_attribute(&mut attrs, attr)?;
82        } else if attr.path().is_ident("source") {
83            attr.meta.require_path_only()?;
84            if attrs.source.is_some() {
85                return Err(Error::new_spanned(attr, "duplicate #[source] attribute"));
86            }
87            let span = (attr.pound_token.span)
88                .join(attr.bracket_token.span.join())
89                .unwrap_or(attr.path().get_ident().unwrap().span());
90            attrs.source = Some(Source {
91                original: attr,
92                span,
93            });
94        } else if attr.path().is_ident("backtrace") {
95            attr.meta.require_path_only()?;
96            if attrs.backtrace.is_some() {
97                return Err(Error::new_spanned(attr, "duplicate #[backtrace] attribute"));
98            }
99            attrs.backtrace = Some(attr);
100        } else if attr.path().is_ident("from") {
101            match attr.meta {
102                Meta::Path(_) => {}
103                Meta::List(_) | Meta::NameValue(_) => {
104                    // Assume this is meant for derive_more crate or something.
105                    continue;
106                }
107            }
108            if attrs.from.is_some() {
109                return Err(Error::new_spanned(attr, "duplicate #[from] attribute"));
110            }
111            let span = (attr.pound_token.span)
112                .join(attr.bracket_token.span.join())
113                .unwrap_or(attr.path().get_ident().unwrap().span());
114            attrs.from = Some(From {
115                original: attr,
116                span,
117            });
118        }
119    }
120
121    Ok(attrs)
122}
123
124fn parse_error_attribute<'a>(attrs: &mut Attrs<'a>, attr: &'a Attribute) -> Result<()> {
125    mod kw {
126        #[allow(non_camel_case_types)]
pub struct transparent {
    #[allow(dead_code)]
    pub span: ::syn::__private::Span,
}
#[doc(hidden)]
#[allow(dead_code, non_snake_case)]
pub fn transparent<__S: ::syn::__private::IntoSpans<::syn::__private::Span>>(span:
        __S) -> transparent {
    transparent { span: ::syn::__private::IntoSpans::into_spans(span) }
}
const _: () =
    {
        impl ::syn::__private::Default for transparent {
            fn default() -> Self {
                transparent { span: ::syn::__private::Span::call_site() }
            }
        }
        impl ::syn::__private::CustomToken for transparent {
            fn peek(cursor: ::syn::buffer::Cursor) -> ::syn::__private::bool {
                if let ::syn::__private::Some((ident, _rest)) = cursor.ident()
                    {
                    ident == "transparent"
                } else { false }
            }
            fn display() -> &'static ::syn::__private::str { "`transparent`" }
        }
        impl ::syn::parse::Parse for transparent {
            fn parse(input: ::syn::parse::ParseStream)
                -> ::syn::parse::Result<transparent> {
                input.step(|cursor|
                        {
                            if let ::syn::__private::Some((ident, rest)) =
                                    cursor.ident() {
                                if ident == "transparent" {
                                    return ::syn::__private::Ok((transparent {
                                                    span: ident.span(),
                                                }, rest));
                                }
                            }
                            ::syn::__private::Err(cursor.error("expected `transparent`"))
                        })
            }
        }
        impl ::syn::__private::ToTokens for transparent {
            fn to_tokens(&self, tokens: &mut ::syn::__private::TokenStream2) {
                let ident = ::syn::Ident::new("transparent", self.span);
                ::syn::__private::TokenStreamExt::append(tokens, ident);
            }
        }
        impl ::syn::__private::Copy for transparent {}
        #[allow(clippy :: expl_impl_clone_on_copy)]
        impl ::syn::__private::Clone for transparent {
            fn clone(&self) -> Self { *self }
        }
        ;
    };syn::custom_keyword!(transparent);
127        #[allow(non_camel_case_types)]
pub struct fmt {
    #[allow(dead_code)]
    pub span: ::syn::__private::Span,
}
#[doc(hidden)]
#[allow(dead_code, non_snake_case)]
pub fn fmt<__S: ::syn::__private::IntoSpans<::syn::__private::Span>>(span:
        __S) -> fmt {
    fmt { span: ::syn::__private::IntoSpans::into_spans(span) }
}
const _: () =
    {
        impl ::syn::__private::Default for fmt {
            fn default() -> Self {
                fmt { span: ::syn::__private::Span::call_site() }
            }
        }
        impl ::syn::__private::CustomToken for fmt {
            fn peek(cursor: ::syn::buffer::Cursor) -> ::syn::__private::bool {
                if let ::syn::__private::Some((ident, _rest)) = cursor.ident()
                    {
                    ident == "fmt"
                } else { false }
            }
            fn display() -> &'static ::syn::__private::str { "`fmt`" }
        }
        impl ::syn::parse::Parse for fmt {
            fn parse(input: ::syn::parse::ParseStream)
                -> ::syn::parse::Result<fmt> {
                input.step(|cursor|
                        {
                            if let ::syn::__private::Some((ident, rest)) =
                                    cursor.ident() {
                                if ident == "fmt" {
                                    return ::syn::__private::Ok((fmt { span: ident.span() },
                                                rest));
                                }
                            }
                            ::syn::__private::Err(cursor.error("expected `fmt`"))
                        })
            }
        }
        impl ::syn::__private::ToTokens for fmt {
            fn to_tokens(&self, tokens: &mut ::syn::__private::TokenStream2) {
                let ident = ::syn::Ident::new("fmt", self.span);
                ::syn::__private::TokenStreamExt::append(tokens, ident);
            }
        }
        impl ::syn::__private::Copy for fmt {}
        #[allow(clippy :: expl_impl_clone_on_copy)]
        impl ::syn::__private::Clone for fmt {
            fn clone(&self) -> Self { *self }
        }
        ;
    };syn::custom_keyword!(fmt);
128    }
129
130    attr.parse_args_with(|input: ParseStream| {
131        let lookahead = input.lookahead1();
132        let fmt = if lookahead.peek(LitStr) {
133            input.parse::<LitStr>()?
134        } else if lookahead.peek(kw::transparent) {
135            let kw: kw::transparent = input.parse()?;
136            if attrs.transparent.is_some() {
137                return Err(Error::new_spanned(
138                    attr,
139                    "duplicate #[error(transparent)] attribute",
140                ));
141            }
142            attrs.transparent = Some(Transparent {
143                original: attr,
144                span: kw.span,
145            });
146            return Ok(());
147        } else if lookahead.peek(kw::fmt) {
148            input.parse::<kw::fmt>()?;
149            input.parse::<Token![=]>()?;
150            let path: ExprPath = input.parse()?;
151            if attrs.fmt.is_some() {
152                return Err(Error::new_spanned(
153                    attr,
154                    "duplicate #[error(fmt = ...)] attribute",
155                ));
156            }
157            attrs.fmt = Some(Fmt {
158                original: attr,
159                path,
160            });
161            return Ok(());
162        } else {
163            return Err(lookahead.error());
164        };
165
166        let args = if input.is_empty() || input.peek(::syn::token::CommaToken![,]) && input.peek2(End) {
167            input.parse::<Option<Token![,]>>()?;
168            TokenStream::new()
169        } else {
170            parse_token_expr(input, false)?
171        };
172
173        let requires_fmt_machinery = !args.is_empty();
174
175        let display = Display {
176            original: attr,
177            fmt,
178            args,
179            requires_fmt_machinery,
180            has_bonus_display: false,
181            infinite_recursive: false,
182            implied_bounds: Set::new(),
183            bindings: Vec::new(),
184        };
185        if attrs.display.is_some() {
186            return Err(Error::new_spanned(
187                attr,
188                "only one #[error(...)] attribute is allowed",
189            ));
190        }
191        attrs.display = Some(display);
192        Ok(())
193    })
194}
195
196fn parse_token_expr(input: ParseStream, mut begin_expr: bool) -> Result<TokenStream> {
197    let mut tokens = Vec::new();
198    while !input.is_empty() {
199        if input.peek(token::Group) {
200            let group: TokenTree = input.parse()?;
201            tokens.push(group);
202            begin_expr = false;
203            continue;
204        }
205
206        if begin_expr && input.peek(::syn::token::DotToken![.]) {
207            if input.peek2(Ident) {
208                input.parse::<Token![.]>()?;
209                begin_expr = false;
210                continue;
211            } else if input.peek2(LitInt) {
212                input.parse::<Token![.]>()?;
213                let int: Index = input.parse()?;
214                tokens.push({
215                    let ident = match ::quote::__private::IdentFragmentAdapter(&int.index) {
    arg =>
        ::quote::__private::mk_ident(&::alloc::__export::must_use({
                        ::alloc::fmt::format(format_args!("_{0}", arg))
                    }),
            ::quote::__private::Option::Some::<::quote::__private::Span>(int.span)),
}format_ident!("_{}", int.index, span = int.span);
216                    TokenTree::Ident(ident)
217                });
218                begin_expr = false;
219                continue;
220            } else if input.peek2(LitFloat) {
221                let ahead = input.fork();
222                ahead.parse::<Token![.]>()?;
223                let float: LitFloat = ahead.parse()?;
224                let repr = float.to_string();
225                let mut indices = repr.split('.').map(syn::parse_str::<Index>);
226                if let (Some(Ok(first)), Some(Ok(second)), None) =
227                    (indices.next(), indices.next(), indices.next())
228                {
229                    input.advance_to(&ahead);
230                    tokens.push({
231                        let ident = match ::quote::__private::IdentFragmentAdapter(&first) {
    arg =>
        ::quote::__private::mk_ident(&::alloc::__export::must_use({
                        ::alloc::fmt::format(format_args!("_{0}", arg))
                    }),
            ::quote::__private::Option::Some::<::quote::__private::Span>(float.span())),
}format_ident!("_{}", first, span = float.span());
232                        TokenTree::Ident(ident)
233                    });
234                    tokens.push({
235                        let mut punct = Punct::new('.', Spacing::Alone);
236                        punct.set_span(float.span());
237                        TokenTree::Punct(punct)
238                    });
239                    tokens.push({
240                        let mut literal = Literal::u32_unsuffixed(second.index);
241                        literal.set_span(float.span());
242                        TokenTree::Literal(literal)
243                    });
244                    begin_expr = false;
245                    continue;
246                }
247            }
248        }
249
250        begin_expr = input.peek(::syn::token::BreakToken![break])
251            || input.peek(::syn::token::ContinueToken![continue])
252            || input.peek(::syn::token::IfToken![if])
253            || input.peek(::syn::token::InToken![in])
254            || input.peek(::syn::token::MatchToken![match])
255            || input.peek(::syn::token::MutToken![mut])
256            || input.peek(::syn::token::ReturnToken![return])
257            || input.peek(::syn::token::WhileToken![while])
258            || input.peek(::syn::token::PlusToken![+])
259            || input.peek(::syn::token::AndToken![&])
260            || input.peek(::syn::token::NotToken![!])
261            || input.peek(::syn::token::CaretToken![^])
262            || input.peek(::syn::token::CommaToken![,])
263            || input.peek(::syn::token::SlashToken![/])
264            || input.peek(::syn::token::EqToken![=])
265            || input.peek(::syn::token::GtToken![>])
266            || input.peek(::syn::token::LtToken![<])
267            || input.peek(::syn::token::OrToken![|])
268            || input.peek(::syn::token::PercentToken![%])
269            || input.peek(::syn::token::SemiToken![;])
270            || input.peek(::syn::token::StarToken![*])
271            || input.peek(::syn::token::MinusToken![-]);
272
273        let token: TokenTree = if input.peek(token::Paren) {
274            let content;
275            let delimiter = match ::syn::__private::parse_parens(&input) {
    ::syn::__private::Ok(parens) => { content = parens.content; parens.token }
    ::syn::__private::Err(error) => { return ::syn::__private::Err(error); }
}parenthesized!(content in input);
276            let nested = parse_token_expr(&content, true)?;
277            let mut group = Group::new(Delimiter::Parenthesis, nested);
278            group.set_span(delimiter.span.join());
279            TokenTree::Group(group)
280        } else if input.peek(token::Brace) {
281            let content;
282            let delimiter = match ::syn::__private::parse_braces(&input) {
    ::syn::__private::Ok(braces) => { content = braces.content; braces.token }
    ::syn::__private::Err(error) => { return ::syn::__private::Err(error); }
}braced!(content in input);
283            let nested = parse_token_expr(&content, true)?;
284            let mut group = Group::new(Delimiter::Brace, nested);
285            group.set_span(delimiter.span.join());
286            TokenTree::Group(group)
287        } else if input.peek(token::Bracket) {
288            let content;
289            let delimiter = match ::syn::__private::parse_brackets(&input) {
    ::syn::__private::Ok(brackets) => {
        content = brackets.content;
        brackets.token
    }
    ::syn::__private::Err(error) => { return ::syn::__private::Err(error); }
}bracketed!(content in input);
290            let nested = parse_token_expr(&content, true)?;
291            let mut group = Group::new(Delimiter::Bracket, nested);
292            group.set_span(delimiter.span.join());
293            TokenTree::Group(group)
294        } else {
295            input.parse()?
296        };
297        tokens.push(token);
298    }
299    Ok(TokenStream::from_iter(tokens))
300}
301
302impl ToTokens for Display<'_> {
303    fn to_tokens(&self, tokens: &mut TokenStream) {
304        if self.infinite_recursive {
305            let span = self.fmt.span();
306            tokens.extend({
    let mut _s = ::quote::__private::TokenStream::new();
    let _span: ::quote::__private::Span =
        ::quote::__private::get_span(span).__into_span();
    ::quote::__private::push_pound_spanned(&mut _s, _span);
    ::quote::__private::push_group_spanned(&mut _s, _span,
        ::quote::__private::Delimiter::Bracket,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            let _span: ::quote::__private::Span =
                ::quote::__private::get_span(_span).__into_span();
            ::quote::__private::push_ident_spanned(&mut _s, _span, "warn");
            ::quote::__private::push_group_spanned(&mut _s, _span,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    let _span: ::quote::__private::Span =
                        ::quote::__private::get_span(_span).__into_span();
                    ::quote::__private::push_ident_spanned(&mut _s, _span,
                        "unconditional_recursion");
                    _s
                });
            _s
        });
    ::quote::__private::push_ident_spanned(&mut _s, _span, "fn");
    ::quote::__private::push_ident_spanned(&mut _s, _span, "_fmt");
    ::quote::__private::push_group_spanned(&mut _s, _span,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let _: ::quote::__private::Span =
                ::quote::__private::get_span(_span).__into_span();
            ::quote::__private::TokenStream::new()
        });
    ::quote::__private::push_group_spanned(&mut _s, _span,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            let _span: ::quote::__private::Span =
                ::quote::__private::get_span(_span).__into_span();
            ::quote::__private::push_ident_spanned(&mut _s, _span, "_fmt");
            ::quote::__private::push_group_spanned(&mut _s, _span,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let _: ::quote::__private::Span =
                        ::quote::__private::get_span(_span).__into_span();
                    ::quote::__private::TokenStream::new()
                });
            _s
        });
    _s
}quote_spanned! {span=>
307                #[warn(unconditional_recursion)]
308                fn _fmt() { _fmt() }
309            });
310        }
311
312        let fmt = &self.fmt;
313        let args = &self.args;
314
315        // Currently `write!(f, "text")` produces less efficient code than
316        // `f.write_str("text")`. We recognize the case when the format string
317        // has no braces and no interpolated values, and generate simpler code.
318        let write = if self.requires_fmt_machinery {
319            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "write");
    ::quote::__private::push_bang(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "__formatter");
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&fmt, &mut _s);
            ::quote::ToTokens::to_tokens(&args, &mut _s);
            _s
        });
    _s
}quote! {
320                ::core::write!(__formatter, #fmt #args)
321            }
322        } else {
323            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "__formatter");
    ::quote::__private::push_dot(&mut _s);
    ::quote::__private::push_ident(&mut _s, "write_str");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::ToTokens::to_tokens(&fmt, &mut _s);
            _s
        });
    _s
}quote! {
324                __formatter.write_str(#fmt)
325            }
326        };
327
328        tokens.extend(if self.bindings.is_empty() {
329            write
330        } else {
331            let locals = self.bindings.iter().map(|(local, _value)| local);
332            let values = self.bindings.iter().map(|(_local, value)| value);
333            {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "match");
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            {
                use ::quote::__private::ext::*;
                let has_iter =
                    ::quote::__private::ThereIsNoIteratorInRepetition;
                #[allow(unused_mut)]
                let (mut values, i) = values.quote_into_iter();
                let has_iter = has_iter | i;
                let _: ::quote::__private::HasIterator = has_iter;
                while true {
                    let values =
                        match values.next() {
                            Some(_x) => ::quote::__private::RepInterp(_x),
                            None => break,
                        };
                    ::quote::ToTokens::to_tokens(&values, &mut _s);
                    ::quote::__private::push_comma(&mut _s);
                }
            }
            _s
        });
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                {
                    let mut _s = ::quote::__private::TokenStream::new();
                    {
                        use ::quote::__private::ext::*;
                        let has_iter =
                            ::quote::__private::ThereIsNoIteratorInRepetition;
                        #[allow(unused_mut)]
                        let (mut locals, i) = locals.quote_into_iter();
                        let has_iter = has_iter | i;
                        let _: ::quote::__private::HasIterator = has_iter;
                        while true {
                            let locals =
                                match locals.next() {
                                    Some(_x) => ::quote::__private::RepInterp(_x),
                                    None => break,
                                };
                            ::quote::ToTokens::to_tokens(&locals, &mut _s);
                            ::quote::__private::push_comma(&mut _s);
                        }
                    }
                    _s
                });
            ::quote::__private::push_fat_arrow(&mut _s);
            ::quote::ToTokens::to_tokens(&write, &mut _s);
            _s
        });
    _s
}quote! {
334                match (#(#values,)*) {
335                    (#(#locals,)*) => #write
336                }
337            }
338        });
339    }
340}
341
342impl ToTokens for Trait {
343    fn to_tokens(&self, tokens: &mut TokenStream) {
344        let trait_name = match self {
345            Trait::Debug => "Debug",
346            Trait::Display => "Display",
347            Trait::Octal => "Octal",
348            Trait::LowerHex => "LowerHex",
349            Trait::UpperHex => "UpperHex",
350            Trait::Pointer => "Pointer",
351            Trait::Binary => "Binary",
352            Trait::LowerExp => "LowerExp",
353            Trait::UpperExp => "UpperExp",
354        };
355        let ident = Ident::new(trait_name, Span::call_site());
356        tokens.extend({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "core");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "fmt");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::ToTokens::to_tokens(&ident, &mut _s);
    _s
}quote!(::core::fmt::#ident));
357    }
358}