tests: Move run-pass tests without naming conflicts to ui

This commit is contained in:
Vadim Petrochenkov 2019-07-27 01:33:01 +03:00
parent ca9faa52f5
commit 9be35f82c1
3226 changed files with 64 additions and 196 deletions

View file

@ -0,0 +1,367 @@
// run-pass
// Checks if the "sysv64" calling convention behaves the same as the
// "C" calling convention on platforms where both should be the same
// This file contains versions of the following run-pass tests with
// the calling convention changed to "sysv64"
// cabi-int-widening
// extern-pass-char
// extern-pass-u32
// extern-pass-u64
// extern-pass-double
// extern-pass-empty
// extern-pass-TwoU8s
// extern-pass-TwoU16s
// extern-pass-TwoU32s
// extern-pass-TwoU64s
// extern-return-TwoU8s
// extern-return-TwoU16s
// extern-return-TwoU32s
// extern-return-TwoU64s
// foreign-fn-with-byval
// issue-28676
// issue-62350-sysv-neg-reg-counts
// struct-return
// ignore-android
// ignore-arm
// ignore-aarch64
// ignore-windows
// note: windows is ignored as rust_test_helpers does not have the sysv64 abi on windows
#[allow(dead_code)]
#[allow(improper_ctypes)]
#[cfg(target_arch = "x86_64")]
mod tests {
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct TwoU8s {
one: u8, two: u8
}
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct TwoU16s {
one: u16, two: u16
}
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct TwoU32s {
one: u32, two: u32
}
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct TwoU64s {
one: u64, two: u64
}
#[repr(C)]
pub struct ManyInts {
arg1: i8,
arg2: i16,
arg3: i32,
arg4: i16,
arg5: i8,
arg6: TwoU8s,
}
#[repr(C)]
pub struct Empty;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct S {
x: u64,
y: u64,
z: u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
#[derive(Copy, Clone)]
pub struct QuadFloats { a: f32, b: f32, c: f32, d: f32 }
#[repr(C)]
#[derive(Copy, Clone)]
pub struct Floats { a: f64, b: u8, c: f64 }
#[link(name = "rust_test_helpers", kind = "static")]
extern "sysv64" {
pub fn rust_int8_to_int32(_: i8) -> i32;
pub fn rust_dbg_extern_identity_u8(v: u8) -> u8;
pub fn rust_dbg_extern_identity_u32(v: u32) -> u32;
pub fn rust_dbg_extern_identity_u64(v: u64) -> u64;
pub fn rust_dbg_extern_identity_double(v: f64) -> f64;
pub fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts);
pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s;
pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s;
pub fn rust_dbg_extern_identity_TwoU32s(v: TwoU32s) -> TwoU32s;
pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s;
pub fn rust_dbg_extern_return_TwoU8s() -> TwoU8s;
pub fn rust_dbg_extern_return_TwoU16s() -> TwoU16s;
pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s;
pub fn rust_dbg_extern_return_TwoU64s() -> TwoU64s;
pub fn get_x(x: S) -> u64;
pub fn get_y(x: S) -> u64;
pub fn get_z(x: S) -> u64;
pub fn get_c_many_params(_: *const (), _: *const (),
_: *const (), _: *const (), f: Quad) -> u64;
pub fn get_c_exhaust_sysv64_ints(
_: *const (),
_: *const (),
_: *const (),
_: *const (),
_: *const (),
_: *const (),
_: *const (),
h: QuadFloats,
) -> f32;
pub fn rust_dbg_abi_1(q: Quad) -> Quad;
pub fn rust_dbg_abi_2(f: Floats) -> Floats;
}
pub fn cabi_int_widening() {
let x = unsafe {
rust_int8_to_int32(-1)
};
assert!(x == -1);
}
pub fn extern_pass_char() {
unsafe {
assert_eq!(22, rust_dbg_extern_identity_u8(22));
}
}
pub fn extern_pass_u32() {
unsafe {
assert_eq!(22, rust_dbg_extern_identity_u32(22));
}
}
pub fn extern_pass_u64() {
unsafe {
assert_eq!(22, rust_dbg_extern_identity_u64(22));
}
}
pub fn extern_pass_double() {
unsafe {
assert_eq!(22.0_f64, rust_dbg_extern_identity_double(22.0_f64));
}
}
pub fn extern_pass_empty() {
unsafe {
let x = ManyInts {
arg1: 2,
arg2: 3,
arg3: 4,
arg4: 5,
arg5: 6,
arg6: TwoU8s { one: 7, two: 8, }
};
let y = ManyInts {
arg1: 1,
arg2: 2,
arg3: 3,
arg4: 4,
arg5: 5,
arg6: TwoU8s { one: 6, two: 7, }
};
let empty = Empty;
rust_dbg_extern_empty_struct(x, empty, y);
}
}
pub fn extern_pass_twou8s() {
unsafe {
let x = TwoU8s {one: 22, two: 23};
let y = rust_dbg_extern_identity_TwoU8s(x);
assert_eq!(x, y);
}
}
pub fn extern_pass_twou16s() {
unsafe {
let x = TwoU16s {one: 22, two: 23};
let y = rust_dbg_extern_identity_TwoU16s(x);
assert_eq!(x, y);
}
}
pub fn extern_pass_twou32s() {
unsafe {
let x = TwoU32s {one: 22, two: 23};
let y = rust_dbg_extern_identity_TwoU32s(x);
assert_eq!(x, y);
}
}
pub fn extern_pass_twou64s() {
unsafe {
let x = TwoU64s {one: 22, two: 23};
let y = rust_dbg_extern_identity_TwoU64s(x);
assert_eq!(x, y);
}
}
pub fn extern_return_twou8s() {
unsafe {
let y = rust_dbg_extern_return_TwoU8s();
assert_eq!(y.one, 10);
assert_eq!(y.two, 20);
}
}
pub fn extern_return_twou16s() {
unsafe {
let y = rust_dbg_extern_return_TwoU16s();
assert_eq!(y.one, 10);
assert_eq!(y.two, 20);
}
}
pub fn extern_return_twou32s() {
unsafe {
let y = rust_dbg_extern_return_TwoU32s();
assert_eq!(y.one, 10);
assert_eq!(y.two, 20);
}
}
pub fn extern_return_twou64s() {
unsafe {
let y = rust_dbg_extern_return_TwoU64s();
assert_eq!(y.one, 10);
assert_eq!(y.two, 20);
}
}
#[inline(never)]
fn indirect_call(func: unsafe extern "sysv64" fn(s: S) -> u64, s: S) -> u64 {
unsafe {
func(s)
}
}
pub fn foreign_fn_with_byval() {
let s = S { x: 1, y: 2, z: 3 };
assert_eq!(s.x, indirect_call(get_x, s));
assert_eq!(s.y, indirect_call(get_y, s));
assert_eq!(s.z, indirect_call(get_z, s));
}
fn test() {
use std::ptr;
unsafe {
let null = ptr::null();
let q = Quad {
a: 1,
b: 2,
c: 3,
d: 4
};
assert_eq!(get_c_many_params(null, null, null, null, q), q.c);
}
}
pub fn issue_28676() {
test();
}
fn test_62350() {
use std::ptr;
unsafe {
let null = ptr::null();
let q = QuadFloats {
a: 10.2,
b: 20.3,
c: 30.4,
d: 40.5
};
assert_eq!(
get_c_exhaust_sysv64_ints(null, null, null, null, null, null, null, q),
q.c,
);
}
}
pub fn issue_62350() {
test_62350();
}
fn test1() {
unsafe {
let q = Quad { a: 0xaaaa_aaaa_aaaa_aaaa,
b: 0xbbbb_bbbb_bbbb_bbbb,
c: 0xcccc_cccc_cccc_cccc,
d: 0xdddd_dddd_dddd_dddd };
let qq = rust_dbg_abi_1(q);
println!("a: {:x}", qq.a as usize);
println!("b: {:x}", qq.b as usize);
println!("c: {:x}", qq.c as usize);
println!("d: {:x}", qq.d as usize);
assert_eq!(qq.a, q.c + 1);
assert_eq!(qq.b, q.d - 1);
assert_eq!(qq.c, q.a + 1);
assert_eq!(qq.d, q.b - 1);
}
}
fn test2() {
unsafe {
let f = Floats { a: 1.234567890e-15_f64,
b: 0b_1010_1010,
c: 1.0987654321e-15_f64 };
let ff = rust_dbg_abi_2(f);
println!("a: {}", ff.a as f64);
println!("b: {}", ff.b as usize);
println!("c: {}", ff.c as f64);
assert_eq!(ff.a, f.c + 1.0f64);
assert_eq!(ff.b, 0xff);
assert_eq!(ff.c, f.a - 1.0f64);
}
}
pub fn struct_return() {
test1();
test2();
}
}
#[cfg(target_arch = "x86_64")]
fn main() {
use tests::*;
cabi_int_widening();
extern_pass_char();
extern_pass_u32();
extern_pass_u64();
extern_pass_double();
extern_pass_empty();
extern_pass_twou8s();
extern_pass_twou16s();
extern_pass_twou32s();
extern_pass_twou64s();
extern_return_twou8s();
extern_return_twou16s();
extern_return_twou32s();
extern_return_twou64s();
foreign_fn_with_byval();
issue_28676();
issue_62350();
struct_return();
}
#[cfg(not(target_arch = "x86_64"))]
fn main() {
}

View file

@ -0,0 +1,96 @@
// run-pass
// Checks if the correct registers are being used to pass arguments
// when the sysv64 ABI is specified.
// ignore-android
// ignore-arm
// ignore-aarch64
#![feature(asm)]
#[cfg(target_arch = "x86_64")]
pub extern "sysv64" fn all_the_registers(rdi: i64, rsi: i64, rdx: i64,
rcx: i64, r8 : i64, r9 : i64,
xmm0: f32, xmm1: f32, xmm2: f32,
xmm3: f32, xmm4: f32, xmm5: f32,
xmm6: f32, xmm7: f32) -> i64 {
assert_eq!(rdi, 1);
assert_eq!(rsi, 2);
assert_eq!(rdx, 3);
assert_eq!(rcx, 4);
assert_eq!(r8, 5);
assert_eq!(r9, 6);
assert_eq!(xmm0, 1.0f32);
assert_eq!(xmm1, 2.0f32);
assert_eq!(xmm2, 4.0f32);
assert_eq!(xmm3, 8.0f32);
assert_eq!(xmm4, 16.0f32);
assert_eq!(xmm5, 32.0f32);
assert_eq!(xmm6, 64.0f32);
assert_eq!(xmm7, 128.0f32);
42
}
// this struct contains 8 i64's, while only 6 can be passed in registers.
#[cfg(target_arch = "x86_64")]
#[derive(PartialEq, Eq, Debug)]
pub struct LargeStruct(i64, i64, i64, i64, i64, i64, i64, i64);
#[cfg(target_arch = "x86_64")]
#[inline(never)]
pub extern "sysv64" fn large_struct_by_val(mut foo: LargeStruct) -> LargeStruct {
foo.0 *= 1;
foo.1 *= 2;
foo.2 *= 3;
foo.3 *= 4;
foo.4 *= 5;
foo.5 *= 6;
foo.6 *= 7;
foo.7 *= 8;
foo
}
#[cfg(target_arch = "x86_64")]
pub fn main() {
let result: i64;
unsafe {
asm!("mov rdi, 1;
mov rsi, 2;
mov rdx, 3;
mov rcx, 4;
mov r8, 5;
mov r9, 6;
mov eax, 0x3F800000;
movd xmm0, eax;
mov eax, 0x40000000;
movd xmm1, eax;
mov eax, 0x40800000;
movd xmm2, eax;
mov eax, 0x41000000;
movd xmm3, eax;
mov eax, 0x41800000;
movd xmm4, eax;
mov eax, 0x42000000;
movd xmm5, eax;
mov eax, 0x42800000;
movd xmm6, eax;
mov eax, 0x43000000;
movd xmm7, eax;
call r10
"
: "={rax}"(result)
: "{r10}"(all_the_registers as usize)
: "rdi", "rsi", "rdx", "rcx", "r8", "r9", "r11", "cc", "memory"
: "intel", "alignstack"
)
}
assert_eq!(result, 42);
assert_eq!(
large_struct_by_val(LargeStruct(1, 2, 3, 4, 5, 6, 7, 8)),
LargeStruct(1, 4, 9, 16, 25, 36, 49, 64)
);
}
#[cfg(not(target_arch = "x86_64"))]
pub fn main() {}

View file

@ -0,0 +1,46 @@
// run-pass
#![allow(dead_code)]
#![allow(improper_ctypes)]
// ignore-wasm32-bare no libc to test ffi with
#[derive(Copy, Clone)]
pub struct QuadFloats { a: f32, b: f32, c: f32, d: f32 }
mod rustrt {
use super::QuadFloats;
#[link(name = "rust_test_helpers", kind = "static")]
extern {
pub fn get_c_exhaust_sysv64_ints(
_: *const (),
_: *const (),
_: *const (),
_: *const (),
_: *const (),
_: *const (),
_: *const (),
h: QuadFloats,
) -> f32;
}
}
fn test() {
unsafe {
let null = std::ptr::null();
let q = QuadFloats {
a: 10.2,
b: 20.3,
c: 30.4,
d: 40.5
};
assert_eq!(
rustrt::get_c_exhaust_sysv64_ints(null, null, null, null, null, null, null, q),
q.c,
);
}
}
pub fn main() {
test();
}

View file

@ -0,0 +1,38 @@
// run-pass
#![allow(unused_must_use)]
// Since we mark some ABIs as "nounwind" to LLVM, we must make sure that
// we never unwind through them.
// ignore-cloudabi no env and process
// ignore-emscripten no processes
// ignore-sgx no processes
use std::{env, panic};
use std::io::prelude::*;
use std::io;
use std::process::{Command, Stdio};
extern "C" fn panic_in_ffi() {
panic!("Test");
}
fn test() {
let _ = panic::catch_unwind(|| { panic_in_ffi(); });
// The process should have aborted by now.
io::stdout().write(b"This should never be printed.\n");
let _ = io::stdout().flush();
}
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() > 1 && args[1] == "test" {
return test();
}
let mut p = Command::new(&args[0])
.stdout(Stdio::piped())
.stdin(Stdio::piped())
.arg("test").spawn().unwrap();
assert!(!p.wait().unwrap().success());
}

View file

@ -0,0 +1,20 @@
// run-pass
#![allow(non_camel_case_types)]
#![allow(dead_code)]
// Regression test for issue #374
// pretty-expanded FIXME #23616
enum sty { ty_nil, }
struct RawT {struct_: sty, cname: Option<String>, hash: usize}
fn mk_raw_ty(st: sty, cname: Option<String>) -> RawT {
return RawT {struct_: st, cname: cname, hash: 0};
}
pub fn main() { mk_raw_ty(sty::ty_nil, None::<String>); }

View file

@ -0,0 +1,17 @@
// run-pass
#![allow(stable_features)]
#![allow(unused_variables)]
// #45662
#![feature(repr_align)]
#[repr(align(16))]
pub struct A(i64);
pub extern "C" fn foo(x: A) {}
fn main() {
foo(A(0));
}

View file

@ -0,0 +1,39 @@
// run-pass
#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![feature(box_syntax)]
struct pair<A,B> {
a: A, b: B
}
trait Invokable<A> {
fn f(&self) -> (A, u16);
}
struct Invoker<A> {
a: A,
b: u16,
}
impl<A:Clone> Invokable<A> for Invoker<A> {
fn f(&self) -> (A, u16) {
(self.a.clone(), self.b)
}
}
fn f<A:Clone + 'static>(a: A, b: u16) -> Box<dyn Invokable<A>+'static> {
box Invoker {
a: a,
b: b,
} as (Box<dyn Invokable<A>+'static>)
}
pub fn main() {
let (a, b) = f(22_u64, 44u16).f();
println!("a={} b={}", a, b);
assert_eq!(a, 22u64);
assert_eq!(b, 44u16);
}

View file

@ -0,0 +1,15 @@
// run-pass
#![allow(non_camel_case_types)]
#![allow(dead_code)]
// pretty-expanded FIXME #23616
enum option<T> { some(T), none, }
struct R<T> {v: Vec<option<T>> }
fn f<T>() -> Vec<T> { return Vec::new(); }
pub fn main() { let mut r: R<isize> = R {v: Vec::new()}; r.v = f(); }

View file

@ -0,0 +1,18 @@
// run-pass
#![allow(stable_features)]
#![feature(allocator_api, nonnull)]
use std::alloc::{Alloc, Global, Layout, handle_alloc_error};
fn main() {
unsafe {
let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| {
handle_alloc_error(Layout::new::<i32>())
});
*ptr.as_ptr() = 4;
assert_eq!(*ptr.as_ptr(), 4);
Global.dealloc_one(ptr);
}
}

View file

@ -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)
}

View file

@ -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)
}
}

View file

@ -0,0 +1,9 @@
// no-prefer-dynamic
#![crate_type = "rlib"]
use std::fmt;
pub fn work_with(p: &fmt::Debug) {
drop(p);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -0,0 +1,58 @@
// run-pass
// aux-build:helper.rs
// no-prefer-dynamic
#![feature(allocator_api)]
extern crate helper;
use std::alloc::{self, Global, Alloc, System, Layout};
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);
System.alloc(layout)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
HITS.fetch_add(1, Ordering::SeqCst);
System.dealloc(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 ptr = Global.alloc(layout.clone()).unwrap();
helper::work_with(&ptr);
assert_eq!(HITS.load(Ordering::SeqCst), n + 1);
Global.dealloc(ptr, layout.clone());
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 ptr = System.alloc(layout.clone()).unwrap();
assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
helper::work_with(&ptr);
System.dealloc(ptr, layout);
assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
}
}

View file

@ -0,0 +1,35 @@
// run-pass
// aux-build:custom.rs
// aux-build:helper.rs
// no-prefer-dynamic
#![feature(allocator_api)]
extern crate custom;
extern crate helper;
use std::alloc::{Global, Alloc, System, Layout};
use std::sync::atomic::{Ordering, AtomicUsize};
#[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 ptr = Global.alloc(layout.clone()).unwrap();
helper::work_with(&ptr);
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
Global.dealloc(ptr, layout.clone());
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
let ptr = System.alloc(layout.clone()).unwrap();
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
helper::work_with(&ptr);
System.dealloc(ptr, layout);
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
}
}

View file

@ -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);
}
}

View file

@ -0,0 +1,18 @@
// run-pass
// pretty-expanded FIXME #23616
// ignore-wasm32-bare no libc to test ffi with
#![feature(rustc_private)]
extern crate libc;
#[link(name = "rust_test_helpers", kind = "static")]
extern {
fn rust_get_test_int() -> libc::intptr_t;
}
pub fn main() {
unsafe {
let _ = rust_get_test_int();
}
}

View file

@ -0,0 +1,25 @@
// run-pass
struct X {
x: isize
}
fn f1(a: &mut X, b: &mut isize, c: isize) -> isize {
let r = a.x + *b + c;
a.x = 0;
*b = 10;
return r;
}
fn f2<F>(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; }
pub fn main() {
let mut a = X {x: 1};
let mut b = 2;
let c = 3;
assert_eq!(f1(&mut a, &mut b, c), 6);
assert_eq!(a.x, 0);
assert_eq!(b, 10);
assert_eq!(f2(a.x, |_| a.x = 50), 0);
assert_eq!(a.x, 50);
}

View file

@ -0,0 +1,31 @@
// run-pass
use std::cell::Cell;
#[derive(Debug)]
struct B<'a> {
a: [Cell<Option<&'a B<'a>>>; 2]
}
impl<'a> B<'a> {
fn new() -> B<'a> {
B { a: [Cell::new(None), Cell::new(None)] }
}
}
fn f() {
let (b1, b2, b3);
b1 = B::new();
b2 = B::new();
b3 = B::new();
b1.a[0].set(Some(&b2));
b1.a[1].set(Some(&b3));
b2.a[0].set(Some(&b2));
b2.a[1].set(Some(&b3));
b3.a[0].set(Some(&b1));
b3.a[1].set(Some(&b2));
}
fn main() {
f();
}

View file

@ -0,0 +1,12 @@
// run-pass
#![allow(dead_code)]
#![allow(stable_features)]
#![feature(const_indexing)]
fn main() {
const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
const IDX: usize = 3;
const VAL: i32 = ARR[IDX];
const BLUB: [i32; (ARR[0] - 41) as usize] = [5];
}

View file

@ -0,0 +1,47 @@
// run-pass
#![allow(overflowing_literals)]
// Test that we cleanup a fixed size Box<[D; k]> properly when D has a
// destructor.
// ignore-emscripten no threads support
use std::thread;
use std::sync::atomic::{AtomicUsize, Ordering};
static LOG: AtomicUsize = AtomicUsize::new(0);
struct D(u8);
impl Drop for D {
fn drop(&mut self) {
println!("Dropping {}", self.0);
let old = LOG.load(Ordering::SeqCst);
LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst);
}
}
fn main() {
fn die() -> D { panic!("Oh no"); }
let g = thread::spawn(|| {
let _b1: Box<[D; 4]> = Box::new([D( 1), D( 2), D( 3), D( 4)]);
let _b2: Box<[D; 4]> = Box::new([D( 5), D( 6), D( 7), D( 8)]);
let _b3: Box<[D; 4]> = Box::new([D( 9), D(10), die(), D(12)]);
let _b4: Box<[D; 4]> = Box::new([D(13), D(14), D(15), D(16)]);
});
assert!(g.join().is_err());
// When the panic occurs, we will be in the midst of constructing
// the input to `_b3`. Therefore, we drop the elements of the
// partially filled array first, before we get around to dropping
// the elements of `_b1` and _b2`.
// Issue 23222: The order in which the elements actually get
// dropped is a little funky. See similar notes in nested-vec-3;
// in essence, I would not be surprised if we change the ordering
// given in `expect` in the future.
let expect = 0x__A_9__5_6_7_8__1_2_3_4;
let actual = LOG.load(Ordering::SeqCst);
assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual);
}

View file

@ -0,0 +1,47 @@
// run-pass
#![allow(overflowing_literals)]
// Test that we cleanup dynamic sized Box<[D]> properly when D has a
// destructor.
// ignore-emscripten no threads support
use std::thread;
use std::sync::atomic::{AtomicUsize, Ordering};
static LOG: AtomicUsize = AtomicUsize::new(0);
struct D(u8);
impl Drop for D {
fn drop(&mut self) {
println!("Dropping {}", self.0);
let old = LOG.load(Ordering::SeqCst);
LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst);
}
}
fn main() {
fn die() -> D { panic!("Oh no"); }
let g = thread::spawn(|| {
let _b1: Box<[D; 4]> = Box::new([D( 1), D( 2), D( 3), D( 4)]);
let _b2: Box<[D; 4]> = Box::new([D( 5), D( 6), D( 7), D( 8)]);
let _b3: Box<[D; 4]> = Box::new([D( 9), D(10), die(), D(12)]);
let _b4: Box<[D; 4]> = Box::new([D(13), D(14), D(15), D(16)]);
});
assert!(g.join().is_err());
// When the panic occurs, we will be in the midst of constructing
// the input to `_b3`. Therefore, we drop the elements of the
// partially filled array first, before we get around to dropping
// the elements of `_b1` and _b2`.
// Issue 23222: The order in which the elements actually get
// dropped is a little funky. See similar notes in nested-vec-3;
// in essence, I would not be surprised if we change the ordering
// given in `expect` in the future.
let expect = 0x__A_9__5_6_7_8__1_2_3_4;
let actual = LOG.load(Ordering::SeqCst);
assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual);
}

View file

@ -0,0 +1,14 @@
// run-pass
// issues #10618 and #16382
// pretty-expanded FIXME #23616
const SIZE: isize = 25;
fn main() {
let _a: [bool; 1 as usize];
let _b: [isize; SIZE as usize] = [1; SIZE as usize];
let _c: [bool; '\n' as usize] = [true; '\n' as usize];
let _d: [bool; true as usize] = [true; true as usize];
}

View file

@ -0,0 +1,15 @@
// run-pass
#![allow(dead_code)]
// Checks that mutable static items can have mutable slices
static mut TEST: &'static mut [isize] = &mut [1];
static mut EMPTY: &'static mut [isize] = &mut [];
pub fn main() {
unsafe {
TEST[0] += 1;
assert_eq!(TEST[0], 2);
}
}

View file

@ -0,0 +1,36 @@
// run-pass
// Check that the various ways of getting to a reference to a vec (both sized
// and unsized) work properly.
const AA: [isize; 3] = [1, 2, 3];
const AB: &'static [isize; 3] = &AA;
const AC: &'static [isize] = AB;
const AD: &'static [isize] = &AA;
const AE: &'static [isize; 3] = &[1, 2, 3];
const AF: &'static [isize] = &[1, 2, 3];
static CA: isize = AA[0];
static CB: isize = AB[1];
static CC: isize = AC[2];
static CD: isize = AD[0];
static CE: isize = AE[1];
static CF: isize = AF[2];
static AG: &'static isize = &AA[2];
fn main () {
let b: &[isize] = &[1, 2, 3];
assert_eq!(AC, b);
assert_eq!(AD, b);
assert_eq!(AF, b);
assert_eq!(*AG, 3);
assert_eq!(CA, 1);
assert_eq!(CB, 2);
assert_eq!(CC, 3);
assert_eq!(CD, 1);
assert_eq!(CE, 2);
assert_eq!(CF, 3);
}

View file

@ -0,0 +1,19 @@
// run-pass
// Ensure that we can copy out of a fixed-size array.
//
// (Compare with compile-fail/move-out-of-array-1.rs)
#[derive(Copy, Clone)]
struct C { _x: u8 }
fn main() {
fn d() -> C { C { _x: 0 } }
let _d1 = foo([d(), d(), d(), d()], 1);
let _d3 = foo([d(), d(), d(), d()], 3);
}
fn foo(a: [C; 4], i: usize) -> C {
a[i]
}

View file

@ -0,0 +1,27 @@
// run-pass
// Ensure that we can do a destructuring bind of a fixed-size array,
// even when the element type has a destructor.
struct D { x: u8 }
impl Drop for D { fn drop(&mut self) { } }
fn main() {
fn d(x: u8) -> D { D { x: x } }
let d1 = foo([d(1), d(2), d(3), d(4)], 1);
let d3 = foo([d(5), d(6), d(7), d(8)], 3);
assert_eq!(d1.x, 2);
assert_eq!(d3.x, 8);
}
fn foo([a, b, c, d]: [D; 4], i: usize) -> D {
match i {
0 => a,
1 => b,
2 => c,
3 => d,
_ => panic!("unmatched"),
}
}

View file

@ -0,0 +1,8 @@
// run-pass
// pretty-expanded FIXME #23616
#![allow(unused_mut)]
pub fn main() { let mut _v: Vec<isize> = Vec::new(); }

View file

@ -0,0 +1,50 @@
// run-pass
pub fn main() {
let x = "hello";
let v = "hello";
let y : &str = "there";
println!("{}", x);
println!("{}", y);
assert_eq!(x.as_bytes()[0], 'h' as u8);
assert_eq!(x.as_bytes()[4], 'o' as u8);
let z : &str = "thing";
assert_eq!(v, x);
assert_ne!(x, z);
let a = "aaaa";
let b = "bbbb";
let c = "cccc";
let cc = "ccccc";
println!("{}", a);
assert!(a < b);
assert!(a <= b);
assert_ne!(a, b);
assert!(b >= a);
assert!(b > a);
println!("{}", b);
assert!(a < c);
assert!(a <= c);
assert_ne!(a, c);
assert!(c >= a);
assert!(c > a);
println!("{}", c);
assert!(c < cc);
assert!(c <= cc);
assert_ne!(c, cc);
assert!(cc >= c);
assert!(cc > c);
println!("{}", cc);
}

View file

@ -0,0 +1,47 @@
// run-pass
#![allow(unused_assignments)]
pub fn main() {
let x : &[isize] = &[1,2,3,4,5];
let mut z : &[isize] = &[1,2,3,4,5];
z = x;
assert_eq!(z[0], 1);
assert_eq!(z[4], 5);
let a : &[isize] = &[1,1,1,1,1];
let b : &[isize] = &[2,2,2,2,2];
let c : &[isize] = &[2,2,2,2,3];
let cc : &[isize] = &[2,2,2,2,2,2];
println!("{:?}", a);
assert!(a < b);
assert!(a <= b);
assert!(a != b);
assert!(b >= a);
assert!(b > a);
println!("{:?}", b);
assert!(b < c);
assert!(b <= c);
assert!(b != c);
assert!(c >= b);
assert!(c > b);
assert!(a < c);
assert!(a <= c);
assert!(a != c);
assert!(c >= a);
assert!(c > a);
println!("{:?}", c);
assert!(a < cc);
assert!(a <= cc);
assert!(a != cc);
assert!(cc >= a);
assert!(cc > a);
println!("{:?}", cc);
}

View file

@ -0,0 +1,9 @@
// run-pass
pub fn main() {
let arr = [1,2,3];
let arr2 = arr;
assert_eq!(arr[1], 2);
assert_eq!(arr2[2], 3);
}

View file

@ -0,0 +1,14 @@
// run-pass
use std::mem::size_of;
#[cfg(target_pointer_width = "32")]
pub fn main() {
assert_eq!(size_of::<[u8; (1 << 31) - 1]>(), (1 << 31) - 1);
}
#[cfg(target_pointer_width = "64")]
pub fn main() {
assert_eq!(size_of::<[u8; (1 << 47) - 1]>(), (1 << 47) - 1);
}

View file

@ -0,0 +1,4 @@
// run-pass
fn f(_a: Vec<isize> ) { }
pub fn main() { f(vec![1, 2, 3, 4, 5]); }

View file

@ -0,0 +1,19 @@
// run-pass
fn test1() {
let mut ints = [0; 32];
ints[0] += 1;
assert_eq!(ints[0], 1);
}
fn test2() {
let mut ints = [0; 32];
for i in &mut ints { *i += 22; }
for i in &ints { assert_eq!(*i, 22); }
}
pub fn main() {
test1();
test2();
}

View file

@ -0,0 +1,15 @@
// run-pass
fn grow(v: &mut Vec<isize> ) {
v.push(1);
}
pub fn main() {
let mut v: Vec<isize> = Vec::new();
grow(&mut v);
grow(&mut v);
grow(&mut v);
let len = v.len();
println!("{}", len);
assert_eq!(len, 3 as usize);
}

View file

@ -0,0 +1,8 @@
// run-pass
// Test that using the `vec!` macro nested within itself works
fn main() {
let nested = vec![vec![1u32, 2u32, 3u32]];
assert_eq!(nested[0][1], 2);
}

View file

@ -0,0 +1,15 @@
// run-pass
// Test that using the `vec!` macro nested within itself works
// when the contents implement Drop
struct D(u32);
impl Drop for D {
fn drop(&mut self) { println!("Dropping {}", self.0); }
}
fn main() {
let nested = vec![vec![D(1u32), D(2u32), D(3u32)]];
assert_eq!(nested[0][1].0, 2);
}

View file

@ -0,0 +1,54 @@
// run-pass
#![allow(overflowing_literals)]
// ignore-emscripten no threads support
// Test that using the `vec!` macro nested within itself works when
// the contents implement Drop and we hit a panic in the middle of
// construction.
use std::thread;
use std::sync::atomic::{AtomicUsize, Ordering};
static LOG: AtomicUsize = AtomicUsize::new(0);
struct D(u8);
impl Drop for D {
fn drop(&mut self) {
println!("Dropping {}", self.0);
let old = LOG.load(Ordering::SeqCst);
LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst);
}
}
fn main() {
fn die() -> D { panic!("Oh no"); }
let g = thread::spawn(|| {
let _nested = vec![vec![D( 1), D( 2), D( 3), D( 4)],
vec![D( 5), D( 6), D( 7), D( 8)],
vec![D( 9), D(10), die(), D(12)],
vec![D(13), D(14), D(15), D(16)]];
});
assert!(g.join().is_err());
// When the panic occurs, we will be in the midst of constructing the
// second inner vector. Therefore, we drop the elements of the
// partially filled vector first, before we get around to dropping
// the elements of the filled vector.
// Issue 23222: The order in which the elements actually get
// dropped is a little funky: as noted above, we'll drop the 9+10
// first, but due to #23222, they get dropped in reverse
// order. Likewise, again due to #23222, we will drop the second
// filled vec before the first filled vec.
//
// If Issue 23222 is "fixed", then presumably the corrected
// expected order of events will be 0x__9_A__1_2_3_4__5_6_7_8;
// that is, we would still drop 9+10 first, since they belong to
// the more deeply nested expression when the panic occurs.
let expect = 0x__A_9__5_6_7_8__1_2_3_4;
let actual = LOG.load(Ordering::SeqCst);
assert!(actual == expect, "expect: 0x{:x} actual: 0x{:x}", expect, actual);
}

View file

@ -0,0 +1,7 @@
// run-pass
static FOO: [isize; 3] = [1, 2, 3];
pub fn main() {
println!("{} {} {}", FOO[0], FOO[1], FOO[2]);
}

View file

@ -0,0 +1,33 @@
// run-pass
#![allow(non_camel_case_types)]
trait sum {
fn sum_(self) -> isize;
}
// Note: impl on a slice
impl<'a> sum for &'a [isize] {
fn sum_(self) -> isize {
self.iter().fold(0, |a, &b| a + b)
}
}
fn call_sum(x: &[isize]) -> isize { x.sum_() }
pub fn main() {
let x = vec![1, 2, 3];
let y = call_sum(&x);
println!("y=={}", y);
assert_eq!(y, 6);
let x = vec![1, 2, 3];
let y = x.sum_();
println!("y=={}", y);
assert_eq!(y, 6);
let x = vec![1, 2, 3];
let y = x.sum_();
println!("y=={}", y);
assert_eq!(y, 6);
}

View file

@ -0,0 +1,13 @@
// run-pass
pub fn main() {
let x = [ [true]; 512 ];
let y = [ 0; 1 ];
print!("[");
for xi in &x[..] {
print!("{:?}, ", &xi[..]);
}
println!("]");
println!("{:?}", &y[..]);
}

View file

@ -0,0 +1,8 @@
// run-pass
#[derive(Debug)]
struct Foo(Box<[u8]>);
pub fn main() {
println!("{:?}", Foo(Box::new([0, 1, 2])));
}

View file

@ -0,0 +1,62 @@
// run-pass
// Test slicing expressions on slices and Vecs.
fn main() {
let x: &[isize] = &[1, 2, 3, 4, 5];
let cmp: &[isize] = &[1, 2, 3, 4, 5];
assert_eq!(&x[..], cmp);
let cmp: &[isize] = &[3, 4, 5];
assert_eq!(&x[2..], cmp);
let cmp: &[isize] = &[1, 2, 3];
assert_eq!(&x[..3], cmp);
let cmp: &[isize] = &[2, 3, 4];
assert_eq!(&x[1..4], cmp);
let x: Vec<isize> = vec![1, 2, 3, 4, 5];
let cmp: &[isize] = &[1, 2, 3, 4, 5];
assert_eq!(&x[..], cmp);
let cmp: &[isize] = &[3, 4, 5];
assert_eq!(&x[2..], cmp);
let cmp: &[isize] = &[1, 2, 3];
assert_eq!(&x[..3], cmp);
let cmp: &[isize] = &[2, 3, 4];
assert_eq!(&x[1..4], cmp);
let x: &mut [isize] = &mut [1, 2, 3, 4, 5];
{
let cmp: &mut [isize] = &mut [1, 2, 3, 4, 5];
assert_eq!(&mut x[..], cmp);
}
{
let cmp: &mut [isize] = &mut [3, 4, 5];
assert_eq!(&mut x[2..], cmp);
}
{
let cmp: &mut [isize] = &mut [1, 2, 3];
assert_eq!(&mut x[..3], cmp);
}
{
let cmp: &mut [isize] = &mut [2, 3, 4];
assert_eq!(&mut x[1..4], cmp);
}
let mut x: Vec<isize> = vec![1, 2, 3, 4, 5];
{
let cmp: &mut [isize] = &mut [1, 2, 3, 4, 5];
assert_eq!(&mut x[..], cmp);
}
{
let cmp: &mut [isize] = &mut [3, 4, 5];
assert_eq!(&mut x[2..], cmp);
}
{
let cmp: &mut [isize] = &mut [1, 2, 3];
assert_eq!(&mut x[..3], cmp);
}
{
let cmp: &mut [isize] = &mut [2, 3, 4];
assert_eq!(&mut x[1..4], cmp);
}
}

View file

@ -0,0 +1,53 @@
// run-pass
#![allow(stable_features)]
// compile-flags: -C debug-assertions
#![feature(iter_to_slice)]
use std::slice;
fn foo<T>(v: &[T]) -> Option<&[T]> {
let mut it = v.iter();
for _ in 0..5 {
let _ = it.next();
}
Some(it.as_slice())
}
fn foo_mut<T>(v: &mut [T]) -> Option<&mut [T]> {
let mut it = v.iter_mut();
for _ in 0..5 {
let _ = it.next();
}
Some(it.into_slice())
}
pub fn main() {
// In a slice of zero-size elements the pointer is meaningless.
// Ensure iteration still works even if the pointer is at the end of the address space.
let slice: &[()] = unsafe { slice::from_raw_parts(-5isize as *const (), 10) };
assert_eq!(slice.len(), 10);
assert_eq!(slice.iter().count(), 10);
// .nth() on the iterator should also behave correctly
let mut it = slice.iter();
assert!(it.nth(5).is_some());
assert_eq!(it.count(), 4);
// Converting Iter to a slice should never have a null pointer
assert!(foo(slice).is_some());
// Test mutable iterators as well
let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) };
assert_eq!(slice.len(), 10);
assert_eq!(slice.iter_mut().count(), 10);
{
let mut it = slice.iter_mut();
assert!(it.nth(5).is_some());
assert_eq!(it.count(), 4);
}
assert!(foo_mut(slice).is_some())
}

View file

@ -0,0 +1,26 @@
// run-pass
// ignore-emscripten no threads support
// Test that if a slicing expr[..] fails, the correct cleanups happen.
use std::thread;
struct Foo;
static mut DTOR_COUNT: isize = 0;
impl Drop for Foo {
fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } }
}
fn foo() {
let x: &[_] = &[Foo, Foo];
&x[3..4];
}
fn main() {
let _ = thread::spawn(move|| foo()).join();
unsafe { assert_eq!(DTOR_COUNT, 2); }
}

View file

@ -0,0 +1,30 @@
// run-pass
// ignore-emscripten no threads support
// Test that if a slicing expr[..] fails, the correct cleanups happen.
use std::thread;
struct Foo;
static mut DTOR_COUNT: isize = 0;
impl Drop for Foo {
fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } }
}
fn bar() -> usize {
panic!();
}
fn foo() {
let x: &[_] = &[Foo, Foo];
&x[3..bar()];
}
fn main() {
let _ = thread::spawn(move|| foo()).join();
unsafe { assert_eq!(DTOR_COUNT, 2); }
}

View file

@ -0,0 +1,81 @@
// run-pass
#![allow(unused_variables)]
// Test slicing sugar.
extern crate core;
use core::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
static mut COUNT: usize = 0;
struct Foo;
impl Index<Range<Foo>> for Foo {
type Output = Foo;
fn index(&self, index: Range<Foo>) -> &Foo {
unsafe { COUNT += 1; }
self
}
}
impl Index<RangeTo<Foo>> for Foo {
type Output = Foo;
fn index(&self, index: RangeTo<Foo>) -> &Foo {
unsafe { COUNT += 1; }
self
}
}
impl Index<RangeFrom<Foo>> for Foo {
type Output = Foo;
fn index(&self, index: RangeFrom<Foo>) -> &Foo {
unsafe { COUNT += 1; }
self
}
}
impl Index<RangeFull> for Foo {
type Output = Foo;
fn index(&self, _index: RangeFull) -> &Foo {
unsafe { COUNT += 1; }
self
}
}
impl IndexMut<Range<Foo>> for Foo {
fn index_mut(&mut self, index: Range<Foo>) -> &mut Foo {
unsafe { COUNT += 1; }
self
}
}
impl IndexMut<RangeTo<Foo>> for Foo {
fn index_mut(&mut self, index: RangeTo<Foo>) -> &mut Foo {
unsafe { COUNT += 1; }
self
}
}
impl IndexMut<RangeFrom<Foo>> for Foo {
fn index_mut(&mut self, index: RangeFrom<Foo>) -> &mut Foo {
unsafe { COUNT += 1; }
self
}
}
impl IndexMut<RangeFull> for Foo {
fn index_mut(&mut self, _index: RangeFull) -> &mut Foo {
unsafe { COUNT += 1; }
self
}
}
fn main() {
let mut x = Foo;
&x[..];
&x[Foo..];
&x[..Foo];
&x[Foo..Foo];
&mut x[..];
&mut x[Foo..];
&mut x[..Foo];
&mut x[Foo..Foo];
unsafe {
assert_eq!(COUNT, 8);
}
}

View file

@ -0,0 +1,21 @@
// run-pass
// Test binary_search_by_key lifetime. Issue #34683
#[derive(Debug)]
struct Assignment {
topic: String,
partition: i32,
}
fn main() {
let xs = vec![
Assignment { topic: "abc".into(), partition: 1 },
Assignment { topic: "def".into(), partition: 2 },
Assignment { topic: "ghi".into(), partition: 3 },
];
let key: &str = "def";
let r = xs.binary_search_by_key(&key, |e| &e.topic);
assert_eq!(Ok(1), r.map(|i| i));
}

View file

@ -0,0 +1,20 @@
// run-pass
// Test that vec is now covariant in its argument type.
#![allow(dead_code)]
fn foo<'a,'b>(v1: Vec<&'a i32>, v2: Vec<&'b i32>) -> i32 {
bar(v1, v2).cloned().unwrap_or(0) // only type checks if we can intersect 'a and 'b
}
fn bar<'c>(v1: Vec<&'c i32>, v2: Vec<&'c i32>) -> Option<&'c i32> {
v1.get(0).cloned().or_else(|| v2.get(0).cloned())
}
fn main() {
let x = 22;
let y = 44;
assert_eq!(foo(vec![&x], vec![&y]), 22);
assert_eq!(foo(vec![&y], vec![&x]), 44);
}

View file

@ -0,0 +1,14 @@
// run-pass
use std::vec;
pub fn main() {
let a: Vec<isize> = vec![1, 2, 3, 4, 5];
let b: Vec<isize> = vec![6, 7, 8, 9, 0];
let mut v: Vec<isize> = a;
v.extend_from_slice(&b);
println!("{}", v[9]);
assert_eq!(v[0], 1);
assert_eq!(v[7], 8);
assert_eq!(v[9], 0);
}

View file

@ -0,0 +1,26 @@
// run-pass
#![feature(box_syntax)]
pub fn main() {
// Tests for indexing into box/& [T; n]
let x: [isize; 3] = [1, 2, 3];
let mut x: Box<[isize; 3]> = box x;
assert_eq!(x[0], 1);
assert_eq!(x[1], 2);
assert_eq!(x[2], 3);
x[1] = 45;
assert_eq!(x[0], 1);
assert_eq!(x[1], 45);
assert_eq!(x[2], 3);
let mut x: [isize; 3] = [1, 2, 3];
let x: &mut [isize; 3] = &mut x;
assert_eq!(x[0], 1);
assert_eq!(x[1], 2);
assert_eq!(x[2], 3);
x[1] = 45;
assert_eq!(x[0], 1);
assert_eq!(x[1], 45);
assert_eq!(x[2], 3);
}

View file

@ -0,0 +1,24 @@
// run-pass
use std::mem::size_of;
#[cfg(not(target_pointer_width = "64"))]
fn test_big_vec() {}
#[cfg(target_pointer_width = "64")]
fn test_big_vec()
{
assert_eq!(size_of::<[u8; (1 << 32)]>(), (1 << 32));
}
fn main() {
let x: [isize; 4] = [1, 2, 3, 4];
assert_eq!(x[0], 1);
assert_eq!(x[1], 2);
assert_eq!(x[2], 3);
assert_eq!(x[3], 4);
assert_eq!(size_of::<[u8; 4]>(), 4);
test_big_vec();
}

View file

@ -0,0 +1,16 @@
// run-pass
pub fn main() {
let mut v = vec![1];
v.push(2);
v.push(3);
v.push(4);
v.push(5);
assert_eq!(v[0], 1);
assert_eq!(v[1], 2);
assert_eq!(v[2], 3);
assert_eq!(v[3], 4);
assert_eq!(v[4], 5);
}

View file

@ -0,0 +1,9 @@
// run-pass
#![allow(unused_mut)]
pub fn main() {
let mut later: Vec<isize> ;
if true { later = vec![1]; } else { later = vec![2]; }
println!("{}", later[0]);
}

View file

@ -0,0 +1,27 @@
// run-pass
// ignore-emscripten no no_std executables
#![feature(lang_items, start, rustc_private)]
#![no_std]
extern crate std as other;
extern crate libc;
#[macro_use]
extern crate alloc;
use alloc::vec::Vec;
// Issue #16806
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
let x: Vec<u8> = vec![0, 1, 2];
match x.last() {
Some(&2) => (),
_ => panic!(),
}
0
}

View file

@ -0,0 +1,15 @@
// run-pass
pub fn main() {
assert_eq!(vec![1; 3], vec![1, 1, 1]);
assert_eq!(vec![1; 2], vec![1, 1]);
assert_eq!(vec![1; 1], vec![1]);
assert_eq!(vec![1; 0], vec![]);
// from_elem syntax (see RFC 832)
let el = Box::new(1);
let n = 3;
assert_eq!(vec![el; n], vec![Box::new(1), Box::new(1), Box::new(1)]);
}

View file

@ -0,0 +1,11 @@
// run-pass
fn one() -> i32 { 1 }
// Make sure the vec![...] macro doesn't introduce hidden rvalue
// scopes (such as blocks) around the element expressions.
pub fn main() {
assert_eq!(vec![&one(), &one(), &2], vec![&1, &1, &(one()+one())]);
assert_eq!(vec![&one(); 2], vec![&1, &one()]);
}

View file

@ -0,0 +1,16 @@
// run-pass
#![allow(unused_variables)]
// pretty-expanded FIXME #23616
macro_rules! vec [
($($e:expr),*) => ({
let mut _temp = ::std::vec::Vec::new();
$(_temp.push($e);)*
_temp
})
];
pub fn main() {
let my_vec = vec![1, 2, 3, 4, 5];
}

View file

@ -0,0 +1,8 @@
// run-pass
pub fn main() {
assert_eq!(vec![1], vec![1,]);
assert_eq!(vec![1, 2, 3], vec![1, 2, 3,]);
}

View file

@ -0,0 +1,23 @@
// run-pass
#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620
pub fn main() {
let x = [1, 2, 3];
match x {
[2, _, _] => panic!(),
[1, a, b] => {
assert_eq!([a, b], [2, 3]);
}
[_, _, _] => panic!(),
}
let y = ([(1, true), (2, false)], 0.5f64);
match y {
([(1, a), (b, false)], _) => {
assert_eq!(a, true);
assert_eq!(b, 2);
}
([_, _], 0.5) => panic!(),
([_, _], _) => panic!(),
}
}

View file

@ -0,0 +1,32 @@
// run-pass
#![feature(slice_patterns)]
fn a() {
let x = [1, 2, 3];
match x {
[1, 2, 4] => unreachable!(),
[0, 2, 3, ..] => unreachable!(),
[0, .., 3] => unreachable!(),
[0, ..] => unreachable!(),
[1, 2, 3] => (),
[_, _, _] => unreachable!(),
}
match x {
[..] => (),
}
match x {
[_, _, _, ..] => (),
}
match x {
[a, b, c] => {
assert_eq!(1, a);
assert_eq!(2, b);
assert_eq!(3, c);
}
}
}
pub fn main() {
a();
}

View file

@ -0,0 +1,48 @@
// run-pass
#![feature(slice_patterns)]
use std::fmt::Debug;
fn foldl<T, U, F>(values: &[T],
initial: U,
mut function: F)
-> U where
U: Clone+Debug, T:Debug,
F: FnMut(U, &T) -> U,
{ match values {
&[ref head, ref tail..] =>
foldl(tail, function(initial, head), function),
&[] => {
// FIXME: call guards
let res = initial.clone(); res
}
}
}
fn foldr<T, U, F>(values: &[T],
initial: U,
mut function: F)
-> U where
U: Clone,
F: FnMut(&T, U) -> U,
{
match values {
&[ref head.., ref tail] =>
foldr(head, function(tail, initial), function),
&[] => {
// FIXME: call guards
let res = initial.clone(); res
}
}
}
pub fn main() {
let x = &[1, 2, 3, 4, 5];
let product = foldl(x, 1, |a, b| a * *b);
assert_eq!(product, 120);
let sum = foldr(x, 0, |a, b| *a + b);
assert_eq!(sum, 15);
}

View file

@ -0,0 +1,16 @@
// run-pass
#![allow(unused_variables)]
#![feature(slice_patterns)]
pub fn main() {
let x = &[1, 2, 3, 4, 5];
let x: &[isize] = &[1, 2, 3, 4, 5];
if !x.is_empty() {
let el = match x {
&[1, ref tail..] => &tail[0],
_ => unreachable!()
};
println!("{}", *el);
}
}

View file

@ -0,0 +1,159 @@
// run-pass
#![feature(slice_patterns)]
fn a() {
let x = [1];
match x {
[a] => {
assert_eq!(a, 1);
}
}
}
fn b() {
let x = [1, 2, 3];
match x {
[a, b, c..] => {
assert_eq!(a, 1);
assert_eq!(b, 2);
let expected: &[_] = &[3];
assert_eq!(c, expected);
}
}
match x {
[a.., b, c] => {
let expected: &[_] = &[1];
assert_eq!(a, expected);
assert_eq!(b, 2);
assert_eq!(c, 3);
}
}
match x {
[a, b.., c] => {
assert_eq!(a, 1);
let expected: &[_] = &[2];
assert_eq!(b, expected);
assert_eq!(c, 3);
}
}
match x {
[a, b, c] => {
assert_eq!(a, 1);
assert_eq!(b, 2);
assert_eq!(c, 3);
}
}
}
fn b_slice() {
let x : &[_] = &[1, 2, 3];
match x {
&[a, b, ref c..] => {
assert_eq!(a, 1);
assert_eq!(b, 2);
let expected: &[_] = &[3];
assert_eq!(c, expected);
}
_ => unreachable!()
}
match x {
&[ref a.., b, c] => {
let expected: &[_] = &[1];
assert_eq!(a, expected);
assert_eq!(b, 2);
assert_eq!(c, 3);
}
_ => unreachable!()
}
match x {
&[a, ref b.., c] => {
assert_eq!(a, 1);
let expected: &[_] = &[2];
assert_eq!(b, expected);
assert_eq!(c, 3);
}
_ => unreachable!()
}
match x {
&[a, b, c] => {
assert_eq!(a, 1);
assert_eq!(b, 2);
assert_eq!(c, 3);
}
_ => unreachable!()
}
}
fn c() {
let x = [1];
match x {
[2, ..] => panic!(),
[..] => ()
}
}
fn d() {
let x = [1, 2, 3];
let branch = match x {
[1, 1, ..] => 0,
[1, 2, 3, ..] => 1,
[1, 2, ..] => 2,
_ => 3
};
assert_eq!(branch, 1);
}
fn e() {
let x: &[isize] = &[1, 2, 3];
let a = match *x {
[1, 2] => 0,
[..] => 1,
};
assert_eq!(a, 1);
let b = match *x {
[2, ..] => 0,
[1, 2, ..] => 1,
[_] => 2,
[..] => 3
};
assert_eq!(b, 1);
let c = match *x {
[_, _, _, _, ..] => 0,
[1, 2, ..] => 1,
[_] => 2,
[..] => 3
};
assert_eq!(c, 1);
}
fn f() {
let x = &[1, 2, 3, 4, 5];
let [a, [b, [c, ..].., d].., e] = *x;
assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
let x: &[isize] = x;
let (a, b, c, d, e) = match *x {
[a, [b, [c, ..].., d].., e] => (a, b, c, d, e),
_ => unimplemented!()
};
assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
}
pub fn main() {
a();
b();
b_slice();
c();
d();
e();
f();
}

View file

@ -0,0 +1,3 @@
// run-pass
pub fn main() { let mut v = vec![1, 2, 3]; v.push(1); }

View file

@ -0,0 +1,5 @@
// run-pass
// pretty-expanded FIXME #23616
pub fn main() { let _a = [0; 1 as usize]; }

View file

@ -0,0 +1,31 @@
// run-pass
#![allow(non_camel_case_types)]
use std::cell::Cell;
// Make sure that destructors get run on slice literals
struct foo<'a> {
x: &'a Cell<isize>,
}
impl<'a> Drop for foo<'a> {
fn drop(&mut self) {
self.x.set(self.x.get() + 1);
}
}
fn foo(x: &Cell<isize>) -> foo {
foo {
x: x
}
}
pub fn main() {
let x = &Cell::new(0);
{
let l = &[foo(x)];
assert_eq!(l[0].x.get(), 0);
}
assert_eq!(x.get(), 1);
}

View file

@ -0,0 +1,9 @@
// run-pass
pub fn main() {
let v = vec![1,2,3,4,5];
let v2 = &v[1..3];
assert_eq!(v2[0], 2);
assert_eq!(v2[1], 3);
}

View file

@ -0,0 +1,36 @@
// run-pass
#![feature(slice_patterns)]
struct Foo {
string: &'static str
}
pub fn main() {
let x = [
Foo { string: "foo" },
Foo { string: "bar" },
Foo { string: "baz" }
];
match x {
[ref first, ref tail..] => {
assert_eq!(first.string, "foo");
assert_eq!(tail.len(), 2);
assert_eq!(tail[0].string, "bar");
assert_eq!(tail[1].string, "baz");
match *(tail as &[_]) {
[Foo { .. }, _, Foo { .. }, ref _tail..] => {
unreachable!();
}
[Foo { string: ref a }, Foo { string: ref b }] => {
assert_eq!("bar", &a[0..a.len()]);
assert_eq!("baz", &b[0..b.len()]);
}
_ => {
unreachable!();
}
}
}
}
}

View file

@ -0,0 +1,12 @@
// run-pass
pub fn main() {
assert_eq!(format!("{:?}", vec![0, 1]), "[0, 1]".to_string());
let foo = vec![3, 4];
let bar: &[isize] = &[4, 5];
assert_eq!(format!("{:?}", foo), "[3, 4]");
assert_eq!(format!("{:?}", bar), "[4, 5]");
}

View file

@ -0,0 +1,15 @@
// run-pass
pub fn main() {
let v: Vec<isize> = vec![10, 20];
assert_eq!(v[0], 10);
assert_eq!(v[1], 20);
let mut x: usize = 0;
assert_eq!(v[x], 10);
assert_eq!(v[x + 1], 20);
x = x + 1;
assert_eq!(v[x], 20);
assert_eq!(v[x - 1], 10);
}

View file

@ -0,0 +1,39 @@
// run-pass
use std::cell::Cell;
#[derive(Debug)]
struct C<'a> {
v: Vec<Cell<Option<&'a C<'a>>>>,
}
impl<'a> C<'a> {
fn new() -> C<'a> {
C { v: Vec::new() }
}
}
fn f() {
let (mut c1, mut c2, mut c3);
c1 = C::new();
c2 = C::new();
c3 = C::new();
c1.v.push(Cell::new(None));
c1.v.push(Cell::new(None));
c2.v.push(Cell::new(None));
c2.v.push(Cell::new(None));
c3.v.push(Cell::new(None));
c3.v.push(Cell::new(None));
c1.v[0].set(Some(&c2));
c1.v[1].set(Some(&c3));
c2.v[0].set(Some(&c2));
c2.v[1].set(Some(&c3));
c3.v[0].set(Some(&c1));
c3.v[1].set(Some(&c2));
}
fn main() {
f();
}

View file

@ -0,0 +1,50 @@
// run-pass
use std::cell::Cell;
#[derive(Debug)]
struct Refs<'a> {
v: Vec<Cell<Option<&'a C<'a>>>>,
}
#[derive(Debug)]
struct C<'a> {
refs: Refs<'a>,
}
impl<'a> Refs<'a> {
fn new() -> Refs<'a> {
Refs { v: Vec::new() }
}
}
impl<'a> C<'a> {
fn new() -> C<'a> {
C { refs: Refs::new() }
}
}
fn f() {
let (mut c1, mut c2, mut c3);
c1 = C::new();
c2 = C::new();
c3 = C::new();
c1.refs.v.push(Cell::new(None));
c1.refs.v.push(Cell::new(None));
c2.refs.v.push(Cell::new(None));
c2.refs.v.push(Cell::new(None));
c3.refs.v.push(Cell::new(None));
c3.refs.v.push(Cell::new(None));
c1.refs.v[0].set(Some(&c2));
c1.refs.v[1].set(Some(&c3));
c2.refs.v[0].set(Some(&c2));
c2.refs.v[1].set(Some(&c3));
c3.refs.v[0].set(Some(&c1));
c3.refs.v[1].set(Some(&c2));
}
fn main() {
f();
}

View file

@ -0,0 +1,7 @@
// run-pass
// pretty-expanded FIXME #23616
#![feature(box_syntax)]
pub fn main() { let _quux: Box<Vec<usize>> = box Vec::new(); }

View file

@ -0,0 +1,5 @@
// run-pass
fn f() -> isize { { return 3; } }
pub fn main() { assert_eq!(f(), 3); }

View file

@ -0,0 +1,9 @@
// run-pass
fn main() {
assert_eq!(3 as usize * 3, 9);
assert_eq!(3 as (usize) * 3, 9);
assert_eq!(3 as (usize) / 3, 1);
assert_eq!(3 as usize + 3, 6);
assert_eq!(3 as (usize) + 3, 6);
}

View file

@ -0,0 +1,9 @@
// run-pass
// pretty-expanded FIXME #23616
// ignore-emscripten no asm
#![feature(asm)]
pub fn main() {
unsafe { asm!(concat!("", "")) };
}

View file

@ -0,0 +1,31 @@
// run-pass
#![feature(asm)]
#![allow(dead_code)]
use std::cell::Cell;
#[repr(C)]
struct NoisyDrop<'a>(&'a Cell<&'static str>);
impl<'a> Drop for NoisyDrop<'a> {
fn drop(&mut self) {
self.0.set("destroyed");
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn main() {
let status = Cell::new("alive");
{
let _y: Box<NoisyDrop>;
let x = Box::new(NoisyDrop(&status));
unsafe {
asm!("mov $1, $0" : "=r"(_y) : "r"(x));
}
assert_eq!(status.get(), "alive");
}
assert_eq!(status.get(), "destroyed");
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
fn main() {}

View file

@ -0,0 +1,56 @@
// run-pass
#![feature(asm)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
unsafe fn next_power_of_2(n: u32) -> u32 {
let mut tmp = n;
asm!("dec $0" : "+rm"(tmp) :: "cc");
let mut shift = 1_u32;
while shift <= 16 {
asm!(
"shr %cl, $2
or $2, $0
shl $$1, $1"
: "+&rm"(tmp), "+{ecx}"(shift) : "r"(tmp) : "cc"
);
}
asm!("inc $0" : "+rm"(tmp) :: "cc");
return tmp;
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn main() {
unsafe {
assert_eq!(64, next_power_of_2(37));
assert_eq!(2147483648, next_power_of_2(2147483647));
}
let mut y: isize = 5;
let x: isize;
unsafe {
// Treat the output as initialization.
asm!(
"shl $2, $1
add $3, $1
mov $1, $0"
: "=r"(x), "+r"(y) : "i"(3_usize), "ir"(7_usize) : "cc"
);
}
assert_eq!(x, 47);
assert_eq!(y, 47);
let mut x = x + 1;
assert_eq!(x, 48);
unsafe {
// Assignment to mutable.
// Early clobber "&":
// Forbids the use of a single register by both operands.
asm!("shr $$2, $1; add $1, $0" : "+&r"(x) : "r"(x) : "cc");
}
assert_eq!(x, 60);
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
pub fn main() {}

View file

@ -0,0 +1,43 @@
// run-pass
#![feature(asm)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn read(ptr: &u32) -> u32 {
let out: u32;
unsafe {
asm!("mov $1, $0" : "=r" (out) : "*m" (ptr));
}
out
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn write(ptr: &mut u32, val: u32) {
unsafe {
asm!("mov $1, $0" : "=*m" (ptr) : "r" (val));
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn replace(ptr: &mut u32, val: u32) -> u32 {
let out: u32;
unsafe {
asm!("mov $0, $1; mov $2, $0" : "+*m" (ptr), "=&r" (out) : "r" (val));
}
out
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn main() {
let a = 1;
assert_eq!(read(&a), 1);
let mut b = 2;
write(&mut b, 3);
assert_eq!(b, 3);
let mut c = 4;
assert_eq!(replace(&mut c, 5), 4);
assert_eq!(c, 5);
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
pub fn main() {}

View file

@ -0,0 +1,25 @@
// run-pass
#![feature(asm)]
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn main() {
let x: isize;
unsafe {
// Treat the output as initialization.
asm!("mov $1, $0" : "=r"(x) : "r"(5_usize));
}
assert_eq!(x, 5);
let mut x = x + 1;
assert_eq!(x, 6);
unsafe {
// Assignment to mutable.
asm!("mov $1, $0" : "=r"(x) : "r"(x + 7));
}
assert_eq!(x, 13);
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
pub fn main() {}

View file

@ -0,0 +1,5 @@
// run-pass
fn main() {
assert_eq!(1, 1,);
}

View file

@ -0,0 +1,5 @@
// run-pass
fn main() {
assert!(r#"☃\backslash"#.contains("\\"));
}

View file

@ -0,0 +1,5 @@
// run-pass
fn main() {
assert_ne!(1, 2,);
}

View file

@ -0,0 +1,30 @@
// run-pass
// Issue 483 - Assignment expressions result in nil
fn test_assign() {
let mut x: isize;
let y: () = x = 10;
assert_eq!(x, 10);
assert_eq!(y, ());
let mut z = x = 11;
assert_eq!(x, 11);
assert_eq!(z, ());
z = x = 12;
assert_eq!(x, 12);
assert_eq!(z, ());
}
fn test_assign_op() {
let mut x: isize = 0;
let y: () = x += 10;
assert_eq!(x, 10);
assert_eq!(y, ());
let mut z = x += 11;
assert_eq!(x, 21);
assert_eq!(z, ());
z = x += 12;
assert_eq!(x, 33);
assert_eq!(z, ());
}
pub fn main() { test_assign(); test_assign_op(); }

View file

@ -0,0 +1,13 @@
// run-pass
fn that_odd_parse(c: bool, n: usize) -> u32 {
let x = 2;
let a = [1, 2, 3, 4];
let b = [5, 6, 7, 7];
x + if c { a } else { b }[n]
}
fn main() {
assert_eq!(4, that_odd_parse(true, 1));
assert_eq!(8, that_odd_parse(false, 1));
}

View file

@ -0,0 +1,20 @@
// run-pass
trait Foo {
const NUM: usize;
}
impl Foo for i32 {
const NUM: usize = 1;
}
const FOO: usize = <i32 as Foo>::NUM;
fn main() {
assert_eq!(1, FOO);
match 1 {
<i32 as Foo>::NUM => {},
_ => assert!(false)
}
}

View file

@ -0,0 +1,28 @@
// run-pass
// aux-build:associated-const-cc-lib.rs
extern crate associated_const_cc_lib as foolib;
pub struct LocalFoo;
impl foolib::Foo for LocalFoo {
const BAR: usize = 1;
}
const FOO_1: usize = <foolib::FooNoDefault as foolib::Foo>::BAR;
const FOO_2: usize = <LocalFoo as foolib::Foo>::BAR;
const FOO_3: usize = foolib::InherentBar::BAR;
fn main() {
assert_eq!(0, FOO_1);
assert_eq!(1, FOO_2);
assert_eq!(3, FOO_3);
match 0 {
<foolib::FooNoDefault as foolib::Foo>::BAR => {},
<LocalFoo as foolib::Foo>::BAR => assert!(false),
foolib::InherentBar::BAR => assert!(false),
_ => assert!(false)
}
}

View file

@ -0,0 +1,22 @@
// run-pass
// aux-build:associated-const-cc-lib.rs
extern crate associated_const_cc_lib as foolib;
pub struct LocalFooUseDefault;
impl foolib::FooDefault for LocalFooUseDefault {}
pub struct LocalFooOverwriteDefault;
impl foolib::FooDefault for LocalFooOverwriteDefault {
const BAR: usize = 4;
}
fn main() {
assert_eq!(1, <foolib::FooUseDefault as foolib::FooDefault>::BAR);
assert_eq!(2, <foolib::FooOverwriteDefault as foolib::FooDefault>::BAR);
assert_eq!(1, <LocalFooUseDefault as foolib::FooDefault>::BAR);
assert_eq!(4, <LocalFooOverwriteDefault as foolib::FooDefault>::BAR);
}

View file

@ -0,0 +1,17 @@
// run-pass
// aux-build:associated-const-cc-lib.rs
extern crate associated_const_cc_lib as foolib;
pub struct LocalFoo;
impl foolib::Foo for LocalFoo {
const BAR: usize = 1;
}
fn main() {
assert_eq!(0, <foolib::FooNoDefault as foolib::Foo>::BAR);
assert_eq!(1, <LocalFoo as foolib::Foo>::BAR);
assert_eq!(3, foolib::InherentBar::BAR);
}

View file

@ -0,0 +1,13 @@
// run-pass
struct Foo;
impl Foo {
const BAR: f32 = 1.5;
}
const FOOBAR: f32 = <Foo>::BAR;
fn main() {
assert_eq!(1.5f32, FOOBAR);
}

View file

@ -0,0 +1,11 @@
// run-pass
struct Foo;
impl Foo {
const ID: i32 = 1;
}
fn main() {
assert_eq!(1, Foo::ID);
}

View file

@ -0,0 +1,15 @@
// run-pass
#![deny(dead_code)]
const GLOBAL_BAR: u32 = 1;
struct Foo;
impl Foo {
const BAR: u32 = GLOBAL_BAR;
}
pub fn main() {
let _: u32 = Foo::BAR;
}

View file

@ -0,0 +1,68 @@
// run-pass
// aux-build:empty-struct.rs
extern crate empty_struct;
use empty_struct::XEmpty2 as XFoo;
struct Foo;
#[derive(PartialEq, Eq)]
enum Bar {
Var1,
Var2,
}
// Use inherent and trait impls to test UFCS syntax.
impl Foo {
const MYBAR: Bar = Bar::Var2;
}
trait HasBar {
const THEBAR: Bar;
}
impl HasBar for Foo {
const THEBAR: Bar = Bar::Var1;
}
impl HasBar for XFoo {
const THEBAR: Bar = Bar::Var1;
}
fn main() {
// Inherent impl
assert!(match Bar::Var2 {
Foo::MYBAR => true,
_ => false,
});
assert!(match Bar::Var2 {
<Foo>::MYBAR => true,
_ => false,
});
// Trait impl
assert!(match Bar::Var1 {
Foo::THEBAR => true,
_ => false,
});
assert!(match Bar::Var1 {
<Foo>::THEBAR => true,
_ => false,
});
assert!(match Bar::Var1 {
<Foo as HasBar>::THEBAR => true,
_ => false,
});
assert!(match Bar::Var1 {
XFoo::THEBAR => true,
_ => false,
});
assert!(match Bar::Var1 {
<XFoo>::THEBAR => true,
_ => false,
});
assert!(match Bar::Var1 {
<XFoo as HasBar>::THEBAR => true,
_ => false,
});
}

View file

@ -0,0 +1,10 @@
// run-pass
trait Lattice {
const BOTTOM: Self;
}
impl<T> Lattice for Option<T> {
const BOTTOM: Option<T> = None;
}
fn main(){}

View file

@ -0,0 +1,13 @@
// run-pass
trait Foo {
const ID: i32 = 2;
}
impl Foo for i32 {
const ID: i32 = 1;
}
fn main() {
assert_eq!(1, <i32 as Foo>::ID);
}

View file

@ -0,0 +1,16 @@
// run-pass
mod bar1 {
pub use self::bar2::Foo;
mod bar2 {
pub struct Foo;
impl Foo {
pub const ID: i32 = 1;
}
}
}
fn main() {
assert_eq!(1, bar1::Foo::ID);
}

View file

@ -0,0 +1,40 @@
// run-pass
#![allow(dead_code, unreachable_patterns)]
#![allow(ellipsis_inclusive_range_patterns)]
struct Foo;
trait HasNum {
const NUM: isize;
}
impl HasNum for Foo {
const NUM: isize = 1;
}
fn main() {
assert!(match 2 {
Foo::NUM ... 3 => true,
_ => false,
});
assert!(match 0 {
-1 ... <Foo as HasNum>::NUM => true,
_ => false,
});
assert!(match 1 {
<Foo as HasNum>::NUM ... <Foo>::NUM => true,
_ => false,
});
assert!(match 2 {
Foo::NUM ..= 3 => true,
_ => false,
});
assert!(match 0 {
-1 ..= <Foo as HasNum>::NUM => true,
_ => false,
});
assert!(match 1 {
<Foo as HasNum>::NUM ..= <Foo>::NUM => true,
_ => false,
});
}

View file

@ -0,0 +1,25 @@
// run-pass
struct MyType;
impl MyType {
const IMPL_IS_INHERENT: bool = true;
}
trait MyTrait {
const IMPL_IS_INHERENT: bool;
const IMPL_IS_ON_TRAIT: bool;
}
impl MyTrait for MyType {
const IMPL_IS_INHERENT: bool = false;
const IMPL_IS_ON_TRAIT: bool = true;
}
fn main() {
// Check that the inherent impl is used before the trait, but that the trait
// can still be accessed.
assert!(<MyType>::IMPL_IS_INHERENT);
assert!(!<MyType as MyTrait>::IMPL_IS_INHERENT);
assert!(<MyType>::IMPL_IS_ON_TRAIT);
}

Some files were not shown because too many files have changed in this diff Show more