From b2476c9561f502421f967171b787075dd444e81d Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 22 Mar 2023 21:56:09 +0000 Subject: [PATCH 1/4] Report allocation errors as panics --- library/alloc/Cargo.toml | 3 ++ library/alloc/src/alloc.rs | 85 ++++++++++++++++++++++++++++++++---- library/alloc/src/lib.rs | 1 + library/std/Cargo.toml | 2 +- library/std/src/lib.rs | 1 + library/std/src/panicking.rs | 48 ++++++++++++-------- 6 files changed, 111 insertions(+), 29 deletions(-) diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index e5f828c4c0b34..09a59133b6ae1 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -36,3 +36,6 @@ compiler-builtins-c = ["compiler_builtins/c"] compiler-builtins-no-asm = ["compiler_builtins/no-asm"] compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"] compiler-builtins-weak-intrinsics = ["compiler_builtins/weak-intrinsics"] + +# Make panics and failed asserts immediately abort without formatting any message +panic_immediate_abort = ["core/panic_immediate_abort"] diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index a548de814c53d..6da41bfca6dab 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -12,6 +12,11 @@ use core::ptr::{self, NonNull}; #[doc(inline)] pub use core::alloc::*; +#[cfg(not(no_global_oom_handling))] +use core::any::Any; +#[cfg(not(no_global_oom_handling))] +use core::panic::PanicPayload; + #[cfg(test)] mod tests; @@ -333,14 +338,78 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { } } -// # Allocation error handler +/// Payload passed to the panic handler when `handle_alloc_error` is called. +#[unstable(feature = "panic_oom_payload", issue = "110730")] +#[derive(Debug)] +pub struct AllocErrorPanicPayload { + layout: Layout, +} + +impl AllocErrorPanicPayload { + /// Internal function for the standard library to clone a payload. + #[unstable(feature = "std_internals", issue = "none")] + #[doc(hidden)] + pub fn internal_clone(&self) -> Self { + AllocErrorPanicPayload { layout: self.layout } + } + /// Returns the [`Layout`] of the allocation attempt that caused the error. + #[unstable(feature = "panic_oom_payload", issue = "110730")] + pub fn layout(&self) -> Layout { + self.layout + } +} + +#[unstable(feature = "std_internals", issue = "none")] #[cfg(not(no_global_oom_handling))] -extern "Rust" { - // This is the magic symbol to call the global alloc error handler. rustc generates - // it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the - // default implementations below (`__rdl_oom`) otherwise. - fn __rust_alloc_error_handler(size: usize, align: usize) -> !; +unsafe impl PanicPayload for AllocErrorPanicPayload { + fn take_box(&mut self) -> *mut (dyn Any + Send) { + use crate::boxed::Box; + Box::into_raw(Box::new(self.internal_clone())) + } + + fn get(&mut self) -> &(dyn Any + Send) { + self + } +} + +// # Allocation error handler + +#[cfg(all(not(no_global_oom_handling), not(test)))] +fn rust_oom(layout: Layout) -> ! { + if cfg!(feature = "panic_immediate_abort") { + core::intrinsics::abort() + } + + extern "Rust" { + // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call + // that gets resolved to the `#[panic_handler]` function. + #[lang = "panic_impl"] + fn panic_impl(pi: &core::panic::PanicInfo<'_>) -> !; + + // This symbol is emitted by rustc next to __rust_alloc_error_handler. + // Its value depends on the -Zoom={panic,abort} compiler option. + static __rust_alloc_error_handler_should_panic: u8; + } + + // Hack to work around issues with the lifetime of Arguments. + match format_args!("memory allocation of {} bytes failed", layout.size()) { + fmt => { + // Create a PanicInfo with a custom payload for the panic handler. + let can_unwind = unsafe { __rust_alloc_error_handler_should_panic != 0 }; + let mut pi = core::panic::PanicInfo::internal_constructor( + Some(&fmt), + core::panic::Location::caller(), + can_unwind, + /* force_no_backtrace */ false, + ); + let payload = AllocErrorPanicPayload { layout }; + pi.set_payload(&payload); + + // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. + unsafe { panic_impl(&pi) } + } + } } /// Signal a memory allocation error. @@ -378,9 +447,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! { } fn rt_error(layout: Layout) -> ! { - unsafe { - __rust_alloc_error_handler(layout.size(), layout.align()); - } + rust_oom(layout); } unsafe { core::intrinsics::const_eval_select((layout,), ct_error, rt_error) } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f435f503fc160..3c9daec9da744 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -138,6 +138,7 @@ #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_uninit_array_transpose)] +#![feature(panic_internals)] #![feature(pattern)] #![feature(pointer_byte_offsets)] #![feature(ptr_internals)] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 965132bdedb91..9076a19ce65fa 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -72,7 +72,7 @@ llvm-libunwind = ["unwind/llvm-libunwind"] system-llvm-libunwind = ["unwind/system-llvm-libunwind"] # Make panics and failed asserts immediately abort without formatting any message -panic_immediate_abort = ["core/panic_immediate_abort"] +panic_immediate_abort = ["alloc/panic_immediate_abort"] # Enable std_detect default features for stdarch/crates/std_detect: # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6f78778f01a54..1a1adeca1b522 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -349,6 +349,7 @@ #![feature(get_mut_unchecked)] #![feature(map_try_insert)] #![feature(new_uninit)] +#![feature(panic_oom_payload)] #![feature(slice_concat_trait)] #![feature(thin_box)] #![feature(try_reserve_kind)] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index d7a2baa1ff570..735d230a9de91 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -248,19 +248,24 @@ fn default_hook(info: &PanicInfo<'_>) { // The current implementation always returns `Some`. let location = info.location().unwrap(); - - let msg = match info.payload().downcast_ref::<&'static str>() { - Some(s) => *s, - None => match info.payload().downcast_ref::() { - Some(s) => &s[..], - None => "Box", - }, - }; let thread = thread_info::current_thread(); let name = thread.as_ref().and_then(|t| t.name()).unwrap_or(""); let write = |err: &mut dyn crate::io::Write| { - let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}"); + // Use the panic message directly if available, otherwise take it from + // the payload. + if let Some(msg) = info.message() { + let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}"); + } else { + let msg = if let Some(s) = info.payload().downcast_ref::<&'static str>() { + *s + } else if let Some(s) = info.payload().downcast_ref::() { + &s[..] + } else { + "Box" + }; + let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}"); + } static FIRST_PANIC: AtomicBool = AtomicBool::new(true); @@ -543,6 +548,8 @@ pub fn panicking() -> bool { #[cfg(not(test))] #[panic_handler] pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { + use alloc::alloc::AllocErrorPanicPayload; + struct FormatStringPayload<'a> { inner: &'a fmt::Arguments<'a>, string: Option, @@ -569,8 +576,7 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { unsafe impl<'a> PanicPayload for FormatStringPayload<'a> { fn take_box(&mut self) -> *mut (dyn Any + Send) { // We do two allocations here, unfortunately. But (a) they're required with the current - // scheme, and (b) we don't handle panic + OOM properly anyway (see comment in - // begin_panic below). + // scheme, and (b) OOM uses its own separate payload type which doesn't allocate. let contents = mem::take(self.fill()); Box::into_raw(Box::new(contents)) } @@ -595,9 +601,17 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { let loc = info.location().unwrap(); // The current implementation always returns Some let msg = info.message().unwrap(); // The current implementation always returns Some crate::sys_common::backtrace::__rust_end_short_backtrace(move || { - // FIXME: can we just pass `info` along rather than taking it apart here, only to have - // `rust_panic_with_hook` construct a new `PanicInfo`? - if let Some(msg) = msg.as_str() { + if let Some(payload) = info.payload().downcast_ref::() { + rust_panic_with_hook( + &mut payload.internal_clone(), + info.message(), + loc, + info.can_unwind(), + info.force_no_backtrace(), + ); + } else if let Some(msg) = msg.as_str() { + // FIXME: can we just pass `info` along rather than taking it apart here, only to have + // `rust_panic_with_hook` construct a new `PanicInfo`? rust_panic_with_hook( &mut StaticStrPayload(msg), info.message(), @@ -657,11 +671,7 @@ pub const fn begin_panic(msg: M) -> ! { unsafe impl PanicPayload for Payload { fn take_box(&mut self) -> *mut (dyn Any + Send) { - // Note that this should be the only allocation performed in this code path. Currently - // this means that panic!() on OOM will invoke this code path, but then again we're not - // really ready for panic on OOM anyway. If we do start doing this, then we should - // propagate this allocation to be performed in the parent of this thread instead of the - // thread that's panicking. + // Note that this should be the only allocation performed in this code path. let data = match self.inner.take() { Some(a) => Box::new(a) as Box, None => process::abort(), From d89ecfb61f323ff947a95218e008ca17e1c90495 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 22 Mar 2023 23:43:20 +0000 Subject: [PATCH 2/4] Remove #[alloc_error_handler] from the compiler and library --- compiler/rustc_ast/src/expand/allocator.rs | 7 -- compiler/rustc_builtin_macros/messages.ftl | 1 - .../src/alloc_error_handler.rs | 97 ------------------- compiler/rustc_builtin_macros/src/errors.rs | 7 -- compiler/rustc_builtin_macros/src/lib.rs | 2 - .../example/alloc_example.rs | 7 +- .../rustc_codegen_cranelift/src/allocator.rs | 26 +---- .../example/alloc_example.rs | 7 +- compiler/rustc_codegen_gcc/src/allocator.rs | 90 ++++++++--------- compiler/rustc_codegen_gcc/src/lib.rs | 4 +- compiler/rustc_codegen_llvm/src/allocator.rs | 17 +--- compiler/rustc_codegen_llvm/src/lib.rs | 3 +- .../src/back/symbol_export.rs | 2 +- compiler/rustc_codegen_ssa/src/base.rs | 13 +-- .../rustc_codegen_ssa/src/traits/backend.rs | 1 - compiler/rustc_feature/src/active.rs | 2 - compiler/rustc_feature/src/removed.rs | 2 + compiler/rustc_metadata/messages.ftl | 10 -- compiler/rustc_metadata/src/creader.rs | 70 +------------ compiler/rustc_metadata/src/errors.rs | 17 ---- compiler/rustc_metadata/src/rmeta/decoder.rs | 7 +- .../src/rmeta/decoder/cstore_impl.rs | 3 - compiler/rustc_metadata/src/rmeta/encoder.rs | 1 - compiler/rustc_metadata/src/rmeta/mod.rs | 1 - compiler/rustc_middle/src/query/mod.rs | 11 --- library/alloc/src/alloc.rs | 28 +++--- library/core/src/macros/mod.rs | 10 -- library/core/src/prelude/v1.rs | 4 +- library/std/src/alloc.rs | 86 +--------------- library/std/src/lib.rs | 1 - library/std/src/prelude/v1.rs | 4 +- tests/run-make/issue-51671/Makefile | 1 - tests/run-make/issue-51671/app.rs | 7 +- tests/run-make/issue-69368/Makefile | 19 ---- tests/run-make/issue-69368/a.rs | 26 ----- tests/run-make/issue-69368/b.rs | 8 -- tests/run-make/issue-69368/c.rs | 34 ------- .../run-make/wasm-symbols-not-exported/bar.rs | 7 +- .../alloc-error-handler-bad-signature-1.rs | 18 ---- ...alloc-error-handler-bad-signature-1.stderr | 44 --------- .../alloc-error-handler-bad-signature-2.rs | 17 ---- ...alloc-error-handler-bad-signature-2.stderr | 50 ---------- .../alloc-error-handler-bad-signature-3.rs | 15 --- ...alloc-error-handler-bad-signature-3.stderr | 21 ---- .../alloc-error/default-alloc-error-hook.rs | 4 +- .../no_std-alloc-error-handler-custom.rs | 84 ---------------- .../feature-gate-alloc-error-handler.rs | 16 --- .../feature-gate-alloc-error-handler.stderr | 12 --- tests/ui/missing/missing-allocator.rs | 6 -- 49 files changed, 80 insertions(+), 850 deletions(-) delete mode 100644 compiler/rustc_builtin_macros/src/alloc_error_handler.rs delete mode 100644 tests/run-make/issue-69368/Makefile delete mode 100644 tests/run-make/issue-69368/a.rs delete mode 100644 tests/run-make/issue-69368/b.rs delete mode 100644 tests/run-make/issue-69368/c.rs delete mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs delete mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr delete mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs delete mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr delete mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs delete mode 100644 tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr delete mode 100644 tests/ui/allocator/no_std-alloc-error-handler-custom.rs delete mode 100644 tests/ui/feature-gates/feature-gate-alloc-error-handler.rs delete mode 100644 tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index f825b10f489b0..02572c325ca49 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -14,13 +14,6 @@ pub fn default_fn_name(base: Symbol) -> String { format!("__rdl_{base}") } -pub fn alloc_error_handler_name(alloc_error_handler_kind: AllocatorKind) -> &'static str { - match alloc_error_handler_kind { - AllocatorKind::Global => "__rg_oom", - AllocatorKind::Default => "__rdl_oom", - } -} - pub const NO_ALLOC_SHIM_IS_UNSTABLE: &str = "__rust_no_alloc_shim_is_unstable"; pub enum AllocatorTy { diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 207ae8ad844bb..a0b4c8875262b 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -1,4 +1,3 @@ -builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function builtin_macros_alloc_must_statics = allocators must be statics builtin_macros_asm_clobber_abi = clobber_abi diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs deleted file mode 100644 index 82bae9157e79d..0000000000000 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ /dev/null @@ -1,97 +0,0 @@ -use crate::errors; -use crate::util::check_builtin_macro_attribute; - -use rustc_ast::ptr::P; -use rustc_ast::{self as ast, FnHeader, FnSig, Generics, StmtKind}; -use rustc_ast::{Fn, ItemKind, Stmt, TyKind, Unsafe}; -use rustc_expand::base::{Annotatable, ExtCtxt}; -use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::Span; -use thin_vec::{thin_vec, ThinVec}; - -pub fn expand( - ecx: &mut ExtCtxt<'_>, - _span: Span, - meta_item: &ast::MetaItem, - item: Annotatable, -) -> Vec { - check_builtin_macro_attribute(ecx, meta_item, sym::alloc_error_handler); - - let orig_item = item.clone(); - - // Allow using `#[alloc_error_handler]` on an item statement - // FIXME - if we get deref patterns, use them to reduce duplication here - let (item, is_stmt, sig_span) = - if let Annotatable::Item(item) = &item - && let ItemKind::Fn(fn_kind) = &item.kind - { - (item, false, ecx.with_def_site_ctxt(fn_kind.sig.span)) - } else if let Annotatable::Stmt(stmt) = &item - && let StmtKind::Item(item) = &stmt.kind - && let ItemKind::Fn(fn_kind) = &item.kind - { - (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span)) - } else { - ecx.sess.parse_sess.span_diagnostic.emit_err(errors::AllocErrorMustBeFn {span: item.span() }); - return vec![orig_item]; - }; - - // Generate a bunch of new items using the AllocFnFactory - let span = ecx.with_def_site_ctxt(item.span); - - // Generate item statements for the allocator methods. - let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig_span)]; - - // Generate anonymous constant serving as container for the allocator methods. - let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new())); - let const_body = ecx.expr_block(ecx.block(span, stmts)); - let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body); - let const_item = if is_stmt { - Annotatable::Stmt(P(ecx.stmt_item(span, const_item))) - } else { - Annotatable::Item(const_item) - }; - - // Return the original item and the new methods. - vec![orig_item, const_item] -} - -// #[rustc_std_internal_symbol] -// unsafe fn __rg_oom(size: usize, align: usize) -> ! { -// handler(core::alloc::Layout::from_size_align_unchecked(size, align)) -// } -fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span) -> Stmt { - let usize = cx.path_ident(span, Ident::new(sym::usize, span)); - let ty_usize = cx.ty_path(usize); - let size = Ident::from_str_and_span("size", span); - let align = Ident::from_str_and_span("align", span); - - let layout_new = cx.std_path(&[sym::alloc, sym::Layout, sym::from_size_align_unchecked]); - let layout_new = cx.expr_path(cx.path(span, layout_new)); - let layout = cx.expr_call( - span, - layout_new, - thin_vec![cx.expr_ident(span, size), cx.expr_ident(span, align)], - ); - - let call = cx.expr_call_ident(sig_span, handler, thin_vec![layout]); - - let never = ast::FnRetTy::Ty(cx.ty(span, TyKind::Never)); - let params = thin_vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)]; - let decl = cx.fn_decl(params, never); - let header = FnHeader { unsafety: Unsafe::Yes(span), ..FnHeader::default() }; - let sig = FnSig { decl, header, span: span }; - - let body = Some(cx.block_expr(call)); - let kind = ItemKind::Fn(Box::new(Fn { - defaultness: ast::Defaultness::Final, - sig, - generics: Generics::default(), - body, - })); - - let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)]; - - let item = cx.item(span, Ident::from_str_and_span("__rg_oom", span), attrs, kind); - cx.stmt_item(sig_span, item) -} diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 1238773d58b55..828a7177813dd 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -20,13 +20,6 @@ pub(crate) struct OneCfgPattern { pub(crate) span: Span, } -#[derive(Diagnostic)] -#[diag(builtin_macros_alloc_error_must_be_fn)] -pub(crate) struct AllocErrorMustBeFn { - #[primary_span] - pub(crate) span: Span, -} - #[derive(Diagnostic)] #[diag(builtin_macros_assert_requires_boolean)] pub(crate) struct AssertRequiresBoolean { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index ebf1448f55c99..d91aa1b3c8983 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -26,7 +26,6 @@ use rustc_expand::proc_macro::BangProcMacro; use rustc_fluent_macro::fluent_messages; use rustc_span::symbol::sym; -mod alloc_error_handler; mod assert; mod cfg; mod cfg_accessible; @@ -101,7 +100,6 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { } register_attr! { - alloc_error_handler: alloc_error_handler::expand, bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, diff --git a/compiler/rustc_codegen_cranelift/example/alloc_example.rs b/compiler/rustc_codegen_cranelift/example/alloc_example.rs index 117eed5afd8ab..1a4ed366c849f 100644 --- a/compiler/rustc_codegen_cranelift/example/alloc_example.rs +++ b/compiler/rustc_codegen_cranelift/example/alloc_example.rs @@ -1,4 +1,4 @@ -#![feature(start, core_intrinsics, alloc_error_handler, lang_items)] +#![feature(start, core_intrinsics, lang_items)] #![no_std] extern crate alloc; @@ -22,11 +22,6 @@ fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! { core::intrinsics::abort(); } -#[alloc_error_handler] -fn alloc_error_handler(_: alloc::alloc::Layout) -> ! { - core::intrinsics::abort(); -} - #[lang = "eh_personality"] fn eh_personality() -> ! { loop {} diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index 4e4c595de8257..a4f3ea6e58144 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -4,8 +4,8 @@ use crate::prelude::*; use rustc_ast::expand::allocator::{ - alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, - ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, + default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, + NO_ALLOC_SHIM_IS_UNSTABLE, }; use rustc_codegen_ssa::base::allocator_kind_for_codegen; use rustc_session::config::OomStrategy; @@ -17,13 +17,7 @@ pub(crate) fn codegen( unwind_context: &mut UnwindContext, ) -> bool { let Some(kind) = allocator_kind_for_codegen(tcx) else { return false }; - codegen_inner( - module, - unwind_context, - kind, - tcx.alloc_error_handler_kind(()).unwrap(), - tcx.sess.opts.unstable_opts.oom, - ); + codegen_inner(module, unwind_context, kind, tcx.sess.opts.unstable_opts.oom); true } @@ -31,7 +25,6 @@ fn codegen_inner( module: &mut impl Module, unwind_context: &mut UnwindContext, kind: AllocatorKind, - alloc_error_handler_kind: AllocatorKind, oom_strategy: OomStrategy, ) { let usize_ty = module.target_config().pointer_type(); @@ -75,19 +68,6 @@ fn codegen_inner( } } - let sig = Signature { - call_conv: module.target_config().default_call_conv, - params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)], - returns: vec![], - }; - crate::common::create_wrapper_function( - module, - unwind_context, - sig, - "__rust_alloc_error_handler", - &alloc_error_handler_name(alloc_error_handler_kind), - ); - let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap(); let mut data = DataDescription::new(); data.set_align(1); diff --git a/compiler/rustc_codegen_gcc/example/alloc_example.rs b/compiler/rustc_codegen_gcc/example/alloc_example.rs index 754e7931412da..faff1dca23f3f 100644 --- a/compiler/rustc_codegen_gcc/example/alloc_example.rs +++ b/compiler/rustc_codegen_gcc/example/alloc_example.rs @@ -1,4 +1,4 @@ -#![feature(start, core_intrinsics, alloc_error_handler, lang_items)] +#![feature(start, core_intrinsics, lang_items)] #![no_std] extern crate alloc; @@ -21,11 +21,6 @@ fn panic_handler(_: &core::panic::PanicInfo) -> ! { core::intrinsics::abort(); } -#[alloc_error_handler] -fn alloc_error_handler(_: alloc::alloc::Layout) -> ! { - core::intrinsics::abort(); -} - #[lang = "eh_personality"] fn eh_personality() -> ! { loop {} diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index edd7ab722f617..231a695fcb8a8 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -1,9 +1,9 @@ -#[cfg(feature="master")] +#[cfg(feature = "master")] use gccjit::FnAttribute; use gccjit::{FunctionType, GlobalKind, ToRValue}; use rustc_ast::expand::allocator::{ - alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, - ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, + default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, + NO_ALLOC_SHIM_IS_UNSTABLE, }; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; @@ -11,15 +11,19 @@ use rustc_session::config::OomStrategy; use crate::GccContext; -pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) { +pub(crate) unsafe fn codegen( + tcx: TyCtxt<'_>, + mods: &mut GccContext, + _module_name: &str, + kind: AllocatorKind, +) { let context = &mods.context; - let usize = - match tcx.sess.target.pointer_width { - 16 => context.new_type::(), - 32 => context.new_type::(), - 64 => context.new_type::(), - tws => bug!("Unsupported target word size for int: {}", tws), - }; + let usize = match tcx.sess.target.pointer_width { + 16 => context.new_type::(), + 32 => context.new_type::(), + 64 => context.new_type::(), + tws => bug!("Unsupported target word size for int: {}", tws), + }; let i8 = context.new_type::(); let i8p = i8.make_pointer(); let void = context.new_type::<()>(); @@ -49,13 +53,22 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam }; let name = global_fn_name(method.name); - let args: Vec<_> = types.iter().enumerate() + let args: Vec<_> = types + .iter() + .enumerate() .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) .collect(); - let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false); + let func = context.new_function( + None, + FunctionType::Exported, + output.unwrap_or(void), + &args, + name, + false, + ); if tcx.sess.target.options.default_hidden_visibility { - #[cfg(feature="master")] + #[cfg(feature = "master")] func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); } if tcx.sess.must_emit_unwind_tables() { @@ -63,11 +76,20 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam } let callee = default_fn_name(method.name); - let args: Vec<_> = types.iter().enumerate() + let args: Vec<_> = types + .iter() + .enumerate() .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) .collect(); - let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false); - #[cfg(feature="master")] + let callee = context.new_function( + None, + FunctionType::Extern, + output.unwrap_or(void), + &args, + callee, + false, + ); + #[cfg(feature = "master")] callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); let block = func.new_block("entry"); @@ -81,8 +103,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam //llvm::LLVMSetTailCall(ret, True); if output.is_some() { block.end_with_return(None, ret); - } - else { + } else { block.end_with_void_return(None); } @@ -91,37 +112,6 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam } } - let types = [usize, usize]; - let name = "__rust_alloc_error_handler".to_string(); - let args: Vec<_> = types.iter().enumerate() - .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) - .collect(); - let func = context.new_function(None, FunctionType::Exported, void, &args, name, false); - - if tcx.sess.target.default_hidden_visibility { - #[cfg(feature="master")] - func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); - } - - let callee = alloc_error_handler_name(alloc_error_handler_kind); - let args: Vec<_> = types.iter().enumerate() - .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index))) - .collect(); - let callee = context.new_function(None, FunctionType::Extern, void, &args, callee, false); - #[cfg(feature="master")] - callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); - - let block = func.new_block("entry"); - - let args = args - .iter() - .enumerate() - .map(|(i, _)| func.get_param(i as i32).to_rvalue()) - .collect::>(); - let _ret = context.new_call(None, callee, &args); - //llvm::LLVMSetTailCall(ret, True); - block.end_with_void_return(None); - let name = OomStrategy::SYMBOL.to_string(); let global = context.new_global(None, GlobalKind::Exported, i8, name); let value = tcx.sess.opts.unstable_opts.oom.should_panic(); diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index ce7e31682f101..f1f3d0334e586 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -165,11 +165,11 @@ impl CodegenBackend for GccCodegenBackend { } impl ExtraBackendMethods for GccCodegenBackend { - fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module { + fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind) -> Self::Module { let mut mods = GccContext { context: Context::default(), }; - unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); } + unsafe { allocator::codegen(tcx, &mut mods, module_name, kind); } mods } diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index db5c1388ef846..a8b3afd0efeed 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -1,8 +1,8 @@ use crate::attributes; use libc::c_uint; use rustc_ast::expand::allocator::{ - alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, - ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, + default_fn_name, global_fn_name, AllocatorKind, AllocatorTy, ALLOCATOR_METHODS, + NO_ALLOC_SHIM_IS_UNSTABLE, }; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; @@ -17,7 +17,6 @@ pub(crate) unsafe fn codegen( module_llvm: &mut ModuleLlvm, module_name: &str, kind: AllocatorKind, - alloc_error_handler_kind: AllocatorKind, ) { let llcx = &*module_llvm.llcx; let llmod = module_llvm.llmod(); @@ -61,18 +60,6 @@ pub(crate) unsafe fn codegen( } } - // rust alloc error handler - create_wrapper_function( - tcx, - llcx, - llmod, - "__rust_alloc_error_handler", - &alloc_error_handler_name(alloc_error_handler_kind), - &[usize, usize], // size, align - None, - true, - ); - // __rust_alloc_error_handler_should_panic let name = OomStrategy::SYMBOL; let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 59d1ea05d8a16..545bd2bb57565 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -120,11 +120,10 @@ impl ExtraBackendMethods for LlvmCodegenBackend { tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, - alloc_error_handler_kind: AllocatorKind, ) -> ModuleLlvm { let mut module_llvm = ModuleLlvm::new_metadata(tcx, module_name); unsafe { - allocator::codegen(tcx, &mut module_llvm, module_name, kind, alloc_error_handler_kind); + allocator::codegen(tcx, &mut module_llvm, module_name, kind); } module_llvm } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 9cd4394108a4a..1850272ce079a 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -219,7 +219,7 @@ fn exported_symbols_provider_local( for symbol_name in ALLOCATOR_METHODS .iter() .map(|method| format!("__rust_{}", method.name)) - .chain(["__rust_alloc_error_handler".to_string(), OomStrategy::SYMBOL.to_string()]) + .chain([OomStrategy::SYMBOL.to_string()]) { let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 1e4ea73a1724f..988646c800d37 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -635,16 +635,9 @@ pub fn codegen_crate( if let Some(kind) = allocator_kind_for_codegen(tcx) { let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string(); - let module_llvm = tcx.sess.time("write_allocator_module", || { - backend.codegen_allocator( - tcx, - &llmod_id, - kind, - // If allocator_kind is Some then alloc_error_handler_kind must - // also be Some. - tcx.alloc_error_handler_kind(()).unwrap(), - ) - }); + let module_llvm = tcx + .sess + .time("write_allocator_module", || backend.codegen_allocator(tcx, &llmod_id, kind)); ongoing_codegen.wait_for_signal_to_codegen_item(); ongoing_codegen.check_for_errors(tcx.sess); diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index ac8123bc1be91..f633c8bfa5a8e 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -125,7 +125,6 @@ pub trait ExtraBackendMethods: tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, - alloc_error_handler_kind: AllocatorKind, ) -> Self::Module; /// This generates the codegen unit and returns it along with /// a `u64` giving an estimate of the unit's processing cost. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index a02c04ecd3ecb..33d1326673060 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -320,8 +320,6 @@ declare_features! ( (active, abi_x86_interrupt, "1.17.0", Some(40180), None), /// Allows additional const parameter types, such as `&'static str` or user defined types (incomplete, adt_const_params, "1.56.0", Some(95174), None), - /// Allows defining an `#[alloc_error_handler]`. - (active, alloc_error_handler, "1.29.0", Some(51540), None), /// Allows trait methods with arbitrary self types. (active, arbitrary_self_types, "1.23.0", Some(44874), None), /// Allows using `const` operands in inline assembly. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index da18cb2a239e8..b664641031d2d 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -47,6 +47,8 @@ declare_features! ( (removed, advanced_slice_patterns, "1.0.0", Some(62254), None, Some("merged into `#![feature(slice_patterns)]`")), + /// Allows defining an `#[alloc_error_handler]`. + (removed, alloc_error_handler, "CURRENT_RUSTC_VERSION", Some(51540), None, Some("now handled by panic handler")), (removed, allocator, "1.0.0", None, None, None), /// Allows a test to fail without failing the whole suite. (removed, allow_fail, "1.19.0", Some(46488), None, Some("removed due to no clear use cases")), diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 633004fdddfb7..5beb106221327 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -19,9 +19,6 @@ metadata_cant_find_crate = metadata_compiler_missing_profiler = the compiler may have been built without the profiler runtime -metadata_conflicting_alloc_error_handler = - the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name} - metadata_conflicting_global_alloc = the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name} @@ -202,10 +199,6 @@ metadata_no_dylib_plugin = metadata_no_link_mod_override = overriding linking modifiers from command line is not supported -metadata_no_multiple_alloc_error_handler = - cannot define multiple allocation error handlers - .label = cannot define a new allocation error handler - metadata_no_multiple_global_alloc = cannot define multiple global allocators .label = cannot define a new global allocator @@ -224,9 +217,6 @@ metadata_not_profiler_runtime = metadata_only_provide_library_name = only provide the library name `{$suggested_name}`, not the full filename -metadata_prev_alloc_error_handler = - previous allocation error handler defined here - metadata_prev_global_alloc = previous global allocator defined here diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 69221475356d7..73303fb2f30f3 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -4,7 +4,7 @@ use crate::errors; use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; -use rustc_ast::expand::allocator::{alloc_error_handler_name, global_fn_name, AllocatorKind}; +use rustc_ast::expand::allocator::{global_fn_name, AllocatorKind}; use rustc_ast::{self as ast, *}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; @@ -41,13 +41,8 @@ pub struct CStore { /// This crate needs an allocator and either provides it itself, or finds it in a dependency. /// If the above is true, then this field denotes the kind of the found allocator. allocator_kind: Option, - /// This crate needs an allocation error handler and either provides it itself, or finds it in a dependency. - /// If the above is true, then this field denotes the kind of the found allocator. - alloc_error_handler_kind: Option, /// This crate has a `#[global_allocator]` item. has_global_allocator: bool, - /// This crate has a `#[alloc_error_handler]` item. - has_alloc_error_handler: bool, /// The interned [StableCrateId]s. pub(crate) stable_crate_ids: StableCrateIdMap, @@ -228,18 +223,10 @@ impl CStore { self.allocator_kind } - pub(crate) fn alloc_error_handler_kind(&self) -> Option { - self.alloc_error_handler_kind - } - pub(crate) fn has_global_allocator(&self) -> bool { self.has_global_allocator } - pub(crate) fn has_alloc_error_handler(&self) -> bool { - self.has_alloc_error_handler - } - pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) { let json_unused_externs = tcx.sess.opts.json_unused_externs; @@ -279,9 +266,7 @@ impl CStore { metas: IndexVec::from_iter(iter::once(None)), injected_panic_runtime: None, allocator_kind: None, - alloc_error_handler_kind: None, has_global_allocator: false, - has_alloc_error_handler: false, stable_crate_ids, unused_externs: Vec::new(), } @@ -803,14 +788,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } spans => !spans.is_empty(), }; - self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(krate) { - [span1, span2, ..] => { - self.sess - .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); - true - } - spans => !spans.is_empty(), - }; // Check to see if we actually need an allocator. This desire comes // about through the `#![needs_allocator]` attribute and is typically @@ -851,21 +828,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } } - let mut alloc_error_handler = - self.cstore.has_alloc_error_handler.then(|| Symbol::intern("this crate")); - for (_, data) in self.cstore.iter_crate_data() { - if data.has_alloc_error_handler() { - match alloc_error_handler { - Some(other_crate) => { - self.sess.emit_err(errors::ConflictingAllocErrorHandler { - crate_name: data.name(), - other_crate_name: other_crate, - }); - } - None => alloc_error_handler = Some(data.name()), - } - } - } if global_allocator.is_some() { self.cstore.allocator_kind = Some(AllocatorKind::Global); @@ -881,14 +843,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } self.cstore.allocator_kind = Some(AllocatorKind::Default); } - - if alloc_error_handler.is_some() { - self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Global); - } else { - // The alloc crate provides a default allocation error handler if - // one isn't specified. - self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default); - } } fn inject_forced_externs(&mut self) { @@ -1076,28 +1030,6 @@ fn global_allocator_spans(krate: &ast::Crate) -> Vec { f.spans } -fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec { - struct Finder { - name: Symbol, - spans: Vec, - } - impl<'ast> visit::Visitor<'ast> for Finder { - fn visit_item(&mut self, item: &'ast ast::Item) { - if item.ident.name == self.name - && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol) - { - self.spans.push(item.span); - } - visit::walk_item(self, item) - } - } - - let name = Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)); - let mut f = Finder { name, spans: Vec::new() }; - visit::walk_crate(&mut f, krate); - f.spans -} - // On Windows the compiler would sometimes intermittently fail to open the // proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the // system still holds a lock on the file, so we retry a few times before calling it diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 91220629fb669..a2c9a444fd9ba 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -352,16 +352,6 @@ pub struct NoMultipleGlobalAlloc { pub span1: Span, } -#[derive(Diagnostic)] -#[diag(metadata_no_multiple_alloc_error_handler)] -pub struct NoMultipleAllocErrorHandler { - #[primary_span] - #[label] - pub span2: Span, - #[label(metadata_prev_alloc_error_handler)] - pub span1: Span, -} - #[derive(Diagnostic)] #[diag(metadata_conflicting_global_alloc)] pub struct ConflictingGlobalAlloc { @@ -369,13 +359,6 @@ pub struct ConflictingGlobalAlloc { pub other_crate_name: Symbol, } -#[derive(Diagnostic)] -#[diag(metadata_conflicting_alloc_error_handler)] -pub struct ConflictingAllocErrorHandler { - pub crate_name: Symbol, - pub other_crate_name: Symbol, -} - #[derive(Diagnostic)] #[diag(metadata_global_alloc_required)] pub struct GlobalAllocRequired; diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index b189e79df5646..6a01bd51e24c7 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -760,9 +760,8 @@ impl MetadataBlob { )?; writeln!( out, - "has_global_allocator {} has_alloc_error_handler {} has_panic_handler {} has_default_lib_allocator {}", + "has_global_allocator {} has_panic_handler {} has_default_lib_allocator {}", root.has_global_allocator, - root.has_alloc_error_handler, root.has_panic_handler, root.has_default_lib_allocator )?; @@ -1894,10 +1893,6 @@ impl CrateMetadata { self.root.has_global_allocator } - pub(crate) fn has_alloc_error_handler(&self) -> bool { - self.root.has_alloc_error_handler - } - pub(crate) fn has_default_lib_allocator(&self) -> bool { self.root.has_default_lib_allocator } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f27eee0d79a53..101d634075bd9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -299,7 +299,6 @@ provide! { tcx, def_id, other, cdata, is_panic_runtime => { cdata.root.panic_runtime } is_compiler_builtins => { cdata.root.compiler_builtins } has_global_allocator => { cdata.root.has_global_allocator } - has_alloc_error_handler => { cdata.root.has_alloc_error_handler } has_panic_handler => { cdata.root.has_panic_handler } is_profiler_runtime => { cdata.root.profiler_runtime } required_panic_strategy => { cdata.root.required_panic_strategy } @@ -388,7 +387,6 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { // resolve! Does this work? Unsure! That's what the issue is about providers.queries = rustc_middle::query::Providers { allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(), - alloc_error_handler_kind: |tcx, ()| CStore::from_tcx(tcx).alloc_error_handler_kind(), is_private_dep: |_tcx, LocalCrate| false, native_library: |tcx, id| { tcx.native_libraries(id.krate) @@ -503,7 +501,6 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { dependency_formats: |tcx, ()| Lrc::new(crate::dependency_format::calculate(tcx)), has_global_allocator: |tcx, LocalCrate| CStore::from_tcx(tcx).has_global_allocator(), - has_alloc_error_handler: |tcx, LocalCrate| CStore::from_tcx(tcx).has_alloc_error_handler(), postorder_cnums: |tcx, ()| { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a4ba943275e4c..0d1d827d21c5f 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -683,7 +683,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, edition: tcx.sess.edition(), has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), - has_alloc_error_handler: tcx.has_alloc_error_handler(LOCAL_CRATE), has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), has_default_lib_allocator: attr::contains_name(&attrs, sym::default_lib_allocator), proc_macro_data, diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 42764af52c43f..ed773431036dd 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -257,7 +257,6 @@ pub(crate) struct CrateRoot { panic_in_drop_strategy: PanicStrategy, edition: Edition, has_global_allocator: bool, - has_alloc_error_handler: bool, has_panic_handler: bool, has_default_lib_allocator: bool, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 340c5a769dbc4..8c84efd4726d9 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1446,13 +1446,6 @@ rustc_queries! { desc { "checking if the crate has_global_allocator" } separate_provide_extern } - query has_alloc_error_handler(_: CrateNum) -> bool { - // This query depends on untracked global state in CStore - eval_always - fatal_cycle - desc { "checking if the crate has_alloc_error_handler" } - separate_provide_extern - } query has_panic_handler(_: CrateNum) -> bool { fatal_cycle desc { "checking if the crate has_panic_handler" } @@ -1836,10 +1829,6 @@ rustc_queries! { eval_always desc { "getting the allocator kind for the current crate" } } - query alloc_error_handler_kind(_: ()) -> Option { - eval_always - desc { "alloc error handler kind for the current crate" } - } query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap> { desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) } diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 6da41bfca6dab..badae49551cb7 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -387,7 +387,7 @@ fn rust_oom(layout: Layout) -> ! { #[lang = "panic_impl"] fn panic_impl(pi: &core::panic::PanicInfo<'_>) -> !; - // This symbol is emitted by rustc next to __rust_alloc_error_handler. + // This symbol is emitted by rustc . // Its value depends on the -Zoom={panic,abort} compiler option. static __rust_alloc_error_handler_should_panic: u8; } @@ -418,24 +418,25 @@ fn rust_oom(layout: Layout) -> ! { /// in response to an allocation error are encouraged to call this function, /// rather than directly invoking [`panic!`] or similar. /// -/// This function is guaranteed to diverge (not return normally with a value), but depending on -/// global configuration, it may either panic (resulting in unwinding or aborting as per -/// configuration for all panics), or abort the process (with no unwinding). +/// This function triggers a panic with a special payload of [`AllocErrorPanicPayload`] that holds +/// the [`Layout`] passed into this function. /// -/// The default behavior is: +/// There are 2 ways in which such panics can be handled: /// /// * If the binary links against `std` (typically the case), then -/// print a message to standard error and abort the process. -/// This behavior can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`]. -/// Future versions of Rust may panic by default instead. +/// the payload is available through [`PanicInfo::payload`][std_payload]. By default, panics caused by this +/// function will always abort the process instead of unwinding. This can be overridden by +/// compiling the program with the `-Z oom=unwind` option, in which case the payload is captured +/// and can be recovered through the [`catch_unwind`] function. /// /// * If the binary does not link against `std` (all of its crates are marked -/// [`#![no_std]`][no_std]), then call [`panic!`] with a message. -/// [The panic handler] applies as to any panic. +/// [`#![no_std]`][no_std]), then [the panic handler] is called. The payload is available through +/// [`PanicInfo::payload`][core_payload]. /// -/// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html -/// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html -/// [The panic handler]: https://doc.rust-lang.org/reference/runtime.html#the-panic_handler-attribute +/// [core_payload]: ../../core/panic/struct.PanicInfo.html#method.payload +/// [std_payload]: ../../std/panic/struct.PanicInfo.html#method.payload +/// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html +/// [the panic handler]: https://doc.rust-lang.org/reference/runtime.html#the-panic_handler-attribute /// [no_std]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute #[stable(feature = "global_alloc", since = "1.28.0")] #[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")] @@ -457,6 +458,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! { #[cfg(all(not(no_global_oom_handling), test))] pub use std::alloc::handle_alloc_error; +#[cfg(bootstrap)] #[cfg(all(not(no_global_oom_handling), not(test)))] #[doc(hidden)] #[allow(unused_attributes)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index c27be8d2ffd31..9dcadf344fe41 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1621,16 +1621,6 @@ pub(crate) mod builtin { /* compiler built-in */ } - /// Attribute macro applied to a function to register it as a handler for allocation failure. - /// - /// See also [`std::alloc::handle_alloc_error`](../../../std/alloc/fn.handle_alloc_error.html). - #[unstable(feature = "alloc_error_handler", issue = "51540")] - #[allow_internal_unstable(rustc_attrs)] - #[rustc_builtin_macro] - pub macro alloc_error_handler($item:item) { - /* compiler built-in */ - } - /// Keeps the item it's applied to if the passed path is accessible, and removes it otherwise. #[unstable( feature = "cfg_accessible", diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 10525a16f3a66..9c4c0f6ab7aa5 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -76,9 +76,7 @@ pub use crate::macros::builtin::{RustcDecodable, RustcEncodable}; // Do not `doc(no_inline)` so that they become doc items on their own // (no public module for them to be re-exported from). #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use crate::macros::builtin::{ - alloc_error_handler, bench, derive, global_allocator, test, test_case, -}; +pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case}; #[unstable(feature = "derive_const", issue = "none")] pub use crate::macros::builtin::derive_const; diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index bb786bd59dc84..849d721d62513 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -57,9 +57,8 @@ #![stable(feature = "alloc_module", since = "1.28.0")] use core::intrinsics; +use core::ptr; use core::ptr::NonNull; -use core::sync::atomic::{AtomicPtr, Ordering}; -use core::{mem, ptr}; #[stable(feature = "alloc_module", since = "1.28.0")] #[doc(inline)] @@ -286,89 +285,6 @@ unsafe impl Allocator for System { } } -static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); - -/// Registers a custom allocation error hook, replacing any that was previously registered. -/// -/// The allocation error hook is invoked when an infallible memory allocation fails — that is, -/// as a consequence of calling [`handle_alloc_error`] — before the runtime aborts. -/// -/// The allocation error hook is a global resource. [`take_alloc_error_hook`] may be used to -/// retrieve a previously registered hook and wrap or discard it. -/// -/// # What the provided `hook` function should expect -/// -/// The hook function is provided with a [`Layout`] struct which contains information -/// about the allocation that failed. -/// -/// The hook function may choose to panic or abort; in the event that it returns normally, this -/// will cause an immediate abort. -/// -/// Since [`take_alloc_error_hook`] is a safe function that allows retrieving the hook, the hook -/// function must be _sound_ to call even if no memory allocations were attempted. -/// -/// # The default hook -/// -/// The default hook, used if [`set_alloc_error_hook`] is never called, prints a message to -/// standard error (and then returns, causing the runtime to abort the process). -/// Compiler options may cause it to panic instead, and the default behavior may be changed -/// to panicking in future versions of Rust. -/// -/// # Examples -/// -/// ``` -/// #![feature(alloc_error_hook)] -/// -/// use std::alloc::{Layout, set_alloc_error_hook}; -/// -/// fn custom_alloc_error_hook(layout: Layout) { -/// panic!("memory allocation of {} bytes failed", layout.size()); -/// } -/// -/// set_alloc_error_hook(custom_alloc_error_hook); -/// ``` -#[unstable(feature = "alloc_error_hook", issue = "51245")] -pub fn set_alloc_error_hook(hook: fn(Layout)) { - HOOK.store(hook as *mut (), Ordering::SeqCst); -} - -/// Unregisters the current allocation error hook, returning it. -/// -/// *See also the function [`set_alloc_error_hook`].* -/// -/// If no custom hook is registered, the default hook will be returned. -#[unstable(feature = "alloc_error_hook", issue = "51245")] -pub fn take_alloc_error_hook() -> fn(Layout) { - let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst); - if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } } -} - -fn default_alloc_error_hook(layout: Layout) { - extern "Rust" { - // This symbol is emitted by rustc next to __rust_alloc_error_handler. - // Its value depends on the -Zoom={panic,abort} compiler option. - static __rust_alloc_error_handler_should_panic: u8; - } - - if unsafe { __rust_alloc_error_handler_should_panic != 0 } { - panic!("memory allocation of {} bytes failed", layout.size()); - } else { - rtprintpanic!("memory allocation of {} bytes failed\n", layout.size()); - } -} - -#[cfg(not(test))] -#[doc(hidden)] -#[alloc_error_handler] -#[unstable(feature = "alloc_internals", issue = "none")] -pub fn rust_oom(layout: Layout) -> ! { - let hook = HOOK.load(Ordering::SeqCst); - let hook: fn(Layout) = - if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } }; - hook(layout); - crate::process::abort() -} - #[cfg(not(test))] #[doc(hidden)] #[allow(unused_attributes)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 1a1adeca1b522..4c93ade32214b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -264,7 +264,6 @@ // // Language features: // tidy-alphabetical-start -#![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 7a7a773763559..62aea44f6c57b 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -60,9 +60,7 @@ pub use core::prelude::v1::{RustcDecodable, RustcEncodable}; // Do not `doc(no_inline)` so that they become doc items on their own // (no public module for them to be re-exported from). #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use core::prelude::v1::{ - alloc_error_handler, bench, derive, global_allocator, test, test_case, -}; +pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case}; #[unstable(feature = "derive_const", issue = "none")] pub use core::prelude::v1::derive_const; diff --git a/tests/run-make/issue-51671/Makefile b/tests/run-make/issue-51671/Makefile index c93645369928c..00cf913466238 100644 --- a/tests/run-make/issue-51671/Makefile +++ b/tests/run-make/issue-51671/Makefile @@ -6,4 +6,3 @@ all: $(RUSTC) --emit=obj app.rs nm $(TMPDIR)/app.o | $(CGREP) rust_begin_unwind nm $(TMPDIR)/app.o | $(CGREP) rust_eh_personality - nm $(TMPDIR)/app.o | $(CGREP) __rg_oom diff --git a/tests/run-make/issue-51671/app.rs b/tests/run-make/issue-51671/app.rs index e9dc1e9744fb1..a9d3457bf90e6 100644 --- a/tests/run-make/issue-51671/app.rs +++ b/tests/run-make/issue-51671/app.rs @@ -1,5 +1,5 @@ #![crate_type = "bin"] -#![feature(lang_items, alloc_error_handler)] +#![feature(lang_items)] #![no_main] #![no_std] @@ -13,8 +13,3 @@ fn panic(_: &PanicInfo) -> ! { #[lang = "eh_personality"] fn eh() {} - -#[alloc_error_handler] -fn oom(_: Layout) -> ! { - loop {} -} diff --git a/tests/run-make/issue-69368/Makefile b/tests/run-make/issue-69368/Makefile deleted file mode 100644 index b1229d1b07fc7..0000000000000 --- a/tests/run-make/issue-69368/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# Test that previously triggered a linker failure with root cause -# similar to one found in the issue #69368. -# -# The crate that provides oom lang item is missing some other lang -# items. Necessary to prevent the use of start-group / end-group. -# -# The weak lang items are defined in a separate compilation units, -# so that linker could omit them if not used. -# -# The crates that need those weak lang items are dependencies of -# crates that provide them. - -all: - $(RUSTC) a.rs - $(RUSTC) b.rs - $(RUSTC) c.rs diff --git a/tests/run-make/issue-69368/a.rs b/tests/run-make/issue-69368/a.rs deleted file mode 100644 index a54f429550e74..0000000000000 --- a/tests/run-make/issue-69368/a.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![crate_type = "rlib"] -#![feature(lang_items)] -#![feature(panic_unwind)] -#![no_std] - -extern crate panic_unwind; - -#[panic_handler] -pub fn panic_handler(_: &core::panic::PanicInfo) -> ! { - loop {} -} - -#[no_mangle] -extern "C" fn __rust_drop_panic() -> ! { - loop {} -} - -#[no_mangle] -extern "C" fn __rust_foreign_exception() -> ! { - loop {} -} - -#[lang = "eh_personality"] -fn eh_personality() { - loop {} -} diff --git a/tests/run-make/issue-69368/b.rs b/tests/run-make/issue-69368/b.rs deleted file mode 100644 index 4d6af0266563b..0000000000000 --- a/tests/run-make/issue-69368/b.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![crate_type = "rlib"] -#![feature(alloc_error_handler)] -#![no_std] - -#[alloc_error_handler] -pub fn error_handler(_: core::alloc::Layout) -> ! { - panic!(); -} diff --git a/tests/run-make/issue-69368/c.rs b/tests/run-make/issue-69368/c.rs deleted file mode 100644 index 729c4249a053a..0000000000000 --- a/tests/run-make/issue-69368/c.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![crate_type = "bin"] -#![feature(start)] -#![no_std] - -extern crate alloc; -extern crate a; -extern crate b; - -use alloc::vec::Vec; -use core::alloc::*; - -struct Allocator; - -unsafe impl GlobalAlloc for Allocator { - unsafe fn alloc(&self, _: Layout) -> *mut u8 { - loop {} - } - - unsafe fn dealloc(&self, _: *mut u8, _: Layout) { - loop {} - } -} - -#[global_allocator] -static ALLOCATOR: Allocator = Allocator; - -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { - let mut v = Vec::new(); - for i in 0..argc { - v.push(i); - } - v.iter().sum() -} diff --git a/tests/run-make/wasm-symbols-not-exported/bar.rs b/tests/run-make/wasm-symbols-not-exported/bar.rs index 6ffbd3ec6900d..eb768446b4b92 100644 --- a/tests/run-make/wasm-symbols-not-exported/bar.rs +++ b/tests/run-make/wasm-symbols-not-exported/bar.rs @@ -1,4 +1,4 @@ -#![feature(panic_handler, alloc_error_handler)] +#![feature(panic_handler)] #![crate_type = "cdylib"] #![no_std] @@ -24,11 +24,6 @@ pub extern fn foo(a: u32) -> u32 { a * 2 } -#[alloc_error_handler] -fn a(_: core::alloc::Layout) -> ! { - loop {} -} - #[panic_handler] fn b(_: &core::panic::PanicInfo) -> ! { loop {} diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs deleted file mode 100644 index cd06423e3a557..0000000000000 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.rs +++ /dev/null @@ -1,18 +0,0 @@ -// compile-flags:-C panic=abort - -#![feature(alloc_error_handler)] -#![no_std] -#![no_main] - -use core::alloc::Layout; - -#[alloc_error_handler] -fn oom( - info: &Layout, //~^ ERROR mismatched types -) -> () //~^^ ERROR mismatched types -{ - loop {} -} - -#[panic_handler] -fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr deleted file mode 100644 index de92841d7f18e..0000000000000 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr +++ /dev/null @@ -1,44 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1 - | -LL | #[alloc_error_handler] - | ---------------------- in this procedural macro expansion -LL | // fn oom( -LL | || info: &Layout, -LL | || ) -> () - | ||_______- arguments to this function are incorrect -LL | | { -LL | | loop {} -LL | | } - | |__^ expected `&Layout`, found `Layout` - | -note: function defined here - --> $DIR/alloc-error-handler-bad-signature-1.rs:10:4 - | -LL | fn oom( - | ^^^ -LL | info: &Layout, - | ------------- - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0308]: mismatched types - --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1 - | -LL | #[alloc_error_handler] - | ---------------------- in this procedural macro expansion -LL | // fn oom( -LL | || info: &Layout, -LL | || ) -> () - | ||_______^ expected `!`, found `()` -LL | | { -LL | | loop {} -LL | | } - | |__- expected `!` because of return type - | - = note: expected type `!` - found unit type `()` - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs deleted file mode 100644 index 4f76257fc7267..0000000000000 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -// compile-flags:-C panic=abort - -#![feature(alloc_error_handler)] -#![no_std] -#![no_main] - -struct Layout; - -#[alloc_error_handler] -fn oom( - info: Layout, //~^ ERROR mismatched types -) { //~^^ ERROR mismatched types - loop {} -} - -#[panic_handler] -fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr deleted file mode 100644 index 7a495380f2ba1..0000000000000 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr +++ /dev/null @@ -1,50 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1 - | -LL | #[alloc_error_handler] - | ---------------------- in this procedural macro expansion -LL | // fn oom( -LL | || info: Layout, -LL | || ) { - | ||_- arguments to this function are incorrect -LL | | loop {} -LL | | } - | |__^ expected `Layout`, found `core::alloc::Layout` - | - = note: `core::alloc::Layout` and `Layout` have similar names, but are actually distinct types -note: `core::alloc::Layout` is defined in crate `core` - --> $SRC_DIR/core/src/alloc/layout.rs:LL:COL -note: `Layout` is defined in the current crate - --> $DIR/alloc-error-handler-bad-signature-2.rs:7:1 - | -LL | struct Layout; - | ^^^^^^^^^^^^^ -note: function defined here - --> $DIR/alloc-error-handler-bad-signature-2.rs:10:4 - | -LL | fn oom( - | ^^^ -LL | info: Layout, - | ------------ - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0308]: mismatched types - --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1 - | -LL | #[alloc_error_handler] - | ---------------------- in this procedural macro expansion -LL | // fn oom( -LL | || info: Layout, -LL | || ) { - | ||_^ expected `!`, found `()` -LL | | loop {} -LL | | } - | |__- expected `!` because of return type - | - = note: expected type `!` - found unit type `()` - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs deleted file mode 100644 index ea9ad39a70d81..0000000000000 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.rs +++ /dev/null @@ -1,15 +0,0 @@ -// compile-flags:-C panic=abort - -#![feature(alloc_error_handler)] -#![no_std] -#![no_main] - -struct Layout; - -#[alloc_error_handler] -fn oom() -> ! { //~ ERROR function takes 0 arguments but 1 argument was supplied - loop {} -} - -#[panic_handler] -fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr deleted file mode 100644 index eb739b149a103..0000000000000 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0061]: this function takes 0 arguments but 1 argument was supplied - --> $DIR/alloc-error-handler-bad-signature-3.rs:10:1 - | -LL | #[alloc_error_handler] - | ---------------------- in this procedural macro expansion -LL | fn oom() -> ! { - | _-^^^^^^^^^^^^ -LL | | loop {} -LL | | } - | |_- unexpected argument of type `core::alloc::Layout` - | -note: function defined here - --> $DIR/alloc-error-handler-bad-signature-3.rs:10:4 - | -LL | fn oom() -> ! { - | ^^^ - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/alloc-error/default-alloc-error-hook.rs b/tests/ui/alloc-error/default-alloc-error-hook.rs index 8be09500f4e4e..919d4b714a1ae 100644 --- a/tests/ui/alloc-error/default-alloc-error-hook.rs +++ b/tests/ui/alloc-error/default-alloc-error-hook.rs @@ -2,7 +2,7 @@ // ignore-emscripten no processes // ignore-sgx no processes -use std::alloc::{Layout, handle_alloc_error}; +use std::alloc::{handle_alloc_error, Layout}; use std::env; use std::process::Command; use std::str; @@ -24,5 +24,5 @@ fn main() { .strip_suffix("qemu: uncaught target signal 6 (Aborted) - core dumped\n") .unwrap_or(stderr); - assert_eq!(stderr, "memory allocation of 42 bytes failed\n"); + assert!(stderr.contains("memory allocation of 42 bytes failed")); } diff --git a/tests/ui/allocator/no_std-alloc-error-handler-custom.rs b/tests/ui/allocator/no_std-alloc-error-handler-custom.rs deleted file mode 100644 index 2892624339093..0000000000000 --- a/tests/ui/allocator/no_std-alloc-error-handler-custom.rs +++ /dev/null @@ -1,84 +0,0 @@ -// run-pass -// ignore-android no libc -// ignore-emscripten no libc -// ignore-sgx no libc -// ignore-wasm32 no libc -// only-linux -// compile-flags:-C panic=abort -// aux-build:helper.rs - -#![feature(rustc_private, lang_items)] -#![feature(alloc_error_handler)] -#![no_std] -#![no_main] - -extern crate alloc; -extern crate libc; - -// ARM targets need these symbols -#[no_mangle] -pub fn __aeabi_unwind_cpp_pr0() {} - -#[no_mangle] -pub fn __aeabi_unwind_cpp_pr1() {} - -use alloc::boxed::Box; -use alloc::string::ToString; -use core::alloc::{GlobalAlloc, Layout}; -use core::ptr::null_mut; - -extern crate helper; - -struct MyAllocator; - -#[alloc_error_handler] -fn my_oom(layout: Layout) -> ! { - use alloc::fmt::write; - unsafe { - let size = layout.size(); - let mut s = alloc::string::String::new(); - write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap(); - libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len()); - libc::exit(0) - } -} - -unsafe impl GlobalAlloc for MyAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() } - } - unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} -} - -#[global_allocator] -static A: MyAllocator = MyAllocator; - -#[panic_handler] -fn panic(panic_info: &core::panic::PanicInfo) -> ! { - unsafe { - let s = panic_info.to_string(); - const PSTR: &str = "panic occurred: "; - const CR: &str = "\n"; - libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len()); - libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len()); - libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len()); - libc::exit(1) - } -} - -// Because we are compiling this code with `-C panic=abort`, this wouldn't normally be needed. -// However, `core` and `alloc` are both compiled with `-C panic=unwind`, which means that functions -// in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't -// unwind. So, for this test case we will define the symbol. -#[lang = "eh_personality"] -extern "C" fn rust_eh_personality() {} - -#[derive(Default, Debug)] -struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]); - -#[no_mangle] -fn main(_argc: i32, _argv: *const *const u8) -> isize { - let zero = Box::::new(Default::default()); - helper::work_with(&zero); - 1 -} diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs b/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs deleted file mode 100644 index 78d189d20b64d..0000000000000 --- a/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs +++ /dev/null @@ -1,16 +0,0 @@ -// compile-flags:-C panic=abort - -#![no_std] -#![no_main] - -use core::alloc::Layout; - -#[alloc_error_handler] //~ ERROR use of unstable library feature 'alloc_error_handler' -fn oom(info: Layout) -> ! { - loop {} -} - -#[panic_handler] -fn panic(_: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr deleted file mode 100644 index f414eb463dfbc..0000000000000 --- a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: use of unstable library feature 'alloc_error_handler' - --> $DIR/feature-gate-alloc-error-handler.rs:8:3 - | -LL | #[alloc_error_handler] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #51540 for more information - = help: add `#![feature(alloc_error_handler)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/missing/missing-allocator.rs b/tests/ui/missing/missing-allocator.rs index 2dc509f2c632d..e06e603e3bf94 100644 --- a/tests/ui/missing/missing-allocator.rs +++ b/tests/ui/missing/missing-allocator.rs @@ -3,16 +3,10 @@ #![no_std] #![crate_type = "staticlib"] -#![feature(alloc_error_handler)] #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { loop {} } -#[alloc_error_handler] -fn oom(_: core::alloc::Layout) -> ! { - loop {} -} - extern crate alloc; From 42c0fc70c043c085e3aff310678d2ab5d2e868b4 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 21 Apr 2023 09:29:55 -0700 Subject: [PATCH 3/4] Adjust expected result for coverage test --- library/alloc/src/alloc.rs | 10 +++++----- tests/run-coverage/issue-84561.coverage | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index badae49551cb7..2260d06989dbf 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -419,15 +419,15 @@ fn rust_oom(layout: Layout) -> ! { /// rather than directly invoking [`panic!`] or similar. /// /// This function triggers a panic with a special payload of [`AllocErrorPanicPayload`] that holds -/// the [`Layout`] passed into this function. +/// information about the allocation that failed. /// /// There are 2 ways in which such panics can be handled: /// /// * If the binary links against `std` (typically the case), then -/// the payload is available through [`PanicInfo::payload`][std_payload]. By default, panics caused by this -/// function will always abort the process instead of unwinding. This can be overridden by -/// compiling the program with the `-Z oom=unwind` option, in which case the payload is captured -/// and can be recovered through the [`catch_unwind`] function. +/// the payload is available through [`PanicInfo::payload`][std_payload]. +/// By default, panics caused by thisfunction will always abort the process instead of unwinding. +/// This can be overridden by compiling the program with the `-Z oom=unwind` option, in which case +/// the payload is captured and can be recovered through the [`catch_unwind`] function. /// /// * If the binary does not link against `std` (all of its crates are marked /// [`#![no_std]`][no_std]), then [the panic handler] is called. The payload is available through diff --git a/tests/run-coverage/issue-84561.coverage b/tests/run-coverage/issue-84561.coverage index 222f877d36aad..6d663ec7a2f05 100644 --- a/tests/run-coverage/issue-84561.coverage +++ b/tests/run-coverage/issue-84561.coverage @@ -136,10 +136,10 @@ LL| | LL| |impl std::fmt::Debug for Foo { LL| | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - LL| 7| write!(f, "try and succeed")?; + LL| 9| write!(f, "try and succeed")?; ^0 - LL| 7| Ok(()) - LL| 7| } + LL| 9| Ok(()) + LL| 9| } LL| |} LL| | LL| |static mut DEBUG_LEVEL_ENABLED: bool = false; From 8a24112186e89ca167e6d291fff080dbf73b7304 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 6 Jun 2023 15:52:48 +0100 Subject: [PATCH 4/4] Ensure `panic!` messages are only formatted once --- library/std/src/panicking.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 735d230a9de91..8ab84e7dcea08 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -252,20 +252,20 @@ fn default_hook(info: &PanicInfo<'_>) { let name = thread.as_ref().and_then(|t| t.name()).unwrap_or(""); let write = |err: &mut dyn crate::io::Write| { - // Use the panic message directly if available, otherwise take it from - // the payload. - if let Some(msg) = info.message() { - let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}"); + // The std panic runtime always sets a `&str` or `String` payload for `panic!` and related + // macros with the formatted message. + // We try using the payload first to avoid formatting the message twice. + let msg: &dyn fmt::Display = if let Some(s) = info.payload().downcast_ref::<&'static str>() + { + s + } else if let Some(s) = info.payload().downcast_ref::() { + s + } else if let Some(msg) = info.message() { + msg } else { - let msg = if let Some(s) = info.payload().downcast_ref::<&'static str>() { - *s - } else if let Some(s) = info.payload().downcast_ref::() { - &s[..] - } else { - "Box" - }; - let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}"); - } + &"Box" + }; + let _ = writeln!(err, "thread '{name}' panicked at {location}:\n{msg}"); static FIRST_PANIC: AtomicBool = AtomicBool::new(true);