about summary refs log tree commit diff
path: root/tests/ui/traits/dyn-drop-principal.rs
blob: c233127e43d2d62bd68d4913f8ad3a085b0b0e44 (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
//@ run-pass
//@ check-run-results

use std::{alloc::Layout, any::Any};

const fn yeet_principal(x: Box<dyn Any + Send>) -> Box<dyn Send> {
    x
}

trait Bar: Send + Sync {}

impl<T: Send + Sync> Bar for T {}

const fn yeet_principal_2(x: Box<dyn Bar>) -> Box<dyn Send> {
    x
}

struct CallMe<F: FnOnce()>(Option<F>);

impl<F: FnOnce()> CallMe<F> {
    fn new(f: F) -> Self {
        CallMe(Some(f))
    }
}

impl<F: FnOnce()> Drop for CallMe<F> {
    fn drop(&mut self) {
        (self.0.take().unwrap())();
    }
}

fn goodbye() {
    println!("goodbye");
}

fn main() {
    let x = Box::new(CallMe::new(goodbye)) as Box<dyn Any + Send>;
    let x_layout = Layout::for_value(&*x);
    let y = yeet_principal(x);
    let y_layout = Layout::for_value(&*y);
    assert_eq!(x_layout, y_layout);
    println!("before");
    drop(y);

    let x = Box::new(CallMe::new(goodbye)) as Box<dyn Bar>;
    let x_layout = Layout::for_value(&*x);
    let y = yeet_principal_2(x);
    let y_layout = Layout::for_value(&*y);
    assert_eq!(x_layout, y_layout);
    println!("before");
    drop(y);
}

// Test that upcast works in `const`

const fn yeet_principal_3(x: &(dyn Any + Send + Sync)) -> &(dyn Send + Sync) {
    x
}

#[used]
pub static FOO: &(dyn Send + Sync) = yeet_principal_3(&false);

const fn yeet_principal_4(x: &dyn Bar) -> &(dyn Send + Sync) {
    x
}

#[used]
pub static BAR: &(dyn Send + Sync) = yeet_principal_4(&false);