]> git.lizzy.rs Git - rust.git/blob - src/test/ui/dropck/dropck_trait_cycle_checked.rs
Move some tests with compare-mode=nll output to revisions
[rust.git] / src / test / ui / dropck / dropck_trait_cycle_checked.rs
1 // Reject mixing cyclic structure and Drop when using trait
2 // objects to hide the cross-references.
3 //
4 // (Compare against ui/span/dropck_vec_cycle_checked.rs)
5
6 use std::cell::Cell;
7 use id::Id;
8
9 mod s {
10     use std::sync::atomic::{AtomicUsize, Ordering};
11
12     static S_COUNT: AtomicUsize = AtomicUsize::new(0);
13
14     pub fn next_count() -> usize {
15         S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
16     }
17 }
18
19 mod id {
20     use s;
21     #[derive(Debug)]
22     pub struct Id {
23         orig_count: usize,
24         count: usize,
25     }
26
27     impl Id {
28         pub fn new() -> Id {
29             let c = s::next_count();
30             println!("building Id {}", c);
31             Id { orig_count: c, count: c }
32         }
33         pub fn count(&self) -> usize {
34             println!("Id::count on {} returns {}", self.orig_count, self.count);
35             self.count
36         }
37     }
38
39     impl Drop for Id {
40         fn drop(&mut self) {
41             println!("dropping Id {}", self.count);
42             self.count = 0;
43         }
44     }
45 }
46
47 trait HasId {
48     fn count(&self) -> usize;
49 }
50
51 #[derive(Debug)]
52 struct CheckId<T:HasId> {
53     v: T
54 }
55
56 #[allow(non_snake_case)]
57 fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
58
59 impl<T:HasId> Drop for CheckId<T> {
60     fn drop(&mut self) {
61         assert!(self.v.count() > 0);
62     }
63 }
64
65 trait Obj<'a> : HasId {
66     fn set0(&self, b: &'a Box<dyn Obj<'a>>);
67     fn set1(&self, b: &'a Box<dyn Obj<'a>>);
68 }
69
70 struct O<'a> {
71     id: Id,
72     obj0: CheckId<Cell<Option<&'a Box<dyn Obj<'a>>>>>,
73     obj1: CheckId<Cell<Option<&'a Box<dyn Obj<'a>>>>>,
74 }
75
76 impl<'a> HasId for O<'a> {
77     fn count(&self) -> usize { self.id.count() }
78 }
79
80 impl<'a> O<'a> {
81     fn new() -> Box<O<'a>> {
82         Box::new(O {
83             id: Id::new(),
84             obj0: CheckId(Cell::new(None)),
85             obj1: CheckId(Cell::new(None)),
86         })
87     }
88 }
89
90 impl<'a> HasId for Cell<Option<&'a Box<dyn Obj<'a>>>> {
91     fn count(&self) -> usize {
92         match self.get() {
93             None => 1,
94             Some(c) => c.count(),
95         }
96     }
97 }
98
99 impl<'a> Obj<'a> for O<'a> {
100     fn set0(&self, b: &'a Box<dyn Obj<'a>>) {
101         self.obj0.v.set(Some(b))
102     }
103     fn set1(&self, b: &'a Box<dyn Obj<'a>>) {
104         self.obj1.v.set(Some(b))
105     }
106 }
107
108
109 fn f() {
110     let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
111     o1.set0(&o2); //~ ERROR `o2` does not live long enough
112     o1.set1(&o3); //~ ERROR `o3` does not live long enough
113     o2.set0(&o2); //~ ERROR `o2` does not live long enough
114     o2.set1(&o3); //~ ERROR `o3` does not live long enough
115     o3.set0(&o1); //~ ERROR `o1` does not live long enough
116     o3.set1(&o2); //~ ERROR `o2` does not live long enough
117 }
118
119 fn main() {
120     f();
121 }