Skip to content

Commit fa7f69c

Browse files
committed
tests for #[may_dangle] attribute.
1 parent e185cd5 commit fa7f69c

File tree

7 files changed

+428
-0
lines changed

7 files changed

+428
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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 illustrate that the `#[may_dangle]`
15+
// attribute specifically allows, in the context of a type
16+
// implementing `Drop`, a generic parameter to be instantiated with a
17+
// lifetime that does not strictly outlive the owning type itself,
18+
// and that this attributes effects are preserved when importing
19+
// the type from another crate.
20+
//
21+
// See also dropck-eyepatch.rs for more information about the general
22+
// structure of the test.
23+
24+
use std::fmt;
25+
26+
pub struct Dt<A: fmt::Debug>(pub &'static str, pub A);
27+
pub struct Dr<'a, B:'a+fmt::Debug>(pub &'static str, pub &'a B);
28+
pub struct Pt<A,B: fmt::Debug>(pub &'static str, pub A, pub B);
29+
pub struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(pub &'static str, pub &'a B, pub &'b B);
30+
pub struct St<A: fmt::Debug>(pub &'static str, pub A);
31+
pub struct Sr<'a, B:'a+fmt::Debug>(pub &'static str, pub &'a B);
32+
33+
impl<A: fmt::Debug> Drop for Dt<A> {
34+
fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
35+
}
36+
impl<'a, B: fmt::Debug> Drop for Dr<'a, B> {
37+
fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
38+
}
39+
unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
40+
// (unsafe to access self.1 due to #[may_dangle] on A)
41+
fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
42+
}
43+
unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
44+
// (unsafe to access self.1 due to #[may_dangle] on 'a)
45+
fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
46+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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+
// aux-build:dropck_eyepatch_extern_crate.rs
12+
13+
extern crate dropck_eyepatch_extern_crate as other;
14+
15+
use other::{Dt,Dr,Pt,Pr,St,Sr};
16+
17+
fn main() {
18+
use std::cell::Cell;
19+
let c_long;
20+
let (c, mut dt, mut dr, mut pt, mut pr, st, sr)
21+
: (Cell<_>, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>);
22+
c_long = Cell::new(1);
23+
c = Cell::new(1);
24+
25+
// No error: sufficiently long-lived state can be referenced in dtors
26+
dt = Dt("dt", &c_long);
27+
dr = Dr("dr", &c_long);
28+
// Error: destructor order imprecisely modelled
29+
dt = Dt("dt", &c); //~ ERROR `c` does not live long enough
30+
dr = Dr("dr", &c); //~ ERROR `c` does not live long enough
31+
32+
// No error: Drop impl asserts .1 (A and &'a _) are not accessed
33+
pt = Pt("pt", &c, &c_long);
34+
pr = Pr("pr", &c, &c_long);
35+
36+
// Error: Drop impl's assertion does not apply to `B` nor `&'b _`
37+
pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough
38+
pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough
39+
40+
// No error: St and Sr have no destructor.
41+
st = St("st", &c);
42+
sr = Sr("sr", &c);
43+
44+
println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0));
45+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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 illustrate that the `#[may_dangle]`
15+
// attribute specifically allows, in the context of a type
16+
// implementing `Drop`, a generic parameter to be instantiated with a
17+
// lifetime that does not strictly outlive the owning type itself.
18+
//
19+
// Here we test that only the expected errors are issued.
20+
//
21+
// The illustration is made concrete by comparison with two variations
22+
// on the type with `#[may_dangle]`:
23+
//
24+
// 1. an analogous type that does not implement `Drop` (and thus
25+
// should exhibit maximal flexibility with respect to dropck), and
26+
//
27+
// 2. an analogous type that does not use `#[may_dangle]` (and thus
28+
// should exhibit the standard limitations imposed by dropck.
29+
//
30+
// The types in this file follow a pattern, {D,P,S}{t,r}, where:
31+
//
32+
// - D means "I implement Drop"
33+
//
34+
// - P means "I implement Drop but guarantee my (first) parameter is
35+
// pure, i.e. not accessed from the destructor"; no other parameters
36+
// are pure.
37+
//
38+
// - S means "I do not implement Drop"
39+
//
40+
// - t suffix is used when the first generic is a type
41+
//
42+
// - r suffix is used when the first generic is a lifetime.
43+
44+
use std::fmt;
45+
46+
struct Dt<A: fmt::Debug>(&'static str, A);
47+
struct Dr<'a, B:'a+fmt::Debug>(&'static str, &'a B);
48+
struct Pt<A,B: fmt::Debug>(&'static str, A, B);
49+
struct Pr<'a, 'b, B:'a+'b+fmt::Debug>(&'static str, &'a B, &'b B);
50+
struct St<A: fmt::Debug>(&'static str, A);
51+
struct Sr<'a, B:'a+fmt::Debug>(&'static str, &'a B);
52+
53+
impl<A: fmt::Debug> Drop for Dt<A> {
54+
fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
55+
}
56+
impl<'a, B: fmt::Debug> Drop for Dr<'a, B> {
57+
fn drop(&mut self) { println!("drop {} {:?}", self.0, self.1); }
58+
}
59+
unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
60+
// (unsafe to access self.1 due to #[may_dangle] on A)
61+
fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
62+
}
63+
unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
64+
// (unsafe to access self.1 due to #[may_dangle] on 'a)
65+
fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
66+
}
67+
68+
fn main() {
69+
use std::cell::Cell;
70+
let c_long;
71+
let (c, mut dt, mut dr, mut pt, mut pr, st, sr)
72+
: (Cell<_>, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>);
73+
c_long = Cell::new(1);
74+
c = Cell::new(1);
75+
76+
// No error: sufficiently long-lived state can be referenced in dtors
77+
dt = Dt("dt", &c_long);
78+
dr = Dr("dr", &c_long);
79+
// Error: destructor order imprecisely modelled
80+
dt = Dt("dt", &c); //~ ERROR `c` does not live long enough
81+
dr = Dr("dr", &c); //~ ERROR `c` does not live long enough
82+
83+
// No error: Drop impl asserts .1 (A and &'a _) are not accessed
84+
pt = Pt("pt", &c, &c_long);
85+
pr = Pr("pr", &c, &c_long);
86+
87+
// Error: Drop impl's assertion does not apply to `B` nor `&'b _`
88+
pt = Pt("pt", &c_long, &c); //~ ERROR `c` does not live long enough
89+
pr = Pr("pr", &c_long, &c); //~ ERROR `c` does not live long enough
90+
91+
// No error: St and Sr have no destructor.
92+
st = St("st", &c);
93+
sr = Sr("sr", &c);
94+
95+
println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0));
96+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
// Check that `may_dangle` is rejected if `dropck_eyepatch` feature gate is absent.
12+
13+
#![feature(generic_param_attrs)]
14+
15+
struct Pt<A>(A);
16+
impl<#[may_dangle] A> Drop for Pt<A> {
17+
//~^ ERROR may_dangle has unstable semantics and may be removed in the future
18+
//~| HELP add #![feature(dropck_eyepatch)] to the crate attributes to enable
19+
fn drop(&mut self) { }
20+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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 illustrate that the `#[may_dangle]`
15+
// attribute specifically allows, in the context of a type
16+
// implementing `Drop`, a generic parameter to be instantiated with a
17+
// lifetime that does not strictly outlive the owning type itself,
18+
// and that this attributes effects are preserved when importing
19+
// the type from another crate.
20+
//
21+
// See also dropck-eyepatch.rs for more information about the general
22+
// structure of the test.
23+
24+
use std::cell::RefCell;
25+
26+
pub trait Foo { fn foo(&self, _: &str); }
27+
28+
pub struct Dt<A: Foo>(pub &'static str, pub A);
29+
pub struct Dr<'a, B:'a+Foo>(pub &'static str, pub &'a B);
30+
pub struct Pt<A,B: Foo>(pub &'static str, pub A, pub B);
31+
pub struct Pr<'a, 'b, B:'a+'b+Foo>(pub &'static str, pub &'a B, pub &'b B);
32+
pub struct St<A: Foo>(pub &'static str, pub A);
33+
pub struct Sr<'a, B:'a+Foo>(pub &'static str, pub &'a B);
34+
35+
impl<A: Foo> Drop for Dt<A> {
36+
fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); }
37+
}
38+
impl<'a, B: Foo> Drop for Dr<'a, B> {
39+
fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); }
40+
}
41+
unsafe impl<#[may_dangle] A, B: Foo> Drop for Pt<A, B> {
42+
// (unsafe to access self.1 due to #[may_dangle] on A)
43+
fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); }
44+
}
45+
unsafe impl<#[may_dangle] 'a, 'b, B: Foo> Drop for Pr<'a, 'b, B> {
46+
// (unsafe to access self.1 due to #[may_dangle] on 'a)
47+
fn drop(&mut self) { println!("drop {}", self.0); self.2.foo(self.0); }
48+
}
49+
50+
impl Foo for RefCell<String> {
51+
fn foo(&self, s: &str) {
52+
let s2 = format!("{}|{}", *self.borrow(), s);
53+
*self.borrow_mut() = s2;
54+
}
55+
}
56+
57+
impl<'a, T:Foo> Foo for &'a T {
58+
fn foo(&self, s: &str) {
59+
(*self).foo(s);
60+
}
61+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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+
// aux-build:dropck_eyepatch_extern_crate.rs
12+
13+
extern crate dropck_eyepatch_extern_crate as other;
14+
15+
use other::{Dt,Dr,Pt,Pr,St,Sr};
16+
17+
fn main() {
18+
use std::cell::RefCell;
19+
20+
struct CheckOnDrop(RefCell<String>, &'static str);
21+
impl Drop for CheckOnDrop {
22+
fn drop(&mut self) { assert_eq!(*self.0.borrow(), self.1); }
23+
}
24+
25+
let c_long;
26+
let (c, dt, dr, pt, pr, st, sr)
27+
: (CheckOnDrop, Dt<_>, Dr<_>, Pt<_, _>, Pr<_>, St<_>, Sr<_>);
28+
c_long = CheckOnDrop(RefCell::new("c_long".to_string()),
29+
"c_long|pr|pt|dr|dt");
30+
c = CheckOnDrop(RefCell::new("c".to_string()),
31+
"c");
32+
33+
// No error: sufficiently long-lived state can be referenced in dtors
34+
dt = Dt("dt", &c_long.0);
35+
dr = Dr("dr", &c_long.0);
36+
37+
// No error: Drop impl asserts .1 (A and &'a _) are not accessed
38+
pt = Pt("pt", &c.0, &c_long.0);
39+
pr = Pr("pr", &c.0, &c_long.0);
40+
41+
// No error: St and Sr have no destructor.
42+
st = St("st", &c.0);
43+
sr = Sr("sr", &c.0);
44+
45+
println!("{:?}", (dt.0, dr.0, pt.0, pr.0, st.0, sr.0));
46+
assert_eq!(*c_long.0.borrow(), "c_long");
47+
assert_eq!(*c.0.borrow(), "c");
48+
}

0 commit comments

Comments
 (0)