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