Skip to content

Commit 83077be

Browse files
committed
compile-fail tests.
One just checks that we are feature-gating the UGEH attribute (as usual for attributes associated with unstable features). The other is adapted from the RFC 1238 text, except that it has been extended somewhat to actually *illustrate* the scenario that we are trying to prevent, namely observing the state of data, from safe code, after the destructor for that data has been executed.
1 parent eea299b commit 83077be

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2015 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+
// Ensure that attempts to use the unsafe attribute are feature-gated.
12+
13+
// Example adapted from RFC 1238 text (just left out the feature gate).
14+
15+
// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md#example-of-the-unguarded-escape-hatch
16+
17+
// #![feature(dropck_parametricity)]
18+
19+
use std::cell::Cell;
20+
21+
struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
22+
23+
struct Foo<T> { data: Vec<T> }
24+
25+
impl<T> Drop for Foo<T> {
26+
#[unsafe_destructor_blind_to_params] // This is the UGEH attribute
27+
//~^ ERROR unsafe_destructor_blind_to_params has unstable semantics
28+
fn drop(&mut self) { }
29+
}
30+
31+
fn main() {
32+
let mut foo = Foo { data: Vec::new() };
33+
foo.data.push(Concrete(0, Cell::new(None)));
34+
foo.data.push(Concrete(0, Cell::new(None)));
35+
36+
foo.data[0].1.set(Some(&foo.data[1]));
37+
foo.data[1].1.set(Some(&foo.data[0]));
38+
}
39+
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2015 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+
// Example taken from RFC 1238 text
12+
13+
// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md#examples-of-code-that-will-start-to-be-rejected
14+
15+
// Compare against test/run-pass/issue28498-must-work-ex2.rs
16+
17+
use std::cell::Cell;
18+
19+
#[derive(Copy, Clone, Debug)]
20+
enum Validity { Valid, Invalid }
21+
use self::Validity::{Valid, Invalid};
22+
23+
struct Abstract<T> {
24+
id: u32,
25+
nbor: Cell<Option<T>>,
26+
valid: Validity,
27+
observe: fn(&Cell<Option<T>>) -> (u32, Validity),
28+
}
29+
30+
#[derive(Copy, Clone)]
31+
struct Neighbor<'a>(&'a Abstract<Neighbor<'a>>);
32+
33+
fn observe(c: &Cell<Option<Neighbor>>) -> (u32, Validity) {
34+
let r = c.get().unwrap().0;
35+
(r.id, r.valid)
36+
}
37+
38+
impl<'a> Abstract<Neighbor<'a>> {
39+
fn new(id: u32) -> Self {
40+
Abstract {
41+
id: id,
42+
nbor: Cell::new(None),
43+
valid: Valid,
44+
observe: observe
45+
}
46+
}
47+
}
48+
49+
struct Foo<T> {
50+
data: Vec<T>,
51+
}
52+
53+
impl<T> Drop for Abstract<T> {
54+
fn drop(&mut self) {
55+
let (nbor_id, nbor_valid) = (self.observe)(&self.nbor);
56+
println!("dropping element {} ({:?}), observed neighbor {} ({:?})",
57+
self.id,
58+
self.valid,
59+
nbor_id,
60+
nbor_valid);
61+
self.valid = Invalid;
62+
}
63+
}
64+
65+
fn main() {
66+
let mut foo: Foo<Abstract<Neighbor>> = Foo { data: Vec::new() };
67+
foo.data.push(Abstract::new(0));
68+
foo.data.push(Abstract::new(1));
69+
70+
foo.data[0].nbor.set(Some(Neighbor(&foo.data[1])));
71+
//~^ ERROR `foo.data` does not live long enough
72+
foo.data[1].nbor.set(Some(Neighbor(&foo.data[0])));
73+
//~^ ERROR `foo.data` does not live long enough
74+
}

0 commit comments

Comments
 (0)