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