From 29003c799f41cce948bc043cdd1350ca4bee949e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 10 Sep 2012 16:34:31 -0700 Subject: Rename the poorly named Managed type to Mut. The Mut type is intended to allow freezable data stuctures to be stored in `@mut` boxes. Currently this causes borrowck to be very conserivative since it cannot prove that you are not modifying such a structure while iterating over it, for example. But if you do `@Mut` instead of `@mut T`, you will effectively convert borrowck's static checks into dynamic ones. This lets you use the e.g. send_map just like a Java Map or something else. --- src/libcore/core.rc | 4 +- src/libcore/managed.rs | 143 ------------------------------------------ src/libcore/mutable.rs | 151 +++++++++++++++++++++++++++++++++++++++++++++ src/libstd/map.rs | 4 +- src/test/bench/core-map.rs | 10 +-- 5 files changed, 160 insertions(+), 152 deletions(-) delete mode 100644 src/libcore/managed.rs create mode 100644 src/libcore/mutable.rs diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 25bdcea0bb2..c0c9cf5f9b6 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -57,7 +57,7 @@ export hash; export cmp; export num; export path; -export managed; +export mutable; export flate; export unit; export uniq; @@ -225,7 +225,7 @@ mod run; mod sys; mod unsafe; -mod managed; +mod mutable; mod flate; diff --git a/src/libcore/managed.rs b/src/libcore/managed.rs deleted file mode 100644 index b3119b9d24d..00000000000 --- a/src/libcore/managed.rs +++ /dev/null @@ -1,143 +0,0 @@ -/*! - -Module for wrapping freezable data structures in managed boxes. -Normally freezable data structures require an unaliased reference, -such as `T` or `~T`, so that the compiler can track when they are -being mutated. The `managed` type converts these static checks into -dynamic checks: your program will fail if you attempt to perform -mutation when the data structure should be immutable. - -*/ - -#[forbid(deprecated_mode)]; -#[forbid(deprecated_pattern)]; - -use util::with; -use unsafe::transmute_immut; - -export Managed; - -enum Mode { ReadOnly, Mutable, Immutable } - -struct Data { - priv mut value: T, - priv mut mode: Mode -} - -type Managed = @Data; - -fn Managed(+t: T) -> Managed { - @Data {value: t, mode: ReadOnly} -} - -impl Data { - fn borrow_mut(op: &fn(t: &mut T) -> R) -> R { - match self.mode { - Immutable => fail fmt!("%? currently immutable", - self.value), - ReadOnly | Mutable => {} - } - - do with(&mut self.mode, Mutable) { - op(&mut self.value) - } - } - - fn borrow_const(op: &fn(t: &const T) -> R) -> R { - op(&const self.value) - } - - fn borrow_imm(op: &fn(t: &T) -> R) -> R { - match self.mode { - Mutable => fail fmt!("%? currently mutable", - self.value), - ReadOnly | Immutable => {} - } - - do with(&mut self.mode, Immutable) { - op(unsafe{transmute_immut(&mut self.value)}) - } - } -} - -#[test] -#[ignore(cfg(windows))] -#[should_fail] -fn test_mut_in_imm() { - let m = Managed(1); - do m.borrow_imm |_p| { - do m.borrow_mut |_q| { - // should not be permitted - } - } -} - -#[test] -#[ignore(cfg(windows))] -#[should_fail] -fn test_imm_in_mut() { - let m = Managed(1); - do m.borrow_mut |_p| { - do m.borrow_imm |_q| { - // should not be permitted - } - } -} - -#[test] -fn test_const_in_mut() { - let m = Managed(1); - do m.borrow_mut |p| { - do m.borrow_const |q| { - assert *p == *q; - *p += 1; - assert *p == *q; - } - } -} - -#[test] -fn test_mut_in_const() { - let m = Managed(1); - do m.borrow_const |p| { - do m.borrow_mut |q| { - assert *p == *q; - *q += 1; - assert *p == *q; - } - } -} - -#[test] -fn test_imm_in_const() { - let m = Managed(1); - do m.borrow_const |p| { - do m.borrow_imm |q| { - assert *p == *q; - } - } -} - -#[test] -fn test_const_in_imm() { - let m = Managed(1); - do m.borrow_imm |p| { - do m.borrow_const |q| { - assert *p == *q; - } - } -} - - -#[test] -#[ignore(cfg(windows))] -#[should_fail] -fn test_mut_in_imm_in_const() { - let m = Managed(1); - do m.borrow_const |_p| { - do m.borrow_imm |_q| { - do m.borrow_mut |_r| { - } - } - } -} diff --git a/src/libcore/mutable.rs b/src/libcore/mutable.rs new file mode 100644 index 00000000000..eca9ff6fada --- /dev/null +++ b/src/libcore/mutable.rs @@ -0,0 +1,151 @@ +/*! + +Module for wrapping freezable data structures in managed boxes. +Normally freezable data structures require an unaliased reference, +such as `T` or `~T`, so that the compiler can track when they are +being mutated. The `managed` type converts these static checks into +dynamic checks: your program will fail if you attempt to perform +mutation when the data structure should be immutable. + +*/ + +#[forbid(deprecated_mode)]; +#[forbid(deprecated_pattern)]; + +use util::with; +use unsafe::transmute_immut; + +export Mut; + +enum Mode { ReadOnly, Mutable, Immutable } + +struct Data { + priv mut value: T, + priv mut mode: Mode +} + +type Mut = Data; + +fn Mut(+t: T) -> Mut { + Data {value: t, mode: ReadOnly} +} + +fn unwrap(+m: Mut) -> T { + // Borrowck should prevent us from calling unwrap while the value + // is in use, as that would be a move from a borrowed value. + assert (m.mode as uint) == (ReadOnly as uint); + let Data {value, mode: _} = m; + return move value; +} + +impl Data { + fn borrow_mut(op: &fn(t: &mut T) -> R) -> R { + match self.mode { + Immutable => fail fmt!("%? currently immutable", + self.value), + ReadOnly | Mutable => {} + } + + do with(&mut self.mode, Mutable) { + op(&mut self.value) + } + } + + fn borrow_const(op: &fn(t: &const T) -> R) -> R { + op(&const self.value) + } + + fn borrow_imm(op: &fn(t: &T) -> R) -> R { + match self.mode { + Mutable => fail fmt!("%? currently mutable", + self.value), + ReadOnly | Immutable => {} + } + + do with(&mut self.mode, Immutable) { + op(unsafe{transmute_immut(&mut self.value)}) + } + } +} + +#[test] +#[ignore(cfg(windows))] +#[should_fail] +fn test_mut_in_imm() { + let m = @Mut(1); + do m.borrow_imm |_p| { + do m.borrow_mut |_q| { + // should not be permitted + } + } +} + +#[test] +#[ignore(cfg(windows))] +#[should_fail] +fn test_imm_in_mut() { + let m = @Mut(1); + do m.borrow_mut |_p| { + do m.borrow_imm |_q| { + // should not be permitted + } + } +} + +#[test] +fn test_const_in_mut() { + let m = @Mut(1); + do m.borrow_mut |p| { + do m.borrow_const |q| { + assert *p == *q; + *p += 1; + assert *p == *q; + } + } +} + +#[test] +fn test_mut_in_const() { + let m = @Mut(1); + do m.borrow_const |p| { + do m.borrow_mut |q| { + assert *p == *q; + *q += 1; + assert *p == *q; + } + } +} + +#[test] +fn test_imm_in_const() { + let m = @Mut(1); + do m.borrow_const |p| { + do m.borrow_imm |q| { + assert *p == *q; + } + } +} + +#[test] +fn test_const_in_imm() { + let m = @Mut(1); + do m.borrow_imm |p| { + do m.borrow_const |q| { + assert *p == *q; + } + } +} + + +#[test] +#[ignore(cfg(windows))] +#[should_fail] +fn test_mut_in_imm_in_const() { + let m = @Mut(1); + do m.borrow_const |_p| { + do m.borrow_imm |_q| { + do m.borrow_mut |_r| { + } + } + } +} diff --git a/src/libstd/map.rs b/src/libstd/map.rs index 5436ea1a803..cd19da61ab6 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -5,7 +5,7 @@ use io::WriterUtil; use to_str::ToStr; -use managed::Managed; +use mutable::Mut; use send_map::linear::LinearMap; use core::cmp::Eq; @@ -463,7 +463,7 @@ fn hash_from_uints(items: &[(uint, V)]) -> hashmap { } // XXX Transitional -impl Managed>: +impl @Mut>: map { pure fn size() -> uint { unchecked { diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index 4901a85369a..112c25d5146 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -6,7 +6,7 @@ use std; use std::map; -use managed::Managed; +use mutable::Mut; use send_map::linear::*; use io::WriterUtil; @@ -166,11 +166,11 @@ fn main(args: ~[~str]) { { let rng = rand::seeded_rng(copy seed); let mut results = empty_results(); - int_benchmarks::>>( - || Managed(LinearMap()), + int_benchmarks::<@Mut>>( + || @Mut(LinearMap()), rng, num_keys, &mut results); - str_benchmarks::>>( - || Managed(LinearMap()), + str_benchmarks::<@Mut>>( + || @Mut(LinearMap()), rng, num_keys, &mut results); write_results("libstd::map::hashmap", &results); } -- cgit 1.4.1-3-g733a5