Skip to content

Commit ad02dc4

Browse files
committed
Auto merge of #87194 - eddyb:const-value-mangling, r=michaelwoerister,oli-obk
rustc_symbol_mangling: support structural constants and &str in v0. This PR should unblock #85530 (except for float `const` generics, which AFAIK should've never worked). (cc `@tmiasko` could the #85530 (comment) failures be retried with a quick crater "subset" run of this PR + changing the default to `v0`? Just to make sure I didn't miss anything other than the floats) The encoding is the one suggested before in e.g. #61486 (comment), tho this PR won't by itself finish #61486, before closing that we'd likely want to move to `@oli-obk's` "valtrees" (i.e. #83234 and other associated work). <hr> **EDITs**: 1. switched unit/tuple/braced-with-named-fields `<const-fields>` prefixes from `"u"`/`"T"`/`""` to `"U"`/`"T"`/`"S"` to avoid the ambiguity reported by `@tmiasko` in #87194 (comment). 2. `rustc-demangle` PR: rust-lang/rustc-demangle#55 3. RFC amendment PR: rust-lang/rfcs#3161 * also removed the grammar changes included in that PR, from this description 4. added tests (temporarily using my fork of `rustc-demangle`) <hr> r? `@michaelwoerister`
2 parents 4b9f4b2 + 24526bb commit ad02dc4

21 files changed

+609
-63
lines changed

Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -3398,9 +3398,9 @@ dependencies = [
33983398

33993399
[[package]]
34003400
name = "rustc-demangle"
3401-
version = "0.1.18"
3401+
version = "0.1.21"
34023402
source = "registry+https://github.com/rust-lang/crates.io-index"
3403-
checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
3403+
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
34043404
dependencies = [
34053405
"compiler_builtins",
34063406
"rustc-std-workspace-core",

compiler/rustc_codegen_llvm/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ measureme = "9.1.0"
1515
snap = "1"
1616
tracing = "0.1"
1717
rustc_middle = { path = "../rustc_middle" }
18-
rustc-demangle = "0.1.18"
18+
rustc-demangle = "0.1.21"
1919
rustc_attr = { path = "../rustc_attr" }
2020
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
2121
rustc_data_structures = { path = "../rustc_data_structures" }

compiler/rustc_middle/src/ty/print/pretty.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -1220,13 +1220,20 @@ pub trait PrettyPrinter<'tcx>:
12201220
}
12211221
p!(")");
12221222
}
1223-
ty::Adt(def, substs) if def.variants.is_empty() => {
1224-
p!(print_value_path(def.did, substs));
1223+
ty::Adt(def, _) if def.variants.is_empty() => {
1224+
self = self.typed_value(
1225+
|mut this| {
1226+
write!(this, "unreachable()")?;
1227+
Ok(this)
1228+
},
1229+
|this| this.print_type(ty),
1230+
": ",
1231+
)?;
12251232
}
12261233
ty::Adt(def, substs) => {
1227-
let variant_id =
1228-
contents.variant.expect("destructed const of adt without variant id");
1229-
let variant_def = &def.variants[variant_id];
1234+
let variant_idx =
1235+
contents.variant.expect("destructed const of adt without variant idx");
1236+
let variant_def = &def.variants[variant_idx];
12301237
p!(print_value_path(variant_def.def_id, substs));
12311238

12321239
match variant_def.ctor_kind {

compiler/rustc_symbol_mangling/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ doctest = false
99
[dependencies]
1010
tracing = "0.1"
1111
punycode = "0.4.0"
12-
rustc-demangle = "0.1.18"
12+
rustc-demangle = "0.1.21"
1313

1414
rustc_span = { path = "../rustc_span" }
1515
rustc_middle = { path = "../rustc_middle" }

compiler/rustc_symbol_mangling/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
#![feature(never_type)]
9292
#![feature(nll)]
9393
#![feature(in_band_lifetimes)]
94+
#![feature(iter_zip)]
9495
#![recursion_limit = "256"]
9596

9697
#[macro_use]

compiler/rustc_symbol_mangling/src/v0.rs

+139-22
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use rustc_data_structures::base_n;
22
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
33
use rustc_hir as hir;
4+
use rustc_hir::def::CtorKind;
45
use rustc_hir::def_id::{CrateNum, DefId};
56
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
7+
use rustc_middle::mir::interpret::ConstValue;
68
use rustc_middle::ty::layout::IntegerExt;
79
use rustc_middle::ty::print::{Print, Printer};
810
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
@@ -11,6 +13,7 @@ use rustc_target::abi::Integer;
1113
use rustc_target::spec::abi::Abi;
1214

1315
use std::fmt::Write;
16+
use std::iter;
1417
use std::ops::Range;
1518

1619
pub(super) fn mangle(
@@ -534,39 +537,153 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> {
534537
}
535538

536539
fn print_const(mut self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
540+
// We only mangle a typed value if the const can be evaluated.
541+
let ct = ct.eval(self.tcx, ty::ParamEnv::reveal_all());
542+
match ct.val {
543+
ty::ConstKind::Value(_) => {}
544+
545+
// Placeholders (should be demangled as `_`).
546+
// NOTE(eddyb) despite `Unevaluated` having a `DefId` (and therefore
547+
// a path), even for it we still need to encode a placeholder, as
548+
// the path could refer back to e.g. an `impl` using the constant.
549+
ty::ConstKind::Unevaluated(_)
550+
| ty::ConstKind::Param(_)
551+
| ty::ConstKind::Infer(_)
552+
| ty::ConstKind::Bound(..)
553+
| ty::ConstKind::Placeholder(_)
554+
| ty::ConstKind::Error(_) => {
555+
// Never cached (single-character).
556+
self.push("p");
557+
return Ok(self);
558+
}
559+
}
560+
537561
if let Some(&i) = self.consts.get(&ct) {
538562
return self.print_backref(i);
539563
}
540564
let start = self.out.len();
541565

542-
let mut neg = false;
543-
let val = match ct.ty.kind() {
544-
ty::Uint(_) | ty::Bool | ty::Char => {
545-
ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty)
546-
}
547-
ty::Int(ity) => {
548-
ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty).and_then(|b| {
549-
let val = Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(b) as i128;
566+
match ct.ty.kind() {
567+
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
568+
self = ct.ty.print(self)?;
569+
570+
let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty);
571+
572+
// Negative integer values are mangled using `n` as a "sign prefix".
573+
if let ty::Int(ity) = ct.ty.kind() {
574+
let val =
575+
Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
550576
if val < 0 {
551-
neg = true;
577+
self.push("n");
552578
}
553-
Some(val.unsigned_abs())
554-
})
579+
bits = val.unsigned_abs();
580+
}
581+
582+
let _ = write!(self.out, "{:x}_", bits);
555583
}
584+
585+
// HACK(eddyb) because `ty::Const` only supports sized values (for now),
586+
// we can't use `deref_const` + supporting `str`, we have to specially
587+
// handle `&str` and include both `&` ("R") and `str` ("e") prefixes.
588+
ty::Ref(_, ty, hir::Mutability::Not) if *ty == self.tcx.types.str_ => {
589+
self.push("R");
590+
match ct.val {
591+
ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => {
592+
// NOTE(eddyb) the following comment was kept from `ty::print::pretty`:
593+
// The `inspect` here is okay since we checked the bounds, and there are no
594+
// relocations (we have an active `str` reference here). We don't use this
595+
// result to affect interpreter execution.
596+
let slice =
597+
data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
598+
let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
599+
600+
self.push("e");
601+
// FIXME(eddyb) use a specialized hex-encoding loop.
602+
for byte in s.bytes() {
603+
let _ = write!(self.out, "{:02x}", byte);
604+
}
605+
self.push("_");
606+
}
607+
608+
_ => {
609+
bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
610+
}
611+
}
612+
}
613+
614+
ty::Ref(_, _, mutbl) => {
615+
self.push(match mutbl {
616+
hir::Mutability::Not => "R",
617+
hir::Mutability::Mut => "Q",
618+
});
619+
self = self.tcx.deref_const(ty::ParamEnv::reveal_all().and(ct)).print(self)?;
620+
}
621+
622+
ty::Array(..) | ty::Tuple(..) | ty::Adt(..) => {
623+
let contents = self.tcx.destructure_const(ty::ParamEnv::reveal_all().and(ct));
624+
let fields = contents.fields.iter().copied();
625+
626+
let print_field_list = |mut this: Self| {
627+
for field in fields.clone() {
628+
this = field.print(this)?;
629+
}
630+
this.push("E");
631+
Ok(this)
632+
};
633+
634+
match *ct.ty.kind() {
635+
ty::Array(..) => {
636+
self.push("A");
637+
self = print_field_list(self)?;
638+
}
639+
ty::Tuple(..) => {
640+
self.push("T");
641+
self = print_field_list(self)?;
642+
}
643+
ty::Adt(def, substs) => {
644+
let variant_idx =
645+
contents.variant.expect("destructed const of adt without variant idx");
646+
let variant_def = &def.variants[variant_idx];
647+
648+
self.push("V");
649+
self = self.print_def_path(variant_def.def_id, substs)?;
650+
651+
match variant_def.ctor_kind {
652+
CtorKind::Const => {
653+
self.push("U");
654+
}
655+
CtorKind::Fn => {
656+
self.push("T");
657+
self = print_field_list(self)?;
658+
}
659+
CtorKind::Fictive => {
660+
self.push("S");
661+
for (field_def, field) in iter::zip(&variant_def.fields, fields) {
662+
// HACK(eddyb) this mimics `path_append`,
663+
// instead of simply using `field_def.ident`,
664+
// just to be able to handle disambiguators.
665+
let disambiguated_field =
666+
self.tcx.def_key(field_def.did).disambiguated_data;
667+
let field_name =
668+
disambiguated_field.data.get_opt_name().map(|s| s.as_str());
669+
self.push_disambiguator(
670+
disambiguated_field.disambiguator as u64,
671+
);
672+
self.push_ident(&field_name.as_ref().map_or("", |s| &s[..]));
673+
674+
self = field.print(self)?;
675+
}
676+
self.push("E");
677+
}
678+
}
679+
}
680+
_ => unreachable!(),
681+
}
682+
}
683+
556684
_ => {
557685
bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty, ct);
558686
}
559-
};
560-
561-
if let Some(bits) = val {
562-
// We only print the type if the const can be evaluated.
563-
self = ct.ty.print(self)?;
564-
let _ = write!(self.out, "{}{:x}_", if neg { "n" } else { "" }, bits);
565-
} else {
566-
// NOTE(eddyb) despite having the path, we need to
567-
// encode a placeholder, as the path could refer
568-
// back to e.g. an `impl` using the constant.
569-
self.push("p");
570687
}
571688

572689
// Only cache consts that do not refer to an enclosing

library/std/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ std_detect = { path = "../stdarch/crates/std_detect", default-features = false,
2424

2525
# Dependencies of the `backtrace` crate
2626
addr2line = { version = "0.16.0", optional = true, default-features = false }
27-
rustc-demangle = { version = "0.1.18", features = ['rustc-dep-of-std'] }
27+
rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] }
2828
miniz_oxide = { version = "0.4.0", optional = true, default-features = false }
2929
[dependencies.object]
3030
version = "0.26.1"

src/test/debuginfo/function-call.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// This test does not passed with gdb < 8.0. See #53497.
2-
// min-gdb-version: 8.0
2+
// min-gdb-version: 10.1
33

44
// compile-flags:-g
55

src/test/debuginfo/function-names.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Function names are formatted differently in old versions of GDB
2-
// min-gdb-version: 9.2
2+
// min-gdb-version: 10.1
33

44
// compile-flags:-g
55

src/test/ui/panics/issue-47429-short-backtraces.run.stderr src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:16:5
1+
thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:21:5
22
stack backtrace:
33
0: std::panicking::begin_panic
44
1: issue_47429_short_backtraces::main

src/test/ui/panics/issue-47429-short-backtraces.rs

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
// ignore-emscripten no panic or subprocess support
1313
// ignore-sgx no subprocess support
1414

15+
// NOTE(eddyb) output differs between symbol mangling schemes
16+
// revisions: legacy v0
17+
// [legacy] compile-flags: -Zsymbol-mangling-version=legacy
18+
// [v0] compile-flags: -Zsymbol-mangling-version=v0
19+
1520
fn main() {
1621
panic!()
1722
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:21:5
2+
stack backtrace:
3+
0: std::panicking::begin_panic::<&str>
4+
1: issue_47429_short_backtraces::main
5+
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
11
// build-fail
2-
// compile-flags: -Z symbol-mangling-version=v0
2+
// compile-flags: -Z symbol-mangling-version=v0 --crate-name=c
33
#![feature(rustc_attrs)]
44

55
pub struct Unsigned<const F: u8>;
66

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

1313
pub struct Signed<const F: i16>;
1414

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

2121
pub struct Bool<const F: bool>;
2222

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

2929
pub struct Char<const F: char>;
3030

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

3737
fn main() {}

0 commit comments

Comments
 (0)