Skip to main content

proc_macro2/
wrapper.rs

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