rustc_symbol_mangling: never cache placeholders in print_const.
This commit is contained in:
@@ -534,39 +534,53 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn print_const(mut self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
|
fn print_const(mut self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
|
||||||
|
// 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) {
|
if let Some(&i) = self.consts.get(&ct) {
|
||||||
return self.print_backref(i);
|
return self.print_backref(i);
|
||||||
}
|
}
|
||||||
let start = self.out.len();
|
let start = self.out.len();
|
||||||
|
|
||||||
let mut neg = false;
|
match ct.ty.kind() {
|
||||||
let val = match ct.ty.kind() {
|
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
|
||||||
ty::Uint(_) | ty::Bool | ty::Char => {
|
self = ct.ty.print(self)?;
|
||||||
ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty)
|
|
||||||
}
|
let mut bits = ct.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| {
|
// Negative integer values are mangled using `n` as a "sign prefix".
|
||||||
let val = Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(b) as i128;
|
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 {
|
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);
|
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
|
// Only cache consts that do not refer to an enclosing
|
||||||
|
|||||||
Reference in New Issue
Block a user