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