Skip to main content

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