Skip to content

Commit 59a04f5

Browse files
committed
Immutable static items should be Freeze Fixes #12432
1 parent 0c7a012 commit 59a04f5

File tree

6 files changed

+68
-18
lines changed

6 files changed

+68
-18
lines changed

src/librustc/middle/check_static.rs

+21
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,24 @@ impl Visitor<bool> for CheckStaticVisitor {
118118
self.tcx.sess.span_err(e.span,
119119
"static items are not allowed to have owned pointers");
120120
}
121+
ast::ExprProc(..) => {
122+
self.report_error(e.span,
123+
Some(~"immutable static items must be `Freeze`"));
124+
return;
125+
}
126+
ast::ExprAddrOf(mutability, _) => {
127+
match mutability {
128+
ast::MutMutable => {
129+
self.report_error(e.span,
130+
Some(~"immutable static items must be `Freeze`"));
131+
return;
132+
}
133+
_ => {}
134+
}
135+
}
121136
_ => {
122137
let node_ty = ty::node_id_to_type(self.tcx, e.id);
138+
123139
match ty::get(node_ty).sty {
124140
ty::ty_struct(did, _) |
125141
ty::ty_enum(did, _) => {
@@ -128,6 +144,11 @@ impl Visitor<bool> for CheckStaticVisitor {
128144
Some(~"static items are not allowed to have destructors"));
129145
return;
130146
}
147+
if Some(did) == self.tcx.lang_items.no_freeze_bound() {
148+
self.report_error(e.span,
149+
Some(~"immutable static items must be `Freeze`"));
150+
return;
151+
}
131152
}
132153
_ => {}
133154
}

src/test/compile-fail/check-static-values-constraints.rs

+26
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
// Verifies all possible restrictions for static items values.
1313

14+
use std::kinds::marker;
15+
1416
struct WithDtor;
1517

1618
impl Drop for WithDtor {
@@ -122,6 +124,30 @@ static STATIC18: @SafeStruct = @SafeStruct{field1: Variant1, field2: Variant2(0)
122124
static STATIC19: ~int = box 3;
123125
//~^ ERROR static items are not allowed to have owned pointers
124126

127+
128+
struct StructNoFreeze<'a> {
129+
nf: &'a int
130+
}
131+
132+
enum EnumNoFreeze<'a> {
133+
FreezableVariant,
134+
NonFreezableVariant(StructNoFreeze<'a>)
135+
}
136+
137+
static STATIC20: StructNoFreeze<'static> = StructNoFreeze{nf: &'static mut 4};
138+
//~^ ERROR immutable static items must be `Freeze`
139+
140+
static STATIC21: EnumNoFreeze<'static> = FreezableVariant;
141+
static STATIC22: EnumNoFreeze<'static> = NonFreezableVariant(StructNoFreeze{nf: &'static mut 4});
142+
//~^ ERROR immutable static items must be `Freeze`
143+
144+
struct NFMarker {
145+
nf: marker::NoFreeze
146+
}
147+
148+
static STATIC23: NFMarker = NFMarker{nf: marker::NoFreeze};
149+
//~^ ERROR immutable static items must be `Freeze`
150+
125151
pub fn main() {
126152
let y = { static x: ~int = ~3; x };
127153
//~^ ERROR static items are not allowed to have owned pointers

src/test/compile-fail/static-mut-not-constant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
static mut a: ~int = ~3; //~ ERROR: cannot do allocations in constant expressions
11+
static mut a: ~int = ~3; //~ ERROR: mutable static items are not allowed to have owned pointers
1212

1313
fn main() {}

src/test/run-pass/const-fn-val.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ fn foo() -> int {
1414

1515
struct Bar<'a> { f: 'a || -> int }
1616

17-
static b : Bar<'static> = Bar { f: foo };
17+
static mut b : Bar<'static> = Bar { f: foo };
1818

1919
pub fn main() {
20-
assert_eq!((b.f)(), 0xca7f000d);
20+
unsafe { assert_eq!((b.f)(), 0xca7f000d); }
2121
}

src/test/run-pass/const-vec-of-fns.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
fn f() { }
1919
static bare_fns: &'static [fn()] = &[f, f];
2020
struct S<'a>('a ||);
21-
static closures: &'static [S<'static>] = &[S(f), S(f)];
21+
static mut closures: &'static [S<'static>] = &[S(f), S(f)];
2222

2323
pub fn main() {
24-
for &bare_fn in bare_fns.iter() { bare_fn() }
25-
for closure in closures.iter() {
26-
let S(ref closure) = *closure;
27-
(*closure)()
24+
unsafe {
25+
for &bare_fn in bare_fns.iter() { bare_fn() }
26+
for closure in closures.iter() {
27+
let S(ref closure) = *closure;
28+
(*closure)()
29+
}
2830
}
2931
}

src/test/run-pass/core-run-destroy.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,23 @@ use std::io::process::{Process, ProcessOutput};
2323
#[test]
2424
fn test_destroy_once() {
2525
#[cfg(not(target_os="android"))]
26-
static PROG: &'static str = "echo";
26+
static mut PROG: &'static str = "echo";
27+
2728
#[cfg(target_os="android")]
28-
static PROG: &'static str = "ls"; // android don't have echo binary
29+
static mut PROG: &'static str = "ls"; // android don't have echo binary
2930

30-
let mut p = Process::new(PROG, []).unwrap();
31+
let mut p = unsafe {Process::new(PROG, []).unwrap()};
3132
p.signal_exit().unwrap(); // this shouldn't crash (and nor should the destructor)
3233
}
3334

3435
#[test]
3536
fn test_destroy_twice() {
3637
#[cfg(not(target_os="android"))]
37-
static PROG: &'static str = "echo";
38+
static mut PROG: &'static str = "echo";
3839
#[cfg(target_os="android")]
39-
static PROG: &'static str = "ls"; // android don't have echo binary
40+
static mut PROG: &'static str = "ls"; // android don't have echo binary
4041

41-
let mut p = match Process::new(PROG, []) {
42+
let mut p = match unsafe{Process::new(PROG, [])} {
4243
Ok(p) => p,
4344
Err(e) => fail!("wut: {}", e),
4445
};
@@ -49,13 +50,13 @@ fn test_destroy_twice() {
4950
fn test_destroy_actually_kills(force: bool) {
5051

5152
#[cfg(unix,not(target_os="android"))]
52-
static BLOCK_COMMAND: &'static str = "cat";
53+
static mut BLOCK_COMMAND: &'static str = "cat";
5354

5455
#[cfg(unix,target_os="android")]
55-
static BLOCK_COMMAND: &'static str = "/system/bin/cat";
56+
static mut BLOCK_COMMAND: &'static str = "/system/bin/cat";
5657

5758
#[cfg(windows)]
58-
static BLOCK_COMMAND: &'static str = "cmd";
59+
static mut BLOCK_COMMAND: &'static str = "cmd";
5960

6061
#[cfg(unix,not(target_os="android"))]
6162
fn process_exists(pid: libc::pid_t) -> bool {
@@ -91,7 +92,7 @@ fn test_destroy_actually_kills(force: bool) {
9192
}
9293

9394
// this process will stay alive indefinitely trying to read from stdin
94-
let mut p = Process::new(BLOCK_COMMAND, []).unwrap();
95+
let mut p = unsafe {Process::new(BLOCK_COMMAND, []).unwrap()};
9596

9697
assert!(process_exists(p.id()));
9798

0 commit comments

Comments
 (0)