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 let mut no_source = false;
123 match &attr.meta {
124 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 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}