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