summaryrefslogtreecommitdiff
path: root/src/tools/miri/tests/pass/dyn-arbitrary-self.rs
blob: 6be13b155f41001f3380082bbdb1c5a6b2e93562 (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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//@revisions: stack tree
//@[tree]compile-flags: -Zmiri-tree-borrows
#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)]
#![feature(rustc_attrs)]

fn pin_box_dyn() {
    use std::pin::Pin;

    trait Foo {
        fn bar(self: Pin<&mut Self>) -> bool;
    }

    impl Foo for &'static str {
        fn bar(self: Pin<&mut Self>) -> bool {
            true
        }
    }

    let mut test: Pin<Box<dyn Foo>> = Box::pin("foo");
    test.as_mut().bar();
}

fn stdlib_pointers() {
    use std::{pin::Pin, rc::Rc, sync::Arc};

    trait Trait {
        fn by_rc(self: Rc<Self>) -> i64;
        fn by_arc(self: Arc<Self>) -> i64;
        fn by_pin_mut(self: Pin<&mut Self>) -> i64;
        fn by_pin_box(self: Pin<Box<Self>>) -> i64;
    }

    impl Trait for i64 {
        fn by_rc(self: Rc<Self>) -> i64 {
            *self
        }
        fn by_arc(self: Arc<Self>) -> i64 {
            *self
        }
        fn by_pin_mut(self: Pin<&mut Self>) -> i64 {
            *self
        }
        fn by_pin_box(self: Pin<Box<Self>>) -> i64 {
            *self
        }
    }

    let rc = Rc::new(1i64) as Rc<dyn Trait>;
    assert_eq!(1, rc.by_rc());

    let arc = Arc::new(2i64) as Arc<dyn Trait>;
    assert_eq!(2, arc.by_arc());

    let mut value = 3i64;
    let pin_mut = Pin::new(&mut value) as Pin<&mut dyn Trait>;
    assert_eq!(3, pin_mut.by_pin_mut());

    let pin_box = Into::<Pin<Box<i64>>>::into(Box::new(4i64)) as Pin<Box<dyn Trait>>;
    assert_eq!(4, pin_box.by_pin_box());
}

fn pointers_and_wrappers() {
    use std::{
        marker::Unsize,
        ops::{CoerceUnsized, Deref, DispatchFromDyn},
    };

    struct Ptr<T: ?Sized>(Box<T>);

    impl<T: ?Sized> Deref for Ptr<T> {
        type Target = T;

        fn deref(&self) -> &T {
            &*self.0
        }
    }

    impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
    impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T> {}

    struct Wrapper<T: ?Sized>(T);

    impl<T: ?Sized> Deref for Wrapper<T> {
        type Target = T;

        fn deref(&self) -> &T {
            &self.0
        }
    }

    impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
    impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T> {}

    trait Trait {
        // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable
        // without unsized_locals), but wrappers around `Self` currently are not.
        // FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented
        // fn wrapper(self: Wrapper<Self>) -> i32;
        fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32;
        fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32;
        fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32;
    }

    impl Trait for i32 {
        fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32 {
            **self
        }
        fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32 {
            **self
        }
        fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32 {
            ***self
        }
    }

    let pw = Ptr(Box::new(Wrapper(5))) as Ptr<Wrapper<dyn Trait>>;
    assert_eq!(pw.ptr_wrapper(), 5);

    let wp = Wrapper(Ptr(Box::new(6))) as Wrapper<Ptr<dyn Trait>>;
    assert_eq!(wp.wrapper_ptr(), 6);

    let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper<Ptr<Wrapper<dyn Trait>>>;
    assert_eq!(wpw.wrapper_ptr_wrapper(), 7);
}

fn raw_ptr_receiver() {
    use std::ptr;

    trait Foo {
        fn foo(self: *const Self) -> &'static str;
    }

    impl Foo for i32 {
        fn foo(self: *const Self) -> &'static str {
            "I'm an i32!"
        }
    }

    impl Foo for u32 {
        fn foo(self: *const Self) -> &'static str {
            "I'm a u32!"
        }
    }

    let null_i32 = ptr::null::<i32>() as *const dyn Foo;
    let null_u32 = ptr::null::<u32>() as *const dyn Foo;

    assert_eq!("I'm an i32!", null_i32.foo());
    assert_eq!("I'm a u32!", null_u32.foo());
}

fn main() {
    pin_box_dyn();
    stdlib_pointers();
    pointers_and_wrappers();
    raw_ptr_receiver();
}