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