1 use crate::{IdentFragment, ToTokens, TokenStreamExt}
;
5 pub use proc_macro2
::*;
7 pub struct HasIterator
; // True
8 pub struct ThereIsNoIteratorInRepetition
; // False
10 impl BitOr
<ThereIsNoIteratorInRepetition
> for ThereIsNoIteratorInRepetition
{
11 type Output
= ThereIsNoIteratorInRepetition
;
12 fn bitor(self, _rhs
: ThereIsNoIteratorInRepetition
) -> ThereIsNoIteratorInRepetition
{
13 ThereIsNoIteratorInRepetition
17 impl BitOr
<ThereIsNoIteratorInRepetition
> for HasIterator
{
18 type Output
= HasIterator
;
19 fn bitor(self, _rhs
: ThereIsNoIteratorInRepetition
) -> HasIterator
{
24 impl BitOr
<HasIterator
> for ThereIsNoIteratorInRepetition
{
25 type Output
= HasIterator
;
26 fn bitor(self, _rhs
: HasIterator
) -> HasIterator
{
31 impl BitOr
<HasIterator
> for HasIterator
{
32 type Output
= HasIterator
;
33 fn bitor(self, _rhs
: HasIterator
) -> HasIterator
{
38 /// Extension traits used by the implementation of `quote!`. These are defined
39 /// in separate traits, rather than as a single trait due to ambiguity issues.
41 /// These traits expose a `quote_into_iter` method which should allow calling
42 /// whichever impl happens to be applicable. Calling that method repeatedly on
43 /// the returned value should be idempotent.
46 use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter}
;
48 use std
::collections
::btree_set
::{self, BTreeSet}
;
51 /// Extension trait providing the `quote_into_iter` method on iterators.
52 pub trait RepIteratorExt
: Iterator
+ Sized
{
53 fn quote_into_iter(self) -> (Self, HasIter
) {
58 impl<T
: Iterator
> RepIteratorExt
for T {}
60 /// Extension trait providing the `quote_into_iter` method for
61 /// non-iterable types. These types interpolate the same value in each
62 /// iteration of the repetition.
63 pub trait RepToTokensExt
{
64 /// Pretend to be an iterator for the purposes of `quote_into_iter`.
65 /// This allows repeated calls to `quote_into_iter` to continue
66 /// correctly returning DoesNotHaveIter.
67 fn next(&self) -> Option
<&Self> {
71 fn quote_into_iter(&self) -> (&Self, DoesNotHaveIter
) {
72 (self, DoesNotHaveIter
)
76 impl<T
: ToTokens
+ ?Sized
> RepToTokensExt
for T {}
78 /// Extension trait providing the `quote_into_iter` method for types that
79 /// can be referenced as an iterator.
80 pub trait RepAsIteratorExt
<'q
> {
83 fn quote_into_iter(&'q
self) -> (Self::Iter
, HasIter
);
86 impl<'q
, 'a
, T
: RepAsIteratorExt
<'q
> + ?Sized
> RepAsIteratorExt
<'q
> for &'a T
{
89 fn quote_into_iter(&'q
self) -> (Self::Iter
, HasIter
) {
90 <T
as RepAsIteratorExt
>::quote_into_iter(*self)
94 impl<'q
, 'a
, T
: RepAsIteratorExt
<'q
> + ?Sized
> RepAsIteratorExt
<'q
> for &'a
mut T
{
97 fn quote_into_iter(&'q
self) -> (Self::Iter
, HasIter
) {
98 <T
as RepAsIteratorExt
>::quote_into_iter(*self)
102 impl<'q
, T
: 'q
> RepAsIteratorExt
<'q
> for [T
] {
103 type Iter
= slice
::Iter
<'q
, T
>;
105 fn quote_into_iter(&'q
self) -> (Self::Iter
, HasIter
) {
106 (self.iter(), HasIter
)
110 impl<'q
, T
: 'q
> RepAsIteratorExt
<'q
> for Vec
<T
> {
111 type Iter
= slice
::Iter
<'q
, T
>;
113 fn quote_into_iter(&'q
self) -> (Self::Iter
, HasIter
) {
114 (self.iter(), HasIter
)
118 impl<'q
, T
: 'q
> RepAsIteratorExt
<'q
> for BTreeSet
<T
> {
119 type Iter
= btree_set
::Iter
<'q
, T
>;
121 fn quote_into_iter(&'q
self) -> (Self::Iter
, HasIter
) {
122 (self.iter(), HasIter
)
126 macro_rules
! array_rep_slice
{
129 impl<'q
, T
: 'q
> RepAsIteratorExt
<'q
> for [T
; $l
] {
130 type Iter
= slice
::Iter
<'q
, T
>;
132 fn quote_into_iter(&'q
self) -> (Self::Iter
, HasIter
) {
133 (self.iter(), HasIter
)
141 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
142 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
145 impl<'q
, T
: RepAsIteratorExt
<'q
>> RepAsIteratorExt
<'q
> for RepInterp
<T
> {
148 fn quote_into_iter(&'q
self) -> (Self::Iter
, HasIter
) {
149 self.0.quote_into_iter()
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 pub struct RepInterp
<T
>(pub T
);
159 impl<T
> RepInterp
<T
> {
160 // This method is intended to look like `Iterator::next`, and is called when
161 // a name is bound multiple times, as the previous binding will shadow the
162 // original `Iterator` object. This allows us to avoid advancing the
163 // iterator multiple times per iteration.
164 pub fn next(self) -> Option
<T
> {
169 impl<T
: Iterator
> Iterator
for RepInterp
<T
> {
172 fn next(&mut self) -> Option
<Self::Item
> {
177 impl<T
: ToTokens
> ToTokens
for RepInterp
<T
> {
178 fn to_tokens(&self, tokens
: &mut TokenStream
) {
179 self.0.to_tokens(tokens
);
183 pub fn push_group(tokens
: &mut TokenStream
, delimiter
: Delimiter
, inner
: TokenStream
) {
184 tokens
.append(Group
::new(delimiter
, inner
));
187 pub fn push_group_spanned(
188 tokens
: &mut TokenStream
,
190 delimiter
: Delimiter
,
193 let mut g
= Group
::new(delimiter
, inner
);
198 pub fn parse(tokens
: &mut TokenStream
, s
: &str) {
199 let s
: TokenStream
= s
.parse().expect("invalid token stream");
203 pub fn parse_spanned(tokens
: &mut TokenStream
, span
: Span
, s
: &str) {
204 let s
: TokenStream
= s
.parse().expect("invalid token stream");
205 tokens
.extend(s
.into_iter().map(|mut t
| {
211 pub fn push_ident(tokens
: &mut TokenStream
, s
: &str) {
212 // Optimization over `mk_ident`, as `s` is guaranteed to be a valid ident.
214 // FIXME: When `Ident::new_raw` becomes stable, this method should be
215 // updated to call it when available.
216 if s
.starts_with("r#") {
219 tokens
.append(Ident
::new(s
, Span
::call_site()));
223 pub fn push_ident_spanned(tokens
: &mut TokenStream
, span
: Span
, s
: &str) {
224 // Optimization over `mk_ident`, as `s` is guaranteed to be a valid ident.
226 // FIXME: When `Ident::new_raw` becomes stable, this method should be
227 // updated to call it when available.
228 if s
.starts_with("r#") {
229 parse_spanned(tokens
, span
, s
);
231 tokens
.append(Ident
::new(s
, span
));
235 macro_rules
! push_punct
{
236 ($name
:ident $spanned
:ident $char1
:tt
) => {
237 pub fn $
name(tokens
: &mut TokenStream
) {
238 tokens
.append(Punct
::new($char1
, Spacing
::Alone
));
240 pub fn $
spanned(tokens
: &mut TokenStream
, span
: Span
) {
241 let mut punct
= Punct
::new($char1
, Spacing
::Alone
);
242 punct
.set_span(span
);
243 tokens
.append(punct
);
246 ($name
:ident $spanned
:ident $char1
:tt $char2
:tt
) => {
247 pub fn $
name(tokens
: &mut TokenStream
) {
248 tokens
.append(Punct
::new($char1
, Spacing
::Joint
));
249 tokens
.append(Punct
::new($char2
, Spacing
::Alone
));
251 pub fn $
spanned(tokens
: &mut TokenStream
, span
: Span
) {
252 let mut punct
= Punct
::new($char1
, Spacing
::Joint
);
253 punct
.set_span(span
);
254 tokens
.append(punct
);
255 let mut punct
= Punct
::new($char2
, Spacing
::Alone
);
256 punct
.set_span(span
);
257 tokens
.append(punct
);
260 ($name
:ident $spanned
:ident $char1
:tt $char2
:tt $char3
:tt
) => {
261 pub fn $
name(tokens
: &mut TokenStream
) {
262 tokens
.append(Punct
::new($char1
, Spacing
::Joint
));
263 tokens
.append(Punct
::new($char2
, Spacing
::Joint
));
264 tokens
.append(Punct
::new($char3
, Spacing
::Alone
));
266 pub fn $
spanned(tokens
: &mut TokenStream
, span
: Span
) {
267 let mut punct
= Punct
::new($char1
, Spacing
::Joint
);
268 punct
.set_span(span
);
269 tokens
.append(punct
);
270 let mut punct
= Punct
::new($char2
, Spacing
::Joint
);
271 punct
.set_span(span
);
272 tokens
.append(punct
);
273 let mut punct
= Punct
::new($char3
, Spacing
::Alone
);
274 punct
.set_span(span
);
275 tokens
.append(punct
);
280 push_punct
!(push_add push_add_spanned '
+'
);
281 push_punct
!(push_add_eq push_add_eq_spanned '
+' '
='
);
282 push_punct
!(push_and push_and_spanned '
&'
);
283 push_punct
!(push_and_and push_and_and_spanned '
&' '
&'
);
284 push_punct
!(push_and_eq push_and_eq_spanned '
&' '
='
);
285 push_punct
!(push_at push_at_spanned '@'
);
286 push_punct
!(push_bang push_bang_spanned '
!'
);
287 push_punct
!(push_caret push_caret_spanned '
^');
288 push_punct
!(push_caret_eq push_caret_eq_spanned '
^' '
='
);
289 push_punct
!(push_colon push_colon_spanned '
:'
);
290 push_punct
!(push_colon2 push_colon2_spanned '
:' '
:'
);
291 push_punct
!(push_comma push_comma_spanned '
,'
);
292 push_punct
!(push_div push_div_spanned '
/'
);
293 push_punct
!(push_div_eq push_div_eq_spanned '
/' '
='
);
294 push_punct
!(push_dot push_dot_spanned '
.'
);
295 push_punct
!(push_dot2 push_dot2_spanned '
.' '
.'
);
296 push_punct
!(push_dot3 push_dot3_spanned '
.' '
.' '
.'
);
297 push_punct
!(push_dot_dot_eq push_dot_dot_eq_spanned '
.' '
.' '
='
);
298 push_punct
!(push_eq push_eq_spanned '
='
);
299 push_punct
!(push_eq_eq push_eq_eq_spanned '
=' '
='
);
300 push_punct
!(push_ge push_ge_spanned '
>' '
='
);
301 push_punct
!(push_gt push_gt_spanned '
>'
);
302 push_punct
!(push_le push_le_spanned '
<' '
='
);
303 push_punct
!(push_lt push_lt_spanned '
<'
);
304 push_punct
!(push_mul_eq push_mul_eq_spanned '
*' '
='
);
305 push_punct
!(push_ne push_ne_spanned '
!' '
='
);
306 push_punct
!(push_or push_or_spanned '
|'
);
307 push_punct
!(push_or_eq push_or_eq_spanned '
|' '
='
);
308 push_punct
!(push_or_or push_or_or_spanned '
|' '
|'
);
309 push_punct
!(push_pound push_pound_spanned '
#');
310 push_punct
!(push_question push_question_spanned '?'
);
311 push_punct
!(push_rarrow push_rarrow_spanned '
-' '
>'
);
312 push_punct
!(push_larrow push_larrow_spanned '
<' '
-'
);
313 push_punct
!(push_rem push_rem_spanned '
%'
);
314 push_punct
!(push_rem_eq push_rem_eq_spanned '
%' '
='
);
315 push_punct
!(push_fat_arrow push_fat_arrow_spanned '
=' '
>'
);
316 push_punct
!(push_semi push_semi_spanned '
;'
);
317 push_punct
!(push_shl push_shl_spanned '
<' '
<'
);
318 push_punct
!(push_shl_eq push_shl_eq_spanned '
<' '
<' '
='
);
319 push_punct
!(push_shr push_shr_spanned '
>' '
>'
);
320 push_punct
!(push_shr_eq push_shr_eq_spanned '
>' '
>' '
='
);
321 push_punct
!(push_star push_star_spanned '
*'
);
322 push_punct
!(push_sub push_sub_spanned '
-'
);
323 push_punct
!(push_sub_eq push_sub_eq_spanned '
-' '
='
);
325 // Helper method for constructing identifiers from the `format_ident!` macro,
326 // handling `r#` prefixes.
328 // Directly parsing the input string may produce a valid identifier,
329 // although the input string was invalid, due to ignored characters such as
330 // whitespace and comments. Instead, we always create a non-raw identifier
331 // to validate that the string is OK, and only parse again if needed.
332 pub fn mk_ident(id
: &str, span
: Option
<Span
>) -> Ident
{
333 let span
= span
.unwrap_or_else(Span
::call_site
);
335 let is_raw
= id
.starts_with("r#");
336 let unraw
= Ident
::new(if is_raw { &id[2..] }
else { id }
, span
);
341 // At this point, the identifier is raw, and the unraw-ed version of it was
342 // successfully converted into an identifier. Try to produce a valid raw
343 // identifier by running the `TokenStream` parser, and unwrapping the first
344 // token as an `Ident`.
346 // FIXME: When `Ident::new_raw` becomes stable, this method should be
347 // updated to call it when available.
348 if let Ok(ts
) = id
.parse
::<TokenStream
>() {
349 let mut iter
= ts
.into_iter();
350 if let (Some(TokenTree
::Ident(mut id
)), None
) = (iter
.next(), iter
.next()) {
356 panic
!("not allowed as a raw identifier: `{}`", id
);
359 // Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
360 // macro, and exposes span information from these fragments.
362 // This struct also has forwarding implementations of the formatting traits
363 // `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within
365 #[derive(Copy, Clone)]
366 pub struct IdentFragmentAdapter
<T
: IdentFragment
>(pub T
);
368 impl<T
: IdentFragment
> IdentFragmentAdapter
<T
> {
369 pub fn span(&self) -> Option
<Span
> {
374 impl<T
: IdentFragment
> fmt
::Display
for IdentFragmentAdapter
<T
> {
375 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
376 IdentFragment
::fmt(&self.0, f
)
380 impl<T
: IdentFragment
+ fmt
::Octal
> fmt
::Octal
for IdentFragmentAdapter
<T
> {
381 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
382 fmt
::Octal
::fmt(&self.0, f
)
386 impl<T
: IdentFragment
+ fmt
::LowerHex
> fmt
::LowerHex
for IdentFragmentAdapter
<T
> {
387 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
388 fmt
::LowerHex
::fmt(&self.0, f
)
392 impl<T
: IdentFragment
+ fmt
::UpperHex
> fmt
::UpperHex
for IdentFragmentAdapter
<T
> {
393 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
394 fmt
::UpperHex
::fmt(&self.0, f
)
398 impl<T
: IdentFragment
+ fmt
::Binary
> fmt
::Binary
for IdentFragmentAdapter
<T
> {
399 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
400 fmt
::Binary
::fmt(&self.0, f
)