mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #102318 - Amanieu:default_alloc_error_handler, r=oli-obk
Stabilize default_alloc_error_handler Tracking issue: #66741 This turns `feature(default_alloc_error_handler)` on by default, which causes the compiler to automatically generate a default OOM handler which panics if `#[alloc_error_handler]` is not provided. The FCP completed over 2 years ago but the stabilization was blocked due to an issue with unwinding. This was fixed by #88098 so stabilization can be unblocked. Closes #66741
This commit is contained in:
commit
bbb9cfbbc5
@ -166,12 +166,6 @@ metadata_conflicting_alloc_error_handler =
|
|||||||
metadata_global_alloc_required =
|
metadata_global_alloc_required =
|
||||||
no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
|
no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
|
||||||
|
|
||||||
metadata_alloc_func_required =
|
|
||||||
`#[alloc_error_handler]` function required, but not found
|
|
||||||
|
|
||||||
metadata_missing_alloc_error_handler =
|
|
||||||
use `#![feature(default_alloc_error_handler)]` for a default error handler
|
|
||||||
|
|
||||||
metadata_no_transitive_needs_dep =
|
metadata_no_transitive_needs_dep =
|
||||||
the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
|
the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
|
||||||
|
|
||||||
|
@ -126,6 +126,8 @@ declare_features! (
|
|||||||
(accepted, copy_closures, "1.26.0", Some(44490), None),
|
(accepted, copy_closures, "1.26.0", Some(44490), None),
|
||||||
/// Allows `crate` in paths.
|
/// Allows `crate` in paths.
|
||||||
(accepted, crate_in_paths, "1.30.0", Some(45477), None),
|
(accepted, crate_in_paths, "1.30.0", Some(45477), None),
|
||||||
|
/// Allows rustc to inject a default alloc_error_handler
|
||||||
|
(accepted, default_alloc_error_handler, "CURRENT_RUSTC_VERSION", Some(66741), None),
|
||||||
/// Allows using assigning a default type to type parameters in algebraic data type definitions.
|
/// Allows using assigning a default type to type parameters in algebraic data type definitions.
|
||||||
(accepted, default_type_params, "1.0.0", None, None),
|
(accepted, default_type_params, "1.0.0", None, None),
|
||||||
/// Allows `#[deprecated]` attribute.
|
/// Allows `#[deprecated]` attribute.
|
||||||
|
@ -368,8 +368,6 @@ declare_features! (
|
|||||||
(active, debugger_visualizer, "1.62.0", Some(95939), None),
|
(active, debugger_visualizer, "1.62.0", Some(95939), None),
|
||||||
/// Allows declarative macros 2.0 (`macro`).
|
/// Allows declarative macros 2.0 (`macro`).
|
||||||
(active, decl_macro, "1.17.0", Some(39412), None),
|
(active, decl_macro, "1.17.0", Some(39412), None),
|
||||||
/// Allows rustc to inject a default alloc_error_handler
|
|
||||||
(active, default_alloc_error_handler, "1.48.0", Some(66741), None),
|
|
||||||
/// Allows default type parameters to influence type inference.
|
/// Allows default type parameters to influence type inference.
|
||||||
(active, default_type_parameter_fallback, "1.3.0", Some(27336), None),
|
(active, default_type_parameter_fallback, "1.3.0", Some(27336), None),
|
||||||
/// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
|
/// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
//! Validates all used crates and extern libraries and loads their metadata
|
//! Validates all used crates and extern libraries and loads their metadata
|
||||||
|
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
AllocFuncRequired, ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
|
ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
|
||||||
GlobalAllocRequired, MissingAllocErrorHandler, NoMultipleAllocErrorHandler,
|
GlobalAllocRequired, NoMultipleAllocErrorHandler, NoMultipleGlobalAlloc, NoPanicStrategy,
|
||||||
NoMultipleGlobalAlloc, NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime,
|
NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
|
||||||
ProfilerBuiltinsNeedsCore,
|
|
||||||
};
|
};
|
||||||
use crate::locator::{CrateError, CrateLocator, CratePaths};
|
use crate::locator::{CrateError, CrateLocator, CratePaths};
|
||||||
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
|
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
|
||||||
@ -895,10 +894,6 @@ impl<'a> CrateLoader<'a> {
|
|||||||
} else {
|
} else {
|
||||||
// The alloc crate provides a default allocation error handler if
|
// The alloc crate provides a default allocation error handler if
|
||||||
// one isn't specified.
|
// one isn't specified.
|
||||||
if !self.sess.features_untracked().default_alloc_error_handler {
|
|
||||||
self.sess.emit_err(AllocFuncRequired);
|
|
||||||
self.sess.emit_note(MissingAllocErrorHandler);
|
|
||||||
}
|
|
||||||
self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default);
|
self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,14 +371,6 @@ pub struct ConflictingAllocErrorHandler {
|
|||||||
#[diag(metadata_global_alloc_required)]
|
#[diag(metadata_global_alloc_required)]
|
||||||
pub struct GlobalAllocRequired;
|
pub struct GlobalAllocRequired;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(metadata_alloc_func_required)]
|
|
||||||
pub struct AllocFuncRequired;
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(metadata_missing_alloc_error_handler)]
|
|
||||||
pub struct MissingAllocErrorHandler;
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(metadata_no_transitive_needs_dep)]
|
#[diag(metadata_no_transitive_needs_dep)]
|
||||||
pub struct NoTransitiveNeedsDep<'a> {
|
pub struct NoTransitiveNeedsDep<'a> {
|
||||||
|
@ -7,9 +7,10 @@
|
|||||||
// compile-flags:-C panic=abort
|
// compile-flags:-C panic=abort
|
||||||
// aux-build:helper.rs
|
// aux-build:helper.rs
|
||||||
|
|
||||||
#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
|
#![feature(rustc_private, lang_items)]
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
@ -21,35 +22,30 @@ pub fn __aeabi_unwind_cpp_pr0() {}
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn __aeabi_unwind_cpp_pr1() {}
|
pub fn __aeabi_unwind_cpp_pr1() {}
|
||||||
|
|
||||||
use core::ptr::null_mut;
|
|
||||||
use core::alloc::{GlobalAlloc, Layout};
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
use alloc::string::ToString;
|
||||||
|
use core::alloc::{GlobalAlloc, Layout};
|
||||||
|
use core::ptr::null_mut;
|
||||||
|
|
||||||
extern crate helper;
|
extern crate helper;
|
||||||
|
|
||||||
struct MyAllocator;
|
struct MyAllocator;
|
||||||
|
|
||||||
#[alloc_error_handler]
|
#[alloc_error_handler]
|
||||||
fn my_oom(layout: Layout) -> !
|
fn my_oom(layout: Layout) -> ! {
|
||||||
{
|
|
||||||
use alloc::fmt::write;
|
use alloc::fmt::write;
|
||||||
unsafe {
|
unsafe {
|
||||||
let size = layout.size();
|
let size = layout.size();
|
||||||
let mut s = alloc::string::String::new();
|
let mut s = alloc::string::String::new();
|
||||||
write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap();
|
write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap();
|
||||||
let s = s.as_str();
|
libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
|
||||||
libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
|
|
||||||
libc::exit(0)
|
libc::exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl GlobalAlloc for MyAllocator {
|
unsafe impl GlobalAlloc for MyAllocator {
|
||||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
if layout.size() < 4096 {
|
if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() }
|
||||||
libc::malloc(layout.size()) as _
|
|
||||||
} else {
|
|
||||||
null_mut()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
|
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
|
||||||
}
|
}
|
||||||
@ -60,26 +56,12 @@ static A: MyAllocator = MyAllocator;
|
|||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
let s = panic_info.to_string();
|
||||||
const PSTR: &str = "panic occurred: ";
|
const PSTR: &str = "panic occurred: ";
|
||||||
const CR: &str = "\n";
|
const CR: &str = "\n";
|
||||||
libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
|
libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len());
|
||||||
libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
|
libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
|
||||||
libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
|
libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len());
|
||||||
}
|
|
||||||
if let Some(args) = panic_info.message() {
|
|
||||||
let mut s = alloc::string::String::new();
|
|
||||||
alloc::fmt::write(&mut s, *args).unwrap();
|
|
||||||
let s = s.as_str();
|
|
||||||
const PSTR: &str = "panic occurred: ";
|
|
||||||
const CR: &str = "\n";
|
|
||||||
libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
|
|
||||||
libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
|
|
||||||
libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
|
|
||||||
} else {
|
|
||||||
const PSTR: &str = "panic occurred\n";
|
|
||||||
libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
|
|
||||||
}
|
|
||||||
libc::exit(1)
|
libc::exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,15 +71,14 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
|||||||
// in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't
|
// 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.
|
// unwind. So, for this test case we will define the symbol.
|
||||||
#[lang = "eh_personality"]
|
#[lang = "eh_personality"]
|
||||||
extern fn rust_eh_personality() {}
|
extern "C" fn rust_eh_personality() {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Default, Debug)]
|
||||||
struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
|
struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
|
||||||
|
|
||||||
#[start]
|
#[no_mangle]
|
||||||
pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: i32, _argv: *const *const u8) -> isize {
|
||||||
let zero = Box::<Page>::new_zeroed();
|
let zero = Box::<Page>::new(Default::default());
|
||||||
let zero = unsafe { zero.assume_init() };
|
|
||||||
helper::work_with(&zero);
|
helper::work_with(&zero);
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,10 @@
|
|||||||
// only-linux
|
// only-linux
|
||||||
// compile-flags:-C panic=abort
|
// compile-flags:-C panic=abort
|
||||||
// aux-build:helper.rs
|
// aux-build:helper.rs
|
||||||
// gate-test-default_alloc_error_handler
|
|
||||||
|
|
||||||
#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
|
#![feature(rustc_private, lang_items)]
|
||||||
#![feature(default_alloc_error_handler)]
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
@ -23,6 +22,7 @@ pub fn __aeabi_unwind_cpp_pr0() {}
|
|||||||
pub fn __aeabi_unwind_cpp_pr1() {}
|
pub fn __aeabi_unwind_cpp_pr1() {}
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
use alloc::string::ToString;
|
||||||
use core::alloc::{GlobalAlloc, Layout};
|
use core::alloc::{GlobalAlloc, Layout};
|
||||||
use core::ptr::null_mut;
|
use core::ptr::null_mut;
|
||||||
|
|
||||||
@ -32,11 +32,7 @@ struct MyAllocator;
|
|||||||
|
|
||||||
unsafe impl GlobalAlloc for MyAllocator {
|
unsafe impl GlobalAlloc for MyAllocator {
|
||||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
if layout.size() < 4096 {
|
if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() }
|
||||||
libc::malloc(layout.size()) as _
|
|
||||||
} else {
|
|
||||||
null_mut()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
|
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
|
||||||
}
|
}
|
||||||
@ -47,26 +43,12 @@ static A: MyAllocator = MyAllocator;
|
|||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
|
let s = panic_info.to_string();
|
||||||
const PSTR: &str = "panic occurred: ";
|
const PSTR: &str = "panic occurred: ";
|
||||||
const CR: &str = "\n";
|
const CR: &str = "\n";
|
||||||
libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
|
libc::write(libc::STDERR_FILENO, PSTR.as_ptr() as *const _, PSTR.len());
|
||||||
libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
|
libc::write(libc::STDERR_FILENO, s.as_ptr() as *const _, s.len());
|
||||||
libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
|
libc::write(libc::STDERR_FILENO, CR.as_ptr() as *const _, CR.len());
|
||||||
}
|
|
||||||
if let Some(args) = panic_info.message() {
|
|
||||||
let mut s = alloc::string::String::new();
|
|
||||||
alloc::fmt::write(&mut s, *args).unwrap();
|
|
||||||
let s = s.as_str();
|
|
||||||
const PSTR: &str = "panic occurred: ";
|
|
||||||
const CR: &str = "\n";
|
|
||||||
libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
|
|
||||||
libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
|
|
||||||
libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len());
|
|
||||||
} else {
|
|
||||||
const PSTR: &str = "panic occurred\n";
|
|
||||||
libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len());
|
|
||||||
}
|
|
||||||
libc::exit(0)
|
libc::exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,15 +58,14 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
|
|||||||
// in these libraries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't
|
// 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.
|
// unwind. So, for this test case we will define the symbol.
|
||||||
#[lang = "eh_personality"]
|
#[lang = "eh_personality"]
|
||||||
extern fn rust_eh_personality() {}
|
extern "C" fn rust_eh_personality() {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Default, Debug)]
|
||||||
struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
|
struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
|
||||||
|
|
||||||
#[start]
|
#[no_mangle]
|
||||||
pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: i32, _argv: *const *const u8) -> isize {
|
||||||
let zero = Box::<Page>::new_zeroed();
|
let zero = Box::<Page>::new(Default::default());
|
||||||
let zero = unsafe { zero.assume_init() };
|
|
||||||
helper::work_with(&zero);
|
helper::work_with(&zero);
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// compile-flags: -C panic=abort
|
|
||||||
// no-prefer-dynamic
|
|
||||||
|
|
||||||
#![no_std]
|
|
||||||
#![crate_type = "staticlib"]
|
|
||||||
#![feature(alloc_error_handler)]
|
|
||||||
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern crate alloc;
|
|
||||||
|
|
||||||
#[global_allocator]
|
|
||||||
static A: MyAlloc = MyAlloc;
|
|
||||||
|
|
||||||
struct MyAlloc;
|
|
||||||
|
|
||||||
unsafe impl core::alloc::GlobalAlloc for MyAlloc {
|
|
||||||
unsafe fn alloc(&self, _: core::alloc::Layout) -> *mut u8 { 0 as _ }
|
|
||||||
unsafe fn dealloc(&self, _: *mut u8, _: core::alloc::Layout) {}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
error: `#[alloc_error_handler]` function required, but not found
|
|
||||||
|
|
||||||
note: use `#![feature(default_alloc_error_handler)]` for a default error handler
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user