about summary refs log tree commit diff
path: root/tests/ui/c-variadic/trait-method.rs
blob: 876a303f53ba5f4146a8fcfb4d9a5ec592bad06e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//@ run-pass
//@ ignore-backends: gcc
#![feature(c_variadic)]

#[repr(transparent)]
struct Struct(i32);

impl Struct {
    unsafe extern "C" fn associated_function(mut ap: ...) -> i32 {
        unsafe { ap.arg() }
    }

    unsafe extern "C" fn method(&self, mut ap: ...) -> i32 {
        self.0 + unsafe { ap.arg::<i32>() }
    }
}

trait Trait: Sized {
    fn get(&self) -> i32;

    unsafe extern "C" fn trait_associated_function(mut ap: ...) -> i32 {
        unsafe { ap.arg() }
    }

    unsafe extern "C" fn trait_method_owned(self, mut ap: ...) -> i32 {
        self.get() + unsafe { ap.arg::<i32>() }
    }

    unsafe extern "C" fn trait_method_ref(&self, mut ap: ...) -> i32 {
        self.get() + unsafe { ap.arg::<i32>() }
    }

    unsafe extern "C" fn trait_method_mut(&mut self, mut ap: ...) -> i32 {
        self.get() + unsafe { ap.arg::<i32>() }
    }

    unsafe extern "C" fn trait_fat_pointer(self: Box<Self>, mut ap: ...) -> i32 {
        self.get() + unsafe { ap.arg::<i32>() }
    }
}

impl Trait for Struct {
    fn get(&self) -> i32 {
        self.0
    }
}

fn main() {
    unsafe {
        assert_eq!(Struct::associated_function(32), 32);
        assert_eq!(Struct(100).method(32), 132);

        assert_eq!(Struct::trait_associated_function(32), 32);
        assert_eq!(Struct(100).trait_method_owned(32), 132);
        assert_eq!(Struct(100).trait_method_ref(32), 132);
        assert_eq!(Struct(100).trait_method_mut(32), 132);
        assert_eq!(Struct::trait_fat_pointer(Box::new(Struct(100)), 32), 132);

        assert_eq!(<Struct as Trait>::trait_associated_function(32), 32);
        assert_eq!(Trait::trait_method_owned(Struct(100), 32), 132);
        assert_eq!(Trait::trait_method_ref(&Struct(100), 32), 132);
        assert_eq!(Trait::trait_method_mut(&mut Struct(100), 32), 132);
        assert_eq!(Trait::trait_fat_pointer(Box::new(Struct(100)), 32), 132);

        type Associated = unsafe extern "C" fn(...) -> i32;
        type Method<T> = unsafe extern "C" fn(T, ...) -> i32;

        assert_eq!((Struct::trait_associated_function as Associated)(32), 32);
        assert_eq!((Struct::trait_method_owned as Method<_>)(Struct(100), 32), 132);
        assert_eq!((Struct::trait_method_ref as Method<_>)(&Struct(100), 32), 132);
        assert_eq!((Struct::trait_method_mut as Method<_>)(&mut Struct(100), 32), 132);
        assert_eq!((Struct::trait_fat_pointer as Method<_>)(Box::new(Struct(100)), 32), 132);
    }
}