about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs58
1 files changed, 36 insertions, 22 deletions
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<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) {
             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