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