Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_symbol_mangling: support structural constants and &str in v0. #87194

Merged
merged 10 commits into from
Aug 26, 2021
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3398,9 +3398,9 @@ dependencies = [

[[package]]
name = "rustc-demangle"
version = "0.1.18"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ measureme = "9.1.0"
snap = "1"
tracing = "0.1"
rustc_middle = { path = "../rustc_middle" }
rustc-demangle = "0.1.18"
rustc-demangle = "0.1.21"
rustc_attr = { path = "../rustc_attr" }
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
rustc_data_structures = { path = "../rustc_data_structures" }
Expand Down
17 changes: 12 additions & 5 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1218,13 +1218,20 @@ pub trait PrettyPrinter<'tcx>:
}
p!(")");
}
ty::Adt(def, substs) if def.variants.is_empty() => {
p!(print_value_path(def.did, substs));
ty::Adt(def, _) if def.variants.is_empty() => {
self = self.typed_value(
|mut this| {
write!(this, "unreachable()")?;
Ok(this)
},
|this| this.print_type(ty),
": ",
)?;
}
ty::Adt(def, substs) => {
let variant_id =
contents.variant.expect("destructed const of adt without variant id");
let variant_def = &def.variants[variant_id];
let variant_idx =
contents.variant.expect("destructed const of adt without variant idx");
let variant_def = &def.variants[variant_idx];
p!(print_value_path(variant_def.def_id, substs));

match variant_def.ctor_kind {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_symbol_mangling/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ doctest = false
[dependencies]
tracing = "0.1"
punycode = "0.4.0"
rustc-demangle = "0.1.18"
rustc-demangle = "0.1.21"

rustc_span = { path = "../rustc_span" }
rustc_middle = { path = "../rustc_middle" }
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_symbol_mangling/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
#![feature(never_type)]
#![feature(nll)]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
#![recursion_limit = "256"]

#[macro_use]
Expand Down
161 changes: 139 additions & 22 deletions compiler/rustc_symbol_mangling/src/v0.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use rustc_data_structures::base_n;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::print::{Print, Printer};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
Expand All @@ -11,6 +13,7 @@ use rustc_target::abi::Integer;
use rustc_target::spec::abi::Abi;

use std::fmt::Write;
use std::iter;
use std::ops::Range;

pub(super) fn mangle(
Expand Down Expand Up @@ -534,39 +537,153 @@ 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);
}

// HACK(eddyb) because `ty::Const` only supports sized values (for now),
// we can't use `deref_const` + supporting `str`, we have to specially
// handle `&str` and include both `&` ("R") and `str` ("e") prefixes.
ty::Ref(_, ty, hir::Mutability::Not) if *ty == self.tcx.types.str_ => {
self.push("R");
match ct.val {
ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => {
// NOTE(eddyb) the following comment was kept from `ty::print::pretty`:
// The `inspect` here is okay since we checked the bounds, and there are no
// relocations (we have an active `str` reference here). We don't use this
// result to affect interpreter execution.
let slice =
data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
let s = std::str::from_utf8(slice).expect("non utf8 str from miri");

self.push("e");
// FIXME(eddyb) use a specialized hex-encoding loop.
for byte in s.bytes() {
let _ = write!(self.out, "{:02x}", byte);
}
self.push("_");
}

_ => {
bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
}
}
}

ty::Ref(_, _, mutbl) => {
self.push(match mutbl {
hir::Mutability::Not => "R",
hir::Mutability::Mut => "Q",
});
self = self.tcx.deref_const(ty::ParamEnv::reveal_all().and(ct)).print(self)?;
}

ty::Array(..) | ty::Tuple(..) | ty::Adt(..) => {
let contents = self.tcx.destructure_const(ty::ParamEnv::reveal_all().and(ct));
let fields = contents.fields.iter().copied();

let print_field_list = |mut this: Self| {
for field in fields.clone() {
this = field.print(this)?;
}
this.push("E");
Ok(this)
};

match *ct.ty.kind() {
ty::Array(..) => {
self.push("A");
self = print_field_list(self)?;
}
ty::Tuple(..) => {
self.push("T");
self = print_field_list(self)?;
}
ty::Adt(def, substs) => {
let variant_idx =
contents.variant.expect("destructed const of adt without variant idx");
let variant_def = &def.variants[variant_idx];

self.push("V");
self = self.print_def_path(variant_def.def_id, substs)?;

match variant_def.ctor_kind {
CtorKind::Const => {
self.push("U");
}
CtorKind::Fn => {
self.push("T");
self = print_field_list(self)?;
}
CtorKind::Fictive => {
self.push("S");
for (field_def, field) in iter::zip(&variant_def.fields, fields) {
// HACK(eddyb) this mimics `path_append`,
// instead of simply using `field_def.ident`,
// just to be able to handle disambiguators.
let disambiguated_field =
self.tcx.def_key(field_def.did).disambiguated_data;
let field_name =
disambiguated_field.data.get_opt_name().map(|s| s.as_str());
self.push_disambiguator(
disambiguated_field.disambiguator as u64,
);
eddyb marked this conversation as resolved.
Show resolved Hide resolved
self.push_ident(&field_name.as_ref().map_or("", |s| &s[..]));

self = field.print(self)?;
}
self.push("E");
}
}
}
_ => unreachable!(),
}
}

_ => {
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
Expand Down
2 changes: 1 addition & 1 deletion library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ std_detect = { path = "../stdarch/crates/std_detect", default-features = false,

# Dependencies of the `backtrace` crate
addr2line = { version = "0.16.0", optional = true, default-features = false }
rustc-demangle = { version = "0.1.18", features = ['rustc-dep-of-std'] }
rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] }
miniz_oxide = { version = "0.4.0", optional = true, default-features = false }
[dependencies.object]
version = "0.26.1"
Expand Down
2 changes: 1 addition & 1 deletion src/test/debuginfo/function-call.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This test does not passed with gdb < 8.0. See #53497.
// min-gdb-version: 8.0
// min-gdb-version: 10.1

// compile-flags:-g

Expand Down
2 changes: 1 addition & 1 deletion src/test/debuginfo/function-names.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Function names are formatted differently in old versions of GDB
// min-gdb-version: 9.2
// min-gdb-version: 10.1

// compile-flags:-g

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:16:5
thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:21:5
stack backtrace:
0: std::panicking::begin_panic
1: issue_47429_short_backtraces::main
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/panics/issue-47429-short-backtraces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
// ignore-emscripten no panic or subprocess support
// ignore-sgx no subprocess support

// NOTE(eddyb) output differs between symbol mangling schemes
// revisions: legacy v0
// [legacy] compile-flags: -Zsymbol-mangling-version=legacy
// [v0] compile-flags: -Zsymbol-mangling-version=v0

fn main() {
panic!()
}
5 changes: 5 additions & 0 deletions src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:21:5
stack backtrace:
0: std::panicking::begin_panic::<&str>
1: issue_47429_short_backtraces::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
26 changes: 13 additions & 13 deletions src/test/ui/symbol-names/const-generics-demangling.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
// build-fail
// compile-flags: -Z symbol-mangling-version=v0
// compile-flags: -Z symbol-mangling-version=v0 --crate-name=c
#![feature(rustc_attrs)]

pub struct Unsigned<const F: u8>;

#[rustc_symbol_name]
//~^ ERROR symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
//~| ERROR demangling-alt(<const_generics_demangling::Unsigned<11>>)
//~^ ERROR symbol-name(_RMCsno73SFvQKx_1cINtB0_8UnsignedKhb_E)
//~| ERROR demangling(<c[464da6a86cb672f]::Unsigned<11u8>>)
//~| ERROR demangling-alt(<c::Unsigned<11>>)
impl Unsigned<11> {}

pub struct Signed<const F: i16>;

#[rustc_symbol_name]
//~^ ERROR symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
//~| ERROR demangling-alt(<const_generics_demangling::Signed<-152>>)
//~^ ERROR symbol-name(_RMs_Csno73SFvQKx_1cINtB2_6SignedKsn98_E)
//~| ERROR demangling(<c[464da6a86cb672f]::Signed<-152i16>>)
//~| ERROR demangling-alt(<c::Signed<-152>>)
impl Signed<-152> {}

pub struct Bool<const F: bool>;

#[rustc_symbol_name]
//~^ ERROR symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
//~| ERROR demangling-alt(<const_generics_demangling::Bool<true>>)
//~^ ERROR symbol-name(_RMs0_Csno73SFvQKx_1cINtB3_4BoolKb1_E)
//~| ERROR demangling(<c[464da6a86cb672f]::Bool<true>>)
//~| ERROR demangling-alt(<c::Bool<true>>)
impl Bool<true> {}

pub struct Char<const F: char>;

#[rustc_symbol_name]
//~^ ERROR symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
//~| ERROR demangling-alt(<const_generics_demangling::Char<'∂'>>)
//~^ ERROR symbol-name(_RMs1_Csno73SFvQKx_1cINtB3_4CharKc2202_E)
//~| ERROR demangling(<c[464da6a86cb672f]::Char<'∂'>>)
//~| ERROR demangling-alt(<c::Char<'∂'>>)
impl Char<'∂'> {}

fn main() {}
Loading