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            Span::Compiler(_) => LineColumn { line: 0, column: 0 },
481            Span::Fallback(s) => s.start(),
482        }
483    }
484
485    #[cfg(span_locations)]
486    pub fn end(&self) -> LineColumn {
487        match self {
488            Span::Compiler(_) => LineColumn { line: 0, column: 0 },
489            Span::Fallback(s) => s.end(),
490        }
491    }
492
493    pub fn join(&self, other: Span) -> Option<Span> {
494        let ret = match (self, other) {
495            #[cfg(proc_macro_span)]
496            (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.join(b)?),
497            (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?),
498            _ => return None,
499        };
500        Some(ret)
501    }
502
503    #[cfg(super_unstable)]
504    pub fn eq(&self, other: &Span) -> bool {
505        match (self, other) {
506            (Span::Compiler(a), Span::Compiler(b)) => a.eq(b),
507            (Span::Fallback(a), Span::Fallback(b)) => a.eq(b),
508            _ => false,
509        }
510    }
511
512    pub fn source_text(&self) -> Option<String> {
513        match self {
514            #[cfg(not(no_source_text))]
515            Span::Compiler(s) => s.source_text(),
516            #[cfg(no_source_text)]
517            Span::Compiler(_) => None,
518            Span::Fallback(s) => s.source_text(),
519        }
520    }
521
522    fn unwrap_nightly(self) -> proc_macro::Span {
523        match self {
524            Span::Compiler(s) => s,
525            Span::Fallback(_) => mismatch(line!()),
526        }
527    }
528}
529
530impl From<proc_macro::Span> for crate::Span {
531    fn from(proc_span: proc_macro::Span) -> Self {
532        crate::Span::_new(Span::Compiler(proc_span))
533    }
534}
535
536impl From<fallback::Span> for Span {
537    fn from(inner: fallback::Span) -> Self {
538        Span::Fallback(inner)
539    }
540}
541
542impl Debug for Span {
543    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
544        match self {
545            Span::Compiler(s) => Debug::fmt(s, f),
546            Span::Fallback(s) => Debug::fmt(s, f),
547        }
548    }
549}
550
551pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
552    match span {
553        Span::Compiler(s) => {
554            debug.field("span", &s);
555        }
556        Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s),
557    }
558}
559
560#[derive(Clone)]
561pub(crate) enum Group {
562    Compiler(proc_macro::Group),
563    Fallback(fallback::Group),
564}
565
566impl Group {
567    pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
568        match stream {
569            TokenStream::Compiler(tts) => {
570                let delimiter = match delimiter {
571                    Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis,
572                    Delimiter::Bracket => proc_macro::Delimiter::Bracket,
573                    Delimiter::Brace => proc_macro::Delimiter::Brace,
574                    Delimiter::None => proc_macro::Delimiter::None,
575                };
576                Group::Compiler(proc_macro::Group::new(delimiter, tts.into_token_stream()))
577            }
578            TokenStream::Fallback(stream) => {
579                Group::Fallback(fallback::Group::new(delimiter, stream))
580            }
581        }
582    }
583
584    pub fn delimiter(&self) -> Delimiter {
585        match self {
586            Group::Compiler(g) => match g.delimiter() {
587                proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis,
588                proc_macro::Delimiter::Bracket => Delimiter::Bracket,
589                proc_macro::Delimiter::Brace => Delimiter::Brace,
590                proc_macro::Delimiter::None => Delimiter::None,
591            },
592            Group::Fallback(g) => g.delimiter(),
593        }
594    }
595
596    pub fn stream(&self) -> TokenStream {
597        match self {
598            Group::Compiler(g) => TokenStream::Compiler(DeferredTokenStream::new(g.stream())),
599            Group::Fallback(g) => TokenStream::Fallback(g.stream()),
600        }
601    }
602
603    pub fn span(&self) -> Span {
604        match self {
605            Group::Compiler(g) => Span::Compiler(g.span()),
606            Group::Fallback(g) => Span::Fallback(g.span()),
607        }
608    }
609
610    pub fn span_open(&self) -> Span {
611        match self {
612            Group::Compiler(g) => Span::Compiler(g.span_open()),
613            Group::Fallback(g) => Span::Fallback(g.span_open()),
614        }
615    }
616
617    pub fn span_close(&self) -> Span {
618        match self {
619            Group::Compiler(g) => Span::Compiler(g.span_close()),
620            Group::Fallback(g) => Span::Fallback(g.span_close()),
621        }
622    }
623
624    pub fn set_span(&mut self, span: Span) {
625        match (self, span) {
626            (Group::Compiler(g), Span::Compiler(s)) => g.set_span(s),
627            (Group::Fallback(g), Span::Fallback(s)) => g.set_span(s),
628            (Group::Compiler(_), Span::Fallback(_)) => mismatch(line!()),
629            (Group::Fallback(_), Span::Compiler(_)) => mismatch(line!()),
630        }
631    }
632
633    fn unwrap_nightly(self) -> proc_macro::Group {
634        match self {
635            Group::Compiler(g) => g,
636            Group::Fallback(_) => mismatch(line!()),
637        }
638    }
639}
640
641impl From<fallback::Group> for Group {
642    fn from(g: fallback::Group) -> Self {
643        Group::Fallback(g)
644    }
645}
646
647impl Display for Group {
648    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
649        match self {
650            Group::Compiler(group) => Display::fmt(group, formatter),
651            Group::Fallback(group) => Display::fmt(group, formatter),
652        }
653    }
654}
655
656impl Debug for Group {
657    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
658        match self {
659            Group::Compiler(group) => Debug::fmt(group, formatter),
660            Group::Fallback(group) => Debug::fmt(group, formatter),
661        }
662    }
663}
664
665#[derive(Clone)]
666pub(crate) enum Ident {
667    Compiler(proc_macro::Ident),
668    Fallback(fallback::Ident),
669}
670
671impl Ident {
672    #[track_caller]
673    pub fn new_checked(string: &str, span: Span) -> Self {
674        match span {
675            Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)),
676            Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_checked(string, s)),
677        }
678    }
679
680    pub fn new_unchecked(string: &str, span: fallback::Span) -> Self {
681        Ident::Fallback(fallback::Ident::new_unchecked(string, span))
682    }
683
684    #[track_caller]
685    pub fn new_raw_checked(string: &str, span: Span) -> Self {
686        match span {
687            Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new_raw(string, s)),
688            Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw_checked(string, s)),
689        }
690    }
691
692    pub fn new_raw_unchecked(string: &str, span: fallback::Span) -> Self {
693        Ident::Fallback(fallback::Ident::new_raw_unchecked(string, span))
694    }
695
696    pub fn span(&self) -> Span {
697        match self {
698            Ident::Compiler(t) => Span::Compiler(t.span()),
699            Ident::Fallback(t) => Span::Fallback(t.span()),
700        }
701    }
702
703    pub fn set_span(&mut self, span: Span) {
704        match (self, span) {
705            (Ident::Compiler(t), Span::Compiler(s)) => t.set_span(s),
706            (Ident::Fallback(t), Span::Fallback(s)) => t.set_span(s),
707            (Ident::Compiler(_), Span::Fallback(_)) => mismatch(line!()),
708            (Ident::Fallback(_), Span::Compiler(_)) => mismatch(line!()),
709        }
710    }
711
712    fn unwrap_nightly(self) -> proc_macro::Ident {
713        match self {
714            Ident::Compiler(s) => s,
715            Ident::Fallback(_) => mismatch(line!()),
716        }
717    }
718}
719
720impl PartialEq for Ident {
721    fn eq(&self, other: &Ident) -> bool {
722        match (self, other) {
723            (Ident::Compiler(t), Ident::Compiler(o)) => t.to_string() == o.to_string(),
724            (Ident::Fallback(t), Ident::Fallback(o)) => t == o,
725            (Ident::Compiler(_), Ident::Fallback(_)) => mismatch(line!()),
726            (Ident::Fallback(_), Ident::Compiler(_)) => mismatch(line!()),
727        }
728    }
729}
730
731impl<T> PartialEq<T> for Ident
732where
733    T: ?Sized + AsRef<str>,
734{
735    fn eq(&self, other: &T) -> bool {
736        let other = other.as_ref();
737        match self {
738            Ident::Compiler(t) => t.to_string() == other,
739            Ident::Fallback(t) => t == other,
740        }
741    }
742}
743
744impl Display for Ident {
745    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
746        match self {
747            Ident::Compiler(t) => Display::fmt(t, f),
748            Ident::Fallback(t) => Display::fmt(t, f),
749        }
750    }
751}
752
753impl Debug for Ident {
754    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
755        match self {
756            Ident::Compiler(t) => Debug::fmt(t, f),
757            Ident::Fallback(t) => Debug::fmt(t, f),
758        }
759    }
760}
761
762#[derive(Clone)]
763pub(crate) enum Literal {
764    Compiler(proc_macro::Literal),
765    Fallback(fallback::Literal),
766}
767
768macro_rules! suffixed_numbers {
769    ($($name:ident => $kind:ident,)*) => ($(
770        pub fn $name(n: $kind) -> Literal {
771            if inside_proc_macro() {
772                Literal::Compiler(proc_macro::Literal::$name(n))
773            } else {
774                Literal::Fallback(fallback::Literal::$name(n))
775            }
776        }
777    )*)
778}
779
780macro_rules! unsuffixed_integers {
781    ($($name:ident => $kind:ident,)*) => ($(
782        pub fn $name(n: $kind) -> Literal {
783            if inside_proc_macro() {
784                Literal::Compiler(proc_macro::Literal::$name(n))
785            } else {
786                Literal::Fallback(fallback::Literal::$name(n))
787            }
788        }
789    )*)
790}
791
792impl Literal {
793    pub unsafe fn from_str_unchecked(repr: &str) -> Self {
794        if inside_proc_macro() {
795            Literal::Compiler(proc_macro::Literal::from_str(repr).expect("invalid literal"))
796        } else {
797            Literal::Fallback(unsafe { fallback::Literal::from_str_unchecked(repr) })
798        }
799    }
800
801    suffixed_numbers! {
802        u8_suffixed => u8,
803        u16_suffixed => u16,
804        u32_suffixed => u32,
805        u64_suffixed => u64,
806        u128_suffixed => u128,
807        usize_suffixed => usize,
808        i8_suffixed => i8,
809        i16_suffixed => i16,
810        i32_suffixed => i32,
811        i64_suffixed => i64,
812        i128_suffixed => i128,
813        isize_suffixed => isize,
814
815        f32_suffixed => f32,
816        f64_suffixed => f64,
817    }
818
819    unsuffixed_integers! {
820        u8_unsuffixed => u8,
821        u16_unsuffixed => u16,
822        u32_unsuffixed => u32,
823        u64_unsuffixed => u64,
824        u128_unsuffixed => u128,
825        usize_unsuffixed => usize,
826        i8_unsuffixed => i8,
827        i16_unsuffixed => i16,
828        i32_unsuffixed => i32,
829        i64_unsuffixed => i64,
830        i128_unsuffixed => i128,
831        isize_unsuffixed => isize,
832    }
833
834    pub fn f32_unsuffixed(f: f32) -> Literal {
835        if inside_proc_macro() {
836            Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f))
837        } else {
838            Literal::Fallback(fallback::Literal::f32_unsuffixed(f))
839        }
840    }
841
842    pub fn f64_unsuffixed(f: f64) -> Literal {
843        if inside_proc_macro() {
844            Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f))
845        } else {
846            Literal::Fallback(fallback::Literal::f64_unsuffixed(f))
847        }
848    }
849
850    pub fn string(string: &str) -> Literal {
851        if inside_proc_macro() {
852            Literal::Compiler(proc_macro::Literal::string(string))
853        } else {
854            Literal::Fallback(fallback::Literal::string(string))
855        }
856    }
857
858    pub fn character(ch: char) -> Literal {
859        if inside_proc_macro() {
860            Literal::Compiler(proc_macro::Literal::character(ch))
861        } else {
862            Literal::Fallback(fallback::Literal::character(ch))
863        }
864    }
865
866    pub fn byte_character(byte: u8) -> Literal {
867        if inside_proc_macro() {
868            Literal::Compiler({
869                #[cfg(not(no_literal_byte_character))]
870                {
871                    proc_macro::Literal::byte_character(byte)
872                }
873
874                #[cfg(no_literal_byte_character)]
875                {
876                    let fallback = fallback::Literal::byte_character(byte);
877                    fallback.repr.parse::<proc_macro::Literal>().unwrap()
878                }
879            })
880        } else {
881            Literal::Fallback(fallback::Literal::byte_character(byte))
882        }
883    }
884
885    pub fn byte_string(bytes: &[u8]) -> Literal {
886        if inside_proc_macro() {
887            Literal::Compiler(proc_macro::Literal::byte_string(bytes))
888        } else {
889            Literal::Fallback(fallback::Literal::byte_string(bytes))
890        }
891    }
892
893    pub fn c_string(string: &CStr) -> Literal {
894        if inside_proc_macro() {
895            Literal::Compiler({
896                #[cfg(not(no_literal_c_string))]
897                {
898                    proc_macro::Literal::c_string(string)
899                }
900
901                #[cfg(no_literal_c_string)]
902                {
903                    let fallback = fallback::Literal::c_string(string);
904                    fallback.repr.parse::<proc_macro::Literal>().unwrap()
905                }
906            })
907        } else {
908            Literal::Fallback(fallback::Literal::c_string(string))
909        }
910    }
911
912    pub fn span(&self) -> Span {
913        match self {
914            Literal::Compiler(lit) => Span::Compiler(lit.span()),
915            Literal::Fallback(lit) => Span::Fallback(lit.span()),
916        }
917    }
918
919    pub fn set_span(&mut self, span: Span) {
920        match (self, span) {
921            (Literal::Compiler(lit), Span::Compiler(s)) => lit.set_span(s),
922            (Literal::Fallback(lit), Span::Fallback(s)) => lit.set_span(s),
923            (Literal::Compiler(_), Span::Fallback(_)) => mismatch(line!()),
924            (Literal::Fallback(_), Span::Compiler(_)) => mismatch(line!()),
925        }
926    }
927
928    pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
929        match self {
930            #[cfg(proc_macro_span)]
931            Literal::Compiler(lit) => lit.subspan(range).map(Span::Compiler),
932            #[cfg(not(proc_macro_span))]
933            Literal::Compiler(_lit) => None,
934            Literal::Fallback(lit) => lit.subspan(range).map(Span::Fallback),
935        }
936    }
937
938    fn unwrap_nightly(self) -> proc_macro::Literal {
939        match self {
940            Literal::Compiler(s) => s,
941            Literal::Fallback(_) => mismatch(line!()),
942        }
943    }
944}
945
946impl From<fallback::Literal> for Literal {
947    fn from(s: fallback::Literal) -> Self {
948        Literal::Fallback(s)
949    }
950}
951
952impl FromStr for Literal {
953    type Err = LexError;
954
955    fn from_str(repr: &str) -> Result<Self, Self::Err> {
956        if inside_proc_macro() {
957            let literal = proc_macro::Literal::from_str(repr)?;
958            Ok(Literal::Compiler(literal))
959        } else {
960            let literal = fallback::Literal::from_str(repr)?;
961            Ok(Literal::Fallback(literal))
962        }
963    }
964}
965
966impl Display for Literal {
967    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
968        match self {
969            Literal::Compiler(t) => Display::fmt(t, f),
970            Literal::Fallback(t) => Display::fmt(t, f),
971        }
972    }
973}
974
975impl Debug for Literal {
976    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
977        match self {
978            Literal::Compiler(t) => Debug::fmt(t, f),
979            Literal::Fallback(t) => Debug::fmt(t, f),
980        }
981    }
982}
983
984#[cfg(span_locations)]
985pub(crate) fn invalidate_current_thread_spans() {
986    if inside_proc_macro() {
987        panic!(
988            "proc_macro2::extra::invalidate_current_thread_spans is not available in procedural macros"
989        );
990    } else {
991        crate::fallback::invalidate_current_thread_spans();
992    }
993}