Share inline(never) generics across crates
This reduces code sizes and better respects programmer intent when marking inline(never). Previously such a marking was essentially ignored for generic functions, as we'd still inline them in remote crates.
This commit is contained in:
parent
39cb3386dd
commit
4a216a25d1
26 changed files with 127 additions and 52 deletions
|
@ -4137,6 +4137,7 @@ name = "rustc_monomorphize"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_abi",
|
"rustc_abi",
|
||||||
|
"rustc_attr",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_errors",
|
"rustc_errors",
|
||||||
"rustc_fluent_macro",
|
"rustc_fluent_macro",
|
||||||
|
|
|
@ -104,7 +104,10 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
||||||
|
|
||||||
let is_hidden = if is_generic {
|
let is_hidden = if is_generic {
|
||||||
// This is a monomorphization of a generic function.
|
// This is a monomorphization of a generic function.
|
||||||
if !cx.tcx.sess.opts.share_generics() {
|
if !(cx.tcx.sess.opts.share_generics()
|
||||||
|
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
||||||
|
== rustc_attr::InlineAttr::Never)
|
||||||
|
{
|
||||||
// When not sharing generics, all instances are in the same
|
// When not sharing generics, all instances are in the same
|
||||||
// crate and have hidden visibility.
|
// crate and have hidden visibility.
|
||||||
true
|
true
|
||||||
|
|
|
@ -282,7 +282,7 @@ fn exported_symbols_provider_local(
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() {
|
if tcx.local_crate_exports_generics() {
|
||||||
use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
|
use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
|
||||||
use rustc_middle::ty::InstanceKind;
|
use rustc_middle::ty::InstanceKind;
|
||||||
|
|
||||||
|
@ -310,6 +310,16 @@ fn exported_symbols_provider_local(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !tcx.sess.opts.share_generics() {
|
||||||
|
if tcx.codegen_fn_attrs(mono_item.def_id()).inline == rustc_attr::InlineAttr::Never
|
||||||
|
{
|
||||||
|
// this is OK, we explicitly allow sharing inline(never) across crates even
|
||||||
|
// without share-generics.
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match *mono_item {
|
match *mono_item {
|
||||||
MonoItem::Fn(Instance { def: InstanceKind::Item(def), args }) => {
|
MonoItem::Fn(Instance { def: InstanceKind::Item(def), args }) => {
|
||||||
if args.non_erasable_generics().next().is_some() {
|
if args.non_erasable_generics().next().is_some() {
|
||||||
|
|
|
@ -111,6 +111,13 @@ impl<'tcx> MonoItem<'tcx> {
|
||||||
return InstantiationMode::GloballyShared { may_conflict: false };
|
return InstantiationMode::GloballyShared { may_conflict: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let InlineAttr::Never = tcx.codegen_fn_attrs(instance.def_id()).inline
|
||||||
|
&& self.is_generic_fn()
|
||||||
|
{
|
||||||
|
// Upgrade inline(never) to a globally shared instance.
|
||||||
|
return InstantiationMode::GloballyShared { may_conflict: true };
|
||||||
|
}
|
||||||
|
|
||||||
// At this point we don't have explicit linkage and we're an
|
// At this point we don't have explicit linkage and we're an
|
||||||
// inlined function. If we're inlining into all CGUs then we'll
|
// inlined function. If we're inlining into all CGUs then we'll
|
||||||
// be creating a local copy per CGU.
|
// be creating a local copy per CGU.
|
||||||
|
|
|
@ -1946,8 +1946,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn local_crate_exports_generics(self) -> bool {
|
pub fn local_crate_exports_generics(self) -> bool {
|
||||||
debug_assert!(self.sess.opts.share_generics());
|
|
||||||
|
|
||||||
self.crate_types().iter().any(|crate_type| {
|
self.crate_types().iter().any(|crate_type| {
|
||||||
match crate_type {
|
match crate_type {
|
||||||
CrateType::Executable
|
CrateType::Executable
|
||||||
|
|
|
@ -190,19 +190,23 @@ impl<'tcx> Instance<'tcx> {
|
||||||
/// This method already takes into account the global `-Zshare-generics`
|
/// This method already takes into account the global `-Zshare-generics`
|
||||||
/// setting, always returning `None` if `share-generics` is off.
|
/// setting, always returning `None` if `share-generics` is off.
|
||||||
pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option<CrateNum> {
|
pub fn upstream_monomorphization(&self, tcx: TyCtxt<'tcx>) -> Option<CrateNum> {
|
||||||
// If we are not in share generics mode, we don't link to upstream
|
|
||||||
// monomorphizations but always instantiate our own internal versions
|
|
||||||
// instead.
|
|
||||||
if !tcx.sess.opts.share_generics() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is an item that is defined in the local crate, no upstream
|
// If this is an item that is defined in the local crate, no upstream
|
||||||
// crate can know about it/provide a monomorphization.
|
// crate can know about it/provide a monomorphization.
|
||||||
if self.def_id().is_local() {
|
if self.def_id().is_local() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we are not in share generics mode, we don't link to upstream
|
||||||
|
// monomorphizations but always instantiate our own internal versions
|
||||||
|
// instead.
|
||||||
|
if !tcx.sess.opts.share_generics()
|
||||||
|
// However, if the def_id is marked inline(never), then it's fine to just reuse the
|
||||||
|
// upstream monomorphization.
|
||||||
|
&& tcx.codegen_fn_attrs(self.def_id()).inline != rustc_attr::InlineAttr::Never
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
// If this a non-generic instance, it cannot be a shared monomorphization.
|
// If this a non-generic instance, it cannot be a shared monomorphization.
|
||||||
self.args.non_erasable_generics().next()?;
|
self.args.non_erasable_generics().next()?;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# tidy-alphabetical-start
|
# tidy-alphabetical-start
|
||||||
rustc_abi = { path = "../rustc_abi" }
|
rustc_abi = { path = "../rustc_abi" }
|
||||||
|
rustc_attr = { path = "../rustc_attr" }
|
||||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||||
rustc_errors = { path = "../rustc_errors" }
|
rustc_errors = { path = "../rustc_errors" }
|
||||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||||
|
|
|
@ -208,8 +208,8 @@ where
|
||||||
// available to downstream crates. This depends on whether we are in
|
// available to downstream crates. This depends on whether we are in
|
||||||
// share-generics mode and whether the current crate can even have
|
// share-generics mode and whether the current crate can even have
|
||||||
// downstream crates.
|
// downstream crates.
|
||||||
let export_generics =
|
let can_export_generics = cx.tcx.local_crate_exports_generics();
|
||||||
cx.tcx.sess.opts.share_generics() && cx.tcx.local_crate_exports_generics();
|
let always_export_generics = can_export_generics && cx.tcx.sess.opts.share_generics();
|
||||||
|
|
||||||
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
|
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
|
||||||
let cgu_name_cache = &mut UnordMap::default();
|
let cgu_name_cache = &mut UnordMap::default();
|
||||||
|
@ -249,7 +249,8 @@ where
|
||||||
cx.tcx,
|
cx.tcx,
|
||||||
&mono_item,
|
&mono_item,
|
||||||
&mut can_be_internalized,
|
&mut can_be_internalized,
|
||||||
export_generics,
|
can_export_generics,
|
||||||
|
always_export_generics,
|
||||||
);
|
);
|
||||||
if visibility == Visibility::Hidden && can_be_internalized {
|
if visibility == Visibility::Hidden && can_be_internalized {
|
||||||
internalization_candidates.insert(mono_item);
|
internalization_candidates.insert(mono_item);
|
||||||
|
@ -739,12 +740,19 @@ fn mono_item_linkage_and_visibility<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
mono_item: &MonoItem<'tcx>,
|
mono_item: &MonoItem<'tcx>,
|
||||||
can_be_internalized: &mut bool,
|
can_be_internalized: &mut bool,
|
||||||
export_generics: bool,
|
can_export_generics: bool,
|
||||||
|
always_export_generics: bool,
|
||||||
) -> (Linkage, Visibility) {
|
) -> (Linkage, Visibility) {
|
||||||
if let Some(explicit_linkage) = mono_item.explicit_linkage(tcx) {
|
if let Some(explicit_linkage) = mono_item.explicit_linkage(tcx) {
|
||||||
return (explicit_linkage, Visibility::Default);
|
return (explicit_linkage, Visibility::Default);
|
||||||
}
|
}
|
||||||
let vis = mono_item_visibility(tcx, mono_item, can_be_internalized, export_generics);
|
let vis = mono_item_visibility(
|
||||||
|
tcx,
|
||||||
|
mono_item,
|
||||||
|
can_be_internalized,
|
||||||
|
can_export_generics,
|
||||||
|
always_export_generics,
|
||||||
|
);
|
||||||
(Linkage::External, vis)
|
(Linkage::External, vis)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,7 +775,8 @@ fn mono_item_visibility<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
mono_item: &MonoItem<'tcx>,
|
mono_item: &MonoItem<'tcx>,
|
||||||
can_be_internalized: &mut bool,
|
can_be_internalized: &mut bool,
|
||||||
export_generics: bool,
|
can_export_generics: bool,
|
||||||
|
always_export_generics: bool,
|
||||||
) -> Visibility {
|
) -> Visibility {
|
||||||
let instance = match mono_item {
|
let instance = match mono_item {
|
||||||
// This is pretty complicated; see below.
|
// This is pretty complicated; see below.
|
||||||
|
@ -826,7 +835,11 @@ fn mono_item_visibility<'tcx>(
|
||||||
|
|
||||||
// Upstream `DefId` instances get different handling than local ones.
|
// Upstream `DefId` instances get different handling than local ones.
|
||||||
let Some(def_id) = def_id.as_local() else {
|
let Some(def_id) = def_id.as_local() else {
|
||||||
return if export_generics && is_generic {
|
return if is_generic
|
||||||
|
&& (always_export_generics
|
||||||
|
|| (can_export_generics
|
||||||
|
&& tcx.codegen_fn_attrs(def_id).inline == rustc_attr::InlineAttr::Never))
|
||||||
|
{
|
||||||
// If it is an upstream monomorphization and we export generics, we must make
|
// If it is an upstream monomorphization and we export generics, we must make
|
||||||
// it available to downstream crates.
|
// it available to downstream crates.
|
||||||
*can_be_internalized = false;
|
*can_be_internalized = false;
|
||||||
|
@ -837,7 +850,10 @@ fn mono_item_visibility<'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_generic {
|
if is_generic {
|
||||||
if export_generics {
|
if always_export_generics
|
||||||
|
|| (can_export_generics
|
||||||
|
&& tcx.codegen_fn_attrs(def_id).inline == rustc_attr::InlineAttr::Never)
|
||||||
|
{
|
||||||
if tcx.is_unreachable_local_definition(def_id) {
|
if tcx.is_unreachable_local_definition(def_id) {
|
||||||
// This instance cannot be used from another crate.
|
// This instance cannot be used from another crate.
|
||||||
Visibility::Hidden
|
Visibility::Hidden
|
||||||
|
|
|
@ -757,7 +757,9 @@ impl<A: Allocator> RawVecInner<A> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
// not marked inline(never) since we want optimizers to be able to observe the specifics of this
|
||||||
|
// function, see tests/codegen/vec-reserve-extend.rs.
|
||||||
|
#[cold]
|
||||||
fn finish_grow<A>(
|
fn finish_grow<A>(
|
||||||
new_layout: Layout,
|
new_layout: Layout,
|
||||||
current_memory: Option<(NonNull<u8>, Layout)>,
|
current_memory: Option<(NonNull<u8>, Layout)>,
|
||||||
|
|
|
@ -362,6 +362,7 @@
|
||||||
#![feature(strict_provenance_atomic_ptr)]
|
#![feature(strict_provenance_atomic_ptr)]
|
||||||
#![feature(sync_unsafe_cell)]
|
#![feature(sync_unsafe_cell)]
|
||||||
#![feature(ub_checks)]
|
#![feature(ub_checks)]
|
||||||
|
#![feature(used_with_arg)]
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
//
|
//
|
||||||
// Library features (alloc):
|
// Library features (alloc):
|
||||||
|
|
|
@ -27,6 +27,22 @@ use crate::sys::backtrace;
|
||||||
use crate::sys::stdio::panic_output;
|
use crate::sys::stdio::panic_output;
|
||||||
use crate::{fmt, intrinsics, process, thread};
|
use crate::{fmt, intrinsics, process, thread};
|
||||||
|
|
||||||
|
// This forces codegen of the function called by panic!() inside the std crate, rather than in
|
||||||
|
// downstream crates. Primarily this is useful for rustc's codegen tests, which rely on noticing
|
||||||
|
// complete removal of panic from generated IR. Since begin_panic is inline(never), it's only
|
||||||
|
// codegen'd once per crate-graph so this pushes that to std rather than our codegen test crates.
|
||||||
|
//
|
||||||
|
// (See https://github.com/rust-lang/rust/pull/123244 for more info on why).
|
||||||
|
//
|
||||||
|
// If this is causing problems we can also modify those codegen tests to use a crate type like
|
||||||
|
// cdylib which doesn't export "Rust" symbols to downstream linkage units.
|
||||||
|
#[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[used(compiler)]
|
||||||
|
pub static EMPTY_PANIC: fn(&'static str) -> ! =
|
||||||
|
begin_panic::<&'static str> as fn(&'static str) -> !;
|
||||||
|
|
||||||
// Binary interface to the panic runtime that the standard library depends on.
|
// Binary interface to the panic runtime that the standard library depends on.
|
||||||
//
|
//
|
||||||
// The standard library is tagged with `#![needs_panic_runtime]` (introduced in
|
// The standard library is tagged with `#![needs_panic_runtime]` (introduced in
|
||||||
|
|
|
@ -11,10 +11,21 @@ pub fn foo<T>(x: T) -> (T, u32, i8) {
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn bar<T>(x: T) -> (T, Struct) {
|
fn bar<T>(x: T) -> (T, Struct) {
|
||||||
let _ = not_exported_and_not_generic(0);
|
let _ = not_exported_and_not_generic(0);
|
||||||
|
exported_and_generic::<u32>(0);
|
||||||
(x, Struct(1))
|
(x, Struct(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub static F: fn(u32) -> u32 = exported_and_generic::<u32>;
|
||||||
|
|
||||||
// These should not contribute to the codegen items of other crates.
|
// These should not contribute to the codegen items of other crates.
|
||||||
|
|
||||||
|
// This is generic, but it's only instantiated with a u32 argument and that instantiation is present
|
||||||
|
// in the local crate (see F above).
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn exported_and_generic<T>(x: T) -> T {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
pub fn exported_but_not_generic(x: i32) -> i64 {
|
pub fn exported_but_not_generic(x: i32) -> i64 {
|
||||||
x as i64
|
x as i64
|
||||||
|
|
|
@ -86,7 +86,7 @@ pub extern "C" fn test() {
|
||||||
|
|
||||||
// A call through the Fn trait must use address space 1.
|
// A call through the Fn trait must use address space 1.
|
||||||
//
|
//
|
||||||
// CHECK: call{{.+}}addrspace(1) void @call_through_fn_trait()
|
// CHECK: call{{.+}}addrspace(1) void @call_through_fn_trait({{.*}})
|
||||||
call_through_fn_trait(&mut update_bar_value);
|
call_through_fn_trait(&mut update_bar_value);
|
||||||
|
|
||||||
// A call through a global variable must use address space 1.
|
// A call through a global variable must use address space 1.
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
// A drop([...].clone()) sequence on an Rc should be a no-op
|
// A drop([...].clone()) sequence on an Rc should be a no-op
|
||||||
// In particular, no call to __rust_dealloc should be emitted
|
// In particular, no call to __rust_dealloc should be emitted
|
||||||
#![crate_type = "lib"]
|
//
|
||||||
|
// We use a cdylib since it's a leaf unit for Rust purposes, so doesn't codegen -Zshare-generics
|
||||||
|
// code.
|
||||||
|
#![crate_type = "cdylib"]
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub fn foo(t: &Rc<Vec<usize>>) {
|
pub fn foo(t: &Rc<Vec<usize>>) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(naked_functions, asm_const, linkage)]
|
#![feature(naked_functions, linkage)]
|
||||||
#![crate_type = "dylib"]
|
#![crate_type = "dylib"]
|
||||||
|
|
||||||
use std::arch::naked_asm;
|
use std::arch::naked_asm;
|
||||||
|
@ -38,7 +38,7 @@ pub extern "C" fn public_vanilla() -> u32 {
|
||||||
|
|
||||||
#[naked]
|
#[naked]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn public_naked() -> u32 {
|
pub extern "C" fn public_naked_nongeneric() -> u32 {
|
||||||
unsafe { naked_asm!("mov rax, 42", "ret") }
|
unsafe { naked_asm!("mov rax, 42", "ret") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,12 @@ fn main() {
|
||||||
not_exported(&rdylib, "private_naked");
|
not_exported(&rdylib, "private_naked");
|
||||||
|
|
||||||
global_function(&rdylib, "public_vanilla");
|
global_function(&rdylib, "public_vanilla");
|
||||||
global_function(&rdylib, "public_naked");
|
global_function(&rdylib, "public_naked_nongeneric");
|
||||||
|
|
||||||
not_exported(&rdylib, "public_vanilla_generic");
|
not_exported(&rdylib, "public_vanilla_generic");
|
||||||
not_exported(&rdylib, "public_naked_generic");
|
// #[naked] functions are implicitly #[inline(never)], so they get shared regardless of
|
||||||
|
// -Zshare-generics.
|
||||||
|
global_function(&rdylib, "public_naked_generic");
|
||||||
|
|
||||||
global_function(&rdylib, "vanilla_external_linkage");
|
global_function(&rdylib, "vanilla_external_linkage");
|
||||||
global_function(&rdylib, "naked_external_linkage");
|
global_function(&rdylib, "naked_external_linkage");
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
//@ check-run-results
|
//@ check-run-results
|
||||||
//@ exec-env:RUST_BACKTRACE=1
|
//@ exec-env:RUST_BACKTRACE=1
|
||||||
|
|
||||||
|
// This is needed to avoid test output differences across std being built with v0 symbols vs legacy
|
||||||
|
// symbols.
|
||||||
|
//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic"
|
||||||
|
// And this is for differences between std with and without debuginfo.
|
||||||
|
//@ normalize-stderr-test: "\n +at [^\n]+" -> ""
|
||||||
|
|
||||||
//@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
|
//@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
|
||||||
//@ ignore-android FIXME #17520
|
//@ ignore-android FIXME #17520
|
||||||
//@ ignore-openbsd no support for libbacktrace without filename
|
//@ ignore-openbsd no support for libbacktrace without filename
|
||||||
|
@ -14,11 +20,6 @@
|
||||||
//@ ignore-sgx no subprocess support
|
//@ ignore-sgx no subprocess support
|
||||||
//@ ignore-fuchsia Backtraces not symbolized
|
//@ ignore-fuchsia Backtraces not symbolized
|
||||||
|
|
||||||
// NOTE(eddyb) output differs between symbol mangling schemes
|
|
||||||
//@ revisions: legacy v0
|
|
||||||
//@ [legacy] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy
|
|
||||||
//@ [v0] compile-flags: -Csymbol-mangling-version=v0
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
thread 'main' panicked at $DIR/issue-47429-short-backtraces.rs:23:5:
|
thread 'main' panicked at $DIR/issue-47429-short-backtraces.rs:24:5:
|
||||||
explicit panic
|
explicit panic
|
||||||
stack backtrace:
|
stack backtrace:
|
||||||
0: std::panicking::begin_panic
|
0: std::panicking::begin_panic
|
|
@ -1,6 +0,0 @@
|
||||||
thread 'main' panicked at $DIR/issue-47429-short-backtraces.rs:23:5:
|
|
||||||
explicit panic
|
|
||||||
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.
|
|
|
@ -6,6 +6,12 @@
|
||||||
//@ check-run-results
|
//@ check-run-results
|
||||||
//@ exec-env:RUST_BACKTRACE=0
|
//@ exec-env:RUST_BACKTRACE=0
|
||||||
|
|
||||||
|
// This is needed to avoid test output differences across std being built with v0 symbols vs legacy
|
||||||
|
// symbols.
|
||||||
|
//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic"
|
||||||
|
// And this is for differences between std with and without debuginfo.
|
||||||
|
//@ normalize-stderr-test: "\n +at [^\n]+" -> ""
|
||||||
|
|
||||||
//@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
|
//@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
|
||||||
//@ ignore-android FIXME #17520
|
//@ ignore-android FIXME #17520
|
||||||
//@ ignore-openbsd no support for libbacktrace without filename
|
//@ ignore-openbsd no support for libbacktrace without filename
|
||||||
|
@ -14,11 +20,6 @@
|
||||||
//@ ignore-sgx no subprocess support
|
//@ ignore-sgx no subprocess support
|
||||||
//@ ignore-fuchsia Backtrace not symbolized
|
//@ ignore-fuchsia Backtrace not symbolized
|
||||||
|
|
||||||
// NOTE(eddyb) output differs between symbol mangling schemes
|
|
||||||
//@ revisions: legacy v0
|
|
||||||
//@ [legacy] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy
|
|
||||||
//@ [v0] compile-flags: -Csymbol-mangling-version=v0
|
|
||||||
|
|
||||||
#![feature(panic_backtrace_config)]
|
#![feature(panic_backtrace_config)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
thread 'main' panicked at $DIR/runtime-switch.rs:26:5:
|
thread 'main' panicked at $DIR/runtime-switch.rs:27:5:
|
||||||
explicit panic
|
explicit panic
|
||||||
stack backtrace:
|
stack backtrace:
|
||||||
0: std::panicking::begin_panic
|
0: std::panicking::begin_panic
|
|
@ -1,6 +0,0 @@
|
||||||
thread 'main' panicked at $DIR/runtime-switch.rs:26:5:
|
|
||||||
explicit panic
|
|
||||||
stack backtrace:
|
|
||||||
0: std::panicking::begin_panic::<&str>
|
|
||||||
1: runtime_switch::main
|
|
||||||
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
|
|
|
@ -9,6 +9,11 @@
|
||||||
//@ ignore-sgx Backtraces not symbolized
|
//@ ignore-sgx Backtraces not symbolized
|
||||||
//@ ignore-fuchsia Backtraces not symbolized
|
//@ ignore-fuchsia Backtraces not symbolized
|
||||||
//@ ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
|
//@ ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
|
||||||
|
// This is needed to avoid test output differences across std being built with v0 symbols vs legacy
|
||||||
|
// symbols.
|
||||||
|
//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic"
|
||||||
|
// And this is for differences between std with and without debuginfo.
|
||||||
|
//@ normalize-stderr-test: "\n +at [^\n]+" -> ""
|
||||||
|
|
||||||
/// This test case make sure that we can have multiple pairs of `__rust_{begin,end}_short_backtrace`
|
/// This test case make sure that we can have multiple pairs of `__rust_{begin,end}_short_backtrace`
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:56:5:
|
thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:61:5:
|
||||||
debug!!!
|
debug!!!
|
||||||
stack backtrace:
|
stack backtrace:
|
||||||
0: std::panicking::begin_panic
|
0: std::panicking::begin_panic
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
//@ ignore-fuchsia Backtraces not symbolized
|
//@ ignore-fuchsia Backtraces not symbolized
|
||||||
//@ ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
|
//@ ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
|
||||||
|
|
||||||
|
// This is needed to avoid test output differences across std being built with v0 symbols vs legacy
|
||||||
|
// symbols.
|
||||||
|
//@ normalize-stderr-test: "begin_panic::<&str>" -> "begin_panic"
|
||||||
|
// And this is for differences between std with and without debuginfo.
|
||||||
|
//@ normalize-stderr-test: "\n +at [^\n]+" -> ""
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
|
fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:52:5:
|
thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:57:5:
|
||||||
debug!!!
|
debug!!!
|
||||||
stack backtrace:
|
stack backtrace:
|
||||||
0: std::panicking::begin_panic
|
0: std::panicking::begin_panic
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue