proc_macro2/
wrapper.rs

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