diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs index 86078c4023a13..ebf1904d3cb2a 100644 --- a/src/librustc/middle/check_static.rs +++ b/src/librustc/middle/check_static.rs @@ -118,8 +118,24 @@ impl Visitor for CheckStaticVisitor { 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, _) => { @@ -128,6 +144,11 @@ impl Visitor for CheckStaticVisitor { 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; + } } _ => {} } diff --git a/src/test/compile-fail/check-static-values-constraints.rs b/src/test/compile-fail/check-static-values-constraints.rs index 1248f56d4b88f..852b06d00a64e 100644 --- a/src/test/compile-fail/check-static-values-constraints.rs +++ b/src/test/compile-fail/check-static-values-constraints.rs @@ -11,6 +11,8 @@ // Verifies all possible restrictions for static items values. +use std::kinds::marker; + struct WithDtor; impl Drop for WithDtor { @@ -122,6 +124,30 @@ static STATIC18: @SafeStruct = @SafeStruct{field1: Variant1, field2: Variant2(0) 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 diff --git a/src/test/compile-fail/static-mut-not-constant.rs b/src/test/compile-fail/static-mut-not-constant.rs index 69db9fa1b3590..90dabb7e3a271 100644 --- a/src/test/compile-fail/static-mut-not-constant.rs +++ b/src/test/compile-fail/static-mut-not-constant.rs @@ -8,6 +8,6 @@ // 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() {} diff --git a/src/test/run-pass/const-fn-val.rs b/src/test/run-pass/const-fn-val.rs index 0ad8dfc277cbb..18638ab68776e 100644 --- a/src/test/run-pass/const-fn-val.rs +++ b/src/test/run-pass/const-fn-val.rs @@ -14,8 +14,8 @@ fn foo() -> int { 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); } } diff --git a/src/test/run-pass/const-vec-of-fns.rs b/src/test/run-pass/const-vec-of-fns.rs index 6d193ec400ba7..9a93fcb5f8912 100644 --- a/src/test/run-pass/const-vec-of-fns.rs +++ b/src/test/run-pass/const-vec-of-fns.rs @@ -18,12 +18,14 @@ 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)() + } } } diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index 60f98b1075a47..db7b2803c7116 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -23,22 +23,23 @@ use std::io::process::{Process, ProcessOutput}; #[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), }; @@ -49,13 +50,13 @@ fn test_destroy_twice() { 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 { @@ -91,7 +92,7 @@ fn test_destroy_actually_kills(force: 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()));