]>
Commit | Line | Data |
---|---|---|
c30ab7b3 SL |
1 | // Copyright 2016 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | #![feature(generic_param_attrs)] | |
12 | #![feature(dropck_eyepatch)] | |
13 | ||
14 | // The point of this test is to test uses of `#[may_dangle]` attribute | |
15 | // where the formal declaration order (in the impl generics) does not | |
16 | // match the actual usage order (in the type instantiation). | |
17 | // | |
18 | // See also dropck-eyepatch.rs for more information about the general | |
19 | // structure of the test. | |
20 | ||
21 | trait Foo { fn foo(&self, _: &str); } | |
22 | ||
23 | struct Dt<A: Foo>(&'static str, A); | |
24 | struct Dr<'a, B:'a+Foo>(&'static str, &'a B); | |
25 | struct Pt<A: Foo, B: Foo>(&'static str, A, B); | |
26 | struct Pr<'a, 'b, B:'a+'b+Foo>(&'static str, &'a B, &'b B); | |
27 | struct St<A: Foo>(&'static str, A); | |
28 | struct Sr<'a, B:'a+Foo>(&'static str, &'a B); | |
29 | ||
30 | impl<A: Foo> Drop for Dt<A> { | |
31 | fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } | |
32 | } | |
33 | impl<'a, B: Foo> Drop for Dr<'a, B> { | |
34 | fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); } | |
35 | } | |
36 | unsafe impl<B: Foo, #[may_dangle] A: Foo> Drop for Pt<A, B> { | |
37 | // (unsafe to access self.1 due to #[may_dangle] on A) | |
38 | fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } | |
39 | } | |
40 | unsafe impl<'b, #[may_dangle] 'a, B: Foo> Drop for Pr<'a, 'b, B> { | |
41 | // (unsafe to access self.1 due to #[may_dangle] on 'a) | |
42 | fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); } | |
43 | } | |
44 | ||
45 | fn main() { | |
46 | use std::cell::RefCell; | |
47 | ||
48 | impl Foo for RefCell<String> { | |
49 | fn foo(&self, s: &str) { | |
50 | let s2 = format!("{}|{}", *self.borrow(), s); | |
51 | *self.borrow_mut() = s2; | |
52 | } | |
53 | } | |
54 | ||
55 | impl<'a, T:Foo> Foo for &'a T { | |
56 | fn foo(&self, s: &str) { | |
57 | (*self).foo(s); | |
58 | } | |
59 | } | |
60 | ||
61 | struct CheckOnDrop(RefCell<String>, &'static str); | |
62 | impl Drop for CheckOnDrop { | |
63 | fn drop(&mut self) { assert_eq!(*self.0.borrow(), self.1); } | |
64 | } | |
65 | ||
66 | let c_long; | |
67 | let (c, dt, dr, pt, pr, st, sr) | |
68 | : (CheckOnDrop, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>); | |
69 | c_long = CheckOnDrop(RefCell::new("c_long".to_string()), | |
70 | "c_long|pr|pt|dr|dt"); | |
71 | c = CheckOnDrop(RefCell::new("c".to_string()), | |
72 | "c"); | |
73 | ||
74 | // No error: sufficiently long-lived state can be referenced in dtors | |
75 | dt = Dt("dt", &c_long.0); | |
76 | dr = Dr("dr", &c_long.0); | |
77 | ||
78 | // No error: Drop impl asserts .1 (A and &'a _) are not accessed | |
79 | pt = Pt("pt", &c.0, &c_long.0); | |
80 | pr = Pr("pr", &c.0, &c_long.0); | |
81 | ||
82 | // No error: St and Sr have no destructor. | |
83 | st = St("st", &c.0); | |
84 | sr = Sr("sr", &c.0); | |
85 | ||
86 | println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0)); | |
87 | assert_eq!(*c_long.0.borrow(), "c_long"); | |
88 | assert_eq!(*c.0.borrow(), "c"); | |
89 | } |