Skip to main content

rustc_demangle/
v0.rs

1use core::convert::TryFrom;
2use core::{char, fmt, iter, mem, str};
3
4#[allow(unused_macros)]
5macro_rules! write {
6    ($($ignored:tt)*) => {
7        compile_error!(
8            "use `self.print(value)` or `fmt::Trait::fmt(&value, self.out)`, \
9             instead of `write!(self.out, \"{...}\", value)`"
10        )
11    };
12}
13
14// Maximum recursion depth when parsing symbols before we just bail out saying
15// "this symbol is invalid"
16const MAX_DEPTH: u32 = 500;
17
18/// Representation of a demangled symbol name.
19pub struct Demangle<'a> {
20    inner: &'a str,
21}
22
23#[derive(PartialEq, Eq, Debug)]
24pub enum ParseError {
25    /// Symbol doesn't match the expected `v0` grammar.
26    Invalid,
27
28    /// Parsing the symbol crossed the recursion limit (see `MAX_DEPTH`).
29    RecursedTooDeep,
30}
31
32/// De-mangles a Rust symbol into a more readable version
33///
34/// This function will take a **mangled** symbol and return a value. When printed,
35/// the de-mangled version will be written. If the symbol does not look like
36/// a mangled symbol, the original value will be written instead.
37pub fn demangle(s: &str) -> Result<(Demangle, &str), ParseError> {
38    // First validate the symbol. If it doesn't look like anything we're
39    // expecting, we just print it literally. Note that we must handle non-Rust
40    // symbols because we could have any function in the backtrace.
41    let inner;
42    if s.len() > 2 && s.starts_with("_R") {
43        inner = &s[2..];
44    } else if s.len() > 1 && s.starts_with('R') {
45        // On Windows, dbghelp strips leading underscores, so we accept "R..."
46        // form too.
47        inner = &s[1..];
48    } else if s.len() > 3 && s.starts_with("__R") {
49        // On OSX, symbols are prefixed with an extra _
50        inner = &s[3..];
51    } else {
52        return Err(ParseError::Invalid);
53    }
54
55    // Paths always start with uppercase characters.
56    match inner.as_bytes()[0] {
57        b'A'..=b'Z' => {}
58        _ => return Err(ParseError::Invalid),
59    }
60
61    // only work with ascii text
62    if inner.bytes().any(|c| c & 0x80 != 0) {
63        return Err(ParseError::Invalid);
64    }
65
66    // Verify that the symbol is indeed a valid path.
67    let try_parse_path = |parser| {
68        let mut dummy_printer = Printer {
69            parser: Ok(parser),
70            out: None,
71            bound_lifetime_depth: 0,
72        };
73        dummy_printer
74            .print_path(false)
75            .expect("`fmt::Error`s should be impossible without a `fmt::Formatter`");
76        dummy_printer.parser
77    };
78    let mut parser = Parser {
79        sym: inner,
80        next: 0,
81        depth: 0,
82    };
83    parser = try_parse_path(parser)?;
84
85    // Instantiating crate (paths always start with uppercase characters).
86    if let Some(&(b'A'..=b'Z')) = parser.sym.as_bytes().get(parser.next) {
87        parser = try_parse_path(parser)?;
88    }
89
90    Ok((Demangle { inner }, &parser.sym[parser.next..]))
91}
92
93impl<'s> fmt::Display for Demangle<'s> {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        let mut printer = Printer {
96            parser: Ok(Parser {
97                sym: self.inner,
98                next: 0,
99                depth: 0,
100            }),
101            out: Some(f),
102            bound_lifetime_depth: 0,
103        };
104        printer.print_path(true)
105    }
106}
107
108struct Ident<'s> {
109    /// ASCII part of the identifier.
110    ascii: &'s str,
111    /// Punycode insertion codes for Unicode codepoints, if any.
112    punycode: &'s str,
113}
114
115const SMALL_PUNYCODE_LEN: usize = 128;
116
117impl<'s> Ident<'s> {
118    /// Attempt to decode punycode on the stack (allocation-free),
119    /// and pass the char slice to the closure, if successful.
120    /// This supports up to `SMALL_PUNYCODE_LEN` characters.
121    fn try_small_punycode_decode<F: FnOnce(&[char]) -> R, R>(&self, f: F) -> Option<R> {
122        let mut out = ['\0'; SMALL_PUNYCODE_LEN];
123        let mut out_len = 0;
124        let r = self.punycode_decode(|i, c| {
125            // Check there's space left for another character.
126            out.get(out_len).ok_or(())?;
127
128            // Move the characters after the insert position.
129            let mut j = out_len;
130            out_len += 1;
131
132            while j > i {
133                out[j] = out[j - 1];
134                j -= 1;
135            }
136
137            // Insert the new character.
138            out[i] = c;
139
140            Ok(())
141        });
142        if r.is_ok() {
143            Some(f(&out[..out_len]))
144        } else {
145            None
146        }
147    }
148
149    /// Decode punycode as insertion positions and characters
150    /// and pass them to the closure, which can return `Err(())`
151    /// to stop the decoding process.
152    fn punycode_decode<F: FnMut(usize, char) -> Result<(), ()>>(
153        &self,
154        mut insert: F,
155    ) -> Result<(), ()> {
156        let mut punycode_bytes = self.punycode.bytes().peekable();
157        if punycode_bytes.peek().is_none() {
158            return Err(());
159        }
160
161        let mut len = 0;
162
163        // Populate initial output from ASCII fragment.
164        for c in self.ascii.chars() {
165            insert(len, c)?;
166            len += 1;
167        }
168
169        // Punycode parameters and initial state.
170        let base = 36;
171        let t_min = 1;
172        let t_max = 26;
173        let skew = 38;
174        let mut damp = 700;
175        let mut bias = 72;
176        let mut i: usize = 0;
177        let mut n: usize = 0x80;
178
179        loop {
180            // Read one delta value.
181            let mut delta: usize = 0;
182            let mut w = 1;
183            let mut k: usize = 0;
184            loop {
185                use core::cmp::{max, min};
186
187                k += base;
188                let t = min(max(k.saturating_sub(bias), t_min), t_max);
189
190                let d = match punycode_bytes.next() {
191                    Some(d @ b'a'..=b'z') => d - b'a',
192                    Some(d @ b'0'..=b'9') => 26 + (d - b'0'),
193                    _ => return Err(()),
194                };
195                let d = d as usize;
196                delta = delta.checked_add(d.checked_mul(w).ok_or(())?).ok_or(())?;
197                if d < t {
198                    break;
199                }
200                w = w.checked_mul(base - t).ok_or(())?;
201            }
202
203            // Compute the new insert position and character.
204            len += 1;
205            i = i.checked_add(delta).ok_or(())?;
206            n = n.checked_add(i / len).ok_or(())?;
207            i %= len;
208
209            let n_u32 = n as u32;
210            let c = if n_u32 as usize == n {
211                char::from_u32(n_u32).ok_or(())?
212            } else {
213                return Err(());
214            };
215
216            // Insert the new character and increment the insert position.
217            insert(i, c)?;
218            i += 1;
219
220            // If there are no more deltas, decoding is complete.
221            if punycode_bytes.peek().is_none() {
222                return Ok(());
223            }
224
225            // Perform bias adaptation.
226            delta /= damp;
227            damp = 2;
228
229            delta += delta / len;
230            let mut k = 0;
231            while delta > ((base - t_min) * t_max) / 2 {
232                delta /= base - t_min;
233                k += base;
234            }
235            bias = k + ((base - t_min + 1) * delta) / (delta + skew);
236        }
237    }
238}
239
240impl<'s> fmt::Display for Ident<'s> {
241    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
242        self.try_small_punycode_decode(|chars| {
243            for &c in chars {
244                c.fmt(f)?;
245            }
246            Ok(())
247        })
248        .unwrap_or_else(|| {
249            if !self.punycode.is_empty() {
250                f.write_str("punycode{")?;
251
252                // Reconstruct a standard Punycode encoding,
253                // by using `-` as the separator.
254                if !self.ascii.is_empty() {
255                    f.write_str(self.ascii)?;
256                    f.write_str("-")?;
257                }
258                f.write_str(self.punycode)?;
259
260                f.write_str("}")
261            } else {
262                f.write_str(self.ascii)
263            }
264        })
265    }
266}
267
268/// Sequence of lowercase hexadecimal nibbles (`0-9a-f`), used by leaf consts.
269struct HexNibbles<'s> {
270    nibbles: &'s str,
271}
272
273impl<'s> HexNibbles<'s> {
274    /// Decode an integer value (with the "most significant nibble" first),
275    /// returning `None` if it can't fit in an `u64`.
276    // FIXME(eddyb) should this "just" use `u128` instead?
277    fn try_parse_uint(&self) -> Option<u64> {
278        let nibbles = self.nibbles.trim_start_matches("0");
279
280        if nibbles.len() > 16 {
281            return None;
282        }
283
284        let mut v = 0;
285        for nibble in nibbles.chars() {
286            v = (v << 4) | (nibble.to_digit(16).unwrap() as u64);
287        }
288        Some(v)
289    }
290
291    /// Decode a UTF-8 byte sequence (with each byte using a pair of nibbles)
292    /// into individual `char`s, returning `None` for invalid UTF-8.
293    fn try_parse_str_chars(&self) -> Option<impl Iterator<Item = char> + 's> {
294        if self.nibbles.len() % 2 != 0 {
295            return None;
296        }
297
298        // FIXME(eddyb) use `array_chunks` instead, when that becomes stable.
299        let mut bytes = self
300            .nibbles
301            .as_bytes()
302            .chunks_exact(2)
303            .map(|slice| match slice {
304                [a, b] => [a, b],
305                _ => unreachable!(),
306            })
307            .map(|[&hi, &lo]| {
308                let half = |nibble: u8| (nibble as char).to_digit(16).unwrap() as u8;
309                (half(hi) << 4) | half(lo)
310            });
311
312        let chars = iter::from_fn(move || {
313            // As long as there are any bytes left, there's at least one more
314            // UTF-8-encoded `char` to decode (or the possibility of error).
315            bytes.next().map(|first_byte| -> Result<char, ()> {
316                // FIXME(eddyb) this `enum` and `fn` should be somewhere in `core`.
317                enum Utf8FirstByteError {
318                    ContinuationByte,
319                    TooLong,
320                }
321                fn utf8_len_from_first_byte(byte: u8) -> Result<usize, Utf8FirstByteError> {
322                    match byte {
323                        0x00..=0x7f => Ok(1),
324                        0x80..=0xbf => Err(Utf8FirstByteError::ContinuationByte),
325                        0xc0..=0xdf => Ok(2),
326                        0xe0..=0xef => Ok(3),
327                        0xf0..=0xf7 => Ok(4),
328                        0xf8..=0xff => Err(Utf8FirstByteError::TooLong),
329                    }
330                }
331
332                // Collect the appropriate amount of bytes (up to 4), according
333                // to the UTF-8 length implied by the first byte.
334                let utf8_len = utf8_len_from_first_byte(first_byte).map_err(|_| ())?;
335                let utf8 = &mut [first_byte, 0, 0, 0][..utf8_len];
336                for i in 1..utf8_len {
337                    utf8[i] = bytes.next().ok_or(())?;
338                }
339
340                // Fully validate the UTF-8 sequence.
341                let s = str::from_utf8(utf8).map_err(|_| ())?;
342
343                // Since we included exactly one UTF-8 sequence, and validation
344                // succeeded, `str::chars` should return exactly one `char`.
345                let mut chars = s.chars();
346                match (chars.next(), chars.next()) {
347                    (Some(c), None) => Ok(c),
348                    _ => unreachable!(
349                        "str::from_utf8({:?}) = {:?} was expected to have 1 char, \
350                         but {} chars were found",
351                        utf8,
352                        s,
353                        s.chars().count()
354                    ),
355                }
356            })
357        });
358
359        // HACK(eddyb) doing a separate validation iteration like this might be
360        // wasteful, but it's easier to avoid starting to print a string literal
361        // in the first place, than to abort it mid-string.
362        if chars.clone().any(|r| r.is_err()) {
363            None
364        } else {
365            Some(chars.map(Result::unwrap))
366        }
367    }
368}
369
370fn basic_type(tag: u8) -> Option<&'static str> {
371    Some(match tag {
372        b'b' => "bool",
373        b'c' => "char",
374        b'e' => "str",
375        b'u' => "()",
376        b'a' => "i8",
377        b's' => "i16",
378        b'l' => "i32",
379        b'x' => "i64",
380        b'n' => "i128",
381        b'i' => "isize",
382        b'h' => "u8",
383        b't' => "u16",
384        b'm' => "u32",
385        b'y' => "u64",
386        b'o' => "u128",
387        b'j' => "usize",
388        b'f' => "f32",
389        b'd' => "f64",
390        b'z' => "!",
391        b'p' => "_",
392        b'v' => "...",
393
394        _ => return None,
395    })
396}
397
398struct Parser<'s> {
399    sym: &'s str,
400    next: usize,
401    depth: u32,
402}
403
404impl<'s> Parser<'s> {
405    fn push_depth(&mut self) -> Result<(), ParseError> {
406        self.depth += 1;
407        if self.depth > MAX_DEPTH {
408            Err(ParseError::RecursedTooDeep)
409        } else {
410            Ok(())
411        }
412    }
413
414    fn pop_depth(&mut self) {
415        self.depth -= 1;
416    }
417
418    fn peek(&self) -> Option<u8> {
419        self.sym.as_bytes().get(self.next).cloned()
420    }
421
422    fn eat(&mut self, b: u8) -> bool {
423        if self.peek() == Some(b) {
424            self.next += 1;
425            true
426        } else {
427            false
428        }
429    }
430
431    fn next(&mut self) -> Result<u8, ParseError> {
432        let b = self.peek().ok_or(ParseError::Invalid)?;
433        self.next += 1;
434        Ok(b)
435    }
436
437    fn hex_nibbles(&mut self) -> Result<HexNibbles<'s>, ParseError> {
438        let start = self.next;
439        loop {
440            match self.next()? {
441                b'0'..=b'9' | b'a'..=b'f' => {}
442                b'_' => break,
443                _ => return Err(ParseError::Invalid),
444            }
445        }
446        Ok(HexNibbles {
447            nibbles: &self.sym[start..self.next - 1],
448        })
449    }
450
451    fn digit_10(&mut self) -> Result<u8, ParseError> {
452        let d = match self.peek() {
453            Some(d @ b'0'..=b'9') => d - b'0',
454            _ => return Err(ParseError::Invalid),
455        };
456        self.next += 1;
457        Ok(d)
458    }
459
460    fn digit_62(&mut self) -> Result<u8, ParseError> {
461        let d = match self.peek() {
462            Some(d @ b'0'..=b'9') => d - b'0',
463            Some(d @ b'a'..=b'z') => 10 + (d - b'a'),
464            Some(d @ b'A'..=b'Z') => 10 + 26 + (d - b'A'),
465            _ => return Err(ParseError::Invalid),
466        };
467        self.next += 1;
468        Ok(d)
469    }
470
471    fn integer_62(&mut self) -> Result<u64, ParseError> {
472        if self.eat(b'_') {
473            return Ok(0);
474        }
475
476        let mut x: u64 = 0;
477        while !self.eat(b'_') {
478            let d = self.digit_62()? as u64;
479            x = x.checked_mul(62).ok_or(ParseError::Invalid)?;
480            x = x.checked_add(d).ok_or(ParseError::Invalid)?;
481        }
482        x.checked_add(1).ok_or(ParseError::Invalid)
483    }
484
485    fn opt_integer_62(&mut self, tag: u8) -> Result<u64, ParseError> {
486        if !self.eat(tag) {
487            return Ok(0);
488        }
489        self.integer_62()?.checked_add(1).ok_or(ParseError::Invalid)
490    }
491
492    fn disambiguator(&mut self) -> Result<u64, ParseError> {
493        self.opt_integer_62(b's')
494    }
495
496    fn namespace(&mut self) -> Result<Option<char>, ParseError> {
497        match self.next()? {
498            // Special namespaces, like closures and shims.
499            ns @ b'A'..=b'Z' => Ok(Some(ns as char)),
500
501            // Implementation-specific/unspecified namespaces.
502            b'a'..=b'z' => Ok(None),
503
504            _ => Err(ParseError::Invalid),
505        }
506    }
507
508    fn backref(&mut self) -> Result<Parser<'s>, ParseError> {
509        let s_start = self.next - 1;
510        let i = self.integer_62()?;
511        if i >= s_start as u64 {
512            return Err(ParseError::Invalid);
513        }
514        let mut new_parser = Parser {
515            sym: self.sym,
516            next: i as usize,
517            depth: self.depth,
518        };
519        new_parser.push_depth()?;
520        Ok(new_parser)
521    }
522
523    fn ident(&mut self) -> Result<Ident<'s>, ParseError> {
524        let is_punycode = self.eat(b'u');
525        let mut len = self.digit_10()? as usize;
526        if len != 0 {
527            while let Ok(d) = self.digit_10() {
528                len = len.checked_mul(10).ok_or(ParseError::Invalid)?;
529                len = len.checked_add(d as usize).ok_or(ParseError::Invalid)?;
530            }
531        }
532
533        // Skip past the optional `_` separator.
534        self.eat(b'_');
535
536        let start = self.next;
537        self.next = self.next.checked_add(len).ok_or(ParseError::Invalid)?;
538        if self.next > self.sym.len() {
539            return Err(ParseError::Invalid);
540        }
541
542        let ident = &self.sym[start..self.next];
543
544        if is_punycode {
545            let ident = match ident.bytes().rposition(|b| b == b'_') {
546                Some(i) => Ident {
547                    ascii: &ident[..i],
548                    punycode: &ident[i + 1..],
549                },
550                None => Ident {
551                    ascii: "",
552                    punycode: ident,
553                },
554            };
555            if ident.punycode.is_empty() {
556                return Err(ParseError::Invalid);
557            }
558            Ok(ident)
559        } else {
560            Ok(Ident {
561                ascii: ident,
562                punycode: "",
563            })
564        }
565    }
566}
567
568struct Printer<'a, 'b: 'a, 's> {
569    /// The input parser to demangle from, or `Err` if any (parse) error was
570    /// encountered (in order to disallow further likely-incorrect demangling).
571    ///
572    /// See also the documentation on the `invalid!` and `parse!` macros below.
573    parser: Result<Parser<'s>, ParseError>,
574
575    /// The output formatter to demangle to, or `None` while skipping printing.
576    out: Option<&'a mut fmt::Formatter<'b>>,
577
578    /// Cumulative number of lifetimes bound by `for<...>` binders ('G'),
579    /// anywhere "around" the current entity (e.g. type) being demangled.
580    /// This value is not tracked while skipping printing, as it'd be unused.
581    ///
582    /// See also the documentation on the `Printer::in_binder` method.
583    bound_lifetime_depth: u32,
584}
585
586impl ParseError {
587    /// Snippet to print when the error is initially encountered.
588    fn message(&self) -> &str {
589        match self {
590            ParseError::Invalid => "{invalid syntax}",
591            ParseError::RecursedTooDeep => "{recursion limit reached}",
592        }
593    }
594}
595
596/// Mark the parser as errored (with `ParseError::Invalid`), print the
597/// appropriate message (see `ParseError::message`) and return early.
598macro_rules! invalid {
599    ($printer:ident) => {{
600        let err = ParseError::Invalid;
601        $printer.print(err.message())?;
602        $printer.parser = Err(err);
603        return Ok(());
604    }};
605}
606
607/// Call a parser method (if the parser hasn't errored yet),
608/// and mark the parser as errored if it returns `Err`.
609///
610/// If the parser errored, before or now, this returns early,
611/// from the current function, after printing either:
612/// * for a new error, the appropriate message (see `ParseError::message`)
613/// * for an earlier error, only `?` -  this allows callers to keep printing
614///   the approximate syntax of the path/type/const, despite having errors,
615///   e.g. `Vec<[(A, ?); ?]>` instead of `Vec<[(A, ?`
616macro_rules! parse {
617    ($printer:ident, $method:ident $(($($arg:expr),*))*) => {
618        match $printer.parser {
619            Ok(ref mut parser) => match parser.$method($($($arg),*)*) {
620                Ok(x) => x,
621                Err(err) => {
622                    $printer.print(err.message())?;
623                    $printer.parser = Err(err);
624                    return Ok(());
625                }
626            }
627            Err(_) => return $printer.print("?"),
628        }
629    };
630}
631
632impl<'a, 'b, 's> Printer<'a, 'b, 's> {
633    /// Eat the given character from the parser,
634    /// returning `false` if the parser errored.
635    fn eat(&mut self, b: u8) -> bool {
636        self.parser.as_mut().map(|p| p.eat(b)) == Ok(true)
637    }
638
639    /// Skip printing (i.e. `self.out` will be `None`) for the duration of the
640    /// given closure. This should not change parsing behavior, only disable the
641    /// output, but there may be optimizations (such as not traversing backrefs).
642    fn skipping_printing<F>(&mut self, f: F)
643    where
644        F: FnOnce(&mut Self) -> fmt::Result,
645    {
646        let orig_out = self.out.take();
647        f(self).expect("`fmt::Error`s should be impossible without a `fmt::Formatter`");
648        self.out = orig_out;
649    }
650
651    /// Print the target of a backref, using the given closure.
652    /// When printing is being skipped, the backref will only be parsed,
653    /// ignoring the backref's target completely.
654    fn print_backref<F>(&mut self, f: F) -> fmt::Result
655    where
656        F: FnOnce(&mut Self) -> fmt::Result,
657    {
658        let backref_parser = parse!(self, backref);
659
660        if self.out.is_none() {
661            return Ok(());
662        }
663
664        let orig_parser = mem::replace(&mut self.parser, Ok(backref_parser));
665        let r = f(self);
666        self.parser = orig_parser;
667        r
668    }
669
670    fn pop_depth(&mut self) {
671        if let Ok(ref mut parser) = self.parser {
672            parser.pop_depth();
673        }
674    }
675
676    /// Output the given value to `self.out` (using `fmt::Display` formatting),
677    /// if printing isn't being skipped.
678    fn print(&mut self, x: impl fmt::Display) -> fmt::Result {
679        if let Some(out) = &mut self.out {
680            fmt::Display::fmt(&x, out)?;
681        }
682        Ok(())
683    }
684
685    /// Output the given `char`s (escaped using `char::escape_debug`), with the
686    /// whole sequence wrapped in quotes, for either a `char` or `&str` literal,
687    /// if printing isn't being skipped.
688    fn print_quoted_escaped_chars(
689        &mut self,
690        quote: char,
691        chars: impl Iterator<Item = char>,
692    ) -> fmt::Result {
693        if let Some(out) = &mut self.out {
694            use core::fmt::Write;
695
696            out.write_char(quote)?;
697            for c in chars {
698                // Special-case not escaping a single/double quote, when
699                // inside the opposite kind of quote.
700                if matches!((quote, c), ('\'', '"') | ('"', '\'')) {
701                    out.write_char(c)?;
702                    continue;
703                }
704
705                for escaped in c.escape_debug() {
706                    out.write_char(escaped)?;
707                }
708            }
709            out.write_char(quote)?;
710        }
711        Ok(())
712    }
713
714    /// Print the lifetime according to the previously decoded index.
715    /// An index of `0` always refers to `'_`, but starting with `1`,
716    /// indices refer to late-bound lifetimes introduced by a binder.
717    fn print_lifetime_from_index(&mut self, lt: u64) -> fmt::Result {
718        // Bound lifetimes aren't tracked when skipping printing.
719        if self.out.is_none() {
720            return Ok(());
721        }
722
723        self.print("'")?;
724        if lt == 0 {
725            return self.print("_");
726        }
727        match (self.bound_lifetime_depth as u64).checked_sub(lt) {
728            Some(depth) => {
729                // Try to print lifetimes alphabetically first.
730                if depth < 26 {
731                    let c = (b'a' + depth as u8) as char;
732                    self.print(c)
733                } else {
734                    // Use `'_123` after running out of letters.
735                    self.print("_")?;
736                    self.print(depth)
737                }
738            }
739            None => invalid!(self),
740        }
741    }
742
743    /// Optionally enter a binder ('G') for late-bound lifetimes,
744    /// printing e.g. `for<'a, 'b> ` before calling the closure,
745    /// and make those lifetimes visible to it (via depth level).
746    fn in_binder<F>(&mut self, f: F) -> fmt::Result
747    where
748        F: FnOnce(&mut Self) -> fmt::Result,
749    {
750        let bound_lifetimes = parse!(self, opt_integer_62(b'G'));
751
752        // Don't track bound lifetimes when skipping printing.
753        if self.out.is_none() {
754            return f(self);
755        }
756
757        if bound_lifetimes > 0 {
758            self.print("for<")?;
759            for i in 0..bound_lifetimes {
760                if i > 0 {
761                    self.print(", ")?;
762                }
763                self.bound_lifetime_depth += 1;
764                self.print_lifetime_from_index(1)?;
765            }
766            self.print("> ")?;
767        }
768
769        let r = f(self);
770
771        // Restore `bound_lifetime_depth` to the previous value.
772        self.bound_lifetime_depth -= bound_lifetimes as u32;
773
774        r
775    }
776
777    /// Print list elements using the given closure and separator,
778    /// until the end of the list ('E') is found, or the parser errors.
779    /// Returns the number of elements printed.
780    fn print_sep_list<F>(&mut self, f: F, sep: &str) -> Result<usize, fmt::Error>
781    where
782        F: Fn(&mut Self) -> fmt::Result,
783    {
784        let mut i = 0;
785        while self.parser.is_ok() && !self.eat(b'E') {
786            if i > 0 {
787                self.print(sep)?;
788            }
789            f(self)?;
790            i += 1;
791        }
792        Ok(i)
793    }
794
795    fn print_path(&mut self, in_value: bool) -> fmt::Result {
796        parse!(self, push_depth);
797
798        let tag = parse!(self, next);
799        match tag {
800            b'C' => {
801                let dis = parse!(self, disambiguator);
802                let name = parse!(self, ident);
803
804                self.print(name)?;
805                if let Some(out) = &mut self.out {
806                    if !out.alternate() && dis != 0 {
807                        out.write_str("[")?;
808                        fmt::LowerHex::fmt(&dis, out)?;
809                        out.write_str("]")?;
810                    }
811                }
812            }
813            b'N' => {
814                let ns = parse!(self, namespace);
815
816                self.print_path(in_value)?;
817
818                // HACK(eddyb) if the parser is already marked as having errored,
819                // `parse!` below will print a `?` without its preceding `::`
820                // (because printing the `::` is skipped in certain conditions,
821                // i.e. a lowercase namespace with an empty identifier),
822                // so in order to get `::?`, the `::` has to be printed here.
823                if self.parser.is_err() {
824                    self.print("::")?;
825                }
826
827                let dis = parse!(self, disambiguator);
828                let name = parse!(self, ident);
829
830                match ns {
831                    // Special namespaces, like closures and shims.
832                    Some(ns) => {
833                        self.print("::{")?;
834                        match ns {
835                            'C' => self.print("closure")?,
836                            'S' => self.print("shim")?,
837                            _ => self.print(ns)?,
838                        }
839                        if !name.ascii.is_empty() || !name.punycode.is_empty() {
840                            self.print(":")?;
841                            self.print(name)?;
842                        }
843                        self.print("#")?;
844                        self.print(dis)?;
845                        self.print("}")?;
846                    }
847
848                    // Implementation-specific/unspecified namespaces.
849                    None => {
850                        if !name.ascii.is_empty() || !name.punycode.is_empty() {
851                            self.print("::")?;
852                            self.print(name)?;
853                        }
854                    }
855                }
856            }
857            b'M' | b'X' | b'Y' => {
858                if tag != b'Y' {
859                    // Ignore the `impl`'s own path.
860                    parse!(self, disambiguator);
861                    self.skipping_printing(|this| this.print_path(false));
862                }
863
864                self.print("<")?;
865                self.print_type()?;
866                if tag != b'M' {
867                    self.print(" as ")?;
868                    self.print_path(false)?;
869                }
870                self.print(">")?;
871            }
872            b'I' => {
873                self.print_path(in_value)?;
874                if in_value {
875                    self.print("::")?;
876                }
877                self.print("<")?;
878                self.print_sep_list(Self::print_generic_arg, ", ")?;
879                self.print(">")?;
880            }
881            b'B' => {
882                self.print_backref(|this| this.print_path(in_value))?;
883            }
884            _ => invalid!(self),
885        }
886
887        self.pop_depth();
888        Ok(())
889    }
890
891    fn print_generic_arg(&mut self) -> fmt::Result {
892        if self.eat(b'L') {
893            let lt = parse!(self, integer_62);
894            self.print_lifetime_from_index(lt)
895        } else if self.eat(b'K') {
896            self.print_const(false)
897        } else {
898            self.print_type()
899        }
900    }
901
902    fn print_type(&mut self) -> fmt::Result {
903        // The splat feature is unstable and its mangling is subject to change
904        // FIXME(splat):
905        // - for efficiency we might want to use a letter that can't occur in any type, rather than
906        //   taking an unused letter
907        // - splat isn't implemented for legacy mangling
908        if self.eat(b'w') {
909            self.print("#[splat] ")?;
910        }
911        let tag = parse!(self, next);
912
913        if let Some(ty) = basic_type(tag) {
914            return self.print(ty);
915        }
916
917        parse!(self, push_depth);
918
919        match tag {
920            b'R' | b'Q' => {
921                self.print("&")?;
922                if self.eat(b'L') {
923                    let lt = parse!(self, integer_62);
924                    if lt != 0 {
925                        self.print_lifetime_from_index(lt)?;
926                        self.print(" ")?;
927                    }
928                }
929                if tag != b'R' {
930                    self.print("mut ")?;
931                }
932                self.print_type()?;
933            }
934
935            b'P' | b'O' => {
936                self.print("*")?;
937                if tag != b'P' {
938                    self.print("mut ")?;
939                } else {
940                    self.print("const ")?;
941                }
942                self.print_type()?;
943            }
944
945            b'A' | b'S' => {
946                self.print("[")?;
947                self.print_type()?;
948                if tag == b'A' {
949                    self.print("; ")?;
950                    self.print_const(true)?;
951                }
952                self.print("]")?;
953            }
954            b'T' => {
955                self.print("(")?;
956                let count = self.print_sep_list(Self::print_type, ", ")?;
957                if count == 1 {
958                    self.print(",")?;
959                }
960                self.print(")")?;
961            }
962            b'F' => self.in_binder(|this| {
963                let is_unsafe = this.eat(b'U');
964                let abi = if this.eat(b'K') {
965                    if this.eat(b'C') {
966                        Some("C")
967                    } else {
968                        let abi = parse!(this, ident);
969                        if abi.ascii.is_empty() || !abi.punycode.is_empty() {
970                            invalid!(this);
971                        }
972                        Some(abi.ascii)
973                    }
974                } else {
975                    None
976                };
977
978                if is_unsafe {
979                    this.print("unsafe ")?;
980                }
981
982                if let Some(abi) = abi {
983                    this.print("extern \"")?;
984
985                    // If the ABI had any `-`, they were replaced with `_`,
986                    // so the parts between `_` have to be re-joined with `-`.
987                    let mut parts = abi.split('_');
988                    this.print(parts.next().unwrap())?;
989                    for part in parts {
990                        this.print("-")?;
991                        this.print(part)?;
992                    }
993
994                    this.print("\" ")?;
995                }
996
997                this.print("fn(")?;
998                this.print_sep_list(Self::print_type, ", ")?;
999                this.print(")")?;
1000
1001                if this.eat(b'u') {
1002                    // Skip printing the return type if it's 'u', i.e. `()`.
1003                } else {
1004                    this.print(" -> ")?;
1005                    this.print_type()?;
1006                }
1007
1008                Ok(())
1009            })?,
1010            b'D' => {
1011                self.print("dyn ")?;
1012                self.in_binder(|this| {
1013                    this.print_sep_list(Self::print_dyn_trait, " + ")?;
1014                    Ok(())
1015                })?;
1016
1017                if !self.eat(b'L') {
1018                    invalid!(self);
1019                }
1020                let lt = parse!(self, integer_62);
1021                if lt != 0 {
1022                    self.print(" + ")?;
1023                    self.print_lifetime_from_index(lt)?;
1024                }
1025            }
1026            b'B' => {
1027                self.print_backref(Self::print_type)?;
1028            }
1029            b'W' => {
1030                self.print_type()?;
1031                self.print(" is ")?;
1032                self.print_pat()?;
1033            }
1034            _ => {
1035                // Go back to the tag, so `print_path` also sees it.
1036                let _ = self.parser.as_mut().map(|p| p.next -= 1);
1037                self.print_path(false)?;
1038            }
1039        }
1040
1041        self.pop_depth();
1042        Ok(())
1043    }
1044
1045    /// A trait in a trait object may have some "existential projections"
1046    /// (i.e. associated type bindings) after it, which should be printed
1047    /// in the `<...>` of the trait, e.g. `dyn Trait<T, U, Assoc=X>`.
1048    /// To this end, this method will keep the `<...>` of an 'I' path
1049    /// open, by omitting the `>`, and return `Ok(true)` in that case.
1050    fn print_path_maybe_open_generics(&mut self) -> Result<bool, fmt::Error> {
1051        if self.eat(b'B') {
1052            // NOTE(eddyb) the closure may not run if printing is being skipped,
1053            // but in that case the returned boolean doesn't matter.
1054            let mut open = false;
1055            self.print_backref(|this| {
1056                open = this.print_path_maybe_open_generics()?;
1057                Ok(())
1058            })?;
1059            Ok(open)
1060        } else if self.eat(b'I') {
1061            self.print_path(false)?;
1062            self.print("<")?;
1063            self.print_sep_list(Self::print_generic_arg, ", ")?;
1064            Ok(true)
1065        } else {
1066            self.print_path(false)?;
1067            Ok(false)
1068        }
1069    }
1070
1071    fn print_dyn_trait(&mut self) -> fmt::Result {
1072        let mut open = self.print_path_maybe_open_generics()?;
1073
1074        while self.eat(b'p') {
1075            if !open {
1076                self.print("<")?;
1077                open = true;
1078            } else {
1079                self.print(", ")?;
1080            }
1081
1082            let name = parse!(self, ident);
1083            self.print(name)?;
1084            self.print(" = ")?;
1085            if self.eat(b'K') {
1086                self.print_const(false)
1087            } else {
1088                self.print_type()
1089            }?;
1090        }
1091
1092        if open {
1093            self.print(">")?;
1094        }
1095
1096        Ok(())
1097    }
1098
1099    fn print_pat(&mut self) -> fmt::Result {
1100        let tag = parse!(self, next);
1101
1102        match tag {
1103            b'R' => {
1104                self.print_const(false)?;
1105                self.print("..=")?;
1106                self.print_const(false)?;
1107            }
1108            b'O' => {
1109                parse!(self, push_depth);
1110                self.print_pat()?;
1111                while !self.eat(b'E') {
1112                    // May have reached the end of the string,
1113                    // avoid going into an endless loop.
1114                    if self.parser.is_err() {
1115                        invalid!(self)
1116                    }
1117                    self.print(" | ")?;
1118                    self.print_pat()?;
1119                }
1120                self.pop_depth();
1121            }
1122            b'N' => self.print("!null")?,
1123            _ => invalid!(self),
1124        }
1125
1126        Ok(())
1127    }
1128
1129    fn print_const(&mut self, in_value: bool) -> fmt::Result {
1130        let tag = parse!(self, next);
1131
1132        parse!(self, push_depth);
1133
1134        // Only literals (and the names of `const` generic parameters, but they
1135        // don't get mangled at all), can appear in generic argument position
1136        // without any disambiguation, all other expressions require braces.
1137        // To avoid duplicating the mapping between `tag` and what syntax gets
1138        // used (especially any special-casing), every case that needs braces
1139        // has to call `open_brace(self)?` (and the closing brace is automatic).
1140        let mut opened_brace = false;
1141        let mut open_brace_if_outside_expr = |this: &mut Self| {
1142            // If this expression is nested in another, braces aren't required.
1143            if in_value {
1144                return Ok(());
1145            }
1146
1147            opened_brace = true;
1148            this.print("{")
1149        };
1150
1151        match tag {
1152            b'p' => self.print("_")?,
1153
1154            // Primitive leaves with hex-encoded values (see `basic_type`).
1155            b'h' | b't' | b'm' | b'y' | b'o' | b'j' => self.print_const_uint(tag)?,
1156            b'a' | b's' | b'l' | b'x' | b'n' | b'i' => {
1157                if self.eat(b'n') {
1158                    self.print("-")?;
1159                }
1160
1161                self.print_const_uint(tag)?;
1162            }
1163            b'b' => match parse!(self, hex_nibbles).try_parse_uint() {
1164                Some(0) => self.print("false")?,
1165                Some(1) => self.print("true")?,
1166                _ => invalid!(self),
1167            },
1168            b'c' => {
1169                let valid_char = parse!(self, hex_nibbles)
1170                    .try_parse_uint()
1171                    .and_then(|v| u32::try_from(v).ok())
1172                    .and_then(char::from_u32);
1173                match valid_char {
1174                    Some(c) => self.print_quoted_escaped_chars('\'', iter::once(c))?,
1175                    None => invalid!(self),
1176                }
1177            }
1178            b'e' => {
1179                // NOTE(eddyb) a string literal `"..."` has type `&str`, so
1180                // to get back the type `str`, `*"..."` syntax is needed
1181                // (even if that may not be valid in Rust itself).
1182                open_brace_if_outside_expr(self)?;
1183                self.print("*")?;
1184
1185                self.print_const_str_literal()?;
1186            }
1187
1188            b'R' | b'Q' => {
1189                // NOTE(eddyb) this prints `"..."` instead of `&*"..."`, which
1190                // is what `Re..._` would imply (see comment for `str` above).
1191                if tag == b'R' && self.eat(b'e') {
1192                    self.print_const_str_literal()?;
1193                } else {
1194                    open_brace_if_outside_expr(self)?;
1195                    self.print("&")?;
1196                    if tag != b'R' {
1197                        self.print("mut ")?;
1198                    }
1199                    self.print_const(true)?;
1200                }
1201            }
1202            b'A' => {
1203                open_brace_if_outside_expr(self)?;
1204                self.print("[")?;
1205                self.print_sep_list(|this| this.print_const(true), ", ")?;
1206                self.print("]")?;
1207            }
1208            b'T' => {
1209                open_brace_if_outside_expr(self)?;
1210                self.print("(")?;
1211                let count = self.print_sep_list(|this| this.print_const(true), ", ")?;
1212                if count == 1 {
1213                    self.print(",")?;
1214                }
1215                self.print(")")?;
1216            }
1217            b'V' => {
1218                open_brace_if_outside_expr(self)?;
1219                self.print_path(true)?;
1220                match parse!(self, next) {
1221                    b'U' => {}
1222                    b'T' => {
1223                        self.print("(")?;
1224                        self.print_sep_list(|this| this.print_const(true), ", ")?;
1225                        self.print(")")?;
1226                    }
1227                    b'S' => {
1228                        self.print(" { ")?;
1229                        self.print_sep_list(
1230                            |this| {
1231                                parse!(this, disambiguator);
1232                                let name = parse!(this, ident);
1233                                this.print(name)?;
1234                                this.print(": ")?;
1235                                this.print_const(true)
1236                            },
1237                            ", ",
1238                        )?;
1239                        self.print(" }")?;
1240                    }
1241                    _ => invalid!(self),
1242                }
1243            }
1244            b'B' => {
1245                self.print_backref(|this| this.print_const(in_value))?;
1246            }
1247            _ => invalid!(self),
1248        }
1249
1250        if opened_brace {
1251            self.print("}")?;
1252        }
1253
1254        self.pop_depth();
1255        Ok(())
1256    }
1257
1258    fn print_const_uint(&mut self, ty_tag: u8) -> fmt::Result {
1259        let hex = parse!(self, hex_nibbles);
1260
1261        match hex.try_parse_uint() {
1262            Some(v) => self.print(v)?,
1263
1264            // Print anything that doesn't fit in `u64` verbatim.
1265            None => {
1266                self.print("0x")?;
1267                self.print(hex.nibbles)?;
1268            }
1269        }
1270
1271        if let Some(out) = &mut self.out {
1272            if !out.alternate() {
1273                let ty = basic_type(ty_tag).unwrap();
1274                self.print(ty)?;
1275            }
1276        }
1277
1278        Ok(())
1279    }
1280
1281    fn print_const_str_literal(&mut self) -> fmt::Result {
1282        match parse!(self, hex_nibbles).try_parse_str_chars() {
1283            Some(chars) => self.print_quoted_escaped_chars('"', chars),
1284            None => invalid!(self),
1285        }
1286    }
1287}
1288
1289#[cfg(test)]
1290mod tests {
1291    use std::prelude::v1::*;
1292
1293    macro_rules! t {
1294        ($a:expr, $b:expr) => {{
1295            assert_eq!(format!("{}", ::demangle($a)), $b);
1296        }};
1297    }
1298    macro_rules! t_nohash {
1299        ($a:expr, $b:expr) => {{
1300            assert_eq!(format!("{:#}", ::demangle($a)), $b);
1301        }};
1302    }
1303    macro_rules! t_nohash_type {
1304        ($a:expr, $b:expr) => {
1305            t_nohash!(concat!("_RMC0", $a), concat!("<", $b, ">"))
1306        };
1307    }
1308    macro_rules! t_const {
1309        ($mangled:expr, $value:expr) => {
1310            t_nohash!(
1311                concat!("_RIC0K", $mangled, "E"),
1312                concat!("::<", $value, ">")
1313            )
1314        };
1315    }
1316    macro_rules! t_const_suffixed {
1317        ($mangled:expr, $value:expr, $value_ty_suffix:expr) => {{
1318            t_const!($mangled, $value);
1319            t!(
1320                concat!("_RIC0K", $mangled, "E"),
1321                concat!("::<", $value, $value_ty_suffix, ">")
1322            );
1323        }};
1324    }
1325
1326    #[test]
1327    fn demangle_crate_with_leading_digit() {
1328        t_nohash!("_RNvC6_123foo3bar", "123foo::bar");
1329    }
1330
1331    #[test]
1332    fn demangle_crate_with_zero_disambiguator() {
1333        t!("_RC4f128", "f128");
1334        t_nohash!("_RC4f128", "f128");
1335    }
1336
1337    #[test]
1338    fn demangle_utf8_idents() {
1339        t_nohash!(
1340            "_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y",
1341            "utf8_idents::საჭმელად_გემრიელი_სადილი"
1342        );
1343    }
1344
1345    #[test]
1346    fn demangle_closure() {
1347        t_nohash!(
1348            "_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_",
1349            "cc::spawn::{closure#0}::{closure#0}"
1350        );
1351        t_nohash!(
1352            "_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_",
1353            "<core::slice::Iter<u8> as core::iter::iterator::Iterator>::rposition::<core::slice::memchr::memrchr::{closure#1}>::{closure#0}"
1354        );
1355    }
1356
1357    #[test]
1358    fn demangle_dyn_trait() {
1359        t_nohash!(
1360            "_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std",
1361            "alloc::alloc::box_free::<dyn alloc::boxed::FnBox<(), Output = ()>>"
1362        );
1363    }
1364
1365    #[test]
1366    fn demangle_dyn_trait_assoc_const_binding() {
1367        t_nohash_type!("DNtC5krate5Traitp1NKj0_EL_", "dyn krate::Trait<N = 0>");
1368    }
1369
1370    #[test]
1371    fn demangle_pat_ty() {
1372        t_nohash_type!("WmRm1_m9_", "u32 is 1..=9");
1373        t_nohash_type!("WmORm1_m2_Rm5_m6_E", "u32 is 1..=2 | 5..=6");
1374        assert!(::v0::demangle("_RMC0WmORm1_m2_Rm5_m6_").is_err());
1375    }
1376
1377    #[test]
1378    fn demangle_splat() {
1379        t_nohash!(
1380            "_RNvMNtCs5CcWRJzwAYz_4core6optionINtB2_6OptionFwTlEEuE6unwrapCsiksvdpJ6Jnj_14splat_mangling",
1381            "<core::option::Option<fn(#[splat] (i32,))>>::unwrap"
1382        );
1383        t_nohash!(
1384            "_RMNvCsiksvdpJ6Jnj_14splat_mangling4mainINtB0_4TypeFwThmEEuE",
1385            "<splat_mangling::main::Type<fn(#[splat] (u8, u32))>>"
1386        );
1387        t_nohash!(
1388            "_RMs0_NvCsiksvdpJ6Jnj_14splat_mangling4mainINtB3_4TypeFwTThmEEEuE",
1389            "<splat_mangling::main::Type<fn(#[splat] ((u8, u32),))>>"
1390        );
1391        t_nohash!(
1392            "_RMs2_NvCsiksvdpJ6Jnj_14splat_mangling4mainINtB3_4TypePFwTmaEEuE",
1393            "<splat_mangling::main::Type<*const fn(#[splat] (u32, i8))>>"
1394        );
1395        t_nohash!(
1396            "_RMs4_NvCsiksvdpJ6Jnj_14splat_mangling4mainINtB3_4TypeFwTmaEdEuE",
1397            "<splat_mangling::main::Type<fn(#[splat] (u32, i8), f64)>>"
1398        );
1399    }
1400
1401    #[test]
1402    fn demangle_const_generics_preview() {
1403        // NOTE(eddyb) this was hand-written, before rustc had working
1404        // const generics support (but the mangling format did include them).
1405        t_nohash_type!(
1406            "INtC8arrayvec8ArrayVechKj7b_E",
1407            "arrayvec::ArrayVec<u8, 123>"
1408        );
1409        t_const_suffixed!("j7b_", "123", "usize");
1410    }
1411
1412    #[test]
1413    fn demangle_min_const_generics() {
1414        t_const!("p", "_");
1415        t_const_suffixed!("hb_", "11", "u8");
1416        t_const_suffixed!("off00ff00ff00ff00ff_", "0xff00ff00ff00ff00ff", "u128");
1417        t_const_suffixed!("s98_", "152", "i16");
1418        t_const_suffixed!("anb_", "-11", "i8");
1419        t_const!("b0_", "false");
1420        t_const!("b1_", "true");
1421        t_const!("c76_", "'v'");
1422        t_const!("c22_", r#"'"'"#);
1423        t_const!("ca_", "'\\n'");
1424        t_const!("c2202_", "'∂'");
1425    }
1426
1427    #[test]
1428    fn demangle_const_str() {
1429        t_const!("e616263_", "{*\"abc\"}");
1430        t_const!("e27_", r#"{*"'"}"#);
1431        t_const!("e090a_", "{*\"\\t\\n\"}");
1432        t_const!("ee28882c3bc_", "{*\"∂ü\"}");
1433        t_const!(
1434            "ee183a1e18390e183ade1839be18394e1839ae18390e183935fe18392e18394e1839b\
1435              e183a0e18398e18394e1839ae183985fe183a1e18390e18393e18398e1839ae18398_",
1436            "{*\"საჭმელად_გემრიელი_სადილი\"}"
1437        );
1438        t_const!(
1439            "ef09f908af09fa688f09fa686f09f90ae20c2a720f09f90b6f09f9192e298\
1440              95f09f94a520c2a720f09fa7a1f09f929bf09f929af09f9299f09f929c_",
1441            "{*\"🐊🦈🦆🐮 § 🐶👒☕🔥 § 🧡💛💚💙💜\"}"
1442        );
1443    }
1444
1445    // NOTE(eddyb) this uses the same strings as `demangle_const_str` and should
1446    // be kept in sync with it - while a macro could be used to generate both
1447    // `str` and `&str` tests, from a single list of strings, this seems clearer.
1448    #[test]
1449    fn demangle_const_ref_str() {
1450        t_const!("Re616263_", "\"abc\"");
1451        t_const!("Re27_", r#""'""#);
1452        t_const!("Re090a_", "\"\\t\\n\"");
1453        t_const!("Ree28882c3bc_", "\"∂ü\"");
1454        t_const!(
1455            "Ree183a1e18390e183ade1839be18394e1839ae18390e183935fe18392e18394e1839b\
1456               e183a0e18398e18394e1839ae183985fe183a1e18390e18393e18398e1839ae18398_",
1457            "\"საჭმელად_გემრიელი_სადილი\""
1458        );
1459        t_const!(
1460            "Ref09f908af09fa688f09fa686f09f90ae20c2a720f09f90b6f09f9192e298\
1461               95f09f94a520c2a720f09fa7a1f09f929bf09f929af09f9299f09f929c_",
1462            "\"🐊🦈🦆🐮 § 🐶👒☕🔥 § 🧡💛💚💙💜\""
1463        );
1464    }
1465
1466    #[test]
1467    fn demangle_const_ref() {
1468        t_const!("Rp", "{&_}");
1469        t_const!("Rh7b_", "{&123}");
1470        t_const!("Rb0_", "{&false}");
1471        t_const!("Rc58_", "{&'X'}");
1472        t_const!("RRRh0_", "{&&&0}");
1473        t_const!("RRRe_", "{&&\"\"}");
1474        t_const!("QAE", "{&mut []}");
1475    }
1476
1477    #[test]
1478    fn demangle_const_array() {
1479        t_const!("AE", "{[]}");
1480        t_const!("Aj0_E", "{[0]}");
1481        t_const!("Ah1_h2_h3_E", "{[1, 2, 3]}");
1482        t_const!("ARe61_Re62_Re63_E", "{[\"a\", \"b\", \"c\"]}");
1483        t_const!("AAh1_h2_EAh3_h4_EE", "{[[1, 2], [3, 4]]}");
1484    }
1485
1486    #[test]
1487    fn demangle_const_tuple() {
1488        t_const!("TE", "{()}");
1489        t_const!("Tj0_E", "{(0,)}");
1490        t_const!("Th1_b0_E", "{(1, false)}");
1491        t_const!(
1492            "TRe616263_c78_RAh1_h2_h3_EE",
1493            "{(\"abc\", 'x', &[1, 2, 3])}"
1494        );
1495    }
1496
1497    #[test]
1498    fn demangle_const_adt() {
1499        t_const!(
1500            "VNvINtNtC4core6option6OptionjE4NoneU",
1501            "{core::option::Option::<usize>::None}"
1502        );
1503        t_const!(
1504            "VNvINtNtC4core6option6OptionjE4SomeTj0_E",
1505            "{core::option::Option::<usize>::Some(0)}"
1506        );
1507        t_const!(
1508            "VNtC3foo3BarS1sRe616263_2chc78_5sliceRAh1_h2_h3_EE",
1509            "{foo::Bar { s: \"abc\", ch: 'x', slice: &[1, 2, 3] }}"
1510        );
1511    }
1512
1513    #[test]
1514    fn demangle_exponential_explosion() {
1515        // NOTE(eddyb) because of the prefix added by `t_nohash_type!` is
1516        // 3 bytes long, `B2_` refers to the start of the type, not `B_`.
1517        // 6 backrefs (`B8_E` through `B3_E`) result in 2^6 = 64 copies of `_`.
1518        // Also, because the `p` (`_`) type is after all of the starts of the
1519        // backrefs, it can be replaced with any other type, independently.
1520        t_nohash_type!(
1521            concat!("TTTTTT", "p", "B8_E", "B7_E", "B6_E", "B5_E", "B4_E", "B3_E"),
1522            "((((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \
1523             ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))), \
1524             (((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \
1525             ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))))"
1526        );
1527    }
1528
1529    #[test]
1530    fn demangle_thinlto() {
1531        t_nohash!("_RC3foo.llvm.9D1C9369", "foo");
1532        t_nohash!("_RC3foo.llvm.9D1C9369@@16", "foo");
1533        t_nohash!("_RNvC9backtrace3foo.llvm.A5310EB9", "backtrace::foo");
1534    }
1535
1536    #[test]
1537    fn demangle_extra_suffix() {
1538        // From alexcrichton/rustc-demangle#27:
1539        t_nohash!(
1540            "_RNvNtNtNtNtCs92dm3009vxr_4rand4rngs7adapter9reseeding4fork23FORK_HANDLER_REGISTERED.0.0",
1541            "rand::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0"
1542        );
1543    }
1544
1545    #[test]
1546    fn demangling_limits() {
1547        // Stress tests found via fuzzing.
1548
1549        for sym in include_str!("v0-large-test-symbols/early-recursion-limit")
1550            .lines()
1551            .filter(|line| !line.is_empty() && !line.starts_with('#'))
1552        {
1553            assert_eq!(
1554                super::demangle(sym).map(|_| ()),
1555                Err(super::ParseError::RecursedTooDeep)
1556            );
1557        }
1558
1559        assert_contains!(
1560            ::demangle(
1561                "RIC20tRYIMYNRYFG05_EB5_B_B6_RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
1562        RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRB_E",
1563            )
1564            .to_string(),
1565            "{recursion limit reached}"
1566        );
1567    }
1568
1569    #[test]
1570    fn recursion_limit_leaks() {
1571        // NOTE(eddyb) this test checks that both paths and types support the
1572        // recursion limit correctly, i.e. matching `push_depth` and `pop_depth`,
1573        // and don't leak "recursion levels" and trip the limit.
1574        // The test inputs are generated on the fly, using a repeated pattern,
1575        // as hardcoding the actual strings would be too verbose.
1576        // Also, `MAX_DEPTH` can be directly used, instead of assuming its value.
1577        for &(sym_leaf, expected_leaf) in &[("p", "_"), ("Rp", "&_"), ("C1x", "x")] {
1578            let mut sym = format!("_RIC0p");
1579            let mut expected = format!("::<_");
1580            for _ in 0..(super::MAX_DEPTH * 2) {
1581                sym.push_str(sym_leaf);
1582                expected.push_str(", ");
1583                expected.push_str(expected_leaf);
1584            }
1585            sym.push('E');
1586            expected.push('>');
1587
1588            t_nohash!(&sym, expected);
1589        }
1590    }
1591
1592    #[test]
1593    fn recursion_limit_backref_free_bypass() {
1594        // NOTE(eddyb) this test checks that long symbols cannot bypass the
1595        // recursion limit by not using backrefs, and cause a stack overflow.
1596
1597        // This value was chosen to be high enough that stack overflows were
1598        // observed even with `cargo test --release`.
1599        let depth = 100_000;
1600
1601        // In order to hide the long mangling from the initial "shallow" parse,
1602        // it's nested in an identifier (crate name), preceding its use.
1603        let mut sym = format!("_RIC{}", depth);
1604        let backref_start = sym.len() - 2;
1605        for _ in 0..depth {
1606            sym.push('R');
1607        }
1608
1609        // Write a backref to just after the length of the identifier.
1610        sym.push('B');
1611        sym.push(char::from_digit((backref_start - 1) as u32, 36).unwrap());
1612        sym.push('_');
1613
1614        // Close the `I` at the start.
1615        sym.push('E');
1616
1617        assert_contains!(::demangle(&sym).to_string(), "{recursion limit reached}");
1618    }
1619}