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.
This commit is contained in:
Felix S. Klock II 2015-10-06 13:56:36 +02:00
parent eea299beaa
commit 83077bee93
2 changed files with 113 additions and 0 deletions

View file

@ -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]));
}

View file

@ -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
}