]> git.proxmox.com Git - rustc.git/blame - vendor/quote/src/runtime.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / vendor / quote / src / runtime.rs
CommitLineData
e74abb32
XL
1use crate::{IdentFragment, ToTokens, TokenStreamExt};
2use std::fmt;
5099ac24 3use std::iter;
e74abb32
XL
4use std::ops::BitOr;
5
6pub use proc_macro2::*;
7
8pub struct HasIterator; // True
9pub struct ThereIsNoIteratorInRepetition; // False
10
11impl BitOr<ThereIsNoIteratorInRepetition> for ThereIsNoIteratorInRepetition {
12 type Output = ThereIsNoIteratorInRepetition;
13 fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition {
14 ThereIsNoIteratorInRepetition
15 }
16}
17
18impl BitOr<ThereIsNoIteratorInRepetition> for HasIterator {
19 type Output = HasIterator;
20 fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator {
21 HasIterator
22 }
23}
24
25impl BitOr<HasIterator> for ThereIsNoIteratorInRepetition {
26 type Output = HasIterator;
27 fn bitor(self, _rhs: HasIterator) -> HasIterator {
28 HasIterator
29 }
30}
31
32impl BitOr<HasIterator> for HasIterator {
33 type Output = HasIterator;
34 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.
45pub 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 {
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.
68 fn next(&self) -> Option<&Self> {
69 Some(self)
70 }
71
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
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
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
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
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
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
122 fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
123 (self.iter(), HasIter)
124 }
125 }
126
e74abb32
XL
127 impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp<T> {
128 type Iter = T::Iter;
129
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)]
139pub struct RepInterp<T>(pub T);
140
141impl<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.
146 pub fn next(self) -> Option<T> {
147 Some(self.0)
148 }
149}
150
151impl<T: Iterator> Iterator for RepInterp<T> {
152 type Item = T::Item;
153
154 fn next(&mut self) -> Option<Self::Item> {
155 self.0.next()
156 }
157}
158
159impl<T: ToTokens> ToTokens for RepInterp<T> {
160 fn to_tokens(&self, tokens: &mut TokenStream) {
161 self.0.to_tokens(tokens);
162 }
163}
164
f035d41b
XL
165pub fn push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream) {
166 tokens.append(Group::new(delimiter, inner));
e74abb32
XL
167}
168
f035d41b
XL
169pub 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);
e74abb32
XL
178}
179
f035d41b
XL
180pub fn parse(tokens: &mut TokenStream, s: &str) {
181 let s: TokenStream = s.parse().expect("invalid token stream");
5099ac24 182 tokens.extend(iter::once(s));
f035d41b 183}
e74abb32 184
f035d41b
XL
185pub fn parse_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
186 let s: TokenStream = s.parse().expect("invalid token stream");
5099ac24
FG
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.
191fn 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
e74abb32
XL
205}
206
f035d41b
XL
207pub 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);
e74abb32 214 } else {
f035d41b
XL
215 tokens.append(Ident::new(s, Span::call_site()));
216 }
217}
218
219pub 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));
e74abb32
XL
228 }
229}
230
5099ac24
FG
231pub 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
261pub 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
e74abb32 295macro_rules! push_punct {
f035d41b
XL
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) {
e74abb32
XL
301 let mut punct = Punct::new($char1, Spacing::Alone);
302 punct.set_span(span);
303 tokens.append(punct);
304 }
305 };
f035d41b
XL
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) {
e74abb32
XL
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 };
f035d41b
XL
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) {
e74abb32
XL
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
f035d41b
XL
340push_punct!(push_add push_add_spanned '+');
341push_punct!(push_add_eq push_add_eq_spanned '+' '=');
342push_punct!(push_and push_and_spanned '&');
343push_punct!(push_and_and push_and_and_spanned '&' '&');
344push_punct!(push_and_eq push_and_eq_spanned '&' '=');
345push_punct!(push_at push_at_spanned '@');
346push_punct!(push_bang push_bang_spanned '!');
347push_punct!(push_caret push_caret_spanned '^');
348push_punct!(push_caret_eq push_caret_eq_spanned '^' '=');
349push_punct!(push_colon push_colon_spanned ':');
350push_punct!(push_colon2 push_colon2_spanned ':' ':');
351push_punct!(push_comma push_comma_spanned ',');
352push_punct!(push_div push_div_spanned '/');
353push_punct!(push_div_eq push_div_eq_spanned '/' '=');
354push_punct!(push_dot push_dot_spanned '.');
355push_punct!(push_dot2 push_dot2_spanned '.' '.');
356push_punct!(push_dot3 push_dot3_spanned '.' '.' '.');
357push_punct!(push_dot_dot_eq push_dot_dot_eq_spanned '.' '.' '=');
358push_punct!(push_eq push_eq_spanned '=');
359push_punct!(push_eq_eq push_eq_eq_spanned '=' '=');
360push_punct!(push_ge push_ge_spanned '>' '=');
361push_punct!(push_gt push_gt_spanned '>');
362push_punct!(push_le push_le_spanned '<' '=');
363push_punct!(push_lt push_lt_spanned '<');
364push_punct!(push_mul_eq push_mul_eq_spanned '*' '=');
365push_punct!(push_ne push_ne_spanned '!' '=');
366push_punct!(push_or push_or_spanned '|');
367push_punct!(push_or_eq push_or_eq_spanned '|' '=');
368push_punct!(push_or_or push_or_or_spanned '|' '|');
369push_punct!(push_pound push_pound_spanned '#');
370push_punct!(push_question push_question_spanned '?');
371push_punct!(push_rarrow push_rarrow_spanned '-' '>');
372push_punct!(push_larrow push_larrow_spanned '<' '-');
373push_punct!(push_rem push_rem_spanned '%');
374push_punct!(push_rem_eq push_rem_eq_spanned '%' '=');
375push_punct!(push_fat_arrow push_fat_arrow_spanned '=' '>');
376push_punct!(push_semi push_semi_spanned ';');
377push_punct!(push_shl push_shl_spanned '<' '<');
378push_punct!(push_shl_eq push_shl_eq_spanned '<' '<' '=');
379push_punct!(push_shr push_shr_spanned '>' '>');
380push_punct!(push_shr_eq push_shr_eq_spanned '>' '>' '=');
381push_punct!(push_star push_star_spanned '*');
382push_punct!(push_sub push_sub_spanned '-');
383push_punct!(push_sub_eq push_sub_eq_spanned '-' '=');
e74abb32 384
5099ac24
FG
385pub fn push_underscore(tokens: &mut TokenStream) {
386 push_underscore_spanned(tokens, Span::call_site());
387}
388
389pub fn push_underscore_spanned(tokens: &mut TokenStream, span: Span) {
390 tokens.append(Ident::new("_", span));
391}
392
e74abb32
XL
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.
e74abb32
XL
400pub 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.
5869c6ff
XL
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;
e74abb32 421 }
e74abb32 422 }
5869c6ff
XL
423
424 panic!("not allowed as a raw identifier: `{}`", id);
e74abb32
XL
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)]
434pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
435
436impl<T: IdentFragment> IdentFragmentAdapter<T> {
437 pub fn span(&self) -> Option<Span> {
438 self.0.span()
439 }
440}
441
442impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
443 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
444 IdentFragment::fmt(&self.0, f)
445 }
446}
447
448impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
449 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
450 fmt::Octal::fmt(&self.0, f)
451 }
452}
453
454impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
455 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
456 fmt::LowerHex::fmt(&self.0, f)
457 }
458}
459
460impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
461 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
462 fmt::UpperHex::fmt(&self.0, f)
463 }
464}
465
466impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
467 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
468 fmt::Binary::fmt(&self.0, f)
469 }
470}