auto merge of #5678 : Thiez/rust/no-Mut, r=thestinger
This pull request completely removes Mut<T> and the associated file (libcore/mutable.rs). Some minor changes were made to workcache (libstd/workcache.rs) as it was using Mut. r?
This commit is contained in:
commit
5f13e9ccc2
3 changed files with 61 additions and 232 deletions
|
@ -212,7 +212,6 @@ pub mod rand;
|
|||
pub mod run;
|
||||
pub mod sys;
|
||||
pub mod cast;
|
||||
pub mod mutable;
|
||||
pub mod flate;
|
||||
pub mod repr;
|
||||
pub mod cleanup;
|
||||
|
|
|
@ -1,158 +0,0 @@
|
|||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/*!
|
||||
|
||||
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<T>` 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.
|
||||
|
||||
*/
|
||||
|
||||
use util::with;
|
||||
use cast::transmute_immut;
|
||||
|
||||
enum Mode { ReadOnly, Mutable, Immutable }
|
||||
|
||||
struct Data<T> {
|
||||
priv mut value: T,
|
||||
priv mut mode: Mode
|
||||
}
|
||||
|
||||
pub type Mut<T> = Data<T>;
|
||||
|
||||
pub fn Mut<T>(t: T) -> Mut<T> {
|
||||
Data {value: t, mode: ReadOnly}
|
||||
}
|
||||
|
||||
pub fn unwrap<T>(m: Mut<T>) -> 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: value, mode: _} = m;
|
||||
value
|
||||
}
|
||||
|
||||
pub impl<T> Data<T> {
|
||||
fn borrow_mut<R>(&self, op: &fn(t: &mut T) -> R) -> R {
|
||||
match self.mode {
|
||||
Immutable => fail!(~"currently immutable"),
|
||||
ReadOnly | Mutable => {}
|
||||
}
|
||||
|
||||
do with(&mut self.mode, Mutable) {
|
||||
op(&mut self.value)
|
||||
}
|
||||
}
|
||||
|
||||
fn borrow_const<R>(&self, op: &fn(t: &const T) -> R) -> R {
|
||||
op(&const self.value)
|
||||
}
|
||||
|
||||
fn borrow_imm<R>(&self, op: &fn(t: &T) -> R) -> R {
|
||||
match self.mode {
|
||||
Mutable => fail!(~"currently mutable"),
|
||||
ReadOnly | Immutable => {}
|
||||
}
|
||||
|
||||
do with(&mut self.mode, Immutable) {
|
||||
op(unsafe{transmute_immut(&mut self.value)})
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn unwrap(self) -> T { unwrap(self) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore(cfg(windows))]
|
||||
#[should_fail]
|
||||
pub 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]
|
||||
pub fn test_imm_in_mut() {
|
||||
let m = @Mut(1);
|
||||
do m.borrow_mut |_p| {
|
||||
do m.borrow_imm |_q| {
|
||||
// should not be permitted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub 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]
|
||||
pub 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]
|
||||
pub fn test_imm_in_const() {
|
||||
let m = @Mut(1);
|
||||
do m.borrow_const |p| {
|
||||
do m.borrow_imm |q| {
|
||||
assert!(*p == *q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub 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]
|
||||
pub 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| {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,6 @@ use core::run;
|
|||
use core::hashmap::linear::LinearMap;
|
||||
use core::task;
|
||||
use core::to_bytes;
|
||||
use core::mutable::Mut;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -168,7 +167,7 @@ impl<D:Decoder> Decodable<D> for WorkMap {
|
|||
struct Database {
|
||||
db_filename: Path,
|
||||
db_cache: LinearMap<~str, ~str>,
|
||||
mut db_dirty: bool
|
||||
db_dirty: bool
|
||||
}
|
||||
|
||||
pub impl Database {
|
||||
|
@ -210,8 +209,8 @@ pub impl Logger {
|
|||
}
|
||||
|
||||
struct Context {
|
||||
db: @Mut<Database>,
|
||||
logger: @Mut<Logger>,
|
||||
db: @mut Database,
|
||||
logger: @mut Logger,
|
||||
cfg: @json::Object,
|
||||
freshness: LinearMap<~str,@fn(&str,&str)->bool>
|
||||
}
|
||||
|
@ -228,7 +227,7 @@ struct Exec {
|
|||
}
|
||||
|
||||
struct Work<T> {
|
||||
prep: @Mut<Prep>,
|
||||
prep: @mut Prep,
|
||||
res: Option<Either<T,PortOne<(Exec,T)>>>
|
||||
}
|
||||
|
||||
|
@ -261,8 +260,8 @@ fn digest_file(path: &Path) -> ~str {
|
|||
|
||||
pub impl Context {
|
||||
|
||||
fn new(db: @Mut<Database>,
|
||||
lg: @Mut<Logger>,
|
||||
fn new(db: @mut Database,
|
||||
lg: @mut Logger,
|
||||
cfg: @json::Object) -> Context {
|
||||
Context {
|
||||
db: db,
|
||||
|
@ -277,19 +276,19 @@ pub impl Context {
|
|||
Decodable<json::Decoder>>( // FIXME(#5121)
|
||||
@self,
|
||||
fn_name:&str,
|
||||
blk: &fn(@Mut<Prep>)->Work<T>) -> Work<T> {
|
||||
let p = @Mut(Prep {
|
||||
blk: &fn(@mut Prep)->Work<T>) -> Work<T> {
|
||||
let p = @mut Prep {
|
||||
ctxt: self,
|
||||
fn_name: fn_name.to_owned(),
|
||||
declared_inputs: WorkMap::new()
|
||||
});
|
||||
};
|
||||
blk(p)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
trait TPrep {
|
||||
fn declare_input(&self, kind:&str, name:&str, val:&str);
|
||||
fn declare_input(&mut self, kind:&str, name:&str, val:&str);
|
||||
fn is_fresh(&self, cat:&str, kind:&str, name:&str, val:&str) -> bool;
|
||||
fn all_fresh(&self, cat:&str, map:&WorkMap) -> bool;
|
||||
fn exec<T:Owned +
|
||||
|
@ -298,30 +297,25 @@ trait TPrep {
|
|||
&self, blk: ~fn(&Exec) -> T) -> Work<T>;
|
||||
}
|
||||
|
||||
impl TPrep for @Mut<Prep> {
|
||||
fn declare_input(&self, kind:&str, name:&str, val:&str) {
|
||||
do self.borrow_mut |p| {
|
||||
p.declared_inputs.insert(WorkKey::new(kind, name),
|
||||
val.to_owned());
|
||||
}
|
||||
impl TPrep for Prep {
|
||||
fn declare_input(&mut self, kind:&str, name:&str, val:&str) {
|
||||
self.declared_inputs.insert(WorkKey::new(kind, name),
|
||||
val.to_owned());
|
||||
}
|
||||
|
||||
fn is_fresh(&self, cat: &str, kind: &str,
|
||||
name: &str, val: &str) -> bool {
|
||||
do self.borrow_imm |p| {
|
||||
let k = kind.to_owned();
|
||||
let f = (*p.ctxt.freshness.get(&k))(name, val);
|
||||
do p.ctxt.logger.borrow_imm |lg| {
|
||||
if f {
|
||||
lg.info(fmt!("%s %s:%s is fresh",
|
||||
cat, kind, name));
|
||||
} else {
|
||||
lg.info(fmt!("%s %s:%s is not fresh",
|
||||
cat, kind, name))
|
||||
}
|
||||
let k = kind.to_owned();
|
||||
let f = (*self.ctxt.freshness.get(&k))(name, val);
|
||||
let lg = self.ctxt.logger;
|
||||
if f {
|
||||
lg.info(fmt!("%s %s:%s is fresh",
|
||||
cat, kind, name));
|
||||
} else {
|
||||
lg.info(fmt!("%s %s:%s is not fresh",
|
||||
cat, kind, name))
|
||||
}
|
||||
f
|
||||
}
|
||||
f
|
||||
}
|
||||
|
||||
fn all_fresh(&self, cat: &str, map: &WorkMap) -> bool {
|
||||
|
@ -339,38 +333,34 @@ impl TPrep for @Mut<Prep> {
|
|||
&self, blk: ~fn(&Exec) -> T) -> Work<T> {
|
||||
let mut bo = Some(blk);
|
||||
|
||||
do self.borrow_imm |p| {
|
||||
let cached = do p.ctxt.db.borrow_mut |db| {
|
||||
db.prepare(p.fn_name, &p.declared_inputs)
|
||||
};
|
||||
let cached = self.ctxt.db.prepare(self.fn_name, &self.declared_inputs);
|
||||
|
||||
match cached {
|
||||
Some((ref disc_in, ref disc_out, ref res))
|
||||
if self.all_fresh("declared input",
|
||||
&p.declared_inputs) &&
|
||||
self.all_fresh("discovered input", disc_in) &&
|
||||
self.all_fresh("discovered output", disc_out) => {
|
||||
Work::new(*self, Left(json_decode(*res)))
|
||||
}
|
||||
|
||||
_ => {
|
||||
let (chan, port) = oneshot::init();
|
||||
let mut blk = None;
|
||||
blk <-> bo;
|
||||
let blk = blk.unwrap();
|
||||
let chan = Cell(chan);
|
||||
do task::spawn || {
|
||||
let exe = Exec {
|
||||
discovered_inputs: WorkMap::new(),
|
||||
discovered_outputs: WorkMap::new(),
|
||||
};
|
||||
let chan = chan.take();
|
||||
let v = blk(&exe);
|
||||
send_one(chan, (exe, v));
|
||||
}
|
||||
|
||||
Work::new(*self, Right(port))
|
||||
match cached {
|
||||
Some((ref disc_in, ref disc_out, ref res))
|
||||
if self.all_fresh("declared input",
|
||||
&self.declared_inputs) &&
|
||||
self.all_fresh("discovered input", disc_in) &&
|
||||
self.all_fresh("discovered output", disc_out) => {
|
||||
Work::new(@mut *self, Left(json_decode(*res)))
|
||||
}
|
||||
|
||||
_ => {
|
||||
let (chan, port) = oneshot::init();
|
||||
let mut blk = None;
|
||||
blk <-> bo;
|
||||
let blk = blk.unwrap();
|
||||
let chan = Cell(chan);
|
||||
|
||||
do task::spawn || {
|
||||
let exe = Exec {
|
||||
discovered_inputs: WorkMap::new(),
|
||||
discovered_outputs: WorkMap::new(),
|
||||
};
|
||||
let chan = chan.take();
|
||||
let v = blk(&exe);
|
||||
send_one(chan, (exe, v));
|
||||
}
|
||||
Work::new(@mut *self, Right(port))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -379,7 +369,7 @@ impl TPrep for @Mut<Prep> {
|
|||
pub impl<T:Owned +
|
||||
Encodable<json::Encoder> +
|
||||
Decodable<json::Decoder>> Work<T> { // FIXME(#5121)
|
||||
fn new(p: @Mut<Prep>, e: Either<T,PortOne<(Exec,T)>>) -> Work<T> {
|
||||
fn new(p: @mut Prep, e: Either<T,PortOne<(Exec,T)>>) -> Work<T> {
|
||||
Work { prep: p, res: Some(e) }
|
||||
}
|
||||
}
|
||||
|
@ -404,15 +394,13 @@ fn unwrap<T:Owned +
|
|||
|
||||
let s = json_encode(&v);
|
||||
|
||||
do ww.prep.borrow_imm |p| {
|
||||
do p.ctxt.db.borrow_mut |db| {
|
||||
db.cache(p.fn_name,
|
||||
&p.declared_inputs,
|
||||
&exe.discovered_inputs,
|
||||
&exe.discovered_outputs,
|
||||
s);
|
||||
}
|
||||
}
|
||||
let p = &*ww.prep;
|
||||
let db = p.ctxt.db;
|
||||
db.cache(p.fn_name,
|
||||
&p.declared_inputs,
|
||||
&exe.discovered_inputs,
|
||||
&exe.discovered_outputs,
|
||||
s);
|
||||
v
|
||||
}
|
||||
}
|
||||
|
@ -422,10 +410,10 @@ fn unwrap<T:Owned +
|
|||
fn test() {
|
||||
use core::io::WriterUtil;
|
||||
|
||||
let db = @Mut(Database { db_filename: Path("db.json"),
|
||||
let db = @mut Database { db_filename: Path("db.json"),
|
||||
db_cache: LinearMap::new(),
|
||||
db_dirty: false });
|
||||
let lg = @Mut(Logger { a: () });
|
||||
db_dirty: false };
|
||||
let lg = @mut Logger { a: () };
|
||||
let cfg = @LinearMap::new();
|
||||
let cx = @Context::new(db, lg, cfg);
|
||||
let w:Work<~str> = do cx.prep("test1") |prep| {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue