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