diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c4c1ec8ce4e..aa670fc6446 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -534,39 +534,53 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> { } fn print_const(mut self, ct: &'tcx ty::Const<'tcx>) -> Result { + // We only mangle a typed value if the const can be evaluated. + let ct = ct.eval(self.tcx, ty::ParamEnv::reveal_all()); + match ct.val { + ty::ConstKind::Value(_) => {} + + // Placeholders (should be demangled as `_`). + // NOTE(eddyb) despite `Unevaluated` having a `DefId` (and therefore + // a path), even for it we still need to encode a placeholder, as + // the path could refer back to e.g. an `impl` using the constant. + ty::ConstKind::Unevaluated(_) + | ty::ConstKind::Param(_) + | ty::ConstKind::Infer(_) + | ty::ConstKind::Bound(..) + | ty::ConstKind::Placeholder(_) + | ty::ConstKind::Error(_) => { + // Never cached (single-character). + self.push("p"); + return Ok(self); + } + } + if let Some(&i) = self.consts.get(&ct) { return self.print_backref(i); } let start = self.out.len(); - let mut neg = false; - let val = match ct.ty.kind() { - ty::Uint(_) | ty::Bool | ty::Char => { - ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty) - } - ty::Int(ity) => { - ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty).and_then(|b| { - let val = Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(b) as i128; + match ct.ty.kind() { + ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => { + self = ct.ty.print(self)?; + + let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty); + + // Negative integer values are mangled using `n` as a "sign prefix". + if let ty::Int(ity) = ct.ty.kind() { + let val = + Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128; if val < 0 { - neg = true; + self.push("n"); } - Some(val.unsigned_abs()) - }) + bits = val.unsigned_abs(); + } + + let _ = write!(self.out, "{:x}_", bits); } _ => { bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty, ct); } - }; - - if let Some(bits) = val { - // We only print the type if the const can be evaluated. - self = ct.ty.print(self)?; - let _ = write!(self.out, "{}{:x}_", if neg { "n" } else { "" }, bits); - } else { - // NOTE(eddyb) despite having the path, we need to - // encode a placeholder, as the path could refer - // back to e.g. an `impl` using the constant. - self.push("p"); } // Only cache consts that do not refer to an enclosing