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