summaryrefslogtreecommitdiffstats
path: root/src/test/ui/allocator
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/allocator')
-rw-r--r--src/test/ui/allocator/allocator-args.rs13
-rw-r--r--src/test/ui/allocator/allocator-args.stderr8
-rw-r--r--src/test/ui/allocator/auxiliary/custom-as-global.rs16
-rw-r--r--src/test/ui/allocator/auxiliary/custom.rs21
-rw-r--r--src/test/ui/allocator/auxiliary/helper.rs11
-rw-r--r--src/test/ui/allocator/auxiliary/system-allocator.rs8
-rw-r--r--src/test/ui/allocator/auxiliary/system-allocator2.rs8
-rw-r--r--src/test/ui/allocator/custom-in-block.rs22
-rw-r--r--src/test/ui/allocator/custom-in-submodule.rs26
-rw-r--r--src/test/ui/allocator/custom.rs59
-rw-r--r--src/test/ui/allocator/function-allocator.rs4
-rw-r--r--src/test/ui/allocator/function-allocator.stderr8
-rw-r--r--src/test/ui/allocator/hygiene.rs31
-rw-r--r--src/test/ui/allocator/no_std-alloc-error-handler-custom.rs103
-rw-r--r--src/test/ui/allocator/no_std-alloc-error-handler-default.rs90
-rw-r--r--src/test/ui/allocator/not-an-allocator.rs8
-rw-r--r--src/test/ui/allocator/not-an-allocator.stderr47
-rw-r--r--src/test/ui/allocator/object-safe.rs13
-rw-r--r--src/test/ui/allocator/two-allocators.rs9
-rw-r--r--src/test/ui/allocator/two-allocators.stderr14
-rw-r--r--src/test/ui/allocator/two-allocators2.rs12
-rw-r--r--src/test/ui/allocator/two-allocators2.stderr4
-rw-r--r--src/test/ui/allocator/two-allocators3.rs10
-rw-r--r--src/test/ui/allocator/two-allocators3.stderr4
-rw-r--r--src/test/ui/allocator/xcrate-use.rs36
-rw-r--r--src/test/ui/allocator/xcrate-use2.rs47
26 files changed, 632 insertions, 0 deletions
diff --git a/src/test/ui/allocator/allocator-args.rs b/src/test/ui/allocator/allocator-args.rs
new file mode 100644
index 000000000..1033f947c
--- /dev/null
+++ b/src/test/ui/allocator/allocator-args.rs
@@ -0,0 +1,13 @@
+use std::alloc::{GlobalAlloc, Layout};
+
+struct A;
+
+unsafe impl GlobalAlloc for A {
+ unsafe fn alloc(&self, _: Layout) -> *mut u8 { panic!() }
+ unsafe fn dealloc(&self, _: *mut u8, _: Layout) { panic!() }
+}
+
+#[global_allocator(malloc)] //~ ERROR malformed `global_allocator` attribute input
+static S: A = A;
+
+fn main() {}
diff --git a/src/test/ui/allocator/allocator-args.stderr b/src/test/ui/allocator/allocator-args.stderr
new file mode 100644
index 000000000..dfff2a7e7
--- /dev/null
+++ b/src/test/ui/allocator/allocator-args.stderr
@@ -0,0 +1,8 @@
+error: malformed `global_allocator` attribute input
+ --> $DIR/allocator-args.rs:10:1
+ |
+LL | #[global_allocator(malloc)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[global_allocator]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator/auxiliary/custom-as-global.rs b/src/test/ui/allocator/auxiliary/custom-as-global.rs
new file mode 100644
index 000000000..a5e96e775
--- /dev/null
+++ b/src/test/ui/allocator/auxiliary/custom-as-global.rs
@@ -0,0 +1,16 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+extern crate custom;
+
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+use custom::A;
+
+#[global_allocator]
+static ALLOCATOR: A = A(AtomicUsize::new(0));
+
+pub fn get() -> usize {
+ ALLOCATOR.0.load(Ordering::SeqCst)
+}
diff --git a/src/test/ui/allocator/auxiliary/custom.rs b/src/test/ui/allocator/auxiliary/custom.rs
new file mode 100644
index 000000000..b0ec9ab09
--- /dev/null
+++ b/src/test/ui/allocator/auxiliary/custom.rs
@@ -0,0 +1,21 @@
+// no-prefer-dynamic
+
+#![feature(allocator_api)]
+#![crate_type = "rlib"]
+
+use std::alloc::{GlobalAlloc, System, Layout};
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+pub struct A(pub AtomicUsize);
+
+unsafe impl GlobalAlloc for A {
+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+ self.0.fetch_add(1, Ordering::SeqCst);
+ System.alloc(layout)
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+ self.0.fetch_add(1, Ordering::SeqCst);
+ System.dealloc(ptr, layout)
+ }
+}
diff --git a/src/test/ui/allocator/auxiliary/helper.rs b/src/test/ui/allocator/auxiliary/helper.rs
new file mode 100644
index 000000000..008fb3501
--- /dev/null
+++ b/src/test/ui/allocator/auxiliary/helper.rs
@@ -0,0 +1,11 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+#![no_std]
+
+extern crate alloc;
+use alloc::fmt;
+
+pub fn work_with(p: &fmt::Debug) {
+ drop(p);
+}
diff --git a/src/test/ui/allocator/auxiliary/system-allocator.rs b/src/test/ui/allocator/auxiliary/system-allocator.rs
new file mode 100644
index 000000000..97b86bbc9
--- /dev/null
+++ b/src/test/ui/allocator/auxiliary/system-allocator.rs
@@ -0,0 +1,8 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+use std::alloc::System;
+
+#[global_allocator]
+static A: System = System;
diff --git a/src/test/ui/allocator/auxiliary/system-allocator2.rs b/src/test/ui/allocator/auxiliary/system-allocator2.rs
new file mode 100644
index 000000000..97b86bbc9
--- /dev/null
+++ b/src/test/ui/allocator/auxiliary/system-allocator2.rs
@@ -0,0 +1,8 @@
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+use std::alloc::System;
+
+#[global_allocator]
+static A: System = System;
diff --git a/src/test/ui/allocator/custom-in-block.rs b/src/test/ui/allocator/custom-in-block.rs
new file mode 100644
index 000000000..12813a1fc
--- /dev/null
+++ b/src/test/ui/allocator/custom-in-block.rs
@@ -0,0 +1,22 @@
+// run-pass
+// no-prefer-dynamic
+// aux-build:custom.rs
+// aux-build:helper.rs
+
+extern crate custom;
+extern crate helper;
+
+use custom::A;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+fn main() {
+ #[global_allocator]
+ pub static GLOBAL: A = A(AtomicUsize::new(0));
+
+ let n = GLOBAL.0.load(Ordering::SeqCst);
+ let s = Box::new(0);
+ helper::work_with(&s);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
+ drop(s);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
+}
diff --git a/src/test/ui/allocator/custom-in-submodule.rs b/src/test/ui/allocator/custom-in-submodule.rs
new file mode 100644
index 000000000..ea341b1ac
--- /dev/null
+++ b/src/test/ui/allocator/custom-in-submodule.rs
@@ -0,0 +1,26 @@
+// run-pass
+// no-prefer-dynamic
+// aux-build:custom.rs
+// aux-build:helper.rs
+
+extern crate custom;
+extern crate helper;
+
+use custom::A;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+mod submodule {
+ use super::*;
+
+ #[global_allocator]
+ pub static GLOBAL: A = A(AtomicUsize::new(0));
+}
+
+fn main() {
+ let n = submodule::GLOBAL.0.load(Ordering::SeqCst);
+ let s = Box::new(0);
+ helper::work_with(&s);
+ assert_eq!(submodule::GLOBAL.0.load(Ordering::SeqCst), n + 1);
+ drop(s);
+ assert_eq!(submodule::GLOBAL.0.load(Ordering::SeqCst), n + 2);
+}
diff --git a/src/test/ui/allocator/custom.rs b/src/test/ui/allocator/custom.rs
new file mode 100644
index 000000000..10cbc23c4
--- /dev/null
+++ b/src/test/ui/allocator/custom.rs
@@ -0,0 +1,59 @@
+// run-pass
+
+// aux-build:helper.rs
+// no-prefer-dynamic
+
+#![feature(allocator_api)]
+#![feature(slice_ptr_get)]
+
+extern crate helper;
+
+use std::alloc::{self, Allocator, Global, Layout, System};
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+static HITS: AtomicUsize = AtomicUsize::new(0);
+
+struct A;
+
+unsafe impl alloc::GlobalAlloc for A {
+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+ HITS.fetch_add(1, Ordering::SeqCst);
+ alloc::GlobalAlloc::alloc(&System, layout)
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+ HITS.fetch_add(1, Ordering::SeqCst);
+ alloc::GlobalAlloc::dealloc(&System, ptr, layout)
+ }
+}
+
+#[global_allocator]
+static GLOBAL: A = A;
+
+fn main() {
+ println!("hello!");
+
+ let n = HITS.load(Ordering::SeqCst);
+ assert!(n > 0);
+ unsafe {
+ let layout = Layout::from_size_align(4, 2).unwrap();
+
+ let memory = Global.allocate(layout.clone()).unwrap();
+ helper::work_with(&memory);
+ assert_eq!(HITS.load(Ordering::SeqCst), n + 1);
+ Global.deallocate(memory.as_non_null_ptr(), layout);
+ assert_eq!(HITS.load(Ordering::SeqCst), n + 2);
+
+ let s = String::with_capacity(10);
+ helper::work_with(&s);
+ assert_eq!(HITS.load(Ordering::SeqCst), n + 3);
+ drop(s);
+ assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
+
+ let memory = System.allocate(layout.clone()).unwrap();
+ helper::work_with(&memory);
+ assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
+ System.deallocate(memory.as_non_null_ptr(), layout);
+ assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
+ }
+}
diff --git a/src/test/ui/allocator/function-allocator.rs b/src/test/ui/allocator/function-allocator.rs
new file mode 100644
index 000000000..d53f6e9b7
--- /dev/null
+++ b/src/test/ui/allocator/function-allocator.rs
@@ -0,0 +1,4 @@
+#[global_allocator]
+fn foo() {} //~ ERROR: allocators must be statics
+
+fn main() {}
diff --git a/src/test/ui/allocator/function-allocator.stderr b/src/test/ui/allocator/function-allocator.stderr
new file mode 100644
index 000000000..5e47b0f0c
--- /dev/null
+++ b/src/test/ui/allocator/function-allocator.stderr
@@ -0,0 +1,8 @@
+error: allocators must be statics
+ --> $DIR/function-allocator.rs:2:1
+ |
+LL | fn foo() {}
+ | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator/hygiene.rs b/src/test/ui/allocator/hygiene.rs
new file mode 100644
index 000000000..9bd8406a2
--- /dev/null
+++ b/src/test/ui/allocator/hygiene.rs
@@ -0,0 +1,31 @@
+// run-pass
+// no-prefer-dynamic
+// aux-build:custom.rs
+// aux-build:helper.rs
+
+#![allow(nonstandard_style)]
+
+extern crate custom;
+extern crate helper;
+
+use custom::A;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+#[allow(dead_code)]
+struct u8;
+#[allow(dead_code)]
+struct usize;
+#[allow(dead_code)]
+static arg0: () = ();
+
+#[global_allocator]
+pub static GLOBAL: A = A(AtomicUsize::new(0));
+
+fn main() {
+ let n = GLOBAL.0.load(Ordering::SeqCst);
+ let s = Box::new(0);
+ helper::work_with(&s);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
+ drop(s);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
+}
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
new file mode 100644
index 000000000..54b7c8bb9
--- /dev/null
+++ b/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs
@@ -0,0 +1,103 @@
+// 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(start, rustc_private, new_uninit, panic_info_message, lang_items)]
+#![feature(alloc_error_handler)]
+#![no_std]
+
+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 core::ptr::null_mut;
+use core::alloc::{GlobalAlloc, Layout};
+use alloc::boxed::Box;
+
+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();
+ let s = s.as_str();
+ libc::write(libc::STDERR_FILENO, s as *const _ as _, 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 {
+ 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());
+ }
+ 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 libaries 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() {}
+
+#[derive(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() };
+ 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
new file mode 100644
index 000000000..ffa331a99
--- /dev/null
+++ b/src/test/ui/allocator/no_std-alloc-error-handler-default.rs
@@ -0,0 +1,90 @@
+// 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
+// gate-test-default_alloc_error_handler
+
+#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)]
+#![feature(default_alloc_error_handler)]
+#![no_std]
+
+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 core::alloc::{GlobalAlloc, Layout};
+use core::ptr::null_mut;
+
+extern crate helper;
+
+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()
+ }
+ }
+ 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 {
+ 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());
+ }
+ libc::exit(0)
+ }
+}
+
+// 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 libaries 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() {}
+
+#[derive(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() };
+ helper::work_with(&zero);
+ 1
+}
diff --git a/src/test/ui/allocator/not-an-allocator.rs b/src/test/ui/allocator/not-an-allocator.rs
new file mode 100644
index 000000000..4a538d4d0
--- /dev/null
+++ b/src/test/ui/allocator/not-an-allocator.rs
@@ -0,0 +1,8 @@
+#[global_allocator]
+static A: usize = 0;
+//~^ ERROR E0277
+//~| ERROR E0277
+//~| ERROR E0277
+//~| ERROR E0277
+
+fn main() {}
diff --git a/src/test/ui/allocator/not-an-allocator.stderr b/src/test/ui/allocator/not-an-allocator.stderr
new file mode 100644
index 000000000..62bb0679f
--- /dev/null
+++ b/src/test/ui/allocator/not-an-allocator.stderr
@@ -0,0 +1,47 @@
+error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
+ --> $DIR/not-an-allocator.rs:2:11
+ |
+LL | #[global_allocator]
+ | ------------------- in this procedural macro expansion
+LL | static A: usize = 0;
+ | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+ |
+ = help: the trait `GlobalAlloc` is implemented for `System`
+ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
+ --> $DIR/not-an-allocator.rs:2:11
+ |
+LL | #[global_allocator]
+ | ------------------- in this procedural macro expansion
+LL | static A: usize = 0;
+ | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+ |
+ = help: the trait `GlobalAlloc` is implemented for `System`
+ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
+ --> $DIR/not-an-allocator.rs:2:11
+ |
+LL | #[global_allocator]
+ | ------------------- in this procedural macro expansion
+LL | static A: usize = 0;
+ | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+ |
+ = help: the trait `GlobalAlloc` is implemented for `System`
+ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
+ --> $DIR/not-an-allocator.rs:2:11
+ |
+LL | #[global_allocator]
+ | ------------------- in this procedural macro expansion
+LL | static A: usize = 0;
+ | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
+ |
+ = help: the trait `GlobalAlloc` is implemented for `System`
+ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/allocator/object-safe.rs b/src/test/ui/allocator/object-safe.rs
new file mode 100644
index 000000000..fae7ab7fe
--- /dev/null
+++ b/src/test/ui/allocator/object-safe.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+// Check that `Allocator` is object safe, this allows for polymorphic allocators
+
+#![feature(allocator_api)]
+
+use std::alloc::{Allocator, System};
+
+fn ensure_object_safe(_: &dyn Allocator) {}
+
+fn main() {
+ ensure_object_safe(&System);
+}
diff --git a/src/test/ui/allocator/two-allocators.rs b/src/test/ui/allocator/two-allocators.rs
new file mode 100644
index 000000000..aa1291e77
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators.rs
@@ -0,0 +1,9 @@
+use std::alloc::System;
+
+#[global_allocator]
+static A: System = System;
+#[global_allocator]
+static B: System = System;
+//~^ ERROR: cannot define multiple global allocators
+
+fn main() {}
diff --git a/src/test/ui/allocator/two-allocators.stderr b/src/test/ui/allocator/two-allocators.stderr
new file mode 100644
index 000000000..7a914c2a3
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators.stderr
@@ -0,0 +1,14 @@
+error: cannot define multiple global allocators
+ --> $DIR/two-allocators.rs:6:1
+ |
+LL | static A: System = System;
+ | -------------------------- previous global allocator defined here
+LL | #[global_allocator]
+ | ------------------- in this procedural macro expansion
+LL | static B: System = System;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot define a new global allocator
+ |
+ = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator/two-allocators2.rs b/src/test/ui/allocator/two-allocators2.rs
new file mode 100644
index 000000000..6dfefe19c
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators2.rs
@@ -0,0 +1,12 @@
+// aux-build:system-allocator.rs
+// no-prefer-dynamic
+// error-pattern: the `#[global_allocator]` in
+
+extern crate system_allocator;
+
+use std::alloc::System;
+
+#[global_allocator]
+static A: System = System;
+
+fn main() {}
diff --git a/src/test/ui/allocator/two-allocators2.stderr b/src/test/ui/allocator/two-allocators2.stderr
new file mode 100644
index 000000000..b1fb4421e
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators2.stderr
@@ -0,0 +1,4 @@
+error: the `#[global_allocator]` in this crate conflicts with global allocator in: system_allocator
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator/two-allocators3.rs b/src/test/ui/allocator/two-allocators3.rs
new file mode 100644
index 000000000..31dea2d44
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators3.rs
@@ -0,0 +1,10 @@
+// aux-build:system-allocator.rs
+// aux-build:system-allocator2.rs
+// no-prefer-dynamic
+// error-pattern: the `#[global_allocator]` in
+
+
+extern crate system_allocator;
+extern crate system_allocator2;
+
+fn main() {}
diff --git a/src/test/ui/allocator/two-allocators3.stderr b/src/test/ui/allocator/two-allocators3.stderr
new file mode 100644
index 000000000..a3079113d
--- /dev/null
+++ b/src/test/ui/allocator/two-allocators3.stderr
@@ -0,0 +1,4 @@
+error: the `#[global_allocator]` in system_allocator conflicts with global allocator in: system_allocator2
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/allocator/xcrate-use.rs b/src/test/ui/allocator/xcrate-use.rs
new file mode 100644
index 000000000..edd4df75e
--- /dev/null
+++ b/src/test/ui/allocator/xcrate-use.rs
@@ -0,0 +1,36 @@
+// run-pass
+
+// aux-build:custom.rs
+// aux-build:helper.rs
+// no-prefer-dynamic
+
+#![feature(allocator_api)]
+#![feature(slice_ptr_get)]
+
+extern crate custom;
+extern crate helper;
+
+use std::alloc::{Allocator, Global, Layout, System};
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+#[global_allocator]
+static GLOBAL: custom::A = custom::A(AtomicUsize::new(0));
+
+fn main() {
+ unsafe {
+ let n = GLOBAL.0.load(Ordering::SeqCst);
+ let layout = Layout::from_size_align(4, 2).unwrap();
+
+ let memory = Global.allocate(layout.clone()).unwrap();
+ helper::work_with(&memory);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
+ Global.deallocate(memory.as_non_null_ptr(), layout);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
+
+ let memory = System.allocate(layout.clone()).unwrap();
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
+ helper::work_with(&memory);
+ System.deallocate(memory.as_non_null_ptr(), layout);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
+ }
+}
diff --git a/src/test/ui/allocator/xcrate-use2.rs b/src/test/ui/allocator/xcrate-use2.rs
new file mode 100644
index 000000000..d8478fb5e
--- /dev/null
+++ b/src/test/ui/allocator/xcrate-use2.rs
@@ -0,0 +1,47 @@
+// run-pass
+
+// aux-build:custom.rs
+// aux-build:custom-as-global.rs
+// aux-build:helper.rs
+// no-prefer-dynamic
+
+#![feature(allocator_api)]
+
+extern crate custom;
+extern crate custom_as_global;
+extern crate helper;
+
+use std::alloc::{alloc, dealloc, GlobalAlloc, System, Layout};
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+static GLOBAL: custom::A = custom::A(AtomicUsize::new(0));
+
+fn main() {
+ unsafe {
+ let n = custom_as_global::get();
+ let layout = Layout::from_size_align(4, 2).unwrap();
+
+ // Global allocator routes to the `custom_as_global` global
+ let ptr = alloc(layout.clone());
+ helper::work_with(&ptr);
+ assert_eq!(custom_as_global::get(), n + 1);
+ dealloc(ptr, layout.clone());
+ assert_eq!(custom_as_global::get(), n + 2);
+
+ // Usage of the system allocator avoids all globals
+ let ptr = System.alloc(layout.clone());
+ helper::work_with(&ptr);
+ assert_eq!(custom_as_global::get(), n + 2);
+ System.dealloc(ptr, layout.clone());
+ assert_eq!(custom_as_global::get(), n + 2);
+
+ // Usage of our personal allocator doesn't affect other instances
+ let ptr = GLOBAL.alloc(layout.clone());
+ helper::work_with(&ptr);
+ assert_eq!(custom_as_global::get(), n + 2);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 1);
+ GLOBAL.dealloc(ptr, layout);
+ assert_eq!(custom_as_global::get(), n + 2);
+ assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 2);
+ }
+}