proc_macro2/
wrapper.rs

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// Work around https://github.com/rust-lang/rust/issues/65080.
27// In `impl Extend<TokenTree> for TokenStream` which is used heavily by quote,
28// we hold on to the appended tokens and do proc_macro::TokenStream::extend as
29// late as possible to batch together consecutive uses of the Extend impl.
30#[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    // Rustc was supposed to return a LexError, but it panicked instead.
41    // https://github.com/rust-lang/rust/issues/58736
42    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-check provides a fast short circuit for the common case of `extra`
72        // being empty, which saves a round trip over the proc macro bridge.
73        // Improves macro expansion time in winrt by 6% in debug mode.
74        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
160// Assumes inside_proc_macro().
161fn 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                // Here is the reason for DeferredTokenStream.
231                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}