1 use core::convert::TryFrom;
2 use core::{char, fmt, iter, mem, str};
3 
4 #[allow(unused_macros)]
5 macro_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"
16 const MAX_DEPTH: u32 = 500;
17 
18 /// Representation of a demangled symbol name.
19 pub struct Demangle<'a> {
20     inner: &'a str,
21 }
22 
23 #[derive(PartialEq, Eq, Debug)]
24 pub 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.
demangle(s: &str) -> Result<(Demangle, &str), ParseError>37 pub 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 
93 impl<'s> fmt::Display for Demangle<'s> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result94     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 
108 struct 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 
115 const SMALL_PUNYCODE_LEN: usize = 128;
116 
117 impl<'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.
try_small_punycode_decode<F: FnOnce(&[char]) -> R, R>(&self, f: F) -> Option<R>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.
punycode_decode<F: FnMut(usize, char) -> Result<(), ()>>( &self, mut insert: F, ) -> Result<(), ()>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 
240 impl<'s> fmt::Display for Ident<'s> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result241     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.
269 struct HexNibbles<'s> {
270     nibbles: &'s str,
271 }
272 
273 impl<'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?
try_parse_uint(&self) -> Option<u64>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.
try_parse_str_chars(&self) -> Option<impl Iterator<Item = char> + 's>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 
basic_type(tag: u8) -> Option<&'static str>370 fn 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 
398 struct Parser<'s> {
399     sym: &'s str,
400     next: usize,
401     depth: u32,
402 }
403 
404 impl<'s> Parser<'s> {
push_depth(&mut self) -> Result<(), ParseError>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 
pop_depth(&mut self)414     fn pop_depth(&mut self) {
415         self.depth -= 1;
416     }
417 
peek(&self) -> Option<u8>418     fn peek(&self) -> Option<u8> {
419         self.sym.as_bytes().get(self.next).cloned()
420     }
421 
eat(&mut self, b: u8) -> bool422     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 
next(&mut self) -> Result<u8, ParseError>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 
hex_nibbles(&mut self) -> Result<HexNibbles<'s>, ParseError>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 
digit_10(&mut self) -> Result<u8, ParseError>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 
digit_62(&mut self) -> Result<u8, ParseError>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 
integer_62(&mut self) -> Result<u64, ParseError>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 
opt_integer_62(&mut self, tag: u8) -> Result<u64, ParseError>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 
disambiguator(&mut self) -> Result<u64, ParseError>492     fn disambiguator(&mut self) -> Result<u64, ParseError> {
493         self.opt_integer_62(b's')
494     }
495 
namespace(&mut self) -> Result<Option<char>, ParseError>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 
backref(&mut self) -> Result<Parser<'s>, ParseError>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 
ident(&mut self) -> Result<Ident<'s>, ParseError>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 
568 struct 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 
586 impl ParseError {
587     /// Snippet to print when the error is initially encountered.
message(&self) -> &str588     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.
598 macro_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, ?`
616 macro_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 
632 impl<'a, 'b, 's> Printer<'a, 'b, 's> {
633     /// Eat the given character from the parser,
634     /// returning `false` if the parser errored.
eat(&mut self, b: u8) -> bool635     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).
skipping_printing<F>(&mut self, f: F) where F: FnOnce(&mut Self) -> fmt::Result,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.
print_backref<F>(&mut self, f: F) -> fmt::Result where F: FnOnce(&mut Self) -> fmt::Result,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 
pop_depth(&mut self)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.
print(&mut self, x: impl fmt::Display) -> fmt::Result678     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.
print_quoted_escaped_chars( &mut self, quote: char, chars: impl Iterator<Item = char>, ) -> fmt::Result688     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.
print_lifetime_from_index(&mut self, lt: u64) -> fmt::Result717     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).
in_binder<F>(&mut self, f: F) -> fmt::Result where F: FnOnce(&mut Self) -> fmt::Result,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.
print_sep_list<F>(&mut self, f: F, sep: &str) -> Result<usize, fmt::Error> where F: Fn(&mut Self) -> fmt::Result,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 
print_path(&mut self, in_value: bool) -> fmt::Result795     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() {
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 
print_generic_arg(&mut self) -> fmt::Result891     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 
print_type(&mut self) -> fmt::Result902     fn print_type(&mut self) -> fmt::Result {
903         let tag = parse!(self, next);
904 
905         if let Some(ty) = basic_type(tag) {
906             return self.print(ty);
907         }
908 
909         parse!(self, push_depth);
910 
911         match tag {
912             b'R' | b'Q' => {
913                 self.print("&")?;
914                 if self.eat(b'L') {
915                     let lt = parse!(self, integer_62);
916                     if lt != 0 {
917                         self.print_lifetime_from_index(lt)?;
918                         self.print(" ")?;
919                     }
920                 }
921                 if tag != b'R' {
922                     self.print("mut ")?;
923                 }
924                 self.print_type()?;
925             }
926 
927             b'P' | b'O' => {
928                 self.print("*")?;
929                 if tag != b'P' {
930                     self.print("mut ")?;
931                 } else {
932                     self.print("const ")?;
933                 }
934                 self.print_type()?;
935             }
936 
937             b'A' | b'S' => {
938                 self.print("[")?;
939                 self.print_type()?;
940                 if tag == b'A' {
941                     self.print("; ")?;
942                     self.print_const(true)?;
943                 }
944                 self.print("]")?;
945             }
946             b'T' => {
947                 self.print("(")?;
948                 let count = self.print_sep_list(Self::print_type, ", ")?;
949                 if count == 1 {
950                     self.print(",")?;
951                 }
952                 self.print(")")?;
953             }
954             b'F' => self.in_binder(|this| {
955                 let is_unsafe = this.eat(b'U');
956                 let abi = if this.eat(b'K') {
957                     if this.eat(b'C') {
958                         Some("C")
959                     } else {
960                         let abi = parse!(this, ident);
961                         if abi.ascii.is_empty() || !abi.punycode.is_empty() {
962                             invalid!(this);
963                         }
964                         Some(abi.ascii)
965                     }
966                 } else {
967                     None
968                 };
969 
970                 if is_unsafe {
971                     this.print("unsafe ")?;
972                 }
973 
974                 if let Some(abi) = abi {
975                     this.print("extern \"")?;
976 
977                     // If the ABI had any `-`, they were replaced with `_`,
978                     // so the parts between `_` have to be re-joined with `-`.
979                     let mut parts = abi.split('_');
980                     this.print(parts.next().unwrap())?;
981                     for part in parts {
982                         this.print("-")?;
983                         this.print(part)?;
984                     }
985 
986                     this.print("\" ")?;
987                 }
988 
989                 this.print("fn(")?;
990                 this.print_sep_list(Self::print_type, ", ")?;
991                 this.print(")")?;
992 
993                 if this.eat(b'u') {
994                     // Skip printing the return type if it's 'u', i.e. `()`.
995                 } else {
996                     this.print(" -> ")?;
997                     this.print_type()?;
998                 }
999 
1000                 Ok(())
1001             })?,
1002             b'D' => {
1003                 self.print("dyn ")?;
1004                 self.in_binder(|this| {
1005                     this.print_sep_list(Self::print_dyn_trait, " + ")?;
1006                     Ok(())
1007                 })?;
1008 
1009                 if !self.eat(b'L') {
1010                     invalid!(self);
1011                 }
1012                 let lt = parse!(self, integer_62);
1013                 if lt != 0 {
1014                     self.print(" + ")?;
1015                     self.print_lifetime_from_index(lt)?;
1016                 }
1017             }
1018             b'B' => {
1019                 self.print_backref(Self::print_type)?;
1020             }
1021             _ => {
1022                 // Go back to the tag, so `print_path` also sees it.
1023                 let _ = self.parser.as_mut().map(|p| p.next -= 1);
1024                 self.print_path(false)?;
1025             }
1026         }
1027 
1028         self.pop_depth();
1029         Ok(())
1030     }
1031 
1032     /// A trait in a trait object may have some "existential projections"
1033     /// (i.e. associated type bindings) after it, which should be printed
1034     /// in the `<...>` of the trait, e.g. `dyn Trait<T, U, Assoc=X>`.
1035     /// To this end, this method will keep the `<...>` of an 'I' path
1036     /// open, by omitting the `>`, and return `Ok(true)` in that case.
print_path_maybe_open_generics(&mut self) -> Result<bool, fmt::Error>1037     fn print_path_maybe_open_generics(&mut self) -> Result<bool, fmt::Error> {
1038         if self.eat(b'B') {
1039             // NOTE(eddyb) the closure may not run if printing is being skipped,
1040             // but in that case the returned boolean doesn't matter.
1041             let mut open = false;
1042             self.print_backref(|this| {
1043                 open = this.print_path_maybe_open_generics()?;
1044                 Ok(())
1045             })?;
1046             Ok(open)
1047         } else if self.eat(b'I') {
1048             self.print_path(false)?;
1049             self.print("<")?;
1050             self.print_sep_list(Self::print_generic_arg, ", ")?;
1051             Ok(true)
1052         } else {
1053             self.print_path(false)?;
1054             Ok(false)
1055         }
1056     }
1057 
print_dyn_trait(&mut self) -> fmt::Result1058     fn print_dyn_trait(&mut self) -> fmt::Result {
1059         let mut open = self.print_path_maybe_open_generics()?;
1060 
1061         while self.eat(b'p') {
1062             if !open {
1063                 self.print("<")?;
1064                 open = true;
1065             } else {
1066                 self.print(", ")?;
1067             }
1068 
1069             let name = parse!(self, ident);
1070             self.print(name)?;
1071             self.print(" = ")?;
1072             self.print_type()?;
1073         }
1074 
1075         if open {
1076             self.print(">")?;
1077         }
1078 
1079         Ok(())
1080     }
1081 
print_const(&mut self, in_value: bool) -> fmt::Result1082     fn print_const(&mut self, in_value: bool) -> fmt::Result {
1083         let tag = parse!(self, next);
1084 
1085         parse!(self, push_depth);
1086 
1087         // Only literals (and the names of `const` generic parameters, but they
1088         // don't get mangled at all), can appear in generic argument position
1089         // without any disambiguation, all other expressions require braces.
1090         // To avoid duplicating the mapping between `tag` and what syntax gets
1091         // used (especially any special-casing), every case that needs braces
1092         // has to call `open_brace(self)?` (and the closing brace is automatic).
1093         let mut opened_brace = false;
1094         let mut open_brace_if_outside_expr = |this: &mut Self| {
1095             // If this expression is nested in another, braces aren't required.
1096             if in_value {
1097                 return Ok(());
1098             }
1099 
1100             opened_brace = true;
1101             this.print("{")
1102         };
1103 
1104         match tag {
1105             b'p' => self.print("_")?,
1106 
1107             // Primitive leaves with hex-encoded values (see `basic_type`).
1108             b'h' | b't' | b'm' | b'y' | b'o' | b'j' => self.print_const_uint(tag)?,
1109             b'a' | b's' | b'l' | b'x' | b'n' | b'i' => {
1110                 if self.eat(b'n') {
1111                     self.print("-")?;
1112                 }
1113 
1114                 self.print_const_uint(tag)?;
1115             }
1116             b'b' => match parse!(self, hex_nibbles).try_parse_uint() {
1117                 Some(0) => self.print("false")?,
1118                 Some(1) => self.print("true")?,
1119                 _ => invalid!(self),
1120             },
1121             b'c' => {
1122                 let valid_char = parse!(self, hex_nibbles)
1123                     .try_parse_uint()
1124                     .and_then(|v| u32::try_from(v).ok())
1125                     .and_then(char::from_u32);
1126                 match valid_char {
1127                     Some(c) => self.print_quoted_escaped_chars('\'', iter::once(c))?,
1128                     None => invalid!(self),
1129                 }
1130             }
1131             b'e' => {
1132                 // NOTE(eddyb) a string literal `"..."` has type `&str`, so
1133                 // to get back the type `str`, `*"..."` syntax is needed
1134                 // (even if that may not be valid in Rust itself).
1135                 open_brace_if_outside_expr(self)?;
1136                 self.print("*")?;
1137 
1138                 self.print_const_str_literal()?;
1139             }
1140 
1141             b'R' | b'Q' => {
1142                 // NOTE(eddyb) this prints `"..."` instead of `&*"..."`, which
1143                 // is what `Re..._` would imply (see comment for `str` above).
1144                 if tag == b'R' && self.eat(b'e') {
1145                     self.print_const_str_literal()?;
1146                 } else {
1147                     open_brace_if_outside_expr(self)?;
1148                     self.print("&")?;
1149                     if tag != b'R' {
1150                         self.print("mut ")?;
1151                     }
1152                     self.print_const(true)?;
1153                 }
1154             }
1155             b'A' => {
1156                 open_brace_if_outside_expr(self)?;
1157                 self.print("[")?;
1158                 self.print_sep_list(|this| this.print_const(true), ", ")?;
1159                 self.print("]")?;
1160             }
1161             b'T' => {
1162                 open_brace_if_outside_expr(self)?;
1163                 self.print("(")?;
1164                 let count = self.print_sep_list(|this| this.print_const(true), ", ")?;
1165                 if count == 1 {
1166                     self.print(",")?;
1167                 }
1168                 self.print(")")?;
1169             }
1170             b'V' => {
1171                 open_brace_if_outside_expr(self)?;
1172                 self.print_path(true)?;
1173                 match parse!(self, next) {
1174                     b'U' => {}
1175                     b'T' => {
1176                         self.print("(")?;
1177                         self.print_sep_list(|this| this.print_const(true), ", ")?;
1178                         self.print(")")?;
1179                     }
1180                     b'S' => {
1181                         self.print(" { ")?;
1182                         self.print_sep_list(
1183                             |this| {
1184                                 parse!(this, disambiguator);
1185                                 let name = parse!(this, ident);
1186                                 this.print(name)?;
1187                                 this.print(": ")?;
1188                                 this.print_const(true)
1189                             },
1190                             ", ",
1191                         )?;
1192                         self.print(" }")?;
1193                     }
1194                     _ => invalid!(self),
1195                 }
1196             }
1197             b'B' => {
1198                 self.print_backref(|this| this.print_const(in_value))?;
1199             }
1200             _ => invalid!(self),
1201         }
1202 
1203         if opened_brace {
1204             self.print("}")?;
1205         }
1206 
1207         self.pop_depth();
1208         Ok(())
1209     }
1210 
print_const_uint(&mut self, ty_tag: u8) -> fmt::Result1211     fn print_const_uint(&mut self, ty_tag: u8) -> fmt::Result {
1212         let hex = parse!(self, hex_nibbles);
1213 
1214         match hex.try_parse_uint() {
1215             Some(v) => self.print(v)?,
1216 
1217             // Print anything that doesn't fit in `u64` verbatim.
1218             None => {
1219                 self.print("0x")?;
1220                 self.print(hex.nibbles)?;
1221             }
1222         }
1223 
1224         if let Some(out) = &mut self.out {
1225             if !out.alternate() {
1226                 let ty = basic_type(ty_tag).unwrap();
1227                 self.print(ty)?;
1228             }
1229         }
1230 
1231         Ok(())
1232     }
1233 
print_const_str_literal(&mut self) -> fmt::Result1234     fn print_const_str_literal(&mut self) -> fmt::Result {
1235         match parse!(self, hex_nibbles).try_parse_str_chars() {
1236             Some(chars) => self.print_quoted_escaped_chars('"', chars),
1237             None => invalid!(self),
1238         }
1239     }
1240 }
1241 
1242 #[cfg(test)]
1243 mod tests {
1244     use std::prelude::v1::*;
1245 
1246     macro_rules! t {
1247         ($a:expr, $b:expr) => {{
1248             assert_eq!(format!("{}", ::demangle($a)), $b);
1249         }};
1250     }
1251     macro_rules! t_nohash {
1252         ($a:expr, $b:expr) => {{
1253             assert_eq!(format!("{:#}", ::demangle($a)), $b);
1254         }};
1255     }
1256     macro_rules! t_nohash_type {
1257         ($a:expr, $b:expr) => {
1258             t_nohash!(concat!("_RMC0", $a), concat!("<", $b, ">"))
1259         };
1260     }
1261     macro_rules! t_const {
1262         ($mangled:expr, $value:expr) => {
1263             t_nohash!(
1264                 concat!("_RIC0K", $mangled, "E"),
1265                 concat!("::<", $value, ">")
1266             )
1267         };
1268     }
1269     macro_rules! t_const_suffixed {
1270         ($mangled:expr, $value:expr, $value_ty_suffix:expr) => {{
1271             t_const!($mangled, $value);
1272             t!(
1273                 concat!("_RIC0K", $mangled, "E"),
1274                 concat!("[0]::<", $value, $value_ty_suffix, ">")
1275             );
1276         }};
1277     }
1278 
1279     #[test]
demangle_crate_with_leading_digit()1280     fn demangle_crate_with_leading_digit() {
1281         t_nohash!("_RNvC6_123foo3bar", "123foo::bar");
1282     }
1283 
1284     #[test]
demangle_utf8_idents()1285     fn demangle_utf8_idents() {
1286         t_nohash!(
1287             "_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y",
1288             "utf8_idents::საჭმელად_გემრიელი_სადილი"
1289         );
1290     }
1291 
1292     #[test]
demangle_closure()1293     fn demangle_closure() {
1294         t_nohash!(
1295             "_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_",
1296             "cc::spawn::{closure#0}::{closure#0}"
1297         );
1298         t_nohash!(
1299             "_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_",
1300             "<core::slice::Iter<u8> as core::iter::iterator::Iterator>::rposition::<core::slice::memchr::memrchr::{closure#1}>::{closure#0}"
1301         );
1302     }
1303 
1304     #[test]
demangle_dyn_trait()1305     fn demangle_dyn_trait() {
1306         t_nohash!(
1307             "_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std",
1308             "alloc::alloc::box_free::<dyn alloc::boxed::FnBox<(), Output = ()>>"
1309         );
1310     }
1311 
1312     #[test]
demangle_const_generics_preview()1313     fn demangle_const_generics_preview() {
1314         // NOTE(eddyb) this was hand-written, before rustc had working
1315         // const generics support (but the mangling format did include them).
1316         t_nohash_type!(
1317             "INtC8arrayvec8ArrayVechKj7b_E",
1318             "arrayvec::ArrayVec<u8, 123>"
1319         );
1320         t_const_suffixed!("j7b_", "123", "usize");
1321     }
1322 
1323     #[test]
demangle_min_const_generics()1324     fn demangle_min_const_generics() {
1325         t_const!("p", "_");
1326         t_const_suffixed!("hb_", "11", "u8");
1327         t_const_suffixed!("off00ff00ff00ff00ff_", "0xff00ff00ff00ff00ff", "u128");
1328         t_const_suffixed!("s98_", "152", "i16");
1329         t_const_suffixed!("anb_", "-11", "i8");
1330         t_const!("b0_", "false");
1331         t_const!("b1_", "true");
1332         t_const!("c76_", "'v'");
1333         t_const!("c22_", r#"'"'"#);
1334         t_const!("ca_", "'\\n'");
1335         t_const!("c2202_", "'∂'");
1336     }
1337 
1338     #[test]
demangle_const_str()1339     fn demangle_const_str() {
1340         t_const!("e616263_", "{*\"abc\"}");
1341         t_const!("e27_", r#"{*"'"}"#);
1342         t_const!("e090a_", "{*\"\\t\\n\"}");
1343         t_const!("ee28882c3bc_", "{*\"∂ü\"}");
1344         t_const!(
1345             "ee183a1e18390e183ade1839be18394e1839ae18390e183935fe18392e18394e1839b\
1346               e183a0e18398e18394e1839ae183985fe183a1e18390e18393e18398e1839ae18398_",
1347             "{*\"საჭმელად_გემრიელი_სადილი\"}"
1348         );
1349         t_const!(
1350             "ef09f908af09fa688f09fa686f09f90ae20c2a720f09f90b6f09f9192e298\
1351               95f09f94a520c2a720f09fa7a1f09f929bf09f929af09f9299f09f929c_",
1352             "{*\"�������� § ����☕�� § ����������\"}"
1353         );
1354     }
1355 
1356     // NOTE(eddyb) this uses the same strings as `demangle_const_str` and should
1357     // be kept in sync with it - while a macro could be used to generate both
1358     // `str` and `&str` tests, from a single list of strings, this seems clearer.
1359     #[test]
demangle_const_ref_str()1360     fn demangle_const_ref_str() {
1361         t_const!("Re616263_", "\"abc\"");
1362         t_const!("Re27_", r#""'""#);
1363         t_const!("Re090a_", "\"\\t\\n\"");
1364         t_const!("Ree28882c3bc_", "\"∂ü\"");
1365         t_const!(
1366             "Ree183a1e18390e183ade1839be18394e1839ae18390e183935fe18392e18394e1839b\
1367                e183a0e18398e18394e1839ae183985fe183a1e18390e18393e18398e1839ae18398_",
1368             "\"საჭმელად_გემრიელი_სადილი\""
1369         );
1370         t_const!(
1371             "Ref09f908af09fa688f09fa686f09f90ae20c2a720f09f90b6f09f9192e298\
1372                95f09f94a520c2a720f09fa7a1f09f929bf09f929af09f9299f09f929c_",
1373             "\"�������� § ����☕�� § ����������\""
1374         );
1375     }
1376 
1377     #[test]
demangle_const_ref()1378     fn demangle_const_ref() {
1379         t_const!("Rp", "{&_}");
1380         t_const!("Rh7b_", "{&123}");
1381         t_const!("Rb0_", "{&false}");
1382         t_const!("Rc58_", "{&'X'}");
1383         t_const!("RRRh0_", "{&&&0}");
1384         t_const!("RRRe_", "{&&\"\"}");
1385         t_const!("QAE", "{&mut []}");
1386     }
1387 
1388     #[test]
demangle_const_array()1389     fn demangle_const_array() {
1390         t_const!("AE", "{[]}");
1391         t_const!("Aj0_E", "{[0]}");
1392         t_const!("Ah1_h2_h3_E", "{[1, 2, 3]}");
1393         t_const!("ARe61_Re62_Re63_E", "{[\"a\", \"b\", \"c\"]}");
1394         t_const!("AAh1_h2_EAh3_h4_EE", "{[[1, 2], [3, 4]]}");
1395     }
1396 
1397     #[test]
demangle_const_tuple()1398     fn demangle_const_tuple() {
1399         t_const!("TE", "{()}");
1400         t_const!("Tj0_E", "{(0,)}");
1401         t_const!("Th1_b0_E", "{(1, false)}");
1402         t_const!(
1403             "TRe616263_c78_RAh1_h2_h3_EE",
1404             "{(\"abc\", 'x', &[1, 2, 3])}"
1405         );
1406     }
1407 
1408     #[test]
demangle_const_adt()1409     fn demangle_const_adt() {
1410         t_const!(
1411             "VNvINtNtC4core6option6OptionjE4NoneU",
1412             "{core::option::Option::<usize>::None}"
1413         );
1414         t_const!(
1415             "VNvINtNtC4core6option6OptionjE4SomeTj0_E",
1416             "{core::option::Option::<usize>::Some(0)}"
1417         );
1418         t_const!(
1419             "VNtC3foo3BarS1sRe616263_2chc78_5sliceRAh1_h2_h3_EE",
1420             "{foo::Bar { s: \"abc\", ch: 'x', slice: &[1, 2, 3] }}"
1421         );
1422     }
1423 
1424     #[test]
demangle_exponential_explosion()1425     fn demangle_exponential_explosion() {
1426         // NOTE(eddyb) because of the prefix added by `t_nohash_type!` is
1427         // 3 bytes long, `B2_` refers to the start of the type, not `B_`.
1428         // 6 backrefs (`B8_E` through `B3_E`) result in 2^6 = 64 copies of `_`.
1429         // Also, because the `p` (`_`) type is after all of the starts of the
1430         // backrefs, it can be replaced with any other type, independently.
1431         t_nohash_type!(
1432             concat!("TTTTTT", "p", "B8_E", "B7_E", "B6_E", "B5_E", "B4_E", "B3_E"),
1433             "((((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \
1434              ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))), \
1435              (((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \
1436              ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))))"
1437         );
1438     }
1439 
1440     #[test]
demangle_thinlto()1441     fn demangle_thinlto() {
1442         t_nohash!("_RC3foo.llvm.9D1C9369", "foo");
1443         t_nohash!("_RC3foo.llvm.9D1C9369@@16", "foo");
1444         t_nohash!("_RNvC9backtrace3foo.llvm.A5310EB9", "backtrace::foo");
1445     }
1446 
1447     #[test]
demangle_extra_suffix()1448     fn demangle_extra_suffix() {
1449         // From alexcrichton/rustc-demangle#27:
1450         t_nohash!(
1451             "_RNvNtNtNtNtCs92dm3009vxr_4rand4rngs7adapter9reseeding4fork23FORK_HANDLER_REGISTERED.0.0",
1452             "rand::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0"
1453         );
1454     }
1455 
1456     #[test]
demangling_limits()1457     fn demangling_limits() {
1458         // Stress tests found via fuzzing.
1459 
1460         for sym in include_str!("v0-large-test-symbols/early-recursion-limit")
1461             .lines()
1462             .filter(|line| !line.is_empty() && !line.starts_with('#'))
1463         {
1464             assert_eq!(
1465                 super::demangle(sym).map(|_| ()),
1466                 Err(super::ParseError::RecursedTooDeep)
1467             );
1468         }
1469 
1470         assert_contains!(
1471             ::demangle(
1472                 "RIC20tRYIMYNRYFG05_EB5_B_B6_RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\
1473         RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRB_E",
1474             )
1475             .to_string(),
1476             "{recursion limit reached}"
1477         );
1478     }
1479 
1480     #[test]
recursion_limit_leaks()1481     fn recursion_limit_leaks() {
1482         // NOTE(eddyb) this test checks that both paths and types support the
1483         // recursion limit correctly, i.e. matching `push_depth` and `pop_depth`,
1484         // and don't leak "recursion levels" and trip the limit.
1485         // The test inputs are generated on the fly, using a repeated pattern,
1486         // as hardcoding the actual strings would be too verbose.
1487         // Also, `MAX_DEPTH` can be directly used, instead of assuming its value.
1488         for &(sym_leaf, expected_leaf) in &[("p", "_"), ("Rp", "&_"), ("C1x", "x")] {
1489             let mut sym = format!("_RIC0p");
1490             let mut expected = format!("::<_");
1491             for _ in 0..(super::MAX_DEPTH * 2) {
1492                 sym.push_str(sym_leaf);
1493                 expected.push_str(", ");
1494                 expected.push_str(expected_leaf);
1495             }
1496             sym.push('E');
1497             expected.push('>');
1498 
1499             t_nohash!(&sym, expected);
1500         }
1501     }
1502 
1503     #[test]
recursion_limit_backref_free_bypass()1504     fn recursion_limit_backref_free_bypass() {
1505         // NOTE(eddyb) this test checks that long symbols cannot bypass the
1506         // recursion limit by not using backrefs, and cause a stack overflow.
1507 
1508         // This value was chosen to be high enough that stack overflows were
1509         // observed even with `cargo test --release`.
1510         let depth = 100_000;
1511 
1512         // In order to hide the long mangling from the initial "shallow" parse,
1513         // it's nested in an identifier (crate name), preceding its use.
1514         let mut sym = format!("_RIC{}", depth);
1515         let backref_start = sym.len() - 2;
1516         for _ in 0..depth {
1517             sym.push('R');
1518         }
1519 
1520         // Write a backref to just after the length of the identifier.
1521         sym.push('B');
1522         sym.push(char::from_digit((backref_start - 1) as u32, 36).unwrap());
1523         sym.push('_');
1524 
1525         // Close the `I` at the start.
1526         sym.push('E');
1527 
1528         assert_contains!(::demangle(&sym).to_string(), "{recursion limit reached}");
1529     }
1530 }
1531