about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlavio Percoco <flaper87@gmail.com>2014-02-21 20:31:50 +0100
committerFlavio Percoco <flaper87@gmail.com>2014-02-27 18:09:35 +0100
commit59a04f5b122793134cd3e9b98d2b361cbafae482 (patch)
tree23018d57d88830f2408a84a42f3aef55e3e2b47a
parent0c7a0125b458429e12fed44acf0f2a8d6b0a7c38 (diff)
Immutable static items should be `Freeze` Fixes #12432
-rw-r--r--src/librustc/middle/check_static.rs21
-rw-r--r--src/test/compile-fail/check-static-values-constraints.rs26
-rw-r--r--src/test/compile-fail/static-mut-not-constant.rs2
-rw-r--r--src/test/run-pass/const-fn-val.rs4
-rw-r--r--src/test/run-pass/const-vec-of-fns.rs12
-rw-r--r--src/test/run-pass/core-run-destroy.rs21
6 files changed, 68 insertions, 18 deletions
diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs
index 86078c4023a..ebf1904d3cb 100644
--- a/src/librustc/middle/check_static.rs
+++ b/src/librustc/middle/check_static.rs
@@ -118,8 +118,24 @@ impl Visitor<bool> 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<bool> 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 1248f56d4b8..852b06d00a6 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 69db9fa1b35..90dabb7e3a2 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 0ad8dfc277c..18638ab6877 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 6d193ec400b..9a93fcb5f89 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 60f98b1075a..db7b2803c71 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()));