Coverage Report

Created: 2026-02-21 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/proc-macro2-1.0.106/src/fallback.rs
Line
Count
Source
1
#[cfg(wrap_proc_macro)]
2
use crate::imp;
3
#[cfg(span_locations)]
4
use crate::location::LineColumn;
5
use crate::parse::{self, Cursor};
6
use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut};
7
use crate::{Delimiter, Spacing, TokenTree};
8
use alloc::borrow::ToOwned as _;
9
use alloc::boxed::Box;
10
#[cfg(all(span_locations, not(fuzzing)))]
11
use alloc::collections::BTreeMap;
12
use alloc::format;
13
use alloc::string::{String, ToString as _};
14
#[cfg(all(span_locations, not(fuzzing)))]
15
use alloc::vec;
16
use alloc::vec::Vec;
17
#[cfg(all(span_locations, not(fuzzing)))]
18
use core::cell::RefCell;
19
#[cfg(span_locations)]
20
use core::cmp;
21
#[cfg(all(span_locations, not(fuzzing)))]
22
use core::cmp::Ordering;
23
use core::ffi::CStr;
24
use core::fmt::{self, Debug, Display, Write};
25
use core::mem::ManuallyDrop;
26
#[cfg(span_locations)]
27
use core::ops::Range;
28
use core::ops::RangeBounds;
29
use core::ptr;
30
use core::str;
31
#[cfg(feature = "proc-macro")]
32
use core::str::FromStr;
33
#[cfg(wrap_proc_macro)]
34
use std::panic;
35
#[cfg(span_locations)]
36
use std::path::PathBuf;
37
#[cfg(all(span_locations, not(fuzzing)))]
38
use std::thread_local;
39
40
/// Force use of proc-macro2's fallback implementation of the API for now, even
41
/// if the compiler's implementation is available.
42
0
pub fn force() {
43
    #[cfg(wrap_proc_macro)]
44
0
    crate::detection::force_fallback();
45
0
}
46
47
/// Resume using the compiler's implementation of the proc macro API if it is
48
/// available.
49
0
pub fn unforce() {
50
    #[cfg(wrap_proc_macro)]
51
0
    crate::detection::unforce_fallback();
52
0
}
53
54
#[derive(Clone)]
55
pub(crate) struct TokenStream {
56
    inner: RcVec<TokenTree>,
57
}
58
59
#[derive(Debug)]
60
pub(crate) struct LexError {
61
    pub(crate) span: Span,
62
}
63
64
impl LexError {
65
0
    pub(crate) fn span(&self) -> Span {
66
0
        self.span
67
0
    }
68
69
0
    pub(crate) fn call_site() -> Self {
70
0
        LexError {
71
0
            span: Span::call_site(),
72
0
        }
73
0
    }
74
}
75
76
impl TokenStream {
77
0
    pub(crate) fn new() -> Self {
78
0
        TokenStream {
79
0
            inner: RcVecBuilder::new().build(),
80
0
        }
81
0
    }
82
83
431
    pub(crate) fn from_str_checked(src: &str) -> Result<Self, LexError> {
84
        // Create a dummy file & add it to the source map
85
431
        let mut cursor = get_cursor(src);
86
87
        // Strip a byte order mark if present
88
        const BYTE_ORDER_MARK: &str = "\u{feff}";
89
431
        if cursor.starts_with(BYTE_ORDER_MARK) {
90
0
            cursor = cursor.advance(BYTE_ORDER_MARK.len());
91
431
        }
92
93
431
        parse::token_stream(cursor)
94
431
    }
95
96
    #[cfg(feature = "proc-macro")]
97
0
    pub(crate) fn from_str_unchecked(src: &str) -> Self {
98
0
        Self::from_str_checked(src).unwrap()
99
0
    }
100
101
0
    pub(crate) fn is_empty(&self) -> bool {
102
0
        self.inner.len() == 0
103
0
    }
104
105
0
    fn take_inner(self) -> RcVecBuilder<TokenTree> {
106
0
        let nodrop = ManuallyDrop::new(self);
107
0
        unsafe { ptr::read(&nodrop.inner) }.make_owned()
108
0
    }
109
}
110
111
0
fn push_token_from_proc_macro(mut vec: RcVecMut<TokenTree>, token: TokenTree) {
112
    // https://github.com/dtolnay/proc-macro2/issues/235
113
0
    match token {
114
        TokenTree::Literal(crate::Literal {
115
            #[cfg(wrap_proc_macro)]
116
0
                inner: crate::imp::Literal::Fallback(literal),
117
            #[cfg(not(wrap_proc_macro))]
118
                inner: literal,
119
            ..
120
0
        }) if literal.repr.starts_with('-') => {
121
0
            push_negative_literal(vec, literal);
122
0
        }
123
0
        _ => vec.push(token),
124
    }
125
126
    #[cold]
127
0
    fn push_negative_literal(mut vec: RcVecMut<TokenTree>, mut literal: Literal) {
128
0
        literal.repr.remove(0);
129
0
        let mut punct = crate::Punct::new('-', Spacing::Alone);
130
0
        punct.set_span(crate::Span::_new_fallback(literal.span));
131
0
        vec.push(TokenTree::Punct(punct));
132
0
        vec.push(TokenTree::Literal(crate::Literal::_new_fallback(literal)));
133
0
    }
134
0
}
135
136
// Nonrecursive to prevent stack overflow.
137
impl Drop for TokenStream {
138
562k
    fn drop(&mut self) {
139
562k
        let mut stack = Vec::new();
140
562k
        let mut current = match self.inner.get_mut() {
141
562k
            Some(inner) => inner.take().into_iter(),
142
0
            None => return,
143
        };
144
        loop {
145
7.59M
            while let Some(token) = current.next() {
146
6.49M
                let group = match token {
147
541k
                    TokenTree::Group(group) => group.inner,
148
5.95M
                    _ => continue,
149
                };
150
                #[cfg(wrap_proc_macro)]
151
541k
                let group = match group {
152
541k
                    crate::imp::Group::Fallback(group) => group,
153
0
                    crate::imp::Group::Compiler(_) => continue,
154
                };
155
541k
                let mut group = group;
156
541k
                if let Some(inner) = group.stream.inner.get_mut() {
157
541k
                    stack.push(current);
158
541k
                    current = inner.take().into_iter();
159
541k
                }
160
            }
161
1.10M
            match stack.pop() {
162
541k
                Some(next) => current = next,
163
562k
                None => return,
164
            }
165
        }
166
562k
    }
167
}
168
169
pub(crate) struct TokenStreamBuilder {
170
    inner: RcVecBuilder<TokenTree>,
171
}
172
173
impl TokenStreamBuilder {
174
8.51M
    pub(crate) fn new() -> Self {
175
8.51M
        TokenStreamBuilder {
176
8.51M
            inner: RcVecBuilder::new(),
177
8.51M
        }
178
8.51M
    }
179
180
14.9k
    pub(crate) fn with_capacity(cap: usize) -> Self {
181
14.9k
        TokenStreamBuilder {
182
14.9k
            inner: RcVecBuilder::with_capacity(cap),
183
14.9k
        }
184
14.9k
    }
185
186
10.5M
    pub(crate) fn push_token_from_parser(&mut self, tt: TokenTree) {
187
10.5M
        self.inner.push(tt);
188
10.5M
    }
189
190
562k
    pub(crate) fn build(self) -> TokenStream {
191
562k
        TokenStream {
192
562k
            inner: self.inner.build(),
193
562k
        }
194
562k
    }
195
}
196
197
#[cfg(span_locations)]
198
fn get_cursor(src: &str) -> Cursor {
199
    #[cfg(fuzzing)]
200
    return Cursor { rest: src, off: 1 };
201
202
    // Create a dummy file & add it to the source map
203
    #[cfg(not(fuzzing))]
204
    SOURCE_MAP.with(|sm| {
205
        let mut sm = sm.borrow_mut();
206
        let span = sm.add_file(src);
207
        Cursor {
208
            rest: src,
209
            off: span.lo,
210
        }
211
    })
212
}
213
214
#[cfg(not(span_locations))]
215
431
fn get_cursor(src: &str) -> Cursor {
216
431
    Cursor { rest: src }
217
431
}
218
219
impl Display for LexError {
220
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221
0
        f.write_str("cannot parse string into token stream")
222
0
    }
223
}
224
225
impl Display for TokenStream {
226
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
227
0
        let mut joint = false;
228
0
        for (i, tt) in self.inner.iter().enumerate() {
229
0
            if i != 0 && !joint {
230
0
                write!(f, " ")?;
231
0
            }
232
0
            joint = false;
233
0
            match tt {
234
0
                TokenTree::Group(tt) => write!(f, "{}", tt),
235
0
                TokenTree::Ident(tt) => write!(f, "{}", tt),
236
0
                TokenTree::Punct(tt) => {
237
0
                    joint = tt.spacing() == Spacing::Joint;
238
0
                    write!(f, "{}", tt)
239
                }
240
0
                TokenTree::Literal(tt) => write!(f, "{}", tt),
241
0
            }?;
242
        }
243
244
0
        Ok(())
245
0
    }
246
}
247
248
impl Debug for TokenStream {
249
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
250
0
        f.write_str("TokenStream ")?;
251
0
        f.debug_list().entries(self.clone()).finish()
252
0
    }
253
}
254
255
#[cfg(feature = "proc-macro")]
256
impl From<proc_macro::TokenStream> for TokenStream {
257
0
    fn from(inner: proc_macro::TokenStream) -> Self {
258
0
        TokenStream::from_str_unchecked(&inner.to_string())
259
0
    }
260
}
261
262
#[cfg(feature = "proc-macro")]
263
impl From<TokenStream> for proc_macro::TokenStream {
264
0
    fn from(inner: TokenStream) -> Self {
265
0
        proc_macro::TokenStream::from_str_unchecked(&inner.to_string())
266
0
    }
267
}
268
269
impl From<TokenTree> for TokenStream {
270
0
    fn from(tree: TokenTree) -> Self {
271
0
        let mut stream = RcVecBuilder::new();
272
0
        push_token_from_proc_macro(stream.as_mut(), tree);
273
0
        TokenStream {
274
0
            inner: stream.build(),
275
0
        }
276
0
    }
277
}
278
279
impl FromIterator<TokenTree> for TokenStream {
280
0
    fn from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self {
281
0
        let mut stream = TokenStream::new();
282
0
        stream.extend(tokens);
283
0
        stream
284
0
    }
285
}
286
287
impl FromIterator<TokenStream> for TokenStream {
288
0
    fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
289
0
        let mut v = RcVecBuilder::new();
290
291
0
        for stream in streams {
292
0
            v.extend(stream.take_inner());
293
0
        }
294
295
0
        TokenStream { inner: v.build() }
296
0
    }
297
}
298
299
impl Extend<TokenTree> for TokenStream {
300
0
    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I) {
301
0
        let mut vec = self.inner.make_mut();
302
0
        tokens
303
0
            .into_iter()
304
0
            .for_each(|token| push_token_from_proc_macro(vec.as_mut(), token));
305
0
    }
306
}
307
308
impl Extend<TokenStream> for TokenStream {
309
0
    fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
310
0
        self.inner.make_mut().extend(streams.into_iter().flatten());
311
0
    }
312
}
313
314
pub(crate) type TokenTreeIter = RcVecIntoIter<TokenTree>;
315
316
impl IntoIterator for TokenStream {
317
    type Item = TokenTree;
318
    type IntoIter = TokenTreeIter;
319
320
0
    fn into_iter(self) -> TokenTreeIter {
321
0
        self.take_inner().into_iter()
322
0
    }
323
}
324
325
#[cfg(all(span_locations, not(fuzzing)))]
326
thread_local! {
327
    static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
328
        // Start with a single dummy file which all call_site() and def_site()
329
        // spans reference.
330
        files: vec![FileInfo {
331
            source_text: String::new(),
332
            span: Span { lo: 0, hi: 0 },
333
            lines: vec![0],
334
            char_index_to_byte_offset: BTreeMap::new(),
335
        }],
336
    });
337
}
338
339
#[cfg(span_locations)]
340
pub(crate) fn invalidate_current_thread_spans() {
341
    #[cfg(not(fuzzing))]
342
    SOURCE_MAP.with(|sm| sm.borrow_mut().files.truncate(1));
343
}
344
345
#[cfg(all(span_locations, not(fuzzing)))]
346
struct FileInfo {
347
    source_text: String,
348
    span: Span,
349
    lines: Vec<usize>,
350
    char_index_to_byte_offset: BTreeMap<usize, usize>,
351
}
352
353
#[cfg(all(span_locations, not(fuzzing)))]
354
impl FileInfo {
355
    fn offset_line_column(&self, offset: usize) -> LineColumn {
356
        assert!(self.span_within(Span {
357
            lo: offset as u32,
358
            hi: offset as u32,
359
        }));
360
        let offset = offset - self.span.lo as usize;
361
        match self.lines.binary_search(&offset) {
362
            Ok(found) => LineColumn {
363
                line: found + 1,
364
                column: 0,
365
            },
366
            Err(idx) => LineColumn {
367
                line: idx,
368
                column: offset - self.lines[idx - 1],
369
            },
370
        }
371
    }
372
373
    fn span_within(&self, span: Span) -> bool {
374
        span.lo >= self.span.lo && span.hi <= self.span.hi
375
    }
376
377
    fn byte_range(&mut self, span: Span) -> Range<usize> {
378
        self.byte(span.lo)..self.byte(span.hi)
379
    }
380
381
    fn byte(&mut self, ch: u32) -> usize {
382
        let char_index = (ch - self.span.lo) as usize;
383
384
        // Look up offset of the largest already-computed char index that is
385
        // less than or equal to the current requested one.
386
        let (&previous_char_index, &previous_byte_offset) = self
387
            .char_index_to_byte_offset
388
            .range(..=char_index)
389
            .next_back()
390
            .unwrap_or((&0, &0));
391
392
        if previous_char_index == char_index {
393
            return previous_byte_offset;
394
        }
395
396
        // Look up next char index that is greater than the requested one. We
397
        // resume counting chars from whichever point is closer.
398
        let byte_offset = match self.char_index_to_byte_offset.range(char_index..).next() {
399
            Some((&next_char_index, &next_byte_offset))
400
                if next_char_index - char_index < char_index - previous_char_index =>
401
            {
402
                self.source_text[..next_byte_offset]
403
                    .char_indices()
404
                    .nth_back(next_char_index - char_index - 1)
405
                    .unwrap()
406
                    .0
407
            }
408
            _ => {
409
                match self.source_text[previous_byte_offset..]
410
                    .char_indices()
411
                    .nth(char_index - previous_char_index)
412
                {
413
                    Some((byte_offset_from_previous, _ch)) => {
414
                        previous_byte_offset + byte_offset_from_previous
415
                    }
416
                    None => self.source_text.len(),
417
                }
418
            }
419
        };
420
421
        self.char_index_to_byte_offset
422
            .insert(char_index, byte_offset);
423
        byte_offset
424
    }
425
426
    fn source_text(&mut self, span: Span) -> String {
427
        let byte_range = self.byte_range(span);
428
        self.source_text[byte_range].to_owned()
429
    }
430
}
431
432
/// Computes the offsets of each line in the given source string
433
/// and the total number of characters
434
#[cfg(all(span_locations, not(fuzzing)))]
435
fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
436
    let mut lines = vec![0];
437
    let mut total = 0;
438
439
    for ch in s.chars() {
440
        total += 1;
441
        if ch == '\n' {
442
            lines.push(total);
443
        }
444
    }
445
446
    (total, lines)
447
}
448
449
#[cfg(all(span_locations, not(fuzzing)))]
450
struct SourceMap {
451
    files: Vec<FileInfo>,
452
}
453
454
#[cfg(all(span_locations, not(fuzzing)))]
455
impl SourceMap {
456
    fn next_start_pos(&self) -> u32 {
457
        // Add 1 so there's always space between files.
458
        //
459
        // We'll always have at least 1 file, as we initialize our files list
460
        // with a dummy file.
461
        self.files.last().unwrap().span.hi + 1
462
    }
463
464
    fn add_file(&mut self, src: &str) -> Span {
465
        let (len, lines) = lines_offsets(src);
466
        let lo = self.next_start_pos();
467
        let span = Span {
468
            lo,
469
            hi: lo + (len as u32),
470
        };
471
472
        self.files.push(FileInfo {
473
            source_text: src.to_owned(),
474
            span,
475
            lines,
476
            // Populated lazily by source_text().
477
            char_index_to_byte_offset: BTreeMap::new(),
478
        });
479
480
        span
481
    }
482
483
    fn find(&self, span: Span) -> usize {
484
        match self.files.binary_search_by(|file| {
485
            if file.span.hi < span.lo {
486
                Ordering::Less
487
            } else if file.span.lo > span.hi {
488
                Ordering::Greater
489
            } else {
490
                assert!(file.span_within(span));
491
                Ordering::Equal
492
            }
493
        }) {
494
            Ok(i) => i,
495
            Err(_) => unreachable!("Invalid span with no related FileInfo!"),
496
        }
497
    }
498
499
    fn filepath(&self, span: Span) -> String {
500
        let i = self.find(span);
501
        if i == 0 {
502
            "<unspecified>".to_owned()
503
        } else {
504
            format!("<parsed string {}>", i)
505
        }
506
    }
507
508
    fn fileinfo(&self, span: Span) -> &FileInfo {
509
        let i = self.find(span);
510
        &self.files[i]
511
    }
512
513
    fn fileinfo_mut(&mut self, span: Span) -> &mut FileInfo {
514
        let i = self.find(span);
515
        &mut self.files[i]
516
    }
517
}
518
519
#[derive(Clone, Copy, PartialEq, Eq)]
520
pub(crate) struct Span {
521
    #[cfg(span_locations)]
522
    pub(crate) lo: u32,
523
    #[cfg(span_locations)]
524
    pub(crate) hi: u32,
525
}
526
527
impl Span {
528
    #[cfg(not(span_locations))]
529
10.4M
    pub(crate) fn call_site() -> Self {
530
10.4M
        Span {}
531
10.4M
    }
532
533
    #[cfg(span_locations)]
534
    pub(crate) fn call_site() -> Self {
535
        Span { lo: 0, hi: 0 }
536
    }
537
538
0
    pub(crate) fn mixed_site() -> Self {
539
0
        Span::call_site()
540
0
    }
541
542
    #[cfg(procmacro2_semver_exempt)]
543
    pub(crate) fn def_site() -> Self {
544
        Span::call_site()
545
    }
546
547
0
    pub(crate) fn resolved_at(&self, _other: Span) -> Span {
548
        // Stable spans consist only of line/column information, so
549
        // `resolved_at` and `located_at` only select which span the
550
        // caller wants line/column information from.
551
0
        *self
552
0
    }
553
554
0
    pub(crate) fn located_at(&self, other: Span) -> Span {
555
0
        other
556
0
    }
557
558
    #[cfg(span_locations)]
559
    pub(crate) fn byte_range(&self) -> Range<usize> {
560
        #[cfg(fuzzing)]
561
        return 0..0;
562
563
        #[cfg(not(fuzzing))]
564
        {
565
            if self.is_call_site() {
566
                0..0
567
            } else {
568
                SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).byte_range(*self))
569
            }
570
        }
571
    }
572
573
    #[cfg(span_locations)]
574
    pub(crate) fn start(&self) -> LineColumn {
575
        #[cfg(fuzzing)]
576
        return LineColumn { line: 0, column: 0 };
577
578
        #[cfg(not(fuzzing))]
579
        SOURCE_MAP.with(|sm| {
580
            let sm = sm.borrow();
581
            let fi = sm.fileinfo(*self);
582
            fi.offset_line_column(self.lo as usize)
583
        })
584
    }
585
586
    #[cfg(span_locations)]
587
    pub(crate) fn end(&self) -> LineColumn {
588
        #[cfg(fuzzing)]
589
        return LineColumn { line: 0, column: 0 };
590
591
        #[cfg(not(fuzzing))]
592
        SOURCE_MAP.with(|sm| {
593
            let sm = sm.borrow();
594
            let fi = sm.fileinfo(*self);
595
            fi.offset_line_column(self.hi as usize)
596
        })
597
    }
598
599
    #[cfg(span_locations)]
600
    pub(crate) fn file(&self) -> String {
601
        #[cfg(fuzzing)]
602
        return "<unspecified>".to_owned();
603
604
        #[cfg(not(fuzzing))]
605
        SOURCE_MAP.with(|sm| {
606
            let sm = sm.borrow();
607
            sm.filepath(*self)
608
        })
609
    }
610
611
    #[cfg(span_locations)]
612
    pub(crate) fn local_file(&self) -> Option<PathBuf> {
613
        None
614
    }
615
616
    #[cfg(not(span_locations))]
617
0
    pub(crate) fn join(&self, _other: Span) -> Option<Span> {
618
0
        Some(Span {})
619
0
    }
620
621
    #[cfg(span_locations)]
622
    pub(crate) fn join(&self, other: Span) -> Option<Span> {
623
        #[cfg(fuzzing)]
624
        return {
625
            let _ = other;
626
            None
627
        };
628
629
        #[cfg(not(fuzzing))]
630
        SOURCE_MAP.with(|sm| {
631
            let sm = sm.borrow();
632
            // If `other` is not within the same FileInfo as us, return None.
633
            if !sm.fileinfo(*self).span_within(other) {
634
                return None;
635
            }
636
            Some(Span {
637
                lo: cmp::min(self.lo, other.lo),
638
                hi: cmp::max(self.hi, other.hi),
639
            })
640
        })
641
    }
642
643
    #[cfg(not(span_locations))]
644
0
    pub(crate) fn source_text(&self) -> Option<String> {
645
0
        None
646
0
    }
647
648
    #[cfg(span_locations)]
649
    pub(crate) fn source_text(&self) -> Option<String> {
650
        #[cfg(fuzzing)]
651
        return None;
652
653
        #[cfg(not(fuzzing))]
654
        {
655
            if self.is_call_site() {
656
                None
657
            } else {
658
                Some(SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).source_text(*self)))
659
            }
660
        }
661
    }
662
663
    #[cfg(not(span_locations))]
664
0
    pub(crate) fn first_byte(self) -> Self {
665
0
        self
666
0
    }
667
668
    #[cfg(span_locations)]
669
    pub(crate) fn first_byte(self) -> Self {
670
        Span {
671
            lo: self.lo,
672
            hi: cmp::min(self.lo.saturating_add(1), self.hi),
673
        }
674
    }
675
676
    #[cfg(not(span_locations))]
677
0
    pub(crate) fn last_byte(self) -> Self {
678
0
        self
679
0
    }
680
681
    #[cfg(span_locations)]
682
    pub(crate) fn last_byte(self) -> Self {
683
        Span {
684
            lo: cmp::max(self.hi.saturating_sub(1), self.lo),
685
            hi: self.hi,
686
        }
687
    }
688
689
    #[cfg(span_locations)]
690
    fn is_call_site(&self) -> bool {
691
        self.lo == 0 && self.hi == 0
692
    }
693
}
694
695
impl Debug for Span {
696
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
697
        #[cfg(span_locations)]
698
        return write!(f, "bytes({}..{})", self.lo, self.hi);
699
700
        #[cfg(not(span_locations))]
701
0
        write!(f, "Span")
702
0
    }
703
}
704
705
0
pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
706
    #[cfg(span_locations)]
707
    {
708
        if span.is_call_site() {
709
            return;
710
        }
711
    }
712
713
0
    if cfg!(span_locations) {
714
0
        debug.field("span", &span);
715
0
    }
716
0
}
717
718
#[derive(Clone)]
719
pub(crate) struct Group {
720
    delimiter: Delimiter,
721
    stream: TokenStream,
722
    span: Span,
723
}
724
725
impl Group {
726
562k
    pub(crate) fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
727
562k
        Group {
728
562k
            delimiter,
729
562k
            stream,
730
562k
            span: Span::call_site(),
731
562k
        }
732
562k
    }
733
734
0
    pub(crate) fn delimiter(&self) -> Delimiter {
735
0
        self.delimiter
736
0
    }
737
738
0
    pub(crate) fn stream(&self) -> TokenStream {
739
0
        self.stream.clone()
740
0
    }
741
742
0
    pub(crate) fn span(&self) -> Span {
743
0
        self.span
744
0
    }
745
746
0
    pub(crate) fn span_open(&self) -> Span {
747
0
        self.span.first_byte()
748
0
    }
749
750
0
    pub(crate) fn span_close(&self) -> Span {
751
0
        self.span.last_byte()
752
0
    }
753
754
562k
    pub(crate) fn set_span(&mut self, span: Span) {
755
562k
        self.span = span;
756
562k
    }
757
}
758
759
impl Display for Group {
760
    // We attempt to match libproc_macro's formatting.
761
    // Empty parens: ()
762
    // Nonempty parens: (...)
763
    // Empty brackets: []
764
    // Nonempty brackets: [...]
765
    // Empty braces: { }
766
    // Nonempty braces: { ... }
767
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
768
0
        let (open, close) = match self.delimiter {
769
0
            Delimiter::Parenthesis => ("(", ")"),
770
0
            Delimiter::Brace => ("{ ", "}"),
771
0
            Delimiter::Bracket => ("[", "]"),
772
0
            Delimiter::None => ("", ""),
773
        };
774
775
0
        f.write_str(open)?;
776
0
        Display::fmt(&self.stream, f)?;
777
0
        if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() {
778
0
            f.write_str(" ")?;
779
0
        }
780
0
        f.write_str(close)?;
781
782
0
        Ok(())
783
0
    }
784
}
785
786
impl Debug for Group {
787
0
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
788
0
        let mut debug = fmt.debug_struct("Group");
789
0
        debug.field("delimiter", &self.delimiter);
790
0
        debug.field("stream", &self.stream);
791
0
        debug_span_field_if_nontrivial(&mut debug, self.span);
792
0
        debug.finish()
793
0
    }
794
}
795
796
#[derive(Clone)]
797
pub(crate) struct Ident {
798
    sym: Box<str>,
799
    span: Span,
800
    raw: bool,
801
}
802
803
impl Ident {
804
    #[track_caller]
805
0
    pub(crate) fn new_checked(string: &str, span: Span) -> Self {
806
0
        validate_ident(string);
807
0
        Ident::new_unchecked(string, span)
808
0
    }
809
810
605k
    pub(crate) fn new_unchecked(string: &str, span: Span) -> Self {
811
605k
        Ident {
812
605k
            sym: Box::from(string),
813
605k
            span,
814
605k
            raw: false,
815
605k
        }
816
605k
    }
817
818
    #[track_caller]
819
0
    pub(crate) fn new_raw_checked(string: &str, span: Span) -> Self {
820
0
        validate_ident_raw(string);
821
0
        Ident::new_raw_unchecked(string, span)
822
0
    }
823
824
1.12k
    pub(crate) fn new_raw_unchecked(string: &str, span: Span) -> Self {
825
1.12k
        Ident {
826
1.12k
            sym: Box::from(string),
827
1.12k
            span,
828
1.12k
            raw: true,
829
1.12k
        }
830
1.12k
    }
831
832
0
    pub(crate) fn span(&self) -> Span {
833
0
        self.span
834
0
    }
835
836
591k
    pub(crate) fn set_span(&mut self, span: Span) {
837
591k
        self.span = span;
838
591k
    }
839
}
840
841
3.77M
pub(crate) fn is_ident_start(c: char) -> bool {
842
3.77M
    c == '_' || unicode_ident::is_xid_start(c)
843
3.77M
}
844
845
21.0M
pub(crate) fn is_ident_continue(c: char) -> bool {
846
21.0M
    unicode_ident::is_xid_continue(c)
847
21.0M
}
848
849
#[track_caller]
850
0
fn validate_ident(string: &str) {
851
0
    if string.is_empty() {
852
0
        panic!("Ident is not allowed to be empty; use Option<Ident>");
853
0
    }
854
855
0
    if string.bytes().all(|digit| b'0' <= digit && digit <= b'9') {
856
0
        panic!("Ident cannot be a number; use Literal instead");
857
0
    }
858
859
0
    fn ident_ok(string: &str) -> bool {
860
0
        let mut chars = string.chars();
861
0
        let first = chars.next().unwrap();
862
0
        if !is_ident_start(first) {
863
0
            return false;
864
0
        }
865
0
        for ch in chars {
866
0
            if !is_ident_continue(ch) {
867
0
                return false;
868
0
            }
869
        }
870
0
        true
871
0
    }
872
873
0
    if !ident_ok(string) {
874
0
        panic!("{:?} is not a valid Ident", string);
875
0
    }
876
0
}
877
878
#[track_caller]
879
0
fn validate_ident_raw(string: &str) {
880
0
    validate_ident(string);
881
882
0
    match string {
883
0
        "_" | "super" | "self" | "Self" | "crate" => {
884
0
            panic!("`r#{}` cannot be a raw identifier", string);
885
        }
886
0
        _ => {}
887
    }
888
0
}
889
890
impl PartialEq for Ident {
891
0
    fn eq(&self, other: &Ident) -> bool {
892
0
        self.sym == other.sym && self.raw == other.raw
893
0
    }
894
}
895
896
impl<T> PartialEq<T> for Ident
897
where
898
    T: ?Sized + AsRef<str>,
899
{
900
0
    fn eq(&self, other: &T) -> bool {
901
0
        let other = other.as_ref();
902
0
        if self.raw {
903
0
            other.starts_with("r#") && *self.sym == other[2..]
904
        } else {
905
0
            *self.sym == *other
906
        }
907
0
    }
908
}
909
910
impl Display for Ident {
911
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
912
0
        if self.raw {
913
0
            f.write_str("r#")?;
914
0
        }
915
0
        f.write_str(&self.sym)
916
0
    }
917
}
918
919
#[allow(clippy::missing_fields_in_debug)]
920
impl Debug for Ident {
921
    // Ident(proc_macro), Ident(r#union)
922
    #[cfg(not(span_locations))]
923
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
924
0
        let mut debug = f.debug_tuple("Ident");
925
0
        debug.field(&format_args!("{}", self));
926
0
        debug.finish()
927
0
    }
928
929
    // Ident {
930
    //     sym: proc_macro,
931
    //     span: bytes(128..138)
932
    // }
933
    #[cfg(span_locations)]
934
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
935
        let mut debug = f.debug_struct("Ident");
936
        debug.field("sym", &format_args!("{}", self));
937
        debug_span_field_if_nontrivial(&mut debug, self.span);
938
        debug.finish()
939
    }
940
}
941
942
#[derive(Clone)]
943
pub(crate) struct Literal {
944
    pub(crate) repr: String,
945
    span: Span,
946
}
947
948
macro_rules! suffixed_numbers {
949
    ($($name:ident => $kind:ident,)*) => ($(
950
0
        pub(crate) fn $name(n: $kind) -> Literal {
951
0
            Literal::_new(format!(concat!("{}", stringify!($kind)), n))
952
0
        }
Unexecuted instantiation: <proc_macro2::fallback::Literal>::i8_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::u8_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::f32_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::f64_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::i16_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::i32_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::i64_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::u16_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::u32_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::u64_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::i128_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::u128_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::isize_suffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::usize_suffixed
953
    )*)
954
}
955
956
macro_rules! unsuffixed_numbers {
957
    ($($name:ident => $kind:ident,)*) => ($(
958
0
        pub(crate) fn $name(n: $kind) -> Literal {
959
0
            Literal::_new(n.to_string())
960
0
        }
Unexecuted instantiation: <proc_macro2::fallback::Literal>::i8_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::u8_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::i16_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::i32_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::i64_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::u16_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::u32_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::u64_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::i128_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::u128_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::isize_unsuffixed
Unexecuted instantiation: <proc_macro2::fallback::Literal>::usize_unsuffixed
961
    )*)
962
}
963
964
impl Literal {
965
2.27M
    pub(crate) fn _new(repr: String) -> Self {
966
2.27M
        Literal {
967
2.27M
            repr,
968
2.27M
            span: Span::call_site(),
969
2.27M
        }
970
2.27M
    }
971
972
0
    pub(crate) fn from_str_checked(repr: &str) -> Result<Self, LexError> {
973
0
        let mut cursor = get_cursor(repr);
974
        #[cfg(span_locations)]
975
        let lo = cursor.off;
976
977
0
        let negative = cursor.starts_with_char('-');
978
0
        if negative {
979
0
            cursor = cursor.advance(1);
980
0
            if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) {
981
0
                return Err(LexError::call_site());
982
0
            }
983
0
        }
984
985
0
        if let Ok((rest, mut literal)) = parse::literal(cursor) {
986
0
            if rest.is_empty() {
987
0
                if negative {
988
0
                    literal.repr.insert(0, '-');
989
0
                }
990
0
                literal.span = Span {
991
0
                    #[cfg(span_locations)]
992
0
                    lo,
993
0
                    #[cfg(span_locations)]
994
0
                    hi: rest.off,
995
0
                };
996
0
                return Ok(literal);
997
0
            }
998
0
        }
999
0
        Err(LexError::call_site())
1000
0
    }
1001
1002
0
    pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self {
1003
0
        Literal::_new(repr.to_owned())
1004
0
    }
1005
1006
    suffixed_numbers! {
1007
        u8_suffixed => u8,
1008
        u16_suffixed => u16,
1009
        u32_suffixed => u32,
1010
        u64_suffixed => u64,
1011
        u128_suffixed => u128,
1012
        usize_suffixed => usize,
1013
        i8_suffixed => i8,
1014
        i16_suffixed => i16,
1015
        i32_suffixed => i32,
1016
        i64_suffixed => i64,
1017
        i128_suffixed => i128,
1018
        isize_suffixed => isize,
1019
1020
        f32_suffixed => f32,
1021
        f64_suffixed => f64,
1022
    }
1023
1024
    unsuffixed_numbers! {
1025
        u8_unsuffixed => u8,
1026
        u16_unsuffixed => u16,
1027
        u32_unsuffixed => u32,
1028
        u64_unsuffixed => u64,
1029
        u128_unsuffixed => u128,
1030
        usize_unsuffixed => usize,
1031
        i8_unsuffixed => i8,
1032
        i16_unsuffixed => i16,
1033
        i32_unsuffixed => i32,
1034
        i64_unsuffixed => i64,
1035
        i128_unsuffixed => i128,
1036
        isize_unsuffixed => isize,
1037
    }
1038
1039
0
    pub(crate) fn f32_unsuffixed(f: f32) -> Literal {
1040
0
        let mut s = f.to_string();
1041
0
        if !s.contains('.') {
1042
0
            s.push_str(".0");
1043
0
        }
1044
0
        Literal::_new(s)
1045
0
    }
1046
1047
0
    pub(crate) fn f64_unsuffixed(f: f64) -> Literal {
1048
0
        let mut s = f.to_string();
1049
0
        if !s.contains('.') {
1050
0
            s.push_str(".0");
1051
0
        }
1052
0
        Literal::_new(s)
1053
0
    }
1054
1055
14.9k
    pub(crate) fn string(string: &str) -> Literal {
1056
14.9k
        let mut repr = String::with_capacity(string.len() + 2);
1057
14.9k
        repr.push('"');
1058
14.9k
        escape_utf8(string, &mut repr);
1059
14.9k
        repr.push('"');
1060
14.9k
        Literal::_new(repr)
1061
14.9k
    }
1062
1063
0
    pub(crate) fn character(ch: char) -> Literal {
1064
0
        let mut repr = String::new();
1065
0
        repr.push('\'');
1066
0
        if ch == '"' {
1067
0
            // escape_debug turns this into '\"' which is unnecessary.
1068
0
            repr.push(ch);
1069
0
        } else {
1070
0
            repr.extend(ch.escape_debug());
1071
0
        }
1072
0
        repr.push('\'');
1073
0
        Literal::_new(repr)
1074
0
    }
1075
1076
0
    pub(crate) fn byte_character(byte: u8) -> Literal {
1077
0
        let mut repr = "b'".to_string();
1078
        #[allow(clippy::match_overlapping_arm)]
1079
0
        match byte {
1080
0
            b'\0' => repr.push_str(r"\0"),
1081
0
            b'\t' => repr.push_str(r"\t"),
1082
0
            b'\n' => repr.push_str(r"\n"),
1083
0
            b'\r' => repr.push_str(r"\r"),
1084
0
            b'\'' => repr.push_str(r"\'"),
1085
0
            b'\\' => repr.push_str(r"\\"),
1086
0
            b'\x20'..=b'\x7E' => repr.push(byte as char),
1087
0
            _ => {
1088
0
                let _ = write!(repr, r"\x{:02X}", byte);
1089
0
            }
1090
        }
1091
0
        repr.push('\'');
1092
0
        Literal::_new(repr)
1093
0
    }
1094
1095
0
    pub(crate) fn byte_string(bytes: &[u8]) -> Literal {
1096
0
        let mut repr = "b\"".to_string();
1097
0
        let mut bytes = bytes.iter();
1098
0
        while let Some(&b) = bytes.next() {
1099
            #[allow(clippy::match_overlapping_arm)]
1100
0
            match b {
1101
0
                b'\0' => repr.push_str(match bytes.as_slice().first() {
1102
                    // circumvent clippy::octal_escapes lint
1103
0
                    Some(b'0'..=b'7') => r"\x00",
1104
0
                    _ => r"\0",
1105
                }),
1106
0
                b'\t' => repr.push_str(r"\t"),
1107
0
                b'\n' => repr.push_str(r"\n"),
1108
0
                b'\r' => repr.push_str(r"\r"),
1109
0
                b'"' => repr.push_str("\\\""),
1110
0
                b'\\' => repr.push_str(r"\\"),
1111
0
                b'\x20'..=b'\x7E' => repr.push(b as char),
1112
0
                _ => {
1113
0
                    let _ = write!(repr, r"\x{:02X}", b);
1114
0
                }
1115
            }
1116
        }
1117
0
        repr.push('"');
1118
0
        Literal::_new(repr)
1119
0
    }
1120
1121
0
    pub(crate) fn c_string(string: &CStr) -> Literal {
1122
0
        let mut repr = "c\"".to_string();
1123
0
        let mut bytes = string.to_bytes();
1124
0
        while !bytes.is_empty() {
1125
0
            let (valid, invalid) = match str::from_utf8(bytes) {
1126
0
                Ok(all_valid) => {
1127
0
                    bytes = b"";
1128
0
                    (all_valid, bytes)
1129
                }
1130
0
                Err(utf8_error) => {
1131
0
                    let (valid, rest) = bytes.split_at(utf8_error.valid_up_to());
1132
0
                    let valid = str::from_utf8(valid).unwrap();
1133
0
                    let invalid = utf8_error
1134
0
                        .error_len()
1135
0
                        .map_or(rest, |error_len| &rest[..error_len]);
1136
0
                    bytes = &bytes[valid.len() + invalid.len()..];
1137
0
                    (valid, invalid)
1138
                }
1139
            };
1140
0
            escape_utf8(valid, &mut repr);
1141
0
            for &byte in invalid {
1142
0
                let _ = write!(repr, r"\x{:02X}", byte);
1143
0
            }
1144
        }
1145
0
        repr.push('"');
1146
0
        Literal::_new(repr)
1147
0
    }
1148
1149
0
    pub(crate) fn span(&self) -> Span {
1150
0
        self.span
1151
0
    }
1152
1153
2.27M
    pub(crate) fn set_span(&mut self, span: Span) {
1154
2.27M
        self.span = span;
1155
2.27M
    }
1156
1157
0
    pub(crate) fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
1158
        #[cfg(not(span_locations))]
1159
        {
1160
0
            let _ = range;
1161
0
            None
1162
        }
1163
1164
        #[cfg(span_locations)]
1165
        {
1166
            use core::ops::Bound;
1167
1168
            let lo = match range.start_bound() {
1169
                Bound::Included(start) => {
1170
                    let start = u32::try_from(*start).ok()?;
1171
                    self.span.lo.checked_add(start)?
1172
                }
1173
                Bound::Excluded(start) => {
1174
                    let start = u32::try_from(*start).ok()?;
1175
                    self.span.lo.checked_add(start)?.checked_add(1)?
1176
                }
1177
                Bound::Unbounded => self.span.lo,
1178
            };
1179
            let hi = match range.end_bound() {
1180
                Bound::Included(end) => {
1181
                    let end = u32::try_from(*end).ok()?;
1182
                    self.span.lo.checked_add(end)?.checked_add(1)?
1183
                }
1184
                Bound::Excluded(end) => {
1185
                    let end = u32::try_from(*end).ok()?;
1186
                    self.span.lo.checked_add(end)?
1187
                }
1188
                Bound::Unbounded => self.span.hi,
1189
            };
1190
            if lo <= hi && hi <= self.span.hi {
1191
                Some(Span { lo, hi })
1192
            } else {
1193
                None
1194
            }
1195
        }
1196
0
    }
1197
}
1198
1199
impl Display for Literal {
1200
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1201
0
        Display::fmt(&self.repr, f)
1202
0
    }
1203
}
1204
1205
impl Debug for Literal {
1206
0
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1207
0
        let mut debug = fmt.debug_struct("Literal");
1208
0
        debug.field("lit", &format_args!("{}", self.repr));
1209
0
        debug_span_field_if_nontrivial(&mut debug, self.span);
1210
0
        debug.finish()
1211
0
    }
1212
}
1213
1214
14.9k
fn escape_utf8(string: &str, repr: &mut String) {
1215
14.9k
    let mut chars = string.chars();
1216
27.3M
    while let Some(ch) = chars.next() {
1217
27.3M
        if ch == '\0' {
1218
1.38M
            repr.push_str(
1219
1.38M
                if chars
1220
1.38M
                    .as_str()
1221
1.38M
                    .starts_with(|next| '0' <= next && next <= '7')
1222
                {
1223
                    // circumvent clippy::octal_escapes lint
1224
10.0k
                    r"\x00"
1225
                } else {
1226
1.37M
                    r"\0"
1227
                },
1228
            );
1229
25.9M
        } else if ch == '\'' {
1230
2.03k
            // escape_debug turns this into "\'" which is unnecessary.
1231
2.03k
            repr.push(ch);
1232
25.9M
        } else {
1233
25.9M
            repr.extend(ch.escape_debug());
1234
25.9M
        }
1235
    }
1236
14.9k
}
1237
1238
#[cfg(feature = "proc-macro")]
1239
pub(crate) trait FromStr2: FromStr<Err = proc_macro::LexError> {
1240
    #[cfg(wrap_proc_macro)]
1241
    fn valid(src: &str) -> bool;
1242
1243
    #[cfg(wrap_proc_macro)]
1244
0
    fn from_str_checked(src: &str) -> Result<Self, imp::LexError> {
1245
        // Validate using fallback parser, because rustc is incapable of
1246
        // returning a recoverable Err for certain invalid token streams, and
1247
        // will instead permanently poison the compilation.
1248
0
        if !Self::valid(src) {
1249
0
            return Err(imp::LexError::CompilerPanic);
1250
0
        }
1251
1252
        // Catch panic to work around https://github.com/rust-lang/rust/issues/58736.
1253
0
        match panic::catch_unwind(|| Self::from_str(src)) {
Unexecuted instantiation: <proc_macro::TokenStream as proc_macro2::fallback::FromStr2>::from_str_checked::{closure#0}
Unexecuted instantiation: <proc_macro::Literal as proc_macro2::fallback::FromStr2>::from_str_checked::{closure#0}
1254
0
            Ok(Ok(ok)) => Ok(ok),
1255
0
            Ok(Err(lex)) => Err(imp::LexError::Compiler(lex)),
1256
0
            Err(_panic) => Err(imp::LexError::CompilerPanic),
1257
        }
1258
0
    }
Unexecuted instantiation: <proc_macro::TokenStream as proc_macro2::fallback::FromStr2>::from_str_checked
Unexecuted instantiation: <proc_macro::Literal as proc_macro2::fallback::FromStr2>::from_str_checked
1259
1260
0
    fn from_str_unchecked(src: &str) -> Self {
1261
0
        Self::from_str(src).unwrap()
1262
0
    }
Unexecuted instantiation: <proc_macro::TokenStream as proc_macro2::fallback::FromStr2>::from_str_unchecked
Unexecuted instantiation: <proc_macro::Literal as proc_macro2::fallback::FromStr2>::from_str_unchecked
1263
}
1264
1265
#[cfg(feature = "proc-macro")]
1266
impl FromStr2 for proc_macro::TokenStream {
1267
    #[cfg(wrap_proc_macro)]
1268
0
    fn valid(src: &str) -> bool {
1269
0
        TokenStream::from_str_checked(src).is_ok()
1270
0
    }
1271
}
1272
1273
#[cfg(feature = "proc-macro")]
1274
impl FromStr2 for proc_macro::Literal {
1275
    #[cfg(wrap_proc_macro)]
1276
0
    fn valid(src: &str) -> bool {
1277
0
        Literal::from_str_checked(src).is_ok()
1278
0
    }
1279
}