1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 3 use crate::detection::inside_proc_macro; 4 use crate::fallback::{self, FromStr2 as _}; 5 #[cfg(span_locations)] 6 use crate::location::LineColumn; 7 #[cfg(proc_macro_span)] 8 use crate::probe::proc_macro_span; 9 #[cfg(all(span_locations, proc_macro_span_file))] 10 use crate::probe::proc_macro_span_file; 11 #[cfg(all(span_locations, proc_macro_span_location))] 12 use crate::probe::proc_macro_span_location; 13 use crate::{Delimiter, Punct, Spacing, TokenTree}; 14 use core::fmt::{self, Debug, Display}; 15 #[cfg(span_locations)] 16 use core::ops::Range; 17 use core::ops::RangeBounds; 18 use std::ffi::CStr; 19 #[cfg(span_locations)] 20 use std::path::PathBuf; 21 22 #[derive(Clone)] 23 pub(crate) enum TokenStream { 24 Compiler(DeferredTokenStream), 25 Fallback(fallback::TokenStream), 26 } 27 28 // Work around https://github.com/rust-lang/rust/issues/65080. 29 // In `impl Extend<TokenTree> for TokenStream` which is used heavily by quote, 30 // we hold on to the appended tokens and do proc_macro::TokenStream::extend as 31 // late as possible to batch together consecutive uses of the Extend impl. 32 #[derive(Clone)] 33 pub(crate) struct DeferredTokenStream { 34 stream: proc_macro::TokenStream, 35 extra: Vec<proc_macro::TokenTree>, 36 } 37 38 pub(crate) enum LexError { 39 Compiler(proc_macro::LexError), 40 Fallback(fallback::LexError), 41 42 // Rustc was supposed to return a LexError, but it panicked instead. 43 // https://github.com/rust-lang/rust/issues/58736 44 CompilerPanic, 45 } 46 47 #[cold] 48 fn mismatch(line: u32) -> ! { 49 #[cfg(procmacro2_backtrace)] 50 { 51 let backtrace = std::backtrace::Backtrace::force_capture(); 52 panic!("compiler/fallback mismatch L{}\n\n{}", line, backtrace) 53 } 54 #[cfg(not(procmacro2_backtrace))] 55 { 56 panic!("compiler/fallback mismatch L{}", line) 57 } 58 } 59 60 impl DeferredTokenStream { 61 fn new(stream: proc_macro::TokenStream) -> Self { 62 DeferredTokenStream { 63 stream, 64 extra: Vec::new(), 65 } 66 } 67 68 fn is_empty(&self) -> bool { 69 self.stream.is_empty() && self.extra.is_empty() 70 } 71 72 fn evaluate_now(&mut self) { 73 // If-check provides a fast short circuit for the common case of `extra` 74 // being empty, which saves a round trip over the proc macro bridge. 75 // Improves macro expansion time in winrt by 6% in debug mode. 76 if !self.extra.is_empty() { 77 self.stream.extend(self.extra.drain(..)); 78 } 79 } 80 81 fn into_token_stream(mut self) -> proc_macro::TokenStream { 82 self.evaluate_now(); 83 self.stream 84 } 85 } 86 87 impl TokenStream { 88 pub(crate) fn new() -> Self { 89 if inside_proc_macro() { 90 TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new())) 91 } else { 92 TokenStream::Fallback(fallback::TokenStream::new()) 93 } 94 } 95 96 pub(crate) fn from_str_checked(src: &str) -> Result<Self, LexError> { 97 if inside_proc_macro() { 98 Ok(TokenStream::Compiler(DeferredTokenStream::new( 99 proc_macro::TokenStream::from_str_checked(src)?, 100 ))) 101 } else { 102 Ok(TokenStream::Fallback( 103 fallback::TokenStream::from_str_checked(src)?, 104 )) 105 } 106 } 107 108 pub(crate) fn is_empty(&self) -> bool { 109 match self { 110 TokenStream::Compiler(tts) => tts.is_empty(), 111 TokenStream::Fallback(tts) => tts.is_empty(), 112 } 113 } 114 115 fn unwrap_nightly(self) -> proc_macro::TokenStream { 116 match self { 117 TokenStream::Compiler(s) => s.into_token_stream(), 118 TokenStream::Fallback(_) => mismatch(line!()), 119 } 120 } 121 122 fn unwrap_stable(self) -> fallback::TokenStream { 123 match self { 124 TokenStream::Compiler(_) => mismatch(line!()), 125 TokenStream::Fallback(s) => s, 126 } 127 } 128 } 129 130 impl Display for TokenStream { 131 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 132 match self { 133 TokenStream::Compiler(tts) => Display::fmt(&tts.clone().into_token_stream(), f), 134 TokenStream::Fallback(tts) => Display::fmt(tts, f), 135 } 136 } 137 } 138 139 impl From<proc_macro::TokenStream> for TokenStream { 140 fn from(inner: proc_macro::TokenStream) -> Self { 141 TokenStream::Compiler(DeferredTokenStream::new(inner)) 142 } 143 } 144 145 impl From<TokenStream> for proc_macro::TokenStream { 146 fn from(inner: TokenStream) -> Self { 147 match inner { 148 TokenStream::Compiler(inner) => inner.into_token_stream(), 149 TokenStream::Fallback(inner) => { 150 proc_macro::TokenStream::from_str_unchecked(&inner.to_string()) 151 } 152 } 153 } 154 } 155 156 impl From<fallback::TokenStream> for TokenStream { 157 fn from(inner: fallback::TokenStream) -> Self { 158 TokenStream::Fallback(inner) 159 } 160 } 161 162 // Assumes inside_proc_macro(). 163 fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree { 164 match token { 165 TokenTree::Group(tt) => proc_macro::TokenTree::Group(tt.inner.unwrap_nightly()), 166 TokenTree::Punct(tt) => { 167 let spacing = match tt.spacing() { 168 Spacing::Joint => proc_macro::Spacing::Joint, 169 Spacing::Alone => proc_macro::Spacing::Alone, 170 }; 171 let mut punct = proc_macro::Punct::new(tt.as_char(), spacing); 172 punct.set_span(tt.span().inner.unwrap_nightly()); 173 proc_macro::TokenTree::Punct(punct) 174 } 175 TokenTree::Ident(tt) => proc_macro::TokenTree::Ident(tt.inner.unwrap_nightly()), 176 TokenTree::Literal(tt) => proc_macro::TokenTree::Literal(tt.inner.unwrap_nightly()), 177 } 178 } 179 180 impl From<TokenTree> for TokenStream { 181 fn from(token: TokenTree) -> Self { 182 if inside_proc_macro() { 183 TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::from( 184 into_compiler_token(token), 185 ))) 186 } else { 187 TokenStream::Fallback(fallback::TokenStream::from(token)) 188 } 189 } 190 } 191 192 impl FromIterator<TokenTree> for TokenStream { 193 fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self { 194 if inside_proc_macro() { 195 TokenStream::Compiler(DeferredTokenStream::new( 196 trees.into_iter().map(into_compiler_token).collect(), 197 )) 198 } else { 199 TokenStream::Fallback(trees.into_iter().collect()) 200 } 201 } 202 } 203 204 impl FromIterator<TokenStream> for TokenStream { 205 fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { 206 let mut streams = streams.into_iter(); 207 match streams.next() { 208 Some(TokenStream::Compiler(mut first)) => { 209 first.evaluate_now(); 210 first.stream.extend(streams.map(|s| match s { 211 TokenStream::Compiler(s) => s.into_token_stream(), 212 TokenStream::Fallback(_) => mismatch(line!()), 213 })); 214 TokenStream::Compiler(first) 215 } 216 Some(TokenStream::Fallback(mut first)) => { 217 first.extend(streams.map(|s| match s { 218 TokenStream::Fallback(s) => s, 219 TokenStream::Compiler(_) => mismatch(line!()), 220 })); 221 TokenStream::Fallback(first) 222 } 223 None => TokenStream::new(), 224 } 225 } 226 } 227 228 impl Extend<TokenTree> for TokenStream { 229 fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, stream: I) { 230 match self { 231 TokenStream::Compiler(tts) => { 232 // Here is the reason for DeferredTokenStream. 233 for token in stream { 234 tts.extra.push(into_compiler_token(token)); 235 } 236 } 237 TokenStream::Fallback(tts) => tts.extend(stream), 238 } 239 } 240 } 241 242 impl Extend<TokenStream> for TokenStream { 243 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { 244 match self { 245 TokenStream::Compiler(tts) => { 246 tts.evaluate_now(); 247 tts.stream 248 .extend(streams.into_iter().map(TokenStream::unwrap_nightly)); 249 } 250 TokenStream::Fallback(tts) => { 251 tts.extend(streams.into_iter().map(TokenStream::unwrap_stable)); 252 } 253 } 254 } 255 } 256 257 impl Debug for TokenStream { 258 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 259 match self { 260 TokenStream::Compiler(tts) => Debug::fmt(&tts.clone().into_token_stream(), f), 261 TokenStream::Fallback(tts) => Debug::fmt(tts, f), 262 } 263 } 264 } 265 266 impl LexError { 267 pub(crate) fn span(&self) -> Span { 268 match self { 269 LexError::Compiler(_) | LexError::CompilerPanic => Span::call_site(), 270 LexError::Fallback(e) => Span::Fallback(e.span()), 271 } 272 } 273 } 274 275 impl From<proc_macro::LexError> for LexError { 276 fn from(e: proc_macro::LexError) -> Self { 277 LexError::Compiler(e) 278 } 279 } 280 281 impl From<fallback::LexError> for LexError { 282 fn from(e: fallback::LexError) -> Self { 283 LexError::Fallback(e) 284 } 285 } 286 287 impl Debug for LexError { 288 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 289 match self { 290 LexError::Compiler(e) => Debug::fmt(e, f), 291 LexError::Fallback(e) => Debug::fmt(e, f), 292 LexError::CompilerPanic => { 293 let fallback = fallback::LexError::call_site(); 294 Debug::fmt(&fallback, f) 295 } 296 } 297 } 298 } 299 300 impl Display for LexError { 301 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 302 match self { 303 LexError::Compiler(e) => Display::fmt(e, f), 304 LexError::Fallback(e) => Display::fmt(e, f), 305 LexError::CompilerPanic => { 306 let fallback = fallback::LexError::call_site(); 307 Display::fmt(&fallback, f) 308 } 309 } 310 } 311 } 312 313 #[derive(Clone)] 314 pub(crate) enum TokenTreeIter { 315 Compiler(proc_macro::token_stream::IntoIter), 316 Fallback(fallback::TokenTreeIter), 317 } 318 319 impl IntoIterator for TokenStream { 320 type Item = TokenTree; 321 type IntoIter = TokenTreeIter; 322 323 fn into_iter(self) -> TokenTreeIter { 324 match self { 325 TokenStream::Compiler(tts) => { 326 TokenTreeIter::Compiler(tts.into_token_stream().into_iter()) 327 } 328 TokenStream::Fallback(tts) => TokenTreeIter::Fallback(tts.into_iter()), 329 } 330 } 331 } 332 333 impl Iterator for TokenTreeIter { 334 type Item = TokenTree; 335 336 fn next(&mut self) -> Option<TokenTree> { 337 let token = match self { 338 TokenTreeIter::Compiler(iter) => iter.next()?, 339 TokenTreeIter::Fallback(iter) => return iter.next(), 340 }; 341 Some(match token { 342 proc_macro::TokenTree::Group(tt) => { 343 TokenTree::Group(crate::Group::_new(Group::Compiler(tt))) 344 } 345 proc_macro::TokenTree::Punct(tt) => { 346 let spacing = match tt.spacing() { 347 proc_macro::Spacing::Joint => Spacing::Joint, 348 proc_macro::Spacing::Alone => Spacing::Alone, 349 }; 350 let mut o = Punct::new(tt.as_char(), spacing); 351 o.set_span(crate::Span::_new(Span::Compiler(tt.span()))); 352 TokenTree::Punct(o) 353 } 354 proc_macro::TokenTree::Ident(s) => { 355 TokenTree::Ident(crate::Ident::_new(Ident::Compiler(s))) 356 } 357 proc_macro::TokenTree::Literal(l) => { 358 TokenTree::Literal(crate::Literal::_new(Literal::Compiler(l))) 359 } 360 }) 361 } 362 363 fn size_hint(&self) -> (usize, Option<usize>) { 364 match self { 365 TokenTreeIter::Compiler(tts) => tts.size_hint(), 366 TokenTreeIter::Fallback(tts) => tts.size_hint(), 367 } 368 } 369 } 370 371 #[derive(Copy, Clone)] 372 pub(crate) enum Span { 373 Compiler(proc_macro::Span), 374 Fallback(fallback::Span), 375 } 376 377 impl Span { 378 pub(crate) fn call_site() -> Self { 379 if inside_proc_macro() { 380 Span::Compiler(proc_macro::Span::call_site()) 381 } else { 382 Span::Fallback(fallback::Span::call_site()) 383 } 384 } 385 386 pub(crate) fn mixed_site() -> Self { 387 if inside_proc_macro() { 388 Span::Compiler(proc_macro::Span::mixed_site()) 389 } else { 390 Span::Fallback(fallback::Span::mixed_site()) 391 } 392 } 393 394 #[cfg(super_unstable)] 395 pub(crate) fn def_site() -> Self { 396 if inside_proc_macro() { 397 Span::Compiler(proc_macro::Span::def_site()) 398 } else { 399 Span::Fallback(fallback::Span::def_site()) 400 } 401 } 402 403 pub(crate) fn resolved_at(&self, other: Span) -> Span { 404 match (self, other) { 405 (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), 406 (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), 407 (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()), 408 (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()), 409 } 410 } 411 412 pub(crate) fn located_at(&self, other: Span) -> Span { 413 match (self, other) { 414 (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), 415 (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), 416 (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()), 417 (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()), 418 } 419 } 420 421 pub(crate) fn unwrap(self) -> proc_macro::Span { 422 match self { 423 Span::Compiler(s) => s, 424 Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"), 425 } 426 } 427 428 #[cfg(span_locations)] 429 pub(crate) fn byte_range(&self) -> Range<usize> { 430 match self { 431 #[cfg(proc_macro_span)] 432 Span::Compiler(s) => proc_macro_span::byte_range(s), 433 #[cfg(not(proc_macro_span))] 434 Span::Compiler(_) => 0..0, 435 Span::Fallback(s) => s.byte_range(), 436 } 437 } 438 439 #[cfg(span_locations)] 440 pub(crate) fn start(&self) -> LineColumn { 441 match self { 442 #[cfg(proc_macro_span_location)] 443 Span::Compiler(s) => LineColumn { 444 line: proc_macro_span_location::line(s), 445 column: proc_macro_span_location::column(s).saturating_sub(1), 446 }, 447 #[cfg(not(proc_macro_span_location))] 448 Span::Compiler(_) => LineColumn { line: 0, column: 0 }, 449 Span::Fallback(s) => s.start(), 450 } 451 } 452 453 #[cfg(span_locations)] 454 pub(crate) fn end(&self) -> LineColumn { 455 match self { 456 #[cfg(proc_macro_span_location)] 457 Span::Compiler(s) => { 458 let end = proc_macro_span_location::end(s); 459 LineColumn { 460 line: proc_macro_span_location::line(&end), 461 column: proc_macro_span_location::column(&end).saturating_sub(1), 462 } 463 } 464 #[cfg(not(proc_macro_span_location))] 465 Span::Compiler(_) => LineColumn { line: 0, column: 0 }, 466 Span::Fallback(s) => s.end(), 467 } 468 } 469 470 #[cfg(span_locations)] 471 pub(crate) fn file(&self) -> String { 472 match self { 473 #[cfg(proc_macro_span_file)] 474 Span::Compiler(s) => proc_macro_span_file::file(s), 475 #[cfg(not(proc_macro_span_file))] 476 Span::Compiler(_) => "<token stream>".to_owned(), 477 Span::Fallback(s) => s.file(), 478 } 479 } 480 481 #[cfg(span_locations)] 482 pub(crate) fn local_file(&self) -> Option<PathBuf> { 483 match self { 484 #[cfg(proc_macro_span_file)] 485 Span::Compiler(s) => proc_macro_span_file::local_file(s), 486 #[cfg(not(proc_macro_span_file))] 487 Span::Compiler(_) => None, 488 Span::Fallback(s) => s.local_file(), 489 } 490 } 491 492 pub(crate) fn join(&self, other: Span) -> Option<Span> { 493 let ret = match (self, other) { 494 #[cfg(proc_macro_span)] 495 (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(proc_macro_span::join(a, b)?), 496 (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?), 497 _ => return None, 498 }; 499 Some(ret) 500 } 501 502 #[cfg(super_unstable)] 503 pub(crate) fn eq(&self, other: &Span) -> bool { 504 match (self, other) { 505 (Span::Compiler(a), Span::Compiler(b)) => a.eq(b), 506 (Span::Fallback(a), Span::Fallback(b)) => a.eq(b), 507 _ => false, 508 } 509 } 510 511 pub(crate) fn source_text(&self) -> Option<String> { 512 match self { 513 #[cfg(not(no_source_text))] 514 Span::Compiler(s) => s.source_text(), 515 #[cfg(no_source_text)] 516 Span::Compiler(_) => None, 517 Span::Fallback(s) => s.source_text(), 518 } 519 } 520 521 fn unwrap_nightly(self) -> proc_macro::Span { 522 match self { 523 Span::Compiler(s) => s, 524 Span::Fallback(_) => mismatch(line!()), 525 } 526 } 527 } 528 529 impl From<proc_macro::Span> for crate::Span { 530 fn from(proc_span: proc_macro::Span) -> Self { 531 crate::Span::_new(Span::Compiler(proc_span)) 532 } 533 } 534 535 impl From<fallback::Span> for Span { 536 fn from(inner: fallback::Span) -> Self { 537 Span::Fallback(inner) 538 } 539 } 540 541 impl Debug for Span { 542 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 543 match self { 544 Span::Compiler(s) => Debug::fmt(s, f), 545 Span::Fallback(s) => Debug::fmt(s, f), 546 } 547 } 548 } 549 550 pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { 551 match span { 552 Span::Compiler(s) => { 553 debug.field("span", &s); 554 } 555 Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s), 556 } 557 } 558 559 #[derive(Clone)] 560 pub(crate) enum Group { 561 Compiler(proc_macro::Group), 562 Fallback(fallback::Group), 563 } 564 565 impl Group { 566 pub(crate) fn new(delimiter: Delimiter, stream: TokenStream) -> Self { 567 match stream { 568 TokenStream::Compiler(tts) => { 569 let delimiter = match delimiter { 570 Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis, 571 Delimiter::Bracket => proc_macro::Delimiter::Bracket, 572 Delimiter::Brace => proc_macro::Delimiter::Brace, 573 Delimiter::None => proc_macro::Delimiter::None, 574 }; 575 Group::Compiler(proc_macro::Group::new(delimiter, tts.into_token_stream())) 576 } 577 TokenStream::Fallback(stream) => { 578 Group::Fallback(fallback::Group::new(delimiter, stream)) 579 } 580 } 581 } 582 583 pub(crate) fn delimiter(&self) -> Delimiter { 584 match self { 585 Group::Compiler(g) => match g.delimiter() { 586 proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis, 587 proc_macro::Delimiter::Bracket => Delimiter::Bracket, 588 proc_macro::Delimiter::Brace => Delimiter::Brace, 589 proc_macro::Delimiter::None => Delimiter::None, 590 }, 591 Group::Fallback(g) => g.delimiter(), 592 } 593 } 594 595 pub(crate) fn stream(&self) -> TokenStream { 596 match self { 597 Group::Compiler(g) => TokenStream::Compiler(DeferredTokenStream::new(g.stream())), 598 Group::Fallback(g) => TokenStream::Fallback(g.stream()), 599 } 600 } 601 602 pub(crate) fn span(&self) -> Span { 603 match self { 604 Group::Compiler(g) => Span::Compiler(g.span()), 605 Group::Fallback(g) => Span::Fallback(g.span()), 606 } 607 } 608 609 pub(crate) fn span_open(&self) -> Span { 610 match self { 611 Group::Compiler(g) => Span::Compiler(g.span_open()), 612 Group::Fallback(g) => Span::Fallback(g.span_open()), 613 } 614 } 615 616 pub(crate) fn span_close(&self) -> Span { 617 match self { 618 Group::Compiler(g) => Span::Compiler(g.span_close()), 619 Group::Fallback(g) => Span::Fallback(g.span_close()), 620 } 621 } 622 623 pub(crate) fn set_span(&mut self, span: Span) { 624 match (self, span) { 625 (Group::Compiler(g), Span::Compiler(s)) => g.set_span(s), 626 (Group::Fallback(g), Span::Fallback(s)) => g.set_span(s), 627 (Group::Compiler(_), Span::Fallback(_)) => mismatch(line!()), 628 (Group::Fallback(_), Span::Compiler(_)) => mismatch(line!()), 629 } 630 } 631 632 fn unwrap_nightly(self) -> proc_macro::Group { 633 match self { 634 Group::Compiler(g) => g, 635 Group::Fallback(_) => mismatch(line!()), 636 } 637 } 638 } 639 640 impl From<fallback::Group> for Group { 641 fn from(g: fallback::Group) -> Self { 642 Group::Fallback(g) 643 } 644 } 645 646 impl Display for Group { 647 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 648 match self { 649 Group::Compiler(group) => Display::fmt(group, formatter), 650 Group::Fallback(group) => Display::fmt(group, formatter), 651 } 652 } 653 } 654 655 impl Debug for Group { 656 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 657 match self { 658 Group::Compiler(group) => Debug::fmt(group, formatter), 659 Group::Fallback(group) => Debug::fmt(group, formatter), 660 } 661 } 662 } 663 664 #[derive(Clone)] 665 pub(crate) enum Ident { 666 Compiler(proc_macro::Ident), 667 Fallback(fallback::Ident), 668 } 669 670 impl Ident { 671 #[track_caller] 672 pub(crate) fn new_checked(string: &str, span: Span) -> Self { 673 match span { 674 Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)), 675 Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_checked(string, s)), 676 } 677 } 678 679 #[track_caller] 680 pub(crate) fn new_raw_checked(string: &str, span: Span) -> Self { 681 match span { 682 Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new_raw(string, s)), 683 Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw_checked(string, s)), 684 } 685 } 686 687 pub(crate) fn span(&self) -> Span { 688 match self { 689 Ident::Compiler(t) => Span::Compiler(t.span()), 690 Ident::Fallback(t) => Span::Fallback(t.span()), 691 } 692 } 693 694 pub(crate) fn set_span(&mut self, span: Span) { 695 match (self, span) { 696 (Ident::Compiler(t), Span::Compiler(s)) => t.set_span(s), 697 (Ident::Fallback(t), Span::Fallback(s)) => t.set_span(s), 698 (Ident::Compiler(_), Span::Fallback(_)) => mismatch(line!()), 699 (Ident::Fallback(_), Span::Compiler(_)) => mismatch(line!()), 700 } 701 } 702 703 fn unwrap_nightly(self) -> proc_macro::Ident { 704 match self { 705 Ident::Compiler(s) => s, 706 Ident::Fallback(_) => mismatch(line!()), 707 } 708 } 709 } 710 711 impl From<fallback::Ident> for Ident { 712 fn from(inner: fallback::Ident) -> Self { 713 Ident::Fallback(inner) 714 } 715 } 716 717 impl PartialEq for Ident { 718 fn eq(&self, other: &Ident) -> bool { 719 match (self, other) { 720 (Ident::Compiler(t), Ident::Compiler(o)) => t.to_string() == o.to_string(), 721 (Ident::Fallback(t), Ident::Fallback(o)) => t == o, 722 (Ident::Compiler(_), Ident::Fallback(_)) => mismatch(line!()), 723 (Ident::Fallback(_), Ident::Compiler(_)) => mismatch(line!()), 724 } 725 } 726 } 727 728 impl<T> PartialEq<T> for Ident 729 where 730 T: ?Sized + AsRef<str>, 731 { 732 fn eq(&self, other: &T) -> bool { 733 let other = other.as_ref(); 734 match self { 735 Ident::Compiler(t) => t.to_string() == other, 736 Ident::Fallback(t) => t == other, 737 } 738 } 739 } 740 741 impl Display for Ident { 742 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 743 match self { 744 Ident::Compiler(t) => Display::fmt(t, f), 745 Ident::Fallback(t) => Display::fmt(t, f), 746 } 747 } 748 } 749 750 impl Debug for Ident { 751 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 752 match self { 753 Ident::Compiler(t) => Debug::fmt(t, f), 754 Ident::Fallback(t) => Debug::fmt(t, f), 755 } 756 } 757 } 758 759 #[derive(Clone)] 760 pub(crate) enum Literal { 761 Compiler(proc_macro::Literal), 762 Fallback(fallback::Literal), 763 } 764 765 macro_rules! suffixed_numbers { 766 ($($name:ident => $kind:ident,)*) => ($( 767 pub(crate) fn $name(n: $kind) -> Literal { 768 if inside_proc_macro() { 769 Literal::Compiler(proc_macro::Literal::$name(n)) 770 } else { 771 Literal::Fallback(fallback::Literal::$name(n)) 772 } 773 } 774 )*) 775 } 776 777 macro_rules! unsuffixed_integers { 778 ($($name:ident => $kind:ident,)*) => ($( 779 pub(crate) fn $name(n: $kind) -> Literal { 780 if inside_proc_macro() { 781 Literal::Compiler(proc_macro::Literal::$name(n)) 782 } else { 783 Literal::Fallback(fallback::Literal::$name(n)) 784 } 785 } 786 )*) 787 } 788 789 impl Literal { 790 pub(crate) fn from_str_checked(repr: &str) -> Result<Self, LexError> { 791 if inside_proc_macro() { 792 let literal = proc_macro::Literal::from_str_checked(repr)?; 793 Ok(Literal::Compiler(literal)) 794 } else { 795 let literal = fallback::Literal::from_str_checked(repr)?; 796 Ok(Literal::Fallback(literal)) 797 } 798 } 799 800 pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self { 801 if inside_proc_macro() { 802 Literal::Compiler(proc_macro::Literal::from_str_unchecked(repr)) 803 } else { 804 Literal::Fallback(unsafe { fallback::Literal::from_str_unchecked(repr) }) 805 } 806 } 807 808 suffixed_numbers! { 809 u8_suffixed => u8, 810 u16_suffixed => u16, 811 u32_suffixed => u32, 812 u64_suffixed => u64, 813 u128_suffixed => u128, 814 usize_suffixed => usize, 815 i8_suffixed => i8, 816 i16_suffixed => i16, 817 i32_suffixed => i32, 818 i64_suffixed => i64, 819 i128_suffixed => i128, 820 isize_suffixed => isize, 821 822 f32_suffixed => f32, 823 f64_suffixed => f64, 824 } 825 826 unsuffixed_integers! { 827 u8_unsuffixed => u8, 828 u16_unsuffixed => u16, 829 u32_unsuffixed => u32, 830 u64_unsuffixed => u64, 831 u128_unsuffixed => u128, 832 usize_unsuffixed => usize, 833 i8_unsuffixed => i8, 834 i16_unsuffixed => i16, 835 i32_unsuffixed => i32, 836 i64_unsuffixed => i64, 837 i128_unsuffixed => i128, 838 isize_unsuffixed => isize, 839 } 840 841 pub(crate) fn f32_unsuffixed(f: f32) -> Literal { 842 if inside_proc_macro() { 843 Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f)) 844 } else { 845 Literal::Fallback(fallback::Literal::f32_unsuffixed(f)) 846 } 847 } 848 849 pub(crate) fn f64_unsuffixed(f: f64) -> Literal { 850 if inside_proc_macro() { 851 Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f)) 852 } else { 853 Literal::Fallback(fallback::Literal::f64_unsuffixed(f)) 854 } 855 } 856 857 pub(crate) fn string(string: &str) -> Literal { 858 if inside_proc_macro() { 859 Literal::Compiler(proc_macro::Literal::string(string)) 860 } else { 861 Literal::Fallback(fallback::Literal::string(string)) 862 } 863 } 864 865 pub(crate) fn character(ch: char) -> Literal { 866 if inside_proc_macro() { 867 Literal::Compiler(proc_macro::Literal::character(ch)) 868 } else { 869 Literal::Fallback(fallback::Literal::character(ch)) 870 } 871 } 872 873 pub(crate) fn byte_character(byte: u8) -> Literal { 874 if inside_proc_macro() { 875 Literal::Compiler({ 876 #[cfg(not(no_literal_byte_character))] 877 { 878 proc_macro::Literal::byte_character(byte) 879 } 880 881 #[cfg(no_literal_byte_character)] 882 { 883 let fallback = fallback::Literal::byte_character(byte); 884 proc_macro::Literal::from_str_unchecked(&fallback.repr) 885 } 886 }) 887 } else { 888 Literal::Fallback(fallback::Literal::byte_character(byte)) 889 } 890 } 891 892 pub(crate) fn byte_string(bytes: &[u8]) -> Literal { 893 if inside_proc_macro() { 894 Literal::Compiler(proc_macro::Literal::byte_string(bytes)) 895 } else { 896 Literal::Fallback(fallback::Literal::byte_string(bytes)) 897 } 898 } 899 900 pub(crate) fn c_string(string: &CStr) -> Literal { 901 if inside_proc_macro() { 902 Literal::Compiler({ 903 #[cfg(not(no_literal_c_string))] 904 { 905 proc_macro::Literal::c_string(string) 906 } 907 908 #[cfg(no_literal_c_string)] 909 { 910 let fallback = fallback::Literal::c_string(string); 911 proc_macro::Literal::from_str_unchecked(&fallback.repr) 912 } 913 }) 914 } else { 915 Literal::Fallback(fallback::Literal::c_string(string)) 916 } 917 } 918 919 pub(crate) fn span(&self) -> Span { 920 match self { 921 Literal::Compiler(lit) => Span::Compiler(lit.span()), 922 Literal::Fallback(lit) => Span::Fallback(lit.span()), 923 } 924 } 925 926 pub(crate) fn set_span(&mut self, span: Span) { 927 match (self, span) { 928 (Literal::Compiler(lit), Span::Compiler(s)) => lit.set_span(s), 929 (Literal::Fallback(lit), Span::Fallback(s)) => lit.set_span(s), 930 (Literal::Compiler(_), Span::Fallback(_)) => mismatch(line!()), 931 (Literal::Fallback(_), Span::Compiler(_)) => mismatch(line!()), 932 } 933 } 934 935 pub(crate) fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> { 936 match self { 937 #[cfg(proc_macro_span)] 938 Literal::Compiler(lit) => proc_macro_span::subspan(lit, range).map(Span::Compiler), 939 #[cfg(not(proc_macro_span))] 940 Literal::Compiler(_lit) => None, 941 Literal::Fallback(lit) => lit.subspan(range).map(Span::Fallback), 942 } 943 } 944 945 fn unwrap_nightly(self) -> proc_macro::Literal { 946 match self { 947 Literal::Compiler(s) => s, 948 Literal::Fallback(_) => mismatch(line!()), 949 } 950 } 951 } 952 953 impl From<fallback::Literal> for Literal { 954 fn from(s: fallback::Literal) -> Self { 955 Literal::Fallback(s) 956 } 957 } 958 959 impl Display for Literal { 960 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 961 match self { 962 Literal::Compiler(t) => Display::fmt(t, f), 963 Literal::Fallback(t) => Display::fmt(t, f), 964 } 965 } 966 } 967 968 impl Debug for Literal { 969 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 970 match self { 971 Literal::Compiler(t) => Debug::fmt(t, f), 972 Literal::Fallback(t) => Debug::fmt(t, f), 973 } 974 } 975 } 976 977 #[cfg(span_locations)] 978 pub(crate) fn invalidate_current_thread_spans() { 979 if inside_proc_macro() { 980 panic!( 981 "proc_macro2::extra::invalidate_current_thread_spans is not available in procedural macros" 982 ); 983 } else { 984 crate::fallback::invalidate_current_thread_spans(); 985 } 986 } 987