quote/
runtime.rs

1use self::get_span::{GetSpan, GetSpanBase, GetSpanInner};
2use crate::{IdentFragment, ToTokens, TokenStreamExt};
3use core::fmt;
4use core::iter;
5use core::ops::BitOr;
6use proc_macro2::{Group, Ident, Punct, Spacing, TokenTree};
7
8#[doc(hidden)]
9pub use alloc::format;
10#[doc(hidden)]
11pub use core::option::Option;
12#[doc(hidden)]
13pub use core::stringify;
14
15#[doc(hidden)]
16pub type Delimiter = proc_macro2::Delimiter;
17#[doc(hidden)]
18pub type Span = proc_macro2::Span;
19#[doc(hidden)]
20pub type TokenStream = proc_macro2::TokenStream;
21
22#[doc(hidden)]
23pub struct HasIterator<const B: bool>;
24
25impl BitOr<HasIterator<false>> for HasIterator<false> {
26    type Output = HasIterator<false>;
27    fn bitor(self, _rhs: HasIterator<false>) -> HasIterator<false> {
28        HasIterator::<false>
29    }
30}
31
32impl BitOr<HasIterator<false>> for HasIterator<true> {
33    type Output = HasIterator<true>;
34    fn bitor(self, _rhs: HasIterator<false>) -> HasIterator<true> {
35        HasIterator::<true>
36    }
37}
38
39impl BitOr<HasIterator<true>> for HasIterator<false> {
40    type Output = HasIterator<true>;
41    fn bitor(self, _rhs: HasIterator<true>) -> HasIterator<true> {
42        HasIterator::<true>
43    }
44}
45
46impl BitOr<HasIterator<true>> for HasIterator<true> {
47    type Output = HasIterator<true>;
48    fn bitor(self, _rhs: HasIterator<true>) -> HasIterator<true> {
49        HasIterator::<true>
50    }
51}
52
53#[doc(hidden)]
54#[cfg_attr(
55    not(no_diagnostic_namespace),
56    diagnostic::on_unimplemented(
57        message = "repetition contains no interpolated value that is an iterator",
58        label = "none of the values interpolated inside this repetition are iterable"
59    )
60)]
61pub trait CheckHasIterator<const B: bool>: Sized {
62    fn check(self) {}
63}
64
65impl CheckHasIterator<true> for HasIterator<true> {}
66
67/// Extension traits used by the implementation of `quote!`. These are defined
68/// in separate traits, rather than as a single trait due to ambiguity issues.
69///
70/// These traits expose a `quote_into_iter` method which should allow calling
71/// whichever impl happens to be applicable. Calling that method repeatedly on
72/// the returned value should be idempotent.
73#[doc(hidden)]
74pub mod ext {
75    use super::{HasIterator, RepInterp};
76    use crate::ToTokens;
77    use alloc::collections::btree_set::{self, BTreeSet};
78    use alloc::vec::Vec;
79    use core::slice;
80
81    /// Extension trait providing the `quote_into_iter` method on iterators.
82    #[doc(hidden)]
83    pub trait RepIteratorExt: Iterator + Sized {
84        fn quote_into_iter(self) -> (Self, HasIterator<true>) {
85            (self, HasIterator::<true>)
86        }
87    }
88
89    impl<T: Iterator> RepIteratorExt for T {}
90
91    /// Extension trait providing the `quote_into_iter` method for
92    /// non-iterable types. These types interpolate the same value in each
93    /// iteration of the repetition.
94    #[doc(hidden)]
95    pub trait RepToTokensExt {
96        /// Pretend to be an iterator for the purposes of `quote_into_iter`.
97        /// This allows repeated calls to `quote_into_iter` to continue
98        /// correctly returning HasIterator<false>.
99        fn next(&self) -> Option<&Self> {
100            Some(self)
101        }
102
103        fn quote_into_iter(&self) -> (&Self, HasIterator<false>) {
104            (self, HasIterator::<false>)
105        }
106    }
107
108    impl<T: ToTokens + ?Sized> RepToTokensExt for T {}
109
110    /// Extension trait providing the `quote_into_iter` method for types that
111    /// can be referenced as an iterator.
112    #[doc(hidden)]
113    pub trait RepAsIteratorExt<'q> {
114        type Iter: Iterator;
115
116        fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>);
117    }
118
119    impl<'q, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &T {
120        type Iter = T::Iter;
121
122        fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
123            <T as RepAsIteratorExt>::quote_into_iter(*self)
124        }
125    }
126
127    impl<'q, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &mut T {
128        type Iter = T::Iter;
129
130        fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
131            <T as RepAsIteratorExt>::quote_into_iter(*self)
132        }
133    }
134
135    impl<'q, T: 'q> RepAsIteratorExt<'q> for [T] {
136        type Iter = slice::Iter<'q, T>;
137
138        fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
139            (self.iter(), HasIterator::<true>)
140        }
141    }
142
143    impl<'q, T: 'q, const N: usize> RepAsIteratorExt<'q> for [T; N] {
144        type Iter = slice::Iter<'q, T>;
145
146        fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
147            (self.iter(), HasIterator::<true>)
148        }
149    }
150
151    impl<'q, T: 'q> RepAsIteratorExt<'q> for Vec<T> {
152        type Iter = slice::Iter<'q, T>;
153
154        fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
155            (self.iter(), HasIterator::<true>)
156        }
157    }
158
159    impl<'q, T: 'q> RepAsIteratorExt<'q> for BTreeSet<T> {
160        type Iter = btree_set::Iter<'q, T>;
161
162        fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
163            (self.iter(), HasIterator::<true>)
164        }
165    }
166
167    impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp<T> {
168        type Iter = T::Iter;
169
170        fn quote_into_iter(&'q self) -> (Self::Iter, HasIterator<true>) {
171            self.0.quote_into_iter()
172        }
173    }
174}
175
176// Helper type used within interpolations to allow for repeated binding names.
177// Implements the relevant traits, and exports a dummy `next()` method.
178#[derive(#[automatically_derived]
impl<T: ::core::marker::Copy> ::core::marker::Copy for RepInterp<T> { }Copy, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for RepInterp<T> {
    #[inline]
    fn clone(&self) -> RepInterp<T> {
        RepInterp(::core::clone::Clone::clone(&self.0))
    }
}Clone)]
179#[doc(hidden)]
180pub struct RepInterp<T>(pub T);
181
182impl<T> RepInterp<T> {
183    // This method is intended to look like `Iterator::next`, and is called when
184    // a name is bound multiple times, as the previous binding will shadow the
185    // original `Iterator` object. This allows us to avoid advancing the
186    // iterator multiple times per iteration.
187    pub fn next(self) -> Option<T> {
188        Some(self.0)
189    }
190}
191
192impl<T: Iterator> Iterator for RepInterp<T> {
193    type Item = T::Item;
194
195    fn next(&mut self) -> Option<Self::Item> {
196        self.0.next()
197    }
198}
199
200impl<T: ToTokens> ToTokens for RepInterp<T> {
201    fn to_tokens(&self, tokens: &mut TokenStream) {
202        self.0.to_tokens(tokens);
203    }
204}
205
206#[doc(hidden)]
207#[inline]
208pub fn get_span<T>(span: T) -> GetSpan<T> {
209    GetSpan(GetSpanInner(GetSpanBase(span)))
210}
211
212mod get_span {
213    use core::ops::Deref;
214    use proc_macro2::extra::DelimSpan;
215    use proc_macro2::Span;
216
217    pub struct GetSpan<T>(pub(crate) GetSpanInner<T>);
218
219    pub struct GetSpanInner<T>(pub(crate) GetSpanBase<T>);
220
221    pub struct GetSpanBase<T>(pub(crate) T);
222
223    impl GetSpan<Span> {
224        #[inline]
225        pub fn __into_span(self) -> Span {
226            ((self.0).0).0
227        }
228    }
229
230    impl GetSpanInner<DelimSpan> {
231        #[inline]
232        pub fn __into_span(&self) -> Span {
233            (self.0).0.join()
234        }
235    }
236
237    impl<T> GetSpanBase<T> {
238        #[allow(clippy::unused_self)]
239        pub fn __into_span(&self) -> T {
240            ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
241        }
242    }
243
244    impl<T> Deref for GetSpan<T> {
245        type Target = GetSpanInner<T>;
246
247        #[inline]
248        fn deref(&self) -> &Self::Target {
249            &self.0
250        }
251    }
252
253    impl<T> Deref for GetSpanInner<T> {
254        type Target = GetSpanBase<T>;
255
256        #[inline]
257        fn deref(&self) -> &Self::Target {
258            &self.0
259        }
260    }
261}
262
263#[doc(hidden)]
264pub fn push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream) {
265    tokens.append(Group::new(delimiter, inner));
266}
267
268#[doc(hidden)]
269pub fn push_group_spanned(
270    tokens: &mut TokenStream,
271    span: Span,
272    delimiter: Delimiter,
273    inner: TokenStream,
274) {
275    let mut g = Group::new(delimiter, inner);
276    g.set_span(span);
277    tokens.append(g);
278}
279
280#[doc(hidden)]
281pub fn parse(tokens: &mut TokenStream, s: &str) {
282    let s: TokenStream = s.parse().expect("invalid token stream");
283    tokens.extend(iter::once(s));
284}
285
286#[doc(hidden)]
287pub fn parse_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
288    let s: TokenStream = s.parse().expect("invalid token stream");
289    for token in s {
290        tokens.append(respan_token_tree(token, span));
291    }
292}
293
294// Token tree with every span replaced by the given one.
295fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
296    match &mut token {
297        TokenTree::Group(g) => {
298            let mut tokens = TokenStream::new();
299            for token in g.stream() {
300                tokens.append(respan_token_tree(token, span));
301            }
302            *g = Group::new(g.delimiter(), tokens);
303            g.set_span(span);
304        }
305        other => other.set_span(span),
306    }
307    token
308}
309
310#[doc(hidden)]
311pub fn push_ident(tokens: &mut TokenStream, s: &str) {
312    let span = Span::call_site();
313    push_ident_spanned(tokens, span, s);
314}
315
316#[doc(hidden)]
317pub fn push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
318    tokens.append(ident_maybe_raw(s, span));
319}
320
321#[doc(hidden)]
322pub fn push_lifetime(tokens: &mut TokenStream, lifetime: &str) {
323    tokens.append(TokenTree::Punct(Punct::new('\'', Spacing::Joint)));
324    tokens.append(TokenTree::Ident(Ident::new(
325        &lifetime[1..],
326        Span::call_site(),
327    )));
328}
329
330#[doc(hidden)]
331pub fn push_lifetime_spanned(tokens: &mut TokenStream, span: Span, lifetime: &str) {
332    tokens.append(TokenTree::Punct({
333        let mut apostrophe = Punct::new('\'', Spacing::Joint);
334        apostrophe.set_span(span);
335        apostrophe
336    }));
337    tokens.append(TokenTree::Ident(Ident::new(&lifetime[1..], span)));
338}
339
340macro_rules! push_punct {
341    ($name:ident $spanned:ident $char1:tt) => {
342        #[doc(hidden)]
343        pub fn $name(tokens: &mut TokenStream) {
344            tokens.append(Punct::new($char1, Spacing::Alone));
345        }
346        #[doc(hidden)]
347        pub fn $spanned(tokens: &mut TokenStream, span: Span) {
348            let mut punct = Punct::new($char1, Spacing::Alone);
349            punct.set_span(span);
350            tokens.append(punct);
351        }
352    };
353    ($name:ident $spanned:ident $char1:tt $char2:tt) => {
354        #[doc(hidden)]
355        pub fn $name(tokens: &mut TokenStream) {
356            tokens.append(Punct::new($char1, Spacing::Joint));
357            tokens.append(Punct::new($char2, Spacing::Alone));
358        }
359        #[doc(hidden)]
360        pub fn $spanned(tokens: &mut TokenStream, span: Span) {
361            let mut punct = Punct::new($char1, Spacing::Joint);
362            punct.set_span(span);
363            tokens.append(punct);
364            let mut punct = Punct::new($char2, Spacing::Alone);
365            punct.set_span(span);
366            tokens.append(punct);
367        }
368    };
369    ($name:ident $spanned:ident $char1:tt $char2:tt $char3:tt) => {
370        #[doc(hidden)]
371        pub fn $name(tokens: &mut TokenStream) {
372            tokens.append(Punct::new($char1, Spacing::Joint));
373            tokens.append(Punct::new($char2, Spacing::Joint));
374            tokens.append(Punct::new($char3, Spacing::Alone));
375        }
376        #[doc(hidden)]
377        pub fn $spanned(tokens: &mut TokenStream, span: Span) {
378            let mut punct = Punct::new($char1, Spacing::Joint);
379            punct.set_span(span);
380            tokens.append(punct);
381            let mut punct = Punct::new($char2, Spacing::Joint);
382            punct.set_span(span);
383            tokens.append(punct);
384            let mut punct = Punct::new($char3, Spacing::Alone);
385            punct.set_span(span);
386            tokens.append(punct);
387        }
388    };
389}
390
391#[doc(hidden)]
pub fn push_add(tokens: &mut TokenStream) {
    tokens.append(Punct::new('+', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_add_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('+', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_add push_add_spanned '+');
392#[doc(hidden)]
pub fn push_add_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('+', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_add_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('+', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_add_eq push_add_eq_spanned '+' '=');
393#[doc(hidden)]
pub fn push_and(tokens: &mut TokenStream) {
    tokens.append(Punct::new('&', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_and_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('&', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_and push_and_spanned '&');
394#[doc(hidden)]
pub fn push_and_and(tokens: &mut TokenStream) {
    tokens.append(Punct::new('&', Spacing::Joint));
    tokens.append(Punct::new('&', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_and_and_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('&', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('&', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_and_and push_and_and_spanned '&' '&');
395#[doc(hidden)]
pub fn push_and_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('&', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_and_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('&', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_and_eq push_and_eq_spanned '&' '=');
396#[doc(hidden)]
pub fn push_at(tokens: &mut TokenStream) {
    tokens.append(Punct::new('@', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_at_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('@', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_at push_at_spanned '@');
397#[doc(hidden)]
pub fn push_bang(tokens: &mut TokenStream) {
    tokens.append(Punct::new('!', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_bang_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('!', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_bang push_bang_spanned '!');
398#[doc(hidden)]
pub fn push_caret(tokens: &mut TokenStream) {
    tokens.append(Punct::new('^', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_caret_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('^', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_caret push_caret_spanned '^');
399#[doc(hidden)]
pub fn push_caret_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('^', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_caret_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('^', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_caret_eq push_caret_eq_spanned '^' '=');
400#[doc(hidden)]
pub fn push_colon(tokens: &mut TokenStream) {
    tokens.append(Punct::new(':', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_colon_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new(':', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_colon push_colon_spanned ':');
401#[doc(hidden)]
pub fn push_colon2(tokens: &mut TokenStream) {
    tokens.append(Punct::new(':', Spacing::Joint));
    tokens.append(Punct::new(':', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_colon2_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new(':', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new(':', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_colon2 push_colon2_spanned ':' ':');
402#[doc(hidden)]
pub fn push_comma(tokens: &mut TokenStream) {
    tokens.append(Punct::new(',', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_comma_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new(',', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_comma push_comma_spanned ',');
403#[doc(hidden)]
pub fn push_div(tokens: &mut TokenStream) {
    tokens.append(Punct::new('/', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_div_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('/', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_div push_div_spanned '/');
404#[doc(hidden)]
pub fn push_div_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('/', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_div_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('/', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_div_eq push_div_eq_spanned '/' '=');
405#[doc(hidden)]
pub fn push_dot(tokens: &mut TokenStream) {
    tokens.append(Punct::new('.', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_dot_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('.', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_dot push_dot_spanned '.');
406#[doc(hidden)]
pub fn push_dot2(tokens: &mut TokenStream) {
    tokens.append(Punct::new('.', Spacing::Joint));
    tokens.append(Punct::new('.', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_dot2_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('.', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('.', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_dot2 push_dot2_spanned '.' '.');
407#[doc(hidden)]
pub fn push_dot3(tokens: &mut TokenStream) {
    tokens.append(Punct::new('.', Spacing::Joint));
    tokens.append(Punct::new('.', Spacing::Joint));
    tokens.append(Punct::new('.', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_dot3_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('.', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('.', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('.', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_dot3 push_dot3_spanned '.' '.' '.');
408#[doc(hidden)]
pub fn push_dot_dot_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('.', Spacing::Joint));
    tokens.append(Punct::new('.', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_dot_dot_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('.', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('.', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_dot_dot_eq push_dot_dot_eq_spanned '.' '.' '=');
409#[doc(hidden)]
pub fn push_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_eq push_eq_spanned '=');
410#[doc(hidden)]
pub fn push_eq_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('=', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_eq_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('=', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_eq_eq push_eq_eq_spanned '=' '=');
411#[doc(hidden)]
pub fn push_ge(tokens: &mut TokenStream) {
    tokens.append(Punct::new('>', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_ge_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('>', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_ge push_ge_spanned '>' '=');
412#[doc(hidden)]
pub fn push_gt(tokens: &mut TokenStream) {
    tokens.append(Punct::new('>', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_gt_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('>', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_gt push_gt_spanned '>');
413#[doc(hidden)]
pub fn push_le(tokens: &mut TokenStream) {
    tokens.append(Punct::new('<', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_le_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('<', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_le push_le_spanned '<' '=');
414#[doc(hidden)]
pub fn push_lt(tokens: &mut TokenStream) {
    tokens.append(Punct::new('<', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_lt_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('<', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_lt push_lt_spanned '<');
415#[doc(hidden)]
pub fn push_mul_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('*', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_mul_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('*', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_mul_eq push_mul_eq_spanned '*' '=');
416#[doc(hidden)]
pub fn push_ne(tokens: &mut TokenStream) {
    tokens.append(Punct::new('!', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_ne_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('!', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_ne push_ne_spanned '!' '=');
417#[doc(hidden)]
pub fn push_or(tokens: &mut TokenStream) {
    tokens.append(Punct::new('|', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_or_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('|', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_or push_or_spanned '|');
418#[doc(hidden)]
pub fn push_or_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('|', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_or_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('|', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_or_eq push_or_eq_spanned '|' '=');
419#[doc(hidden)]
pub fn push_or_or(tokens: &mut TokenStream) {
    tokens.append(Punct::new('|', Spacing::Joint));
    tokens.append(Punct::new('|', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_or_or_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('|', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('|', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_or_or push_or_or_spanned '|' '|');
420#[doc(hidden)]
pub fn push_pound(tokens: &mut TokenStream) {
    tokens.append(Punct::new('#', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_pound_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('#', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_pound push_pound_spanned '#');
421#[doc(hidden)]
pub fn push_question(tokens: &mut TokenStream) {
    tokens.append(Punct::new('?', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_question_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('?', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_question push_question_spanned '?');
422#[doc(hidden)]
pub fn push_rarrow(tokens: &mut TokenStream) {
    tokens.append(Punct::new('-', Spacing::Joint));
    tokens.append(Punct::new('>', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_rarrow_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('-', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('>', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_rarrow push_rarrow_spanned '-' '>');
423#[doc(hidden)]
pub fn push_larrow(tokens: &mut TokenStream) {
    tokens.append(Punct::new('<', Spacing::Joint));
    tokens.append(Punct::new('-', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_larrow_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('<', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('-', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_larrow push_larrow_spanned '<' '-');
424#[doc(hidden)]
pub fn push_rem(tokens: &mut TokenStream) {
    tokens.append(Punct::new('%', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_rem_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('%', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_rem push_rem_spanned '%');
425#[doc(hidden)]
pub fn push_rem_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('%', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_rem_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('%', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_rem_eq push_rem_eq_spanned '%' '=');
426#[doc(hidden)]
pub fn push_fat_arrow(tokens: &mut TokenStream) {
    tokens.append(Punct::new('=', Spacing::Joint));
    tokens.append(Punct::new('>', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_fat_arrow_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('=', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('>', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_fat_arrow push_fat_arrow_spanned '=' '>');
427#[doc(hidden)]
pub fn push_semi(tokens: &mut TokenStream) {
    tokens.append(Punct::new(';', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_semi_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new(';', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_semi push_semi_spanned ';');
428#[doc(hidden)]
pub fn push_shl(tokens: &mut TokenStream) {
    tokens.append(Punct::new('<', Spacing::Joint));
    tokens.append(Punct::new('<', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_shl_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('<', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('<', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_shl push_shl_spanned '<' '<');
429#[doc(hidden)]
pub fn push_shl_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('<', Spacing::Joint));
    tokens.append(Punct::new('<', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_shl_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('<', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('<', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_shl_eq push_shl_eq_spanned '<' '<' '=');
430#[doc(hidden)]
pub fn push_shr(tokens: &mut TokenStream) {
    tokens.append(Punct::new('>', Spacing::Joint));
    tokens.append(Punct::new('>', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_shr_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('>', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('>', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_shr push_shr_spanned '>' '>');
431#[doc(hidden)]
pub fn push_shr_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('>', Spacing::Joint));
    tokens.append(Punct::new('>', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_shr_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('>', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('>', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_shr_eq push_shr_eq_spanned '>' '>' '=');
432#[doc(hidden)]
pub fn push_star(tokens: &mut TokenStream) {
    tokens.append(Punct::new('*', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_star_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('*', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_star push_star_spanned '*');
433#[doc(hidden)]
pub fn push_sub(tokens: &mut TokenStream) {
    tokens.append(Punct::new('-', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_sub_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('-', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_sub push_sub_spanned '-');
434#[doc(hidden)]
pub fn push_sub_eq(tokens: &mut TokenStream) {
    tokens.append(Punct::new('-', Spacing::Joint));
    tokens.append(Punct::new('=', Spacing::Alone));
}
#[doc(hidden)]
pub fn push_sub_eq_spanned(tokens: &mut TokenStream, span: Span) {
    let mut punct = Punct::new('-', Spacing::Joint);
    punct.set_span(span);
    tokens.append(punct);
    let mut punct = Punct::new('=', Spacing::Alone);
    punct.set_span(span);
    tokens.append(punct);
}push_punct!(push_sub_eq push_sub_eq_spanned '-' '=');
435
436#[doc(hidden)]
437pub fn push_underscore(tokens: &mut TokenStream) {
438    push_underscore_spanned(tokens, Span::call_site());
439}
440
441#[doc(hidden)]
442pub fn push_underscore_spanned(tokens: &mut TokenStream, span: Span) {
443    tokens.append(Ident::new("_", span));
444}
445
446// Helper method for constructing identifiers from the `format_ident!` macro,
447// handling `r#` prefixes.
448#[doc(hidden)]
449pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
450    let span = span.unwrap_or_else(Span::call_site);
451    ident_maybe_raw(id, span)
452}
453
454fn ident_maybe_raw(id: &str, span: Span) -> Ident {
455    if let Some(id) = id.strip_prefix("r#") {
456        Ident::new_raw(id, span)
457    } else {
458        Ident::new(id, span)
459    }
460}
461
462// Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
463// macro, and exposes span information from these fragments.
464//
465// This struct also has forwarding implementations of the formatting traits
466// `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within
467// `format_ident!`.
468#[derive(#[automatically_derived]
impl<T: ::core::marker::Copy + IdentFragment> ::core::marker::Copy for
    IdentFragmentAdapter<T> {
}Copy, #[automatically_derived]
impl<T: ::core::clone::Clone + IdentFragment> ::core::clone::Clone for
    IdentFragmentAdapter<T> {
    #[inline]
    fn clone(&self) -> IdentFragmentAdapter<T> {
        IdentFragmentAdapter(::core::clone::Clone::clone(&self.0))
    }
}Clone)]
469#[doc(hidden)]
470pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
471
472impl<T: IdentFragment> IdentFragmentAdapter<T> {
473    pub fn span(&self) -> Option<Span> {
474        self.0.span()
475    }
476}
477
478impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
479    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
480        IdentFragment::fmt(&self.0, f)
481    }
482}
483
484impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
485    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
486        fmt::Octal::fmt(&self.0, f)
487    }
488}
489
490impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
491    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
492        fmt::LowerHex::fmt(&self.0, f)
493    }
494}
495
496impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
497    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
498        fmt::UpperHex::fmt(&self.0, f)
499    }
500}
501
502impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
503    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
504        fmt::Binary::fmt(&self.0, f)
505    }
506}