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