From 83077bee9352cea17758b26aa467022b2fbdc599 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 6 Oct 2015 13:56:36 +0200 Subject: [PATCH] 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. --- .../compile-fail/feature-gate-dropck-ugeh.rs | 39 ++++++++++ .../compile-fail/issue28498-reject-ex1.rs | 74 +++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 src/test/compile-fail/feature-gate-dropck-ugeh.rs create mode 100644 src/test/compile-fail/issue28498-reject-ex1.rs diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh.rs b/src/test/compile-fail/feature-gate-dropck-ugeh.rs new file mode 100644 index 000000000000..a7349e360076 --- /dev/null +++ b/src/test/compile-fail/feature-gate-dropck-ugeh.rs @@ -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 or the MIT license +// , 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>>); + +struct Foo { data: Vec } + +impl Drop for Foo { + #[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])); +} + diff --git a/src/test/compile-fail/issue28498-reject-ex1.rs b/src/test/compile-fail/issue28498-reject-ex1.rs new file mode 100644 index 000000000000..1de20411f3a3 --- /dev/null +++ b/src/test/compile-fail/issue28498-reject-ex1.rs @@ -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 or the MIT license +// , 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 { + id: u32, + nbor: Cell>, + valid: Validity, + observe: fn(&Cell>) -> (u32, Validity), +} + +#[derive(Copy, Clone)] +struct Neighbor<'a>(&'a Abstract>); + +fn observe(c: &Cell>) -> (u32, Validity) { + let r = c.get().unwrap().0; + (r.id, r.valid) +} + +impl<'a> Abstract> { + fn new(id: u32) -> Self { + Abstract { + id: id, + nbor: Cell::new(None), + valid: Valid, + observe: observe + } + } +} + +struct Foo { + data: Vec, +} + +impl Drop for Abstract { + 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> = 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 +}