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