1 use core::char;
2 use core::fmt;
3 use core::fmt::{Display, Write};
4
5 // Maximum recursion depth when printing symbols before we just bail out saying
6 // "this symbol is invalid"
7 const MAX_DEPTH: u32 = 1_000;
8
9 // Approximately the maximum size of the symbol that we'll print. This is
10 // approximate because it only limits calls writing to `LimitedFormatter`, but
11 // not all writes exclusively go through `LimitedFormatter`. Some writes go
12 // directly to the underlying formatter, but when that happens we always write
13 // at least a little to the `LimitedFormatter`.
14 const MAX_APPROX_SIZE: usize = 1_000_000;
15
16 /// Representation of a demangled symbol name.
17 pub struct Demangle<'a> {
18 inner: &'a str,
19 }
20
21 /// De-mangles a Rust symbol into a more readable version
22 ///
23 /// This function will take a **mangled** symbol and return a value. When printed,
24 /// the de-mangled version will be written. If the symbol does not look like
25 /// a mangled symbol, the original value will be written instead.
demangle(s: &str) -> Result<(Demangle, &str), Invalid>26 pub fn demangle(s: &str) -> Result<(Demangle, &str), Invalid> {
27 // First validate the symbol. If it doesn't look like anything we're
28 // expecting, we just print it literally. Note that we must handle non-Rust
29 // symbols because we could have any function in the backtrace.
30 let inner;
31 if s.len() > 2 && s.starts_with("_R") {
32 inner = &s[2..];
33 } else if s.len() > 1 && s.starts_with('R') {
34 // On Windows, dbghelp strips leading underscores, so we accept "R..."
35 // form too.
36 inner = &s[1..];
37 } else if s.len() > 3 && s.starts_with("__R") {
38 // On OSX, symbols are prefixed with an extra _
39 inner = &s[3..];
40 } else {
41 return Err(Invalid);
42 }
43
44 // Paths always start with uppercase characters.
45 match inner.as_bytes()[0] {
46 b'A'..=b'Z' => {}
47 _ => return Err(Invalid),
48 }
49
50 // only work with ascii text
51 if inner.bytes().any(|c| c & 0x80 != 0) {
52 return Err(Invalid);
53 }
54
55 // Verify that the symbol is indeed a valid path.
56 let mut parser = Parser {
57 sym: inner,
58 next: 0,
59 };
60 parser.skip_path()?;
61
62 // Instantiating crate (paths always start with uppercase characters).
63 if let Some(&(b'A'..=b'Z')) = parser.sym.as_bytes().get(parser.next) {
64 parser.skip_path()?;
65 }
66
67 Ok((Demangle { inner }, &parser.sym[parser.next..]))
68 }
69
70 impl<'s> Display for Demangle<'s> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 let mut remaining = MAX_APPROX_SIZE;
73 let mut printer = Printer {
74 parser: Ok(Parser {
75 sym: self.inner,
76 next: 0,
77 }),
78 out: LimitedFormatter {
79 remaining: &mut remaining,
80 inner: f,
81 },
82 bound_lifetime_depth: 0,
83 depth: 0,
84 };
85 printer.print_path(true)
86 }
87 }
88
89 #[derive(PartialEq, Eq)]
90 pub struct Invalid;
91
92 struct Ident<'s> {
93 /// ASCII part of the identifier.
94 ascii: &'s str,
95 /// Punycode insertion codes for Unicode codepoints, if any.
96 punycode: &'s str,
97 }
98
99 const SMALL_PUNYCODE_LEN: usize = 128;
100
101 impl<'s> Ident<'s> {
102 /// Attempt to decode punycode on the stack (allocation-free),
103 /// and pass the char slice to the closure, if successful.
104 /// This supports up to `SMALL_PUNYCODE_LEN` characters.
try_small_punycode_decode<F: FnOnce(&[char]) -> R, R>(&self, f: F) -> Option<R>105 fn try_small_punycode_decode<F: FnOnce(&[char]) -> R, R>(&self, f: F) -> Option<R> {
106 let mut out = ['\0'; SMALL_PUNYCODE_LEN];
107 let mut out_len = 0;
108 let r = self.punycode_decode(|i, c| {
109 // Check there's space left for another character.
110 out.get(out_len).ok_or(())?;
111
112 // Move the characters after the insert position.
113 let mut j = out_len;
114 out_len += 1;
115
116 while j > i {
117 out[j] = out[j - 1];
118 j -= 1;
119 }
120
121 // Insert the new character.
122 out[i] = c;
123
124 Ok(())
125 });
126 if r.is_ok() {
127 Some(f(&out[..out_len]))
128 } else {
129 None
130 }
131 }
132
133 /// Decode punycode as insertion positions and characters
134 /// and pass them to the closure, which can return `Err(())`
135 /// to stop the decoding process.
punycode_decode<F: FnMut(usize, char) -> Result<(), ()>>( &self, mut insert: F, ) -> Result<(), ()>136 fn punycode_decode<F: FnMut(usize, char) -> Result<(), ()>>(
137 &self,
138 mut insert: F,
139 ) -> Result<(), ()> {
140 let mut punycode_bytes = self.punycode.bytes().peekable();
141 if punycode_bytes.peek().is_none() {
142 return Err(());
143 }
144
145 let mut len = 0;
146
147 // Populate initial output from ASCII fragment.
148 for c in self.ascii.chars() {
149 insert(len, c)?;
150 len += 1;
151 }
152
153 // Punycode parameters and initial state.
154 let base = 36;
155 let t_min = 1;
156 let t_max = 26;
157 let skew = 38;
158 let mut damp = 700;
159 let mut bias = 72;
160 let mut i: usize = 0;
161 let mut n: usize = 0x80;
162
163 loop {
164 // Read one delta value.
165 let mut delta: usize = 0;
166 let mut w = 1;
167 let mut k: usize = 0;
168 loop {
169 use core::cmp::{max, min};
170
171 k += base;
172 let t = min(max(k.saturating_sub(bias), t_min), t_max);
173
174 let d = match punycode_bytes.next() {
175 Some(d @ b'a'..=b'z') => d - b'a',
176 Some(d @ b'0'..=b'9') => 26 + (d - b'0'),
177 _ => return Err(()),
178 };
179 let d = d as usize;
180 delta = delta.checked_add(d.checked_mul(w).ok_or(())?).ok_or(())?;
181 if d < t {
182 break;
183 }
184 w = w.checked_mul(base - t).ok_or(())?;
185 }
186
187 // Compute the new insert position and character.
188 len += 1;
189 i = i.checked_add(delta).ok_or(())?;
190 n = n.checked_add(i / len).ok_or(())?;
191 i %= len;
192
193 let n_u32 = n as u32;
194 let c = if n_u32 as usize == n {
195 char::from_u32(n_u32).ok_or(())?
196 } else {
197 return Err(());
198 };
199
200 // Insert the new character and increment the insert position.
201 insert(i, c)?;
202 i += 1;
203
204 // If there are no more deltas, decoding is complete.
205 if punycode_bytes.peek().is_none() {
206 return Ok(());
207 }
208
209 // Perform bias adaptation.
210 delta /= damp;
211 damp = 2;
212
213 delta += delta / len;
214 let mut k = 0;
215 while delta > ((base - t_min) * t_max) / 2 {
216 delta /= base - t_min;
217 k += base;
218 }
219 bias = k + ((base - t_min + 1) * delta) / (delta + skew);
220 }
221 }
222 }
223
224 impl<'s> Display for Ident<'s> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result225 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226 self.try_small_punycode_decode(|chars| {
227 for &c in chars {
228 c.fmt(f)?;
229 }
230 Ok(())
231 })
232 .unwrap_or_else(|| {
233 if !self.punycode.is_empty() {
234 f.write_str("punycode{")?;
235
236 // Reconstruct a standard Punycode encoding,
237 // by using `-` as the separator.
238 if !self.ascii.is_empty() {
239 f.write_str(self.ascii)?;
240 f.write_str("-")?;
241 }
242 f.write_str(self.punycode)?;
243
244 f.write_str("}")
245 } else {
246 f.write_str(self.ascii)
247 }
248 })
249 }
250 }
251
basic_type(tag: u8) -> Option<&'static str>252 fn basic_type(tag: u8) -> Option<&'static str> {
253 Some(match tag {
254 b'b' => "bool",
255 b'c' => "char",
256 b'e' => "str",
257 b'u' => "()",
258 b'a' => "i8",
259 b's' => "i16",
260 b'l' => "i32",
261 b'x' => "i64",
262 b'n' => "i128",
263 b'i' => "isize",
264 b'h' => "u8",
265 b't' => "u16",
266 b'm' => "u32",
267 b'y' => "u64",
268 b'o' => "u128",
269 b'j' => "usize",
270 b'f' => "f32",
271 b'd' => "f64",
272 b'z' => "!",
273 b'p' => "_",
274 b'v' => "...",
275
276 _ => return None,
277 })
278 }
279
280 struct Parser<'s> {
281 sym: &'s str,
282 next: usize,
283 }
284
285 impl<'s> Parser<'s> {
peek(&self) -> Option<u8>286 fn peek(&self) -> Option<u8> {
287 self.sym.as_bytes().get(self.next).cloned()
288 }
289
eat(&mut self, b: u8) -> bool290 fn eat(&mut self, b: u8) -> bool {
291 if self.peek() == Some(b) {
292 self.next += 1;
293 true
294 } else {
295 false
296 }
297 }
298
next(&mut self) -> Result<u8, Invalid>299 fn next(&mut self) -> Result<u8, Invalid> {
300 let b = self.peek().ok_or(Invalid)?;
301 self.next += 1;
302 Ok(b)
303 }
304
hex_nibbles(&mut self) -> Result<&'s str, Invalid>305 fn hex_nibbles(&mut self) -> Result<&'s str, Invalid> {
306 let start = self.next;
307 loop {
308 match self.next()? {
309 b'0'..=b'9' | b'a'..=b'f' => {}
310 b'_' => break,
311 _ => return Err(Invalid),
312 }
313 }
314 Ok(&self.sym[start..self.next - 1])
315 }
316
digit_10(&mut self) -> Result<u8, Invalid>317 fn digit_10(&mut self) -> Result<u8, Invalid> {
318 let d = match self.peek() {
319 Some(d @ b'0'..=b'9') => d - b'0',
320 _ => return Err(Invalid),
321 };
322 self.next += 1;
323 Ok(d)
324 }
325
digit_62(&mut self) -> Result<u8, Invalid>326 fn digit_62(&mut self) -> Result<u8, Invalid> {
327 let d = match self.peek() {
328 Some(d @ b'0'..=b'9') => d - b'0',
329 Some(d @ b'a'..=b'z') => 10 + (d - b'a'),
330 Some(d @ b'A'..=b'Z') => 10 + 26 + (d - b'A'),
331 _ => return Err(Invalid),
332 };
333 self.next += 1;
334 Ok(d)
335 }
336
integer_62(&mut self) -> Result<u64, Invalid>337 fn integer_62(&mut self) -> Result<u64, Invalid> {
338 if self.eat(b'_') {
339 return Ok(0);
340 }
341
342 let mut x: u64 = 0;
343 while !self.eat(b'_') {
344 let d = self.digit_62()? as u64;
345 x = x.checked_mul(62).ok_or(Invalid)?;
346 x = x.checked_add(d).ok_or(Invalid)?;
347 }
348 x.checked_add(1).ok_or(Invalid)
349 }
350
opt_integer_62(&mut self, tag: u8) -> Result<u64, Invalid>351 fn opt_integer_62(&mut self, tag: u8) -> Result<u64, Invalid> {
352 if !self.eat(tag) {
353 return Ok(0);
354 }
355 self.integer_62()?.checked_add(1).ok_or(Invalid)
356 }
357
disambiguator(&mut self) -> Result<u64, Invalid>358 fn disambiguator(&mut self) -> Result<u64, Invalid> {
359 self.opt_integer_62(b's')
360 }
361
namespace(&mut self) -> Result<Option<char>, Invalid>362 fn namespace(&mut self) -> Result<Option<char>, Invalid> {
363 match self.next()? {
364 // Special namespaces, like closures and shims.
365 ns @ b'A'..=b'Z' => Ok(Some(ns as char)),
366
367 // Implementation-specific/unspecified namespaces.
368 b'a'..=b'z' => Ok(None),
369
370 _ => Err(Invalid),
371 }
372 }
373
backref(&mut self) -> Result<Parser<'s>, Invalid>374 fn backref(&mut self) -> Result<Parser<'s>, Invalid> {
375 let s_start = self.next - 1;
376 let i = self.integer_62()?;
377 if i >= s_start as u64 {
378 return Err(Invalid);
379 }
380 Ok(Parser {
381 sym: self.sym,
382 next: i as usize,
383 })
384 }
385
ident(&mut self) -> Result<Ident<'s>, Invalid>386 fn ident(&mut self) -> Result<Ident<'s>, Invalid> {
387 let is_punycode = self.eat(b'u');
388 let mut len = self.digit_10()? as usize;
389 if len != 0 {
390 while let Ok(d) = self.digit_10() {
391 len = len.checked_mul(10).ok_or(Invalid)?;
392 len = len.checked_add(d as usize).ok_or(Invalid)?;
393 }
394 }
395
396 // Skip past the optional `_` separator.
397 self.eat(b'_');
398
399 let start = self.next;
400 self.next = self.next.checked_add(len).ok_or(Invalid)?;
401 if self.next > self.sym.len() {
402 return Err(Invalid);
403 }
404
405 let ident = &self.sym[start..self.next];
406
407 if is_punycode {
408 let ident = match ident.bytes().rposition(|b| b == b'_') {
409 Some(i) => Ident {
410 ascii: &ident[..i],
411 punycode: &ident[i + 1..],
412 },
413 None => Ident {
414 ascii: "",
415 punycode: ident,
416 },
417 };
418 if ident.punycode.is_empty() {
419 return Err(Invalid);
420 }
421 Ok(ident)
422 } else {
423 Ok(Ident {
424 ascii: ident,
425 punycode: "",
426 })
427 }
428 }
429
skip_path(&mut self) -> Result<(), Invalid>430 fn skip_path(&mut self) -> Result<(), Invalid> {
431 match self.next()? {
432 b'C' => {
433 self.disambiguator()?;
434 self.ident()?;
435 }
436 b'N' => {
437 self.namespace()?;
438 self.skip_path()?;
439 self.disambiguator()?;
440 self.ident()?;
441 }
442 b'M' => {
443 self.disambiguator()?;
444 self.skip_path()?;
445 self.skip_type()?;
446 }
447 b'X' => {
448 self.disambiguator()?;
449 self.skip_path()?;
450 self.skip_type()?;
451 self.skip_path()?;
452 }
453 b'Y' => {
454 self.skip_type()?;
455 self.skip_path()?;
456 }
457 b'I' => {
458 self.skip_path()?;
459 while !self.eat(b'E') {
460 self.skip_generic_arg()?;
461 }
462 }
463 b'B' => {
464 self.backref()?;
465 }
466 _ => return Err(Invalid),
467 }
468 Ok(())
469 }
470
skip_generic_arg(&mut self) -> Result<(), Invalid>471 fn skip_generic_arg(&mut self) -> Result<(), Invalid> {
472 if self.eat(b'L') {
473 self.integer_62()?;
474 Ok(())
475 } else if self.eat(b'K') {
476 self.skip_const()
477 } else {
478 self.skip_type()
479 }
480 }
481
skip_type(&mut self) -> Result<(), Invalid>482 fn skip_type(&mut self) -> Result<(), Invalid> {
483 match self.next()? {
484 tag if basic_type(tag).is_some() => {}
485
486 b'R' | b'Q' => {
487 if self.eat(b'L') {
488 self.integer_62()?;
489 }
490 self.skip_type()?;
491 }
492 b'P' | b'O' | b'S' => self.skip_type()?,
493 b'A' => {
494 self.skip_type()?;
495 self.skip_const()?;
496 }
497 b'T' => {
498 while !self.eat(b'E') {
499 self.skip_type()?;
500 }
501 }
502 b'F' => {
503 let _binder = self.opt_integer_62(b'G')?;
504 let _is_unsafe = self.eat(b'U');
505 if self.eat(b'K') {
506 let c_abi = self.eat(b'C');
507 if !c_abi {
508 let abi = self.ident()?;
509 if abi.ascii.is_empty() || !abi.punycode.is_empty() {
510 return Err(Invalid);
511 }
512 }
513 }
514 while !self.eat(b'E') {
515 self.skip_type()?;
516 }
517 self.skip_type()?;
518 }
519 b'D' => {
520 let _binder = self.opt_integer_62(b'G')?;
521 while !self.eat(b'E') {
522 self.skip_path()?;
523 while self.eat(b'p') {
524 self.ident()?;
525 self.skip_type()?;
526 }
527 }
528 if !self.eat(b'L') {
529 return Err(Invalid);
530 }
531 self.integer_62()?;
532 }
533 b'B' => {
534 self.backref()?;
535 }
536 _ => {
537 // Go back to the tag, so `skip_path` also sees it.
538 self.next -= 1;
539 self.skip_path()?;
540 }
541 }
542 Ok(())
543 }
544
skip_const(&mut self) -> Result<(), Invalid>545 fn skip_const(&mut self) -> Result<(), Invalid> {
546 if self.eat(b'B') {
547 self.backref()?;
548 return Ok(());
549 }
550
551 let ty_tag = self.next()?;
552
553 if ty_tag == b'p' {
554 // We don't encode the type if the value is a placeholder.
555 return Ok(());
556 }
557
558 match ty_tag {
559 // Unsigned integer types.
560 b'h' | b't' | b'm' | b'y' | b'o' | b'j' |
561 // Bool.
562 b'b' |
563 // Char.
564 b'c' => {}
565
566 // Signed integer types.
567 b'a' | b's' | b'l' | b'x' | b'n' | b'i' => {
568 // Negation on signed integers.
569 let _ = self.eat(b'n');
570 }
571
572 _ => return Err(Invalid),
573 }
574
575 self.hex_nibbles()?;
576 Ok(())
577 }
578 }
579
580 struct Printer<'a, 'b: 'a, 's> {
581 parser: Result<Parser<'s>, Invalid>,
582 out: LimitedFormatter<'a, 'b>,
583 bound_lifetime_depth: u32,
584 depth: u32,
585 }
586
587 /// Mark the parser as errored, print `?` and return early.
588 /// This allows callers to keep printing the approximate
589 /// syntax of the path/type/const, despite having errors.
590 /// E.g. `Vec<[(A, ?); ?]>` instead of `Vec<[(A, ?`.
591 macro_rules! invalid {
592 ($printer:ident) => {{
593 $printer.parser = Err(Invalid);
594 return $printer.out.write_str("?");
595 }};
596 }
597
598 /// Call a parser method (if the parser hasn't errored yet),
599 /// and mark the parser as errored if it returns `Err(Invalid)`.
600 ///
601 /// If the parser errored, before or now, prints `?`, and
602 /// returns early the current function (see `invalid!` above).
603 macro_rules! parse {
604 ($printer:ident, $method:ident $(($($arg:expr),*))*) => {
605 match $printer.parser_mut().and_then(|p| p.$method($($($arg),*)*)) {
606 Ok(x) => x,
607 Err(Invalid) => invalid!($printer),
608 }
609 };
610 }
611
612 impl<'a, 'b, 's> Printer<'a, 'b, 's> {
parser_mut<'c>(&'c mut self) -> Result<&'c mut Parser<'s>, Invalid>613 fn parser_mut<'c>(&'c mut self) -> Result<&'c mut Parser<'s>, Invalid> {
614 self.parser.as_mut().map_err(|_| Invalid)
615 }
616
617 /// Eat the given character from the parser,
618 /// returning `false` if the parser errored.
eat(&mut self, b: u8) -> bool619 fn eat(&mut self, b: u8) -> bool {
620 self.parser_mut().map(|p| p.eat(b)) == Ok(true)
621 }
622
bump_depth(&mut self) -> fmt::Result623 fn bump_depth(&mut self) -> fmt::Result {
624 self.depth += 1;
625 if self.depth > MAX_DEPTH {
626 Err(fmt::Error)
627 } else {
628 Ok(())
629 }
630 }
631
632 /// Return a nested parser for a backref.
backref_printer<'c>(&'c mut self) -> Printer<'c, 'b, 's>633 fn backref_printer<'c>(&'c mut self) -> Printer<'c, 'b, 's> {
634 Printer {
635 parser: self.parser_mut().and_then(|p| p.backref()),
636 out: LimitedFormatter {
637 remaining: self.out.remaining,
638 inner: self.out.inner,
639 },
640 bound_lifetime_depth: self.bound_lifetime_depth,
641 depth: self.depth,
642 }
643 }
644
645 /// Print the lifetime according to the previously decoded index.
646 /// An index of `0` always refers to `'_`, but starting with `1`,
647 /// indices refer to late-bound lifetimes introduced by a binder.
print_lifetime_from_index(&mut self, lt: u64) -> fmt::Result648 fn print_lifetime_from_index(&mut self, lt: u64) -> fmt::Result {
649 self.out.write_str("'")?;
650 if lt == 0 {
651 return self.out.write_str("_");
652 }
653 match (self.bound_lifetime_depth as u64).checked_sub(lt) {
654 Some(depth) => {
655 // Try to print lifetimes alphabetically first.
656 if depth < 26 {
657 let c = (b'a' + depth as u8) as char;
658 c.fmt(self.out.inner)
659 } else {
660 // Use `'_123` after running out of letters.
661 self.out.write_str("_")?;
662 depth.fmt(self.out.inner)
663 }
664 }
665 None => invalid!(self),
666 }
667 }
668
669 /// Optionally enter a binder ('G') for late-bound lifetimes,
670 /// printing e.g. `for<'a, 'b> ` before calling the closure,
671 /// 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,672 fn in_binder<F>(&mut self, f: F) -> fmt::Result
673 where
674 F: FnOnce(&mut Self) -> fmt::Result,
675 {
676 let bound_lifetimes = parse!(self, opt_integer_62(b'G'));
677
678 if bound_lifetimes > 0 {
679 self.out.write_str("for<")?;
680 for i in 0..bound_lifetimes {
681 if i > 0 {
682 self.out.write_str(", ")?;
683 }
684 self.bound_lifetime_depth += 1;
685 self.print_lifetime_from_index(1)?;
686 }
687 self.out.write_str("> ")?;
688 }
689
690 let r = f(self);
691
692 // Restore `bound_lifetime_depth` to the previous value.
693 self.bound_lifetime_depth -= bound_lifetimes as u32;
694
695 r
696 }
697
698 /// Print list elements using the given closure and separator,
699 /// until the end of the list ('E') is found, or the parser errors.
700 /// 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,701 fn print_sep_list<F>(&mut self, f: F, sep: &str) -> Result<usize, fmt::Error>
702 where
703 F: Fn(&mut Self) -> fmt::Result,
704 {
705 let mut i = 0;
706 while self.parser.is_ok() && !self.eat(b'E') {
707 if i > 0 {
708 self.out.write_str(sep)?;
709 }
710 f(self)?;
711 i += 1;
712 }
713 Ok(i)
714 }
715
print_path(&mut self, in_value: bool) -> fmt::Result716 fn print_path(&mut self, in_value: bool) -> fmt::Result {
717 self.bump_depth()?;
718 let tag = parse!(self, next);
719 match tag {
720 b'C' => {
721 let dis = parse!(self, disambiguator);
722 let name = parse!(self, ident);
723
724 name.fmt(self.out.inner)?;
725 if !self.out.inner.alternate() {
726 self.out.write_str("[")?;
727 fmt::LowerHex::fmt(&dis, self.out.inner)?;
728 self.out.write_str("]")?;
729 }
730 }
731 b'N' => {
732 let ns = parse!(self, namespace);
733
734 self.print_path(in_value)?;
735
736 let dis = parse!(self, disambiguator);
737 let name = parse!(self, ident);
738
739 match ns {
740 // Special namespaces, like closures and shims.
741 Some(ns) => {
742 self.out.write_str("::{")?;
743 match ns {
744 'C' => self.out.write_str("closure")?,
745 'S' => self.out.write_str("shim")?,
746 _ => ns.fmt(self.out.inner)?,
747 }
748 if !name.ascii.is_empty() || !name.punycode.is_empty() {
749 self.out.write_str(":")?;
750 name.fmt(self.out.inner)?;
751 }
752 self.out.write_str("#")?;
753 dis.fmt(self.out.inner)?;
754 self.out.write_str("}")?;
755 }
756
757 // Implementation-specific/unspecified namespaces.
758 None => {
759 if !name.ascii.is_empty() || !name.punycode.is_empty() {
760 self.out.write_str("::")?;
761 name.fmt(self.out.inner)?;
762 }
763 }
764 }
765 }
766 b'M' | b'X' | b'Y' => {
767 if tag != b'Y' {
768 // Ignore the `impl`'s own path.
769 parse!(self, disambiguator);
770 parse!(self, skip_path);
771 }
772
773 self.out.write_str("<")?;
774 self.print_type()?;
775 if tag != b'M' {
776 self.out.write_str(" as ")?;
777 self.print_path(false)?;
778 }
779 self.out.write_str(">")?;
780 }
781 b'I' => {
782 self.print_path(in_value)?;
783 if in_value {
784 self.out.write_str("::")?;
785 }
786 self.out.write_str("<")?;
787 self.print_sep_list(Self::print_generic_arg, ", ")?;
788 self.out.write_str(">")?;
789 }
790 b'B' => {
791 self.backref_printer().print_path(in_value)?;
792 }
793 _ => invalid!(self),
794 }
795 self.depth -= 1;
796 Ok(())
797 }
798
print_generic_arg(&mut self) -> fmt::Result799 fn print_generic_arg(&mut self) -> fmt::Result {
800 if self.eat(b'L') {
801 let lt = parse!(self, integer_62);
802 self.print_lifetime_from_index(lt)
803 } else if self.eat(b'K') {
804 self.print_const()
805 } else {
806 self.print_type()
807 }
808 }
809
print_type(&mut self) -> fmt::Result810 fn print_type(&mut self) -> fmt::Result {
811 let tag = parse!(self, next);
812
813 if let Some(ty) = basic_type(tag) {
814 return self.out.write_str(ty);
815 }
816
817 self.bump_depth()?;
818 match tag {
819 b'R' | b'Q' => {
820 self.out.write_str("&")?;
821 if self.eat(b'L') {
822 let lt = parse!(self, integer_62);
823 if lt != 0 {
824 self.print_lifetime_from_index(lt)?;
825 self.out.write_str(" ")?;
826 }
827 }
828 if tag != b'R' {
829 self.out.write_str("mut ")?;
830 }
831 self.print_type()?;
832 }
833
834 b'P' | b'O' => {
835 self.out.write_str("*")?;
836 if tag != b'P' {
837 self.out.write_str("mut ")?;
838 } else {
839 self.out.write_str("const ")?;
840 }
841 self.print_type()?;
842 }
843
844 b'A' | b'S' => {
845 self.out.write_str("[")?;
846 self.print_type()?;
847 if tag == b'A' {
848 self.out.write_str("; ")?;
849 self.print_const()?;
850 }
851 self.out.write_str("]")?;
852 }
853 b'T' => {
854 self.out.write_str("(")?;
855 let count = self.print_sep_list(Self::print_type, ", ")?;
856 if count == 1 {
857 self.out.write_str(",")?;
858 }
859 self.out.write_str(")")?;
860 }
861 b'F' => self.in_binder(|this| {
862 let is_unsafe = this.eat(b'U');
863 let abi = if this.eat(b'K') {
864 if this.eat(b'C') {
865 Some("C")
866 } else {
867 let abi = parse!(this, ident);
868 if abi.ascii.is_empty() || !abi.punycode.is_empty() {
869 invalid!(this);
870 }
871 Some(abi.ascii)
872 }
873 } else {
874 None
875 };
876
877 if is_unsafe {
878 this.out.write_str("unsafe ")?;
879 }
880
881 if let Some(abi) = abi {
882 this.out.write_str("extern \"")?;
883
884 // If the ABI had any `-`, they were replaced with `_`,
885 // so the parts between `_` have to be re-joined with `-`.
886 let mut parts = abi.split('_');
887 this.out.write_str(parts.next().unwrap())?;
888 for part in parts {
889 this.out.write_str("-")?;
890 this.out.write_str(part)?;
891 }
892
893 this.out.write_str("\" ")?;
894 }
895
896 this.out.write_str("fn(")?;
897 this.print_sep_list(Self::print_type, ", ")?;
898 this.out.write_str(")")?;
899
900 if this.eat(b'u') {
901 // Skip printing the return type if it's 'u', i.e. `()`.
902 } else {
903 this.out.write_str(" -> ")?;
904 this.print_type()?;
905 }
906
907 Ok(())
908 })?,
909 b'D' => {
910 self.out.write_str("dyn ")?;
911 self.in_binder(|this| {
912 this.print_sep_list(Self::print_dyn_trait, " + ")?;
913 Ok(())
914 })?;
915
916 if !self.eat(b'L') {
917 invalid!(self);
918 }
919 let lt = parse!(self, integer_62);
920 if lt != 0 {
921 self.out.write_str(" + ")?;
922 self.print_lifetime_from_index(lt)?;
923 }
924 }
925 b'B' => {
926 self.backref_printer().print_type()?;
927 }
928 _ => {
929 // Go back to the tag, so `print_path` also sees it.
930 let _ = self.parser_mut().map(|p| p.next -= 1);
931 self.print_path(false)?;
932 }
933 }
934 self.depth -= 1;
935 Ok(())
936 }
937
938 /// A trait in a trait object may have some "existential projections"
939 /// (i.e. associated type bindings) after it, which should be printed
940 /// in the `<...>` of the trait, e.g. `dyn Trait<T, U, Assoc=X>`.
941 /// To this end, this method will keep the `<...>` of an 'I' path
942 /// open, by omitting the `>`, and return `Ok(true)` in that case.
print_path_maybe_open_generics(&mut self) -> Result<bool, fmt::Error>943 fn print_path_maybe_open_generics(&mut self) -> Result<bool, fmt::Error> {
944 if self.eat(b'B') {
945 self.backref_printer().print_path_maybe_open_generics()
946 } else if self.eat(b'I') {
947 self.print_path(false)?;
948 self.out.write_str("<")?;
949 self.print_sep_list(Self::print_generic_arg, ", ")?;
950 Ok(true)
951 } else {
952 self.print_path(false)?;
953 Ok(false)
954 }
955 }
956
print_dyn_trait(&mut self) -> fmt::Result957 fn print_dyn_trait(&mut self) -> fmt::Result {
958 let mut open = self.print_path_maybe_open_generics()?;
959
960 while self.eat(b'p') {
961 if !open {
962 self.out.write_str("<")?;
963 open = true;
964 } else {
965 self.out.write_str(", ")?;
966 }
967
968 let name = parse!(self, ident);
969 name.fmt(self.out.inner)?;
970 self.out.write_str(" = ")?;
971 self.print_type()?;
972 }
973
974 if open {
975 self.out.write_str(">")?;
976 }
977
978 Ok(())
979 }
980
print_const(&mut self) -> fmt::Result981 fn print_const(&mut self) -> fmt::Result {
982 if self.eat(b'B') {
983 return self.backref_printer().print_const();
984 }
985
986 let ty_tag = parse!(self, next);
987
988 if ty_tag == b'p' {
989 // We don't encode the type if the value is a placeholder.
990 self.out.write_str("_")?;
991 return Ok(());
992 }
993
994 match ty_tag {
995 // Unsigned integer types.
996 b'h' | b't' | b'm' | b'y' | b'o' | b'j' => self.print_const_uint()?,
997 // Signed integer types.
998 b'a' | b's' | b'l' | b'x' | b'n' | b'i' => self.print_const_int()?,
999 // Bool.
1000 b'b' => self.print_const_bool()?,
1001 // Char.
1002 b'c' => self.print_const_char()?,
1003
1004 // This branch ought to be unreachable.
1005 _ => invalid!(self),
1006 };
1007
1008 if !self.out.inner.alternate() {
1009 self.out.write_str(": ")?;
1010 let ty = basic_type(ty_tag).unwrap();
1011 self.out.write_str(ty)?;
1012 }
1013
1014 Ok(())
1015 }
1016
print_const_uint(&mut self) -> fmt::Result1017 fn print_const_uint(&mut self) -> fmt::Result {
1018 let hex = parse!(self, hex_nibbles);
1019
1020 // Print anything that doesn't fit in `u64` verbatim.
1021 if hex.len() > 16 {
1022 self.out.write_str("0x")?;
1023 return self.out.write_str(hex);
1024 }
1025
1026 let mut v = 0;
1027 for c in hex.chars() {
1028 v = (v << 4) | (c.to_digit(16).unwrap() as u64);
1029 }
1030 v.fmt(self.out.inner)
1031 }
1032
print_const_int(&mut self) -> fmt::Result1033 fn print_const_int(&mut self) -> fmt::Result {
1034 if self.eat(b'n') {
1035 self.out.write_str("-")?;
1036 }
1037
1038 self.print_const_uint()
1039 }
1040
print_const_bool(&mut self) -> fmt::Result1041 fn print_const_bool(&mut self) -> fmt::Result {
1042 match parse!(self, hex_nibbles).as_bytes() {
1043 b"0" => self.out.write_str("false"),
1044 b"1" => self.out.write_str("true"),
1045 _ => invalid!(self),
1046 }
1047 }
1048
print_const_char(&mut self) -> fmt::Result1049 fn print_const_char(&mut self) -> fmt::Result {
1050 let hex = parse!(self, hex_nibbles);
1051
1052 // Valid `char`s fit in `u32`.
1053 if hex.len() > 8 {
1054 invalid!(self);
1055 }
1056
1057 let mut v = 0;
1058 for c in hex.chars() {
1059 v = (v << 4) | (c.to_digit(16).unwrap() as u32);
1060 }
1061 if let Some(c) = char::from_u32(v) {
1062 write!(self.out, "{:?}", c)
1063 } else {
1064 invalid!(self)
1065 }
1066 }
1067 }
1068
1069 #[cfg(test)]
1070 mod tests {
1071 macro_rules! t_nohash {
1072 ($a:expr, $b:expr) => {{
1073 assert_eq!(format!("{:#}", ::demangle($a)), $b);
1074 }};
1075 }
1076 macro_rules! t_nohash_type {
1077 ($a:expr, $b:expr) => {
1078 t_nohash!(concat!("_RMC0", $a), concat!("<", $b, ">"))
1079 };
1080 }
1081
1082 #[test]
demangle_crate_with_leading_digit()1083 fn demangle_crate_with_leading_digit() {
1084 t_nohash!("_RNvC6_123foo3bar", "123foo::bar");
1085 }
1086
1087 #[test]
demangle_utf8_idents()1088 fn demangle_utf8_idents() {
1089 t_nohash!(
1090 "_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y",
1091 "utf8_idents::საჭმელად_გემრიელი_სადილი"
1092 );
1093 }
1094
1095 #[test]
demangle_closure()1096 fn demangle_closure() {
1097 t_nohash!(
1098 "_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_",
1099 "cc::spawn::{closure#0}::{closure#0}"
1100 );
1101 t_nohash!(
1102 "_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_",
1103 "<core::slice::Iter<u8> as core::iter::iterator::Iterator>::rposition::<core::slice::memchr::memrchr::{closure#1}>::{closure#0}"
1104 );
1105 }
1106
1107 #[test]
demangle_dyn_trait()1108 fn demangle_dyn_trait() {
1109 t_nohash!(
1110 "_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std",
1111 "alloc::alloc::box_free::<dyn alloc::boxed::FnBox<(), Output = ()>>"
1112 );
1113 }
1114
1115 #[test]
demangle_const_generics()1116 fn demangle_const_generics() {
1117 // NOTE(eddyb) this was hand-written, before rustc had working
1118 // const generics support (but the mangling format did include them).
1119 t_nohash_type!(
1120 "INtC8arrayvec8ArrayVechKj7b_E",
1121 "arrayvec::ArrayVec<u8, 123>"
1122 );
1123 t_nohash!(
1124 "_RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E",
1125 "<const_generic::Unsigned<11>>"
1126 );
1127 t_nohash!(
1128 "_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E",
1129 "<const_generic::Signed<152>>"
1130 );
1131 t_nohash!(
1132 "_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E",
1133 "<const_generic::Signed<-11>>"
1134 );
1135 t_nohash!(
1136 "_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E",
1137 "<const_generic::Bool<false>>"
1138 );
1139 t_nohash!(
1140 "_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E",
1141 "<const_generic::Bool<true>>"
1142 );
1143 t_nohash!(
1144 "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E",
1145 "<const_generic::Char<'v'>>"
1146 );
1147 t_nohash!(
1148 "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKca_E",
1149 "<const_generic::Char<'\\n'>>"
1150 );
1151 t_nohash!(
1152 "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E",
1153 "<const_generic::Char<'∂'>>"
1154 );
1155 t_nohash!(
1156 "_RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO",
1157 "<const_generic::Foo<_>>::foo::FOO"
1158 );
1159 }
1160
1161 #[test]
demangle_exponential_explosion()1162 fn demangle_exponential_explosion() {
1163 // NOTE(eddyb) because of the prefix added by `t_nohash_type!` is
1164 // 3 bytes long, `B2_` refers to the start of the type, not `B_`.
1165 // 6 backrefs (`B8_E` through `B3_E`) result in 2^6 = 64 copies of `_`.
1166 // Also, because the `p` (`_`) type is after all of the starts of the
1167 // backrefs, it can be replaced with any other type, independently.
1168 t_nohash_type!(
1169 concat!("TTTTTT", "p", "B8_E", "B7_E", "B6_E", "B5_E", "B4_E", "B3_E"),
1170 "((((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \
1171 ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))), \
1172 (((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \
1173 ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))))"
1174 );
1175 }
1176
1177 #[test]
demangle_thinlto()1178 fn demangle_thinlto() {
1179 t_nohash!("_RC3foo.llvm.9D1C9369", "foo");
1180 t_nohash!("_RC3foo.llvm.9D1C9369@@16", "foo");
1181 t_nohash!("_RNvC9backtrace3foo.llvm.A5310EB9", "backtrace::foo");
1182 }
1183
1184 #[test]
demangle_extra_suffix()1185 fn demangle_extra_suffix() {
1186 // From alexcrichton/rustc-demangle#27:
1187 t_nohash!(
1188 "_RNvNtNtNtNtCs92dm3009vxr_4rand4rngs7adapter9reseeding4fork23FORK_HANDLER_REGISTERED.0.0",
1189 "rand::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0"
1190 );
1191 }
1192 }
1193
1194 struct LimitedFormatter<'a, 'b> {
1195 remaining: &'a mut usize,
1196 inner: &'a mut fmt::Formatter<'b>,
1197 }
1198
1199 impl Write for LimitedFormatter<'_, '_> {
write_str(&mut self, s: &str) -> fmt::Result1200 fn write_str(&mut self, s: &str) -> fmt::Result {
1201 match self.remaining.checked_sub(s.len()) {
1202 Some(amt) => {
1203 *self.remaining = amt;
1204 self.inner.write_str(s)
1205 }
1206 None => Err(fmt::Error),
1207 }
1208 }
1209 }
1210