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