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