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