summaryrefslogtreecommitdiffstats
path: root/src/test/ui/mir/mir_codegen_calls.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/mir/mir_codegen_calls.rs')
-rw-r--r--src/test/ui/mir/mir_codegen_calls.rs192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/test/ui/mir/mir_codegen_calls.rs b/src/test/ui/mir/mir_codegen_calls.rs
new file mode 100644
index 000000000..6a5a4dace
--- /dev/null
+++ b/src/test/ui/mir/mir_codegen_calls.rs
@@ -0,0 +1,192 @@
+// run-pass
+#![feature(fn_traits, test)]
+
+extern crate test;
+
+fn test1(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
+ // Test passing a number of arguments including a fat pointer.
+ // Also returning via an out pointer
+ fn callee(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
+ (a, b, c)
+ }
+ callee(a, b, c)
+}
+
+fn test2(a: isize) -> isize {
+ // Test passing a single argument.
+ // Not using out pointer.
+ fn callee(a: isize) -> isize {
+ a
+ }
+ callee(a)
+}
+
+#[derive(PartialEq, Eq, Debug)]
+struct Foo;
+impl Foo {
+ fn inherent_method(&self, a: isize) -> isize { a }
+}
+
+fn test3(x: &Foo, a: isize) -> isize {
+ // Test calling inherent method
+ x.inherent_method(a)
+}
+
+trait Bar {
+ fn extension_method(&self, a: isize) -> isize { a }
+}
+impl Bar for Foo {}
+
+fn test4(x: &Foo, a: isize) -> isize {
+ // Test calling extension method
+ x.extension_method(a)
+}
+
+fn test5(x: &dyn Bar, a: isize) -> isize {
+ // Test calling method on trait object
+ x.extension_method(a)
+}
+
+fn test6<T: Bar>(x: &T, a: isize) -> isize {
+ // Test calling extension method on generic callee
+ x.extension_method(a)
+}
+
+trait One<T = Self> {
+ fn one() -> T;
+}
+impl One for isize {
+ fn one() -> isize { 1 }
+}
+
+fn test7() -> isize {
+ // Test calling trait static method
+ <isize as One>::one()
+}
+
+struct Two;
+impl Two {
+ fn two() -> isize { 2 }
+}
+
+fn test8() -> isize {
+ // Test calling impl static method
+ Two::two()
+}
+
+#[allow(improper_ctypes_definitions)]
+extern "C" fn simple_extern(x: u32, y: (u32, u32)) -> u32 {
+ x + y.0 * y.1
+}
+
+fn test9() -> u32 {
+ simple_extern(41, (42, 43))
+}
+
+fn test_closure<F>(f: &F, x: i32, y: i32) -> i32
+ where F: Fn(i32, i32) -> i32
+{
+ f(x, y)
+}
+
+fn test_fn_object(f: &dyn Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
+ f(x, y)
+}
+
+fn test_fn_impl(f: &&dyn Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
+ // This call goes through the Fn implementation for &Fn provided in
+ // core::ops::impls. It expands to a static Fn::call() that calls the
+ // Fn::call() implementation of the object shim underneath.
+ f(x, y)
+}
+
+fn test_fn_direct_call<F>(f: &F, x: i32, y: i32) -> i32
+ where F: Fn(i32, i32) -> i32
+{
+ f.call((x, y))
+}
+
+fn test_fn_const_call<F>(f: &F) -> i32
+ where F: Fn(i32, i32) -> i32
+{
+ f.call((100, -1))
+}
+
+fn test_fn_nil_call<F>(f: &F) -> i32
+ where F: Fn() -> i32
+{
+ f()
+}
+
+fn test_fn_transmute_zst(x: ()) -> [(); 1] {
+ fn id<T>(x: T) -> T {x}
+
+ id(unsafe {
+ std::mem::transmute(x)
+ })
+}
+
+fn test_fn_ignored_pair() -> ((), ()) {
+ ((), ())
+}
+
+fn test_fn_ignored_pair_0() {
+ test_fn_ignored_pair().0
+}
+
+fn id<T>(x: T) -> T { x }
+
+fn ignored_pair_named() -> (Foo, Foo) {
+ (Foo, Foo)
+}
+
+fn test_fn_ignored_pair_named() -> (Foo, Foo) {
+ id(ignored_pair_named())
+}
+
+fn test_fn_nested_pair(x: &((f32, f32), u32)) -> (f32, f32) {
+ let y = *x;
+ let z = y.0;
+ (z.0, z.1)
+}
+
+fn test_fn_const_arg_by_ref(mut a: [u64; 4]) -> u64 {
+ // Mutate the by-reference argument, which won't work with
+ // a non-immediate constant unless it's copied to the stack.
+ let a = test::black_box(&mut a);
+ a[0] += a[1];
+ a[0] += a[2];
+ a[0] += a[3];
+ a[0]
+}
+
+fn main() {
+ assert_eq!(test1(1, (2, 3), &[4, 5, 6]), (1, (2, 3), &[4, 5, 6][..]));
+ assert_eq!(test2(98), 98);
+ assert_eq!(test3(&Foo, 42), 42);
+ assert_eq!(test4(&Foo, 970), 970);
+ assert_eq!(test5(&Foo, 8576), 8576);
+ assert_eq!(test6(&Foo, 12367), 12367);
+ assert_eq!(test7(), 1);
+ assert_eq!(test8(), 2);
+ assert_eq!(test9(), 41 + 42 * 43);
+
+ let r = 3;
+ let closure = |x: i32, y: i32| { r*(x + (y*2)) };
+ assert_eq!(test_fn_const_call(&closure), 294);
+ assert_eq!(test_closure(&closure, 100, 1), 306);
+ let function_object = &closure as &dyn Fn(i32, i32) -> i32;
+ assert_eq!(test_fn_object(function_object, 100, 2), 312);
+ assert_eq!(test_fn_impl(&function_object, 100, 3), 318);
+ assert_eq!(test_fn_direct_call(&closure, 100, 4), 324);
+
+ assert_eq!(test_fn_nil_call(&(|| 42)), 42);
+ assert_eq!(test_fn_transmute_zst(()), [()]);
+
+ assert_eq!(test_fn_ignored_pair_0(), ());
+ assert_eq!(test_fn_ignored_pair_named(), (Foo, Foo));
+ assert_eq!(test_fn_nested_pair(&((1.0, 2.0), 0)), (1.0, 2.0));
+
+ const ARRAY: [u64; 4] = [1, 2, 3, 4];
+ assert_eq!(test_fn_const_arg_by_ref(ARRAY), 1 + 2 + 3 + 4);
+}