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