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