proc_macro2/
wrapper.rs

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