about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-04-22 19:38:32 +0000
committerbors <bors@rust-lang.org>2018-04-22 19:38:32 +0000
commite02868793bdb0e83d2ecee295bdc16f6b2e5a142 (patch)
treeae75a61ad074096fc00e977a2774a833dc3ba0ed
parentff48277add047928dcd19d64ffe93c46b0612a4d (diff)
parent5969712c3f2163b7ca6f809e0f5e31f73e8898bb (diff)
downloadrust-e02868793bdb0e83d2ecee295bdc16f6b2e5a142.tar.gz
rust-e02868793bdb0e83d2ecee295bdc16f6b2e5a142.zip
Auto merge of #50144 - sfackler:oom-lang-item, r=alexcrichton
Replace {Alloc,GlobalAlloc}::oom with a lang item.

The decision of what to do after an allocation fails is orthogonal to the decision of how to allocate the memory, so this PR splits them apart. `Alloc::oom` and `GlobalAlloc::oom` have been removed, and a lang item has been added:

```rust
#[lang = "oom"]
fn oom() -> !;
```

It is specifically a weak lang item, like panic_fmt, except that it is required when you depend on liballoc rather than libcore. libstd provides an implementation that aborts with the message `fatal runtime error: memory allocation failed`, matching the current behavior.

The new implementation is also significantly simpler - it's "just another weak lang item". [RFC 2070](https://github.com/rust-lang/rfcs/blob/master/text/2070-panic-implementation.md) specifies a path towards stabilizing panic_fmt, so any complexities around stable weak lang item definition are already being solved.

To bootstrap, oom silently aborts in stage0. alloc_system no longer has a bunch of code to print to stderr, and alloc_jemalloc no longer depends on alloc_system to pull in that code.

One fun note: System's GlobalAlloc implementation didn't override the default implementation of oom, so it currently aborts silently!

r? @alexcrichton
-rw-r--r--src/Cargo.lock1
-rw-r--r--src/liballoc/alloc.rs38
-rw-r--r--src/liballoc/arc.rs4
-rw-r--r--src/liballoc/heap.rs2
-rw-r--r--src/liballoc/raw_vec.rs14
-rw-r--r--src/liballoc/rc.rs4
-rw-r--r--src/liballoc_jemalloc/Cargo.toml1
-rw-r--r--src/liballoc_jemalloc/lib.rs8
-rw-r--r--src/liballoc_system/lib.rs70
-rw-r--r--src/libcore/alloc.rs37
-rw-r--r--src/librustc/middle/lang_items.rs3
-rw-r--r--src/librustc/middle/weak_lang_items.rs1
-rw-r--r--src/librustc_allocator/expand.rs4
-rw-r--r--src/librustc_allocator/lib.rs6
-rw-r--r--src/librustc_trans/allocator.rs2
-rw-r--r--src/libstd/alloc.rs13
-rw-r--r--src/libstd/collections/hash/map.rs4
-rw-r--r--src/libstd/collections/hash/table.rs6
-rw-r--r--src/libstd/lib.rs3
-rw-r--r--src/test/compile-fail/allocator/not-an-allocator.rs1
-rw-r--r--src/test/run-pass/allocator-alloc-one.rs6
-rw-r--r--src/test/run-pass/realloc-16687.rs6
-rw-r--r--src/test/run-pass/regions-mock-trans.rs4
23 files changed, 61 insertions, 177 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index d7d23f0fa80..6f054dc61a5 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -19,7 +19,6 @@ dependencies = [
 name = "alloc_jemalloc"
 version = "0.0.0"
 dependencies = [
- "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs
index 68a617e0ffe..c0372d24ed5 100644
--- a/src/liballoc/alloc.rs
+++ b/src/liballoc/alloc.rs
@@ -48,9 +48,6 @@ extern "Rust" {
     #[allocator]
     #[rustc_allocator_nounwind]
     fn __rust_alloc(size: usize, align: usize) -> *mut u8;
-    #[cold]
-    #[rustc_allocator_nounwind]
-    fn __rust_oom() -> !;
     #[rustc_allocator_nounwind]
     fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
     #[rustc_allocator_nounwind]
@@ -107,16 +104,6 @@ unsafe impl GlobalAlloc for Global {
         let ptr = __rust_alloc_zeroed(layout.size(), layout.align(), &mut 0);
         ptr as *mut Opaque
     }
-
-    #[inline]
-    fn oom(&self) -> ! {
-        unsafe {
-            #[cfg(not(stage0))]
-            __rust_oom();
-            #[cfg(stage0)]
-            __rust_oom(&mut 0);
-        }
-    }
 }
 
 unsafe impl Alloc for Global {
@@ -144,11 +131,6 @@ unsafe impl Alloc for Global {
     unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
         NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
     }
-
-    #[inline]
-    fn oom(&mut self) -> ! {
-        GlobalAlloc::oom(self)
-    }
 }
 
 /// The allocator for unique pointers.
@@ -165,7 +147,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
         if !ptr.is_null() {
             ptr as *mut u8
         } else {
-            Global.oom()
+            oom()
         }
     }
 }
@@ -182,19 +164,33 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
     }
 }
 
+#[cfg(stage0)]
+pub fn oom() -> ! {
+    unsafe { ::core::intrinsics::abort() }
+}
+
+#[cfg(not(stage0))]
+pub fn oom() -> ! {
+    extern {
+        #[lang = "oom"]
+        fn oom_impl() -> !;
+    }
+    unsafe { oom_impl() }
+}
+
 #[cfg(test)]
 mod tests {
     extern crate test;
     use self::test::Bencher;
     use boxed::Box;
-    use alloc::{Global, Alloc, Layout};
+    use alloc::{Global, Alloc, Layout, oom};
 
     #[test]
     fn allocate_zeroed() {
         unsafe {
             let layout = Layout::from_size_align(1024, 1).unwrap();
             let ptr = Global.alloc_zeroed(layout.clone())
-                .unwrap_or_else(|_| Global.oom());
+                .unwrap_or_else(|_| oom());
 
             let mut i = ptr.cast::<u8>().as_ptr();
             let end = i.offset(layout.size() as isize);
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 225b055d8ee..f5980f4599e 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -31,7 +31,7 @@ use core::hash::{Hash, Hasher};
 use core::{isize, usize};
 use core::convert::From;
 
-use alloc::{Global, Alloc, Layout, box_free};
+use alloc::{Global, Alloc, Layout, box_free, oom};
 use boxed::Box;
 use string::String;
 use vec::Vec;
@@ -553,7 +553,7 @@ impl<T: ?Sized> Arc<T> {
         let layout = Layout::for_value(&*fake_ptr);
 
         let mem = Global.alloc(layout)
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
 
         // Initialize the real ArcInner
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index faac38ca7ce..16f0630b911 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -59,7 +59,7 @@ unsafe impl<T> Alloc for T where T: CoreAlloc {
     }
 
     fn oom(&mut self, _: AllocErr) -> ! {
-        CoreAlloc::oom(self)
+        unsafe { ::core::intrinsics::abort() }
     }
 
     fn usable_size(&self, layout: &Layout) -> (usize, usize) {
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 24b7cd3db0c..7ef0a27fc72 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -14,7 +14,7 @@ use core::ops::Drop;
 use core::ptr::{self, NonNull, Unique};
 use core::slice;
 
-use alloc::{Alloc, Layout, Global};
+use alloc::{Alloc, Layout, Global, oom};
 use alloc::CollectionAllocErr;
 use alloc::CollectionAllocErr::*;
 use boxed::Box;
@@ -101,7 +101,7 @@ impl<T, A: Alloc> RawVec<T, A> {
                 };
                 match result {
                     Ok(ptr) => ptr,
-                    Err(_) => a.oom(),
+                    Err(_) => oom(),
                 }
             };
 
@@ -316,7 +316,7 @@ impl<T, A: Alloc> RawVec<T, A> {
                                                  new_size);
                     match ptr_res {
                         Ok(ptr) => (new_cap, ptr.cast().into()),
-                        Err(_) => self.a.oom(),
+                        Err(_) => oom(),
                     }
                 }
                 None => {
@@ -325,7 +325,7 @@ impl<T, A: Alloc> RawVec<T, A> {
                     let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
                     match self.a.alloc_array::<T>(new_cap) {
                         Ok(ptr) => (new_cap, ptr.into()),
-                        Err(_) => self.a.oom(),
+                        Err(_) => oom(),
                     }
                 }
             };
@@ -442,7 +442,7 @@ impl<T, A: Alloc> RawVec<T, A> {
     pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) {
         match self.try_reserve_exact(used_cap, needed_extra_cap) {
             Err(CapacityOverflow) => capacity_overflow(),
-            Err(AllocErr) => self.a.oom(),
+            Err(AllocErr) => oom(),
             Ok(()) => { /* yay */ }
          }
      }
@@ -552,7 +552,7 @@ impl<T, A: Alloc> RawVec<T, A> {
     pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
         match self.try_reserve(used_cap, needed_extra_cap) {
             Err(CapacityOverflow) => capacity_overflow(),
-            Err(AllocErr) => self.a.oom(),
+            Err(AllocErr) => oom(),
             Ok(()) => { /* yay */ }
          }
      }
@@ -667,7 +667,7 @@ impl<T, A: Alloc> RawVec<T, A> {
                                      old_layout,
                                      new_size) {
                     Ok(p) => self.ptr = p.cast().into(),
-                    Err(_) => self.a.oom(),
+                    Err(_) => oom(),
                 }
             }
             self.cap = amount;
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index de0422d82bb..8fb8e111754 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -259,7 +259,7 @@ use core::ops::CoerceUnsized;
 use core::ptr::{self, NonNull};
 use core::convert::From;
 
-use alloc::{Global, Alloc, Layout, Opaque, box_free};
+use alloc::{Global, Alloc, Layout, Opaque, box_free, oom};
 use string::String;
 use vec::Vec;
 
@@ -668,7 +668,7 @@ impl<T: ?Sized> Rc<T> {
         let layout = Layout::for_value(&*fake_ptr);
 
         let mem = Global.alloc(layout)
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
 
         // Initialize the real RcBox
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml
index 02435170374..7986d5dd2eb 100644
--- a/src/liballoc_jemalloc/Cargo.toml
+++ b/src/liballoc_jemalloc/Cargo.toml
@@ -12,7 +12,6 @@ test = false
 doc = false
 
 [dependencies]
-alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
index 2b66c293f21..4b8755877de 100644
--- a/src/liballoc_jemalloc/lib.rs
+++ b/src/liballoc_jemalloc/lib.rs
@@ -14,7 +14,7 @@
             reason = "this library is unlikely to be stabilized in its current \
                       form or name",
             issue = "27783")]
-#![feature(alloc_system)]
+#![feature(core_intrinsics)]
 #![feature(libc)]
 #![feature(linkage)]
 #![feature(staged_api)]
@@ -23,15 +23,12 @@
 #![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
 #![rustc_alloc_kind = "exe"]
 
-extern crate alloc_system;
 extern crate libc;
 
 #[cfg(not(dummy_jemalloc))]
 pub use contents::*;
 #[cfg(not(dummy_jemalloc))]
 mod contents {
-    use core::alloc::GlobalAlloc;
-    use alloc_system::System;
     use libc::{c_int, c_void, size_t};
 
     // Note that the symbols here are prefixed by default on macOS and Windows (we
@@ -100,10 +97,11 @@ mod contents {
         ptr
     }
 
+    #[cfg(stage0)]
     #[no_mangle]
     #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_oom() -> ! {
-        System.oom()
+        ::core::intrinsics::abort();
     }
 
     #[no_mangle]
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
index fd8109e2a4a..7376ac0f15d 100644
--- a/src/liballoc_system/lib.rs
+++ b/src/liballoc_system/lib.rs
@@ -71,11 +71,6 @@ unsafe impl Alloc for System {
                       new_size: usize) -> Result<NonNull<Opaque>, AllocErr> {
         NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
     }
-
-    #[inline]
-    fn oom(&mut self) -> ! {
-        ::oom()
-    }
 }
 
 #[cfg(stage0)]
@@ -103,11 +98,6 @@ unsafe impl<'a> Alloc for &'a System {
                       new_size: usize) -> Result<NonNull<Opaque>, AllocErr> {
         NonNull::new(GlobalAlloc::realloc(*self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
     }
-
-    #[inline]
-    fn oom(&mut self) -> ! {
-        ::oom()
-    }
 }
 
 #[cfg(any(windows, unix, target_os = "cloudabi", target_os = "redox"))]
@@ -366,63 +356,3 @@ mod platform {
         }
     }
 }
-
-#[inline]
-fn oom() -> ! {
-    write_to_stderr("fatal runtime error: memory allocation failed");
-    unsafe {
-        ::core::intrinsics::abort();
-    }
-}
-
-#[cfg(any(unix, target_os = "redox"))]
-#[inline]
-fn write_to_stderr(s: &str) {
-    extern crate libc;
-
-    unsafe {
-        libc::write(libc::STDERR_FILENO,
-                    s.as_ptr() as *const libc::c_void,
-                    s.len());
-    }
-}
-
-#[cfg(windows)]
-#[inline]
-fn write_to_stderr(s: &str) {
-    use core::ptr;
-
-    type LPVOID = *mut u8;
-    type HANDLE = LPVOID;
-    type DWORD = u32;
-    type BOOL = i32;
-    type LPDWORD = *mut DWORD;
-    type LPOVERLAPPED = *mut u8;
-
-    const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
-
-    extern "system" {
-        fn WriteFile(hFile: HANDLE,
-                     lpBuffer: LPVOID,
-                     nNumberOfBytesToWrite: DWORD,
-                     lpNumberOfBytesWritten: LPDWORD,
-                     lpOverlapped: LPOVERLAPPED)
-                     -> BOOL;
-        fn GetStdHandle(which: DWORD) -> HANDLE;
-    }
-
-    unsafe {
-        // WriteFile silently fails if it is passed an invalid
-        // handle, so there is no need to check the result of
-        // GetStdHandle.
-        WriteFile(GetStdHandle(STD_ERROR_HANDLE),
-                  s.as_ptr() as LPVOID,
-                  s.len() as DWORD,
-                  ptr::null_mut(),
-                  ptr::null_mut());
-    }
-}
-
-#[cfg(not(any(windows, unix, target_os = "redox")))]
-#[inline]
-fn write_to_stderr(_: &str) {}
diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs
index 54440eaa40f..674c4fb57c7 100644
--- a/src/libcore/alloc.rs
+++ b/src/libcore/alloc.rs
@@ -451,17 +451,6 @@ pub unsafe trait GlobalAlloc {
         }
         new_ptr
     }
-
-    /// Aborts the thread or process, optionally performing
-    /// cleanup or logging diagnostic information before panicking or
-    /// aborting.
-    ///
-    /// `oom` is meant to be used by clients unable to cope with an
-    /// unsatisfied allocation request, and wish to abandon
-    /// computation rather than attempt to recover locally.
-    fn oom(&self) -> ! {
-        unsafe { ::intrinsics::abort() }
-    }
 }
 
 /// An implementation of `Alloc` can allocate, reallocate, and
@@ -614,32 +603,6 @@ pub unsafe trait Alloc {
     ///   to allocate that block of memory.
     unsafe fn dealloc(&mut self, ptr: NonNull<Opaque>, layout: Layout);
 
-    /// Allocator-specific method for signaling an out-of-memory
-    /// condition.
-    ///
-    /// `oom` aborts the thread or process, optionally performing
-    /// cleanup or logging diagnostic information before panicking or
-    /// aborting.
-    ///
-    /// `oom` is meant to be used by clients unable to cope with an
-    /// unsatisfied allocation request, and wish to abandon
-    /// computation rather than attempt to recover locally.
-    ///
-    /// Implementations of the `oom` method are discouraged from
-    /// infinitely regressing in nested calls to `oom`. In
-    /// practice this means implementors should eschew allocating,
-    /// especially from `self` (directly or indirectly).
-    ///
-    /// Implementations of the allocation and reallocation methods
-    /// (e.g. `alloc`, `alloc_one`, `realloc`) are discouraged from
-    /// panicking (or aborting) in the event of memory exhaustion;
-    /// instead they should return an appropriate error from the
-    /// invoked method, and let the client decide whether to invoke
-    /// this `oom` method in response.
-    fn oom(&mut self) -> ! {
-        unsafe { ::intrinsics::abort() }
-    }
-
     // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS ==
     // usable_size
 
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index c7412dbeeb3..95e92e21b09 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -303,7 +303,8 @@ language_item_table! {
 
     ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
     BoxFreeFnLangItem,               "box_free",                box_free_fn;
-    DropInPlaceFnLangItem,             "drop_in_place",           drop_in_place_fn;
+    DropInPlaceFnLangItem,           "drop_in_place",           drop_in_place_fn;
+    OomLangItem,                     "oom",                     oom;
 
     StartFnLangItem,                 "start",                   start_fn;
 
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index e19f4483f65..a2bceb19102 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -151,4 +151,5 @@ weak_lang_items! {
     panic_fmt,          PanicFmtLangItem,           rust_begin_unwind;
     eh_personality,     EhPersonalityLangItem,      rust_eh_personality;
     eh_unwind_resume,   EhUnwindResumeLangItem,     rust_eh_unwind_resume;
+    oom,                OomLangItem,                rust_oom;
 }
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index ffd02108c27..9338d000c12 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -245,7 +245,7 @@ impl<'a> AllocFnFactory<'a> {
                 self.cx.expr_ident(self.span, ident)
             }
 
-            AllocatorTy::ResultPtr | AllocatorTy::Bang | AllocatorTy::Unit => {
+            AllocatorTy::ResultPtr | AllocatorTy::Unit => {
                 panic!("can't convert AllocatorTy to an argument")
             }
         }
@@ -262,8 +262,6 @@ impl<'a> AllocFnFactory<'a> {
                 (self.ptr_u8(), expr)
             }
 
-            AllocatorTy::Bang => (self.cx.ty(self.span, TyKind::Never), expr),
-
             AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr),
 
             AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs
index 706eab72d44..969086815de 100644
--- a/src/librustc_allocator/lib.rs
+++ b/src/librustc_allocator/lib.rs
@@ -24,11 +24,6 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
         output: AllocatorTy::ResultPtr,
     },
     AllocatorMethod {
-        name: "oom",
-        inputs: &[],
-        output: AllocatorTy::Bang,
-    },
-    AllocatorMethod {
         name: "dealloc",
         inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
         output: AllocatorTy::Unit,
@@ -52,7 +47,6 @@ pub struct AllocatorMethod {
 }
 
 pub enum AllocatorTy {
-    Bang,
     Layout,
     Ptr,
     ResultPtr,
diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs
index f2dd2ed8460..ffebb959ebf 100644
--- a/src/librustc_trans/allocator.rs
+++ b/src/librustc_trans/allocator.rs
@@ -43,13 +43,11 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
                 AllocatorTy::Ptr => args.push(i8p),
                 AllocatorTy::Usize => args.push(usize),
 
-                AllocatorTy::Bang |
                 AllocatorTy::ResultPtr |
                 AllocatorTy::Unit => panic!("invalid allocator arg"),
             }
         }
         let output = match method.output {
-            AllocatorTy::Bang => None,
             AllocatorTy::ResultPtr => Some(i8p),
             AllocatorTy::Unit => None,
 
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs
index ff578ec42d2..a8578404467 100644
--- a/src/libstd/alloc.rs
+++ b/src/libstd/alloc.rs
@@ -13,10 +13,18 @@
 #![unstable(issue = "32838", feature = "allocator_api")]
 
 #[doc(inline)] #[allow(deprecated)] pub use alloc_crate::alloc::Heap;
-#[doc(inline)] pub use alloc_crate::alloc::Global;
+#[doc(inline)] pub use alloc_crate::alloc::{Global, oom};
 #[doc(inline)] pub use alloc_system::System;
 #[doc(inline)] pub use core::alloc::*;
 
+#[cfg(not(stage0))]
+#[cfg(not(test))]
+#[doc(hidden)]
+#[lang = "oom"]
+pub extern fn rust_oom() -> ! {
+    rtabort!("memory allocation failed");
+}
+
 #[cfg(not(test))]
 #[doc(hidden)]
 #[allow(unused_attributes)]
@@ -35,10 +43,11 @@ pub mod __default_lib_allocator {
         System.alloc(layout) as *mut u8
     }
 
+    #[cfg(stage0)]
     #[no_mangle]
     #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_oom() -> ! {
-        System.oom()
+        super::oom()
     }
 
     #[no_mangle]
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 4fe5c11beb4..a8c70489f44 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -11,7 +11,7 @@
 use self::Entry::*;
 use self::VacantEntryState::*;
 
-use alloc::{Global, Alloc, CollectionAllocErr};
+use alloc::{CollectionAllocErr, oom};
 use cell::Cell;
 use borrow::Borrow;
 use cmp::max;
@@ -784,7 +784,7 @@ impl<K, V, S> HashMap<K, V, S>
     pub fn reserve(&mut self, additional: usize) {
         match self.try_reserve(additional) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => Global.oom(),
+            Err(CollectionAllocErr::AllocErr) => oom(),
             Ok(()) => { /* yay */ }
          }
     }
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 115f9628a23..52c53dc3b12 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::{Global, Alloc, Layout, CollectionAllocErr};
+use alloc::{Global, Alloc, Layout, CollectionAllocErr, oom};
 use cmp;
 use hash::{BuildHasher, Hash, Hasher};
 use marker;
@@ -770,7 +770,7 @@ impl<K, V> RawTable<K, V> {
     unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
         match Self::try_new_uninitialized(capacity) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => Global.oom(),
+            Err(CollectionAllocErr::AllocErr) => oom(),
             Ok(table) => { table }
         }
     }
@@ -809,7 +809,7 @@ impl<K, V> RawTable<K, V> {
     pub fn new(capacity: usize) -> RawTable<K, V> {
         match Self::try_new(capacity) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => Global.oom(),
+            Err(CollectionAllocErr::AllocErr) => oom(),
             Ok(table) => { table }
         }
     }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 43a8d4446fa..1df7bc777d1 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -482,7 +482,6 @@ pub mod path;
 pub mod process;
 pub mod sync;
 pub mod time;
-pub mod alloc;
 
 #[unstable(feature = "allocator_api", issue = "32838")]
 #[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")]
@@ -496,6 +495,8 @@ pub mod heap {
 mod sys_common;
 mod sys;
 
+pub mod alloc;
+
 // Private support modules
 mod panicking;
 mod memchr;
diff --git a/src/test/compile-fail/allocator/not-an-allocator.rs b/src/test/compile-fail/allocator/not-an-allocator.rs
index 1479d0b6264..140cad22f34 100644
--- a/src/test/compile-fail/allocator/not-an-allocator.rs
+++ b/src/test/compile-fail/allocator/not-an-allocator.rs
@@ -16,6 +16,5 @@ static A: usize = 0;
 //~| the trait bound `usize:
 //~| the trait bound `usize:
 //~| the trait bound `usize:
-//~| the trait bound `usize:
 
 fn main() {}
diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs
index d4fcdcf743b..12b115d0938 100644
--- a/src/test/run-pass/allocator-alloc-one.rs
+++ b/src/test/run-pass/allocator-alloc-one.rs
@@ -10,13 +10,11 @@
 
 #![feature(allocator_api, nonnull)]
 
-use std::alloc::{Alloc, Global};
+use std::alloc::{Alloc, Global, oom};
 
 fn main() {
     unsafe {
-        let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| {
-            Global.oom()
-        });
+        let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| oom());
         *ptr.as_ptr() = 4;
         assert_eq!(*ptr.as_ptr(), 4);
         Global.dealloc_one(ptr);
diff --git a/src/test/run-pass/realloc-16687.rs b/src/test/run-pass/realloc-16687.rs
index afa3494c389..308792e5d89 100644
--- a/src/test/run-pass/realloc-16687.rs
+++ b/src/test/run-pass/realloc-16687.rs
@@ -15,7 +15,7 @@
 
 #![feature(heap_api, allocator_api)]
 
-use std::alloc::{Global, Alloc, Layout};
+use std::alloc::{Global, Alloc, Layout, oom};
 use std::ptr::{self, NonNull};
 
 fn main() {
@@ -50,7 +50,7 @@ unsafe fn test_triangle() -> bool {
             println!("allocate({:?})", layout);
         }
 
-        let ret = Global.alloc(layout.clone()).unwrap_or_else(|_| Global.oom());
+        let ret = Global.alloc(layout.clone()).unwrap_or_else(|_| oom());
 
         if PRINT {
             println!("allocate({:?}) = {:?}", layout, ret);
@@ -73,7 +73,7 @@ unsafe fn test_triangle() -> bool {
         }
 
         let ret = Global.realloc(NonNull::new_unchecked(ptr).as_opaque(), old.clone(), new.size())
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
 
         if PRINT {
             println!("reallocate({:?}, old={:?}, new={:?}) = {:?}",
diff --git a/src/test/run-pass/regions-mock-trans.rs b/src/test/run-pass/regions-mock-trans.rs
index 44be59f5c5b..60a7f70931d 100644
--- a/src/test/run-pass/regions-mock-trans.rs
+++ b/src/test/run-pass/regions-mock-trans.rs
@@ -12,7 +12,7 @@
 
 #![feature(allocator_api)]
 
-use std::alloc::{Alloc, Global, Layout};
+use std::alloc::{Alloc, Global, Layout, oom};
 use std::ptr::NonNull;
 
 struct arena(());
@@ -33,7 +33,7 @@ struct Ccx {
 fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> {
     unsafe {
         let ptr = Global.alloc(Layout::new::<Bcx>())
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
         &*(ptr.as_ptr() as *const _)
     }
 }