self.tcx.sess.span_err(e.span,
"static items are not allowed to have owned pointers");
}
+ ast::ExprProc(..) => {
+ self.report_error(e.span,
+ Some(~"immutable static items must be `Freeze`"));
+ return;
+ }
+ ast::ExprAddrOf(mutability, _) => {
+ match mutability {
+ ast::MutMutable => {
+ self.report_error(e.span,
+ Some(~"immutable static items must be `Freeze`"));
+ return;
+ }
+ _ => {}
+ }
+ }
_ => {
let node_ty = ty::node_id_to_type(self.tcx, e.id);
+
match ty::get(node_ty).sty {
ty::ty_struct(did, _) |
ty::ty_enum(did, _) => {
Some(~"static items are not allowed to have destructors"));
return;
}
+ if Some(did) == self.tcx.lang_items.no_freeze_bound() {
+ self.report_error(e.span,
+ Some(~"immutable static items must be `Freeze`"));
+ return;
+ }
}
_ => {}
}
// Verifies all possible restrictions for static items values.
+use std::kinds::marker;
+
struct WithDtor;
impl Drop for WithDtor {
static STATIC19: ~int = box 3;
//~^ ERROR static items are not allowed to have owned pointers
+
+struct StructNoFreeze<'a> {
+ nf: &'a int
+}
+
+enum EnumNoFreeze<'a> {
+ FreezableVariant,
+ NonFreezableVariant(StructNoFreeze<'a>)
+}
+
+static STATIC20: StructNoFreeze<'static> = StructNoFreeze{nf: &'static mut 4};
+//~^ ERROR immutable static items must be `Freeze`
+
+static STATIC21: EnumNoFreeze<'static> = FreezableVariant;
+static STATIC22: EnumNoFreeze<'static> = NonFreezableVariant(StructNoFreeze{nf: &'static mut 4});
+//~^ ERROR immutable static items must be `Freeze`
+
+struct NFMarker {
+ nf: marker::NoFreeze
+}
+
+static STATIC23: NFMarker = NFMarker{nf: marker::NoFreeze};
+//~^ ERROR immutable static items must be `Freeze`
+
pub fn main() {
let y = { static x: ~int = ~3; x };
//~^ ERROR static items are not allowed to have owned pointers
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-static mut a: ~int = ~3; //~ ERROR: cannot do allocations in constant expressions
+static mut a: ~int = ~3; //~ ERROR: mutable static items are not allowed to have owned pointers
fn main() {}
struct Bar<'a> { f: 'a || -> int }
-static b : Bar<'static> = Bar { f: foo };
+static mut b : Bar<'static> = Bar { f: foo };
pub fn main() {
- assert_eq!((b.f)(), 0xca7f000d);
+ unsafe { assert_eq!((b.f)(), 0xca7f000d); }
}
fn f() { }
static bare_fns: &'static [fn()] = &[f, f];
struct S<'a>('a ||);
-static closures: &'static [S<'static>] = &[S(f), S(f)];
+static mut closures: &'static [S<'static>] = &[S(f), S(f)];
pub fn main() {
- for &bare_fn in bare_fns.iter() { bare_fn() }
- for closure in closures.iter() {
- let S(ref closure) = *closure;
- (*closure)()
+ unsafe {
+ for &bare_fn in bare_fns.iter() { bare_fn() }
+ for closure in closures.iter() {
+ let S(ref closure) = *closure;
+ (*closure)()
+ }
}
}
#[test]
fn test_destroy_once() {
#[cfg(not(target_os="android"))]
- static PROG: &'static str = "echo";
+ static mut PROG: &'static str = "echo";
+
#[cfg(target_os="android")]
- static PROG: &'static str = "ls"; // android don't have echo binary
+ static mut PROG: &'static str = "ls"; // android don't have echo binary
- let mut p = Process::new(PROG, []).unwrap();
+ let mut p = unsafe {Process::new(PROG, []).unwrap()};
p.signal_exit().unwrap(); // this shouldn't crash (and nor should the destructor)
}
#[test]
fn test_destroy_twice() {
#[cfg(not(target_os="android"))]
- static PROG: &'static str = "echo";
+ static mut PROG: &'static str = "echo";
#[cfg(target_os="android")]
- static PROG: &'static str = "ls"; // android don't have echo binary
+ static mut PROG: &'static str = "ls"; // android don't have echo binary
- let mut p = match Process::new(PROG, []) {
+ let mut p = match unsafe{Process::new(PROG, [])} {
Ok(p) => p,
Err(e) => fail!("wut: {}", e),
};
fn test_destroy_actually_kills(force: bool) {
#[cfg(unix,not(target_os="android"))]
- static BLOCK_COMMAND: &'static str = "cat";
+ static mut BLOCK_COMMAND: &'static str = "cat";
#[cfg(unix,target_os="android")]
- static BLOCK_COMMAND: &'static str = "/system/bin/cat";
+ static mut BLOCK_COMMAND: &'static str = "/system/bin/cat";
#[cfg(windows)]
- static BLOCK_COMMAND: &'static str = "cmd";
+ static mut BLOCK_COMMAND: &'static str = "cmd";
#[cfg(unix,not(target_os="android"))]
fn process_exists(pid: libc::pid_t) -> bool {
}
// this process will stay alive indefinitely trying to read from stdin
- let mut p = Process::new(BLOCK_COMMAND, []).unwrap();
+ let mut p = unsafe {Process::new(BLOCK_COMMAND, []).unwrap()};
assert!(process_exists(p.id()));