diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl
index d1e1fd54db9..b3ca540417d 100644
--- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl
@@ -166,12 +166,6 @@ metadata_conflicting_alloc_error_handler =
 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
 
-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 =
     the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`
 
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 7678ce323df..e5348039edd 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -126,6 +126,8 @@ declare_features! (
     (accepted, copy_closures, "1.26.0", Some(44490), None),
     /// Allows `crate` in paths.
     (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.
     (accepted, default_type_params, "1.0.0", None, None),
     /// Allows `#[deprecated]` attribute.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 69c5297bf6b..a616dd70f8e 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -368,8 +368,6 @@ declare_features! (
     (active, debugger_visualizer, "1.62.0", Some(95939), None),
     /// Allows declarative macros 2.0 (`macro`).
     (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.
     (active, default_type_parameter_fallback, "1.3.0", Some(27336), None),
     /// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 01d7f3e03c5..9ce3ff98ba9 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -1,10 +1,9 @@
 //! Validates all used crates and extern libraries and loads their metadata
 
 use crate::errors::{
-    AllocFuncRequired, ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
-    GlobalAllocRequired, MissingAllocErrorHandler, NoMultipleAllocErrorHandler,
-    NoMultipleGlobalAlloc, NoPanicStrategy, NoTransitiveNeedsDep, NotProfilerRuntime,
-    ProfilerBuiltinsNeedsCore,
+    ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
+    GlobalAllocRequired, NoMultipleAllocErrorHandler, NoMultipleGlobalAlloc, NoPanicStrategy,
+    NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
 };
 use crate::locator::{CrateError, CrateLocator, CratePaths};
 use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
@@ -895,10 +894,6 @@ impl<'a> CrateLoader<'a> {
         } else {
             // The alloc crate provides a default allocation error handler if
             // 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);
         }
     }
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index 6f7e6e09ca5..de2a879f1d7 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -371,14 +371,6 @@ pub struct ConflictingAllocErrorHandler {
 #[diag(metadata_global_alloc_required)]
 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)]
 #[diag(metadata_no_transitive_needs_dep)]
 pub struct NoTransitiveNeedsDep<'a> {
diff --git a/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs b/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs
index 851da231a73..28926243390 100644
--- a/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs
+++ b/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs
@@ -7,9 +7,10 @@
 // compile-flags:-C panic=abort
 // aux-build:helper.rs
 
-#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
+#![feature(rustc_private, lang_items)]
 #![feature(alloc_error_handler)]
 #![no_std]
+#![no_main]
 
 extern crate alloc;
 extern crate libc;
@@ -21,35 +22,30 @@ pub fn __aeabi_unwind_cpp_pr0() {}
 #[no_mangle]
 pub fn __aeabi_unwind_cpp_pr1() {}
 
-use core::ptr::null_mut;
-use core::alloc::{GlobalAlloc, Layout};
 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) -> !
-{
+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();
-        let s = s.as_str();
-        libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len());
+        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()
-        }
+        if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() }
     }
     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
 }
@@ -60,26 +56,12 @@ static A: MyAllocator = MyAllocator;
 #[panic_handler]
 fn panic(panic_info: &core::panic::PanicInfo) -> ! {
     unsafe {
-        if let Some(s) = panic_info.payload().downcast_ref::<&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());
-        }
-        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());
-        }
+        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)
     }
 }
@@ -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
 // unwind. So, for this test case we will define the symbol.
 #[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]);
 
-#[start]
-pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
-    let zero = Box::<Page>::new_zeroed();
-    let zero = unsafe { zero.assume_init() };
+#[no_mangle]
+fn main(_argc: i32, _argv: *const *const u8) -> isize {
+    let zero = Box::<Page>::new(Default::default());
     helper::work_with(&zero);
     1
 }
diff --git a/src/test/ui/allocator/no_std-alloc-error-handler-default.rs b/src/test/ui/allocator/no_std-alloc-error-handler-default.rs
index 30ce0f162c7..56409e71339 100644
--- a/src/test/ui/allocator/no_std-alloc-error-handler-default.rs
+++ b/src/test/ui/allocator/no_std-alloc-error-handler-default.rs
@@ -6,11 +6,10 @@
 // only-linux
 // compile-flags:-C panic=abort
 // aux-build:helper.rs
-// gate-test-default_alloc_error_handler
 
-#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
-#![feature(default_alloc_error_handler)]
+#![feature(rustc_private, lang_items)]
 #![no_std]
+#![no_main]
 
 extern crate alloc;
 extern crate libc;
@@ -23,6 +22,7 @@ pub fn __aeabi_unwind_cpp_pr0() {}
 pub fn __aeabi_unwind_cpp_pr1() {}
 
 use alloc::boxed::Box;
+use alloc::string::ToString;
 use core::alloc::{GlobalAlloc, Layout};
 use core::ptr::null_mut;
 
@@ -32,11 +32,7 @@ struct MyAllocator;
 
 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()
-        }
+        if layout.size() < 4096 { libc::malloc(layout.size()) as _ } else { null_mut() }
     }
     unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
 }
@@ -47,26 +43,12 @@ static A: MyAllocator = MyAllocator;
 #[panic_handler]
 fn panic(panic_info: &core::panic::PanicInfo) -> ! {
     unsafe {
-        if let Some(s) = panic_info.payload().downcast_ref::<&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());
-        }
-        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());
-        }
+        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(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
 // unwind. So, for this test case we will define the symbol.
 #[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]);
 
-#[start]
-pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
-    let zero = Box::<Page>::new_zeroed();
-    let zero = unsafe { zero.assume_init() };
+#[no_mangle]
+fn main(_argc: i32, _argv: *const *const u8) -> isize {
+    let zero = Box::<Page>::new(Default::default());
     helper::work_with(&zero);
     1
 }
diff --git a/src/test/ui/missing/missing-alloc_error_handler.rs b/src/test/ui/missing/missing-alloc_error_handler.rs
deleted file mode 100644
index 4d378f010ed..00000000000
--- a/src/test/ui/missing/missing-alloc_error_handler.rs
+++ /dev/null
@@ -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) {}
-}
diff --git a/src/test/ui/missing/missing-alloc_error_handler.stderr b/src/test/ui/missing/missing-alloc_error_handler.stderr
deleted file mode 100644
index 995fa7cf85e..00000000000
--- a/src/test/ui/missing/missing-alloc_error_handler.stderr
+++ /dev/null
@@ -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
-