diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 21d5baced7687..05b5000522f46 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1217,13 +1217,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 { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index b444f66258a8e..6811c70de8e57 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -755,7 +755,7 @@ impl DebuggingOptions { } pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { - self.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy) + self.symbol_mangling_version.unwrap_or(SymbolManglingVersion::V0) } } diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index ba59ff96f6554..6b8da71aa3a75 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -91,6 +91,7 @@ #![feature(never_type)] #![feature(nll)] #![feature(in_band_lifetimes)] +#![feature(iter_zip)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 14442806fc0b7..499542ccc5738 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -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}; @@ -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( @@ -545,39 +548,150 @@ impl Printer<'tcx> for 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.compress.as_ref().and_then(|c| c.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"); + } + 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, prefix| { + this.push(prefix); + for field in fields.clone() { + this = field.print(this)?; } - Some(val.unsigned_abs()) - }) + this.push("E"); + Ok(this) + }; + + match *ct.ty.kind() { + ty::Array(..) => { + self = print_field_list(self, "A")?; + } + ty::Tuple(..) => { + self = print_field_list(self, "T")?; + } + 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 = print_field_list(self, "T")?; + } + CtorKind::Fictive => { + 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, + ); + 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 diff --git a/src/test/codegen/vec-shrink-panic.rs b/src/test/codegen/vec-shrink-panik.rs similarity index 100% rename from src/test/codegen/vec-shrink-panic.rs rename to src/test/codegen/vec-shrink-panik.rs diff --git a/src/test/debuginfo/function-call.rs b/src/test/debuginfo/function-call.rs index a5d5942b53953..75334558b589d 100644 --- a/src/test/debuginfo/function-call.rs +++ b/src/test/debuginfo/function-call.rs @@ -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 diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs index 20a49f0bd26eb..94982fd79fb2b 100644 --- a/src/test/debuginfo/function-names.rs +++ b/src/test/debuginfo/function-names.rs @@ -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 diff --git a/src/test/ui/panics/issue-47429-short-backtraces.run.stderr b/src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr similarity index 91% rename from src/test/ui/panics/issue-47429-short-backtraces.run.stderr rename to src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr index 3287963890706..fcdc070a4c39e 100644 --- a/src/test/ui/panics/issue-47429-short-backtraces.run.stderr +++ b/src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr @@ -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 diff --git a/src/test/ui/panics/issue-47429-short-backtraces.rs b/src/test/ui/panics/issue-47429-short-backtraces.rs index 015ab8fdd80df..35ecfc0b27158 100644 --- a/src/test/ui/panics/issue-47429-short-backtraces.rs +++ b/src/test/ui/panics/issue-47429-short-backtraces.rs @@ -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!() } diff --git a/src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr b/src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr new file mode 100644 index 0000000000000..1cbf11739bfc6 --- /dev/null +++ b/src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr @@ -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.