Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3use self::get_span::{GetSpan, GetSpanBase, GetSpanInner};
4use crate::{IdentFragment, ToTokens, TokenStreamExt};
5use core::fmt;
6use core::iter;
7use core::ops::BitOr;
8use proc_macro2::{Group, Ident, Punct, Spacing, TokenTree};
9
10#[doc(hidden)]
11pub use alloc::format;
12#[doc(hidden)]
13pub use core::option::Option;
14
15#[doc(hidden)]
16pub type Delimiter = proc_macro2::Delimiter;
17#[doc(hidden)]
18pub type Span = proc_macro2::Span;
19#[doc(hidden)]
20pub type TokenStream = proc_macro2::TokenStream;
21
22#[doc(hidden)]
23pub struct HasIterator; // True
24#[doc(hidden)]
25pub struct ThereIsNoIteratorInRepetition; // False
26
27impl BitOr<ThereIsNoIteratorInRepetition> for ThereIsNoIteratorInRepetition {
28 type Output = ThereIsNoIteratorInRepetition;
29 fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition {
30 ThereIsNoIteratorInRepetition
31 }
32}
33
34impl BitOr<ThereIsNoIteratorInRepetition> for HasIterator {
35 type Output = HasIterator;
36 fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator {
37 HasIterator
38 }
39}
40
41impl BitOr<HasIterator> for ThereIsNoIteratorInRepetition {
42 type Output = HasIterator;
43 fn bitor(self, _rhs: HasIterator) -> HasIterator {
44 HasIterator
45 }
46}
47
48impl 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)]
62pub 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)]
168pub struct RepInterp<T>(pub T);
169
170impl<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
180impl<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
188impl<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]
196pub fn get_span<T>(span: T) -> GetSpan<T> {
197 GetSpan(GetSpanInner(GetSpanBase(span)))
198}
199
200mod 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)]
252pub fn push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream) {
253 tokens.append(Group::new(delimiter, inner));
254}
255
256#[doc(hidden)]
257pub 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)]
269pub 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)]
275pub 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.
281fn 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)]
298pub 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)]
304pub fn push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
305 tokens.append(ident_maybe_raw(s, span));
306}
307
308#[doc(hidden)]
309pub 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)]
317pub 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
328macro_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
379push_punct!(push_add push_add_spanned '+');
380push_punct!(push_add_eq push_add_eq_spanned '+' '=');
381push_punct!(push_and push_and_spanned '&');
382push_punct!(push_and_and push_and_and_spanned '&' '&');
383push_punct!(push_and_eq push_and_eq_spanned '&' '=');
384push_punct!(push_at push_at_spanned '@');
385push_punct!(push_bang push_bang_spanned '!');
386push_punct!(push_caret push_caret_spanned '^');
387push_punct!(push_caret_eq push_caret_eq_spanned '^' '=');
388push_punct!(push_colon push_colon_spanned ':');
389push_punct!(push_colon2 push_colon2_spanned ':' ':');
390push_punct!(push_comma push_comma_spanned ',');
391push_punct!(push_div push_div_spanned '/');
392push_punct!(push_div_eq push_div_eq_spanned '/' '=');
393push_punct!(push_dot push_dot_spanned '.');
394push_punct!(push_dot2 push_dot2_spanned '.' '.');
395push_punct!(push_dot3 push_dot3_spanned '.' '.' '.');
396push_punct!(push_dot_dot_eq push_dot_dot_eq_spanned '.' '.' '=');
397push_punct!(push_eq push_eq_spanned '=');
398push_punct!(push_eq_eq push_eq_eq_spanned '=' '=');
399push_punct!(push_ge push_ge_spanned '>' '=');
400push_punct!(push_gt push_gt_spanned '>');
401push_punct!(push_le push_le_spanned '<' '=');
402push_punct!(push_lt push_lt_spanned '<');
403push_punct!(push_mul_eq push_mul_eq_spanned '*' '=');
404push_punct!(push_ne push_ne_spanned '!' '=');
405push_punct!(push_or push_or_spanned '|');
406push_punct!(push_or_eq push_or_eq_spanned '|' '=');
407push_punct!(push_or_or push_or_or_spanned '|' '|');
408push_punct!(push_pound push_pound_spanned '#');
409push_punct!(push_question push_question_spanned '?');
410push_punct!(push_rarrow push_rarrow_spanned '-' '>');
411push_punct!(push_larrow push_larrow_spanned '<' '-');
412push_punct!(push_rem push_rem_spanned '%');
413push_punct!(push_rem_eq push_rem_eq_spanned '%' '=');
414push_punct!(push_fat_arrow push_fat_arrow_spanned '=' '>');
415push_punct!(push_semi push_semi_spanned ';');
416push_punct!(push_shl push_shl_spanned '<' '<');
417push_punct!(push_shl_eq push_shl_eq_spanned '<' '<' '=');
418push_punct!(push_shr push_shr_spanned '>' '>');
419push_punct!(push_shr_eq push_shr_eq_spanned '>' '>' '=');
420push_punct!(push_star push_star_spanned '*');
421push_punct!(push_sub push_sub_spanned '-');
422push_punct!(push_sub_eq push_sub_eq_spanned '-' '=');
423
424#[doc(hidden)]
425pub fn push_underscore(tokens: &mut TokenStream) {
426 push_underscore_spanned(tokens, Span::call_site());
427}
428
429#[doc(hidden)]
430pub 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)]
437pub 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
442fn 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)]
458pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
459
460impl<T: IdentFragment> IdentFragmentAdapter<T> {
461 pub fn span(&self) -> Option<Span> {
462 self.0.span()
463 }
464}
465
466impl<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
472impl<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
478impl<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
484impl<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
490impl<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}