Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
Showing
2 changed files
with
113 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
// Ensure that attempts to use the unsafe attribute are feature-gated. | ||
|
||
// Example adapted from RFC 1238 text (just left out the feature gate). | ||
|
||
// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md#example-of-the-unguarded-escape-hatch | ||
|
||
// #![feature(dropck_parametricity)] | ||
|
||
use std::cell::Cell; | ||
|
||
struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>); | ||
|
||
struct Foo<T> { data: Vec<T> } | ||
|
||
impl<T> Drop for Foo<T> { | ||
#[unsafe_destructor_blind_to_params] // This is the UGEH attribute | ||
//~^ ERROR unsafe_destructor_blind_to_params has unstable semantics | ||
fn drop(&mut self) { } | ||
} | ||
|
||
fn main() { | ||
let mut foo = Foo { data: Vec::new() }; | ||
foo.data.push(Concrete(0, Cell::new(None))); | ||
foo.data.push(Concrete(0, Cell::new(None))); | ||
|
||
foo.data[0].1.set(Some(&foo.data[1])); | ||
foo.data[1].1.set(Some(&foo.data[0])); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
// Example taken from RFC 1238 text | ||
|
||
// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md#examples-of-code-that-will-start-to-be-rejected | ||
|
||
// Compare against test/run-pass/issue28498-must-work-ex2.rs | ||
|
||
use std::cell::Cell; | ||
|
||
#[derive(Copy, Clone, Debug)] | ||
enum Validity { Valid, Invalid } | ||
use self::Validity::{Valid, Invalid}; | ||
|
||
struct Abstract<T> { | ||
id: u32, | ||
nbor: Cell<Option<T>>, | ||
valid: Validity, | ||
observe: fn(&Cell<Option<T>>) -> (u32, Validity), | ||
} | ||
|
||
#[derive(Copy, Clone)] | ||
struct Neighbor<'a>(&'a Abstract<Neighbor<'a>>); | ||
|
||
fn observe(c: &Cell<Option<Neighbor>>) -> (u32, Validity) { | ||
let r = c.get().unwrap().0; | ||
(r.id, r.valid) | ||
} | ||
|
||
impl<'a> Abstract<Neighbor<'a>> { | ||
fn new(id: u32) -> Self { | ||
Abstract { | ||
id: id, | ||
nbor: Cell::new(None), | ||
valid: Valid, | ||
observe: observe | ||
} | ||
} | ||
} | ||
|
||
struct Foo<T> { | ||
data: Vec<T>, | ||
} | ||
|
||
impl<T> Drop for Abstract<T> { | ||
fn drop(&mut self) { | ||
let (nbor_id, nbor_valid) = (self.observe)(&self.nbor); | ||
println!("dropping element {} ({:?}), observed neighbor {} ({:?})", | ||
self.id, | ||
self.valid, | ||
nbor_id, | ||
nbor_valid); | ||
self.valid = Invalid; | ||
} | ||
} | ||
|
||
fn main() { | ||
let mut foo: Foo<Abstract<Neighbor>> = Foo { data: Vec::new() }; | ||
foo.data.push(Abstract::new(0)); | ||
foo.data.push(Abstract::new(1)); | ||
|
||
foo.data[0].nbor.set(Some(Neighbor(&foo.data[1]))); | ||
//~^ ERROR `foo.data` does not live long enough | ||
foo.data[1].nbor.set(Some(Neighbor(&foo.data[0]))); | ||
//~^ ERROR `foo.data` does not live long enough | ||
} |