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, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &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, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &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, const N: usize> RepAsIteratorExt<'q> for [T; N] {
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 Vec<T> {
138 type Iter = slice::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: 'q> RepAsIteratorExt<'q> for BTreeSet<T> {
146 type Iter = btree_set::Iter<'q, T>;
147
quote_into_iter(&'q self) -> (Self::Iter, HasIter)148 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
149 (self.iter(), HasIter)
150 }
151 }
152
153 impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp<T> {
154 type Iter = T::Iter;
155
quote_into_iter(&'q self) -> (Self::Iter, HasIter)156 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
157 self.0.quote_into_iter()
158 }
159 }
160 }
161
162 // Helper type used within interpolations to allow for repeated binding names.
163 // Implements the relevant traits, and exports a dummy `next()` method.
164 #[derive(Copy, Clone)]
165 #[doc(hidden)]
166 pub struct RepInterp<T>(pub T);
167
168 impl<T> RepInterp<T> {
169 // This method is intended to look like `Iterator::next`, and is called when
170 // a name is bound multiple times, as the previous binding will shadow the
171 // original `Iterator` object. This allows us to avoid advancing the
172 // iterator multiple times per iteration.
next(self) -> Option<T>173 pub fn next(self) -> Option<T> {
174 Some(self.0)
175 }
176 }
177
178 impl<T: Iterator> Iterator for RepInterp<T> {
179 type Item = T::Item;
180
next(&mut self) -> Option<Self::Item>181 fn next(&mut self) -> Option<Self::Item> {
182 self.0.next()
183 }
184 }
185
186 impl<T: ToTokens> ToTokens for RepInterp<T> {
to_tokens(&self, tokens: &mut TokenStream)187 fn to_tokens(&self, tokens: &mut TokenStream) {
188 self.0.to_tokens(tokens);
189 }
190 }
191
192 #[doc(hidden)]
193 #[inline]
get_span<T>(span: T) -> GetSpan<T>194 pub fn get_span<T>(span: T) -> GetSpan<T> {
195 GetSpan(GetSpanInner(GetSpanBase(span)))
196 }
197
198 mod get_span {
199 use core::ops::Deref;
200 use proc_macro2::extra::DelimSpan;
201 use proc_macro2::Span;
202
203 pub struct GetSpan<T>(pub(crate) GetSpanInner<T>);
204
205 pub struct GetSpanInner<T>(pub(crate) GetSpanBase<T>);
206
207 pub struct GetSpanBase<T>(pub(crate) T);
208
209 impl GetSpan<Span> {
210 #[inline]
__into_span(self) -> Span211 pub fn __into_span(self) -> Span {
212 ((self.0).0).0
213 }
214 }
215
216 impl GetSpanInner<DelimSpan> {
217 #[inline]
__into_span(&self) -> Span218 pub fn __into_span(&self) -> Span {
219 (self.0).0.join()
220 }
221 }
222
223 impl<T> GetSpanBase<T> {
224 #[allow(clippy::unused_self)]
__into_span(&self) -> T225 pub fn __into_span(&self) -> T {
226 unreachable!()
227 }
228 }
229
230 impl<T> Deref for GetSpan<T> {
231 type Target = GetSpanInner<T>;
232
233 #[inline]
deref(&self) -> &Self::Target234 fn deref(&self) -> &Self::Target {
235 &self.0
236 }
237 }
238
239 impl<T> Deref for GetSpanInner<T> {
240 type Target = GetSpanBase<T>;
241
242 #[inline]
deref(&self) -> &Self::Target243 fn deref(&self) -> &Self::Target {
244 &self.0
245 }
246 }
247 }
248
249 #[doc(hidden)]
push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream)250 pub fn push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream) {
251 tokens.append(Group::new(delimiter, inner));
252 }
253
254 #[doc(hidden)]
push_group_spanned( tokens: &mut TokenStream, span: Span, delimiter: Delimiter, inner: TokenStream, )255 pub fn push_group_spanned(
256 tokens: &mut TokenStream,
257 span: Span,
258 delimiter: Delimiter,
259 inner: TokenStream,
260 ) {
261 let mut g = Group::new(delimiter, inner);
262 g.set_span(span);
263 tokens.append(g);
264 }
265
266 #[doc(hidden)]
parse(tokens: &mut TokenStream, s: &str)267 pub fn parse(tokens: &mut TokenStream, s: &str) {
268 let s: TokenStream = s.parse().expect("invalid token stream");
269 tokens.extend(iter::once(s));
270 }
271
272 #[doc(hidden)]
parse_spanned(tokens: &mut TokenStream, span: Span, s: &str)273 pub fn parse_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
274 let s: TokenStream = s.parse().expect("invalid token stream");
275 tokens.extend(s.into_iter().map(|t| respan_token_tree(t, span)));
276 }
277
278 // Token tree with every span replaced by the given one.
respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree279 fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
280 match &mut token {
281 TokenTree::Group(g) => {
282 let stream = g
283 .stream()
284 .into_iter()
285 .map(|token| respan_token_tree(token, span))
286 .collect();
287 *g = Group::new(g.delimiter(), stream);
288 g.set_span(span);
289 }
290 other => other.set_span(span),
291 }
292 token
293 }
294
295 #[doc(hidden)]
push_ident(tokens: &mut TokenStream, s: &str)296 pub fn push_ident(tokens: &mut TokenStream, s: &str) {
297 let span = Span::call_site();
298 push_ident_spanned(tokens, span, s);
299 }
300
301 #[doc(hidden)]
push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str)302 pub fn push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
303 tokens.append(ident_maybe_raw(s, span));
304 }
305
306 #[doc(hidden)]
push_lifetime(tokens: &mut TokenStream, lifetime: &str)307 pub fn push_lifetime(tokens: &mut TokenStream, lifetime: &str) {
308 tokens.extend([
309 TokenTree::Punct(Punct::new('\'', Spacing::Joint)),
310 TokenTree::Ident(Ident::new(&lifetime[1..], Span::call_site())),
311 ]);
312 }
313
314 #[doc(hidden)]
push_lifetime_spanned(tokens: &mut TokenStream, span: Span, lifetime: &str)315 pub fn push_lifetime_spanned(tokens: &mut TokenStream, span: Span, lifetime: &str) {
316 tokens.extend([
317 TokenTree::Punct({
318 let mut apostrophe = Punct::new('\'', Spacing::Joint);
319 apostrophe.set_span(span);
320 apostrophe
321 }),
322 TokenTree::Ident(Ident::new(&lifetime[1..], span)),
323 ]);
324 }
325
326 macro_rules! push_punct {
327 ($name:ident $spanned:ident $char1:tt) => {
328 #[doc(hidden)]
329 pub fn $name(tokens: &mut TokenStream) {
330 tokens.append(Punct::new($char1, Spacing::Alone));
331 }
332 #[doc(hidden)]
333 pub fn $spanned(tokens: &mut TokenStream, span: Span) {
334 let mut punct = Punct::new($char1, Spacing::Alone);
335 punct.set_span(span);
336 tokens.append(punct);
337 }
338 };
339 ($name:ident $spanned:ident $char1:tt $char2:tt) => {
340 #[doc(hidden)]
341 pub fn $name(tokens: &mut TokenStream) {
342 tokens.append(Punct::new($char1, Spacing::Joint));
343 tokens.append(Punct::new($char2, Spacing::Alone));
344 }
345 #[doc(hidden)]
346 pub fn $spanned(tokens: &mut TokenStream, span: Span) {
347 let mut punct = Punct::new($char1, Spacing::Joint);
348 punct.set_span(span);
349 tokens.append(punct);
350 let mut punct = Punct::new($char2, Spacing::Alone);
351 punct.set_span(span);
352 tokens.append(punct);
353 }
354 };
355 ($name:ident $spanned:ident $char1:tt $char2:tt $char3:tt) => {
356 #[doc(hidden)]
357 pub fn $name(tokens: &mut TokenStream) {
358 tokens.append(Punct::new($char1, Spacing::Joint));
359 tokens.append(Punct::new($char2, Spacing::Joint));
360 tokens.append(Punct::new($char3, Spacing::Alone));
361 }
362 #[doc(hidden)]
363 pub fn $spanned(tokens: &mut TokenStream, span: Span) {
364 let mut punct = Punct::new($char1, Spacing::Joint);
365 punct.set_span(span);
366 tokens.append(punct);
367 let mut punct = Punct::new($char2, Spacing::Joint);
368 punct.set_span(span);
369 tokens.append(punct);
370 let mut punct = Punct::new($char3, Spacing::Alone);
371 punct.set_span(span);
372 tokens.append(punct);
373 }
374 };
375 }
376
377 push_punct!(push_add push_add_spanned '+');
378 push_punct!(push_add_eq push_add_eq_spanned '+' '=');
379 push_punct!(push_and push_and_spanned '&');
380 push_punct!(push_and_and push_and_and_spanned '&' '&');
381 push_punct!(push_and_eq push_and_eq_spanned '&' '=');
382 push_punct!(push_at push_at_spanned '@');
383 push_punct!(push_bang push_bang_spanned '!');
384 push_punct!(push_caret push_caret_spanned '^');
385 push_punct!(push_caret_eq push_caret_eq_spanned '^' '=');
386 push_punct!(push_colon push_colon_spanned ':');
387 push_punct!(push_colon2 push_colon2_spanned ':' ':');
388 push_punct!(push_comma push_comma_spanned ',');
389 push_punct!(push_div push_div_spanned '/');
390 push_punct!(push_div_eq push_div_eq_spanned '/' '=');
391 push_punct!(push_dot push_dot_spanned '.');
392 push_punct!(push_dot2 push_dot2_spanned '.' '.');
393 push_punct!(push_dot3 push_dot3_spanned '.' '.' '.');
394 push_punct!(push_dot_dot_eq push_dot_dot_eq_spanned '.' '.' '=');
395 push_punct!(push_eq push_eq_spanned '=');
396 push_punct!(push_eq_eq push_eq_eq_spanned '=' '=');
397 push_punct!(push_ge push_ge_spanned '>' '=');
398 push_punct!(push_gt push_gt_spanned '>');
399 push_punct!(push_le push_le_spanned '<' '=');
400 push_punct!(push_lt push_lt_spanned '<');
401 push_punct!(push_mul_eq push_mul_eq_spanned '*' '=');
402 push_punct!(push_ne push_ne_spanned '!' '=');
403 push_punct!(push_or push_or_spanned '|');
404 push_punct!(push_or_eq push_or_eq_spanned '|' '=');
405 push_punct!(push_or_or push_or_or_spanned '|' '|');
406 push_punct!(push_pound push_pound_spanned '#');
407 push_punct!(push_question push_question_spanned '?');
408 push_punct!(push_rarrow push_rarrow_spanned '-' '>');
409 push_punct!(push_larrow push_larrow_spanned '<' '-');
410 push_punct!(push_rem push_rem_spanned '%');
411 push_punct!(push_rem_eq push_rem_eq_spanned '%' '=');
412 push_punct!(push_fat_arrow push_fat_arrow_spanned '=' '>');
413 push_punct!(push_semi push_semi_spanned ';');
414 push_punct!(push_shl push_shl_spanned '<' '<');
415 push_punct!(push_shl_eq push_shl_eq_spanned '<' '<' '=');
416 push_punct!(push_shr push_shr_spanned '>' '>');
417 push_punct!(push_shr_eq push_shr_eq_spanned '>' '>' '=');
418 push_punct!(push_star push_star_spanned '*');
419 push_punct!(push_sub push_sub_spanned '-');
420 push_punct!(push_sub_eq push_sub_eq_spanned '-' '=');
421
422 #[doc(hidden)]
push_underscore(tokens: &mut TokenStream)423 pub fn push_underscore(tokens: &mut TokenStream) {
424 push_underscore_spanned(tokens, Span::call_site());
425 }
426
427 #[doc(hidden)]
push_underscore_spanned(tokens: &mut TokenStream, span: Span)428 pub fn push_underscore_spanned(tokens: &mut TokenStream, span: Span) {
429 tokens.append(Ident::new("_", span));
430 }
431
432 // Helper method for constructing identifiers from the `format_ident!` macro,
433 // handling `r#` prefixes.
434 #[doc(hidden)]
mk_ident(id: &str, span: Option<Span>) -> Ident435 pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
436 let span = span.unwrap_or_else(Span::call_site);
437 ident_maybe_raw(id, span)
438 }
439
ident_maybe_raw(id: &str, span: Span) -> Ident440 fn ident_maybe_raw(id: &str, span: Span) -> Ident {
441 if let Some(id) = id.strip_prefix("r#") {
442 Ident::new_raw(id, span)
443 } else {
444 Ident::new(id, span)
445 }
446 }
447
448 // Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
449 // macro, and exposes span information from these fragments.
450 //
451 // This struct also has forwarding implementations of the formatting traits
452 // `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within
453 // `format_ident!`.
454 #[derive(Copy, Clone)]
455 #[doc(hidden)]
456 pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
457
458 impl<T: IdentFragment> IdentFragmentAdapter<T> {
span(&self) -> Option<Span>459 pub fn span(&self) -> Option<Span> {
460 self.0.span()
461 }
462 }
463
464 impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result465 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
466 IdentFragment::fmt(&self.0, f)
467 }
468 }
469
470 impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result471 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
472 fmt::Octal::fmt(&self.0, f)
473 }
474 }
475
476 impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result477 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
478 fmt::LowerHex::fmt(&self.0, f)
479 }
480 }
481
482 impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result483 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
484 fmt::UpperHex::fmt(&self.0, f)
485 }
486 }
487
488 impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result489 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
490 fmt::Binary::fmt(&self.0, f)
491 }
492 }
493