Skip to content

Commit

Permalink
Introduce special types for driving kind inference
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Jan 21, 2014
1 parent 28beb06 commit 6ca9ca8
Show file tree
Hide file tree
Showing 28 changed files with 335 additions and 163 deletions.
19 changes: 11 additions & 8 deletions src/libextra/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@
use sync;
use sync::{Mutex, RWLock};

use std::kinds::NotFreeze;
use std::borrow;
use std::cast;
use std::sync::arc::UnsafeArc;
use std::task;
use std::borrow;

/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling.
pub struct Condvar<'a> {
Expand Down Expand Up @@ -151,8 +152,10 @@ impl<T:Freeze + Send> Clone for Arc<T> {
struct MutexArcInner<T> { priv lock: Mutex, priv failed: bool, priv data: T }

/// An Arc with mutable data protected by a blocking mutex.
#[no_freeze]
pub struct MutexArc<T> { priv x: UnsafeArc<MutexArcInner<T>> }
pub struct MutexArc<T> {
priv x: UnsafeArc<MutexArcInner<T>>,
priv nf: NotFreeze,
}


impl<T:Send> Clone for MutexArc<T> {
Expand All @@ -161,7 +164,7 @@ impl<T:Send> Clone for MutexArc<T> {
fn clone(&self) -> MutexArc<T> {
// NB: Cloning the underlying mutex is not necessary. Its reference
// count would be exactly the same as the shared state's.
MutexArc { x: self.x.clone() }
MutexArc { x: self.x.clone(), nf: NotFreeze }
}
}

Expand All @@ -180,7 +183,7 @@ impl<T:Send> MutexArc<T> {
lock: Mutex::new_with_condvars(num_condvars),
failed: false, data: user_data
};
MutexArc { x: UnsafeArc::new(data) }
MutexArc { x: UnsafeArc::new(data), nf: NotFreeze }
}

/**
Expand Down Expand Up @@ -319,16 +322,16 @@ struct RWArcInner<T> { priv lock: RWLock, priv failed: bool, priv data: T }
*
* Unlike mutex_arcs, rw_arcs are safe, because they cannot be nested.
*/
#[no_freeze]
pub struct RWArc<T> {
priv x: UnsafeArc<RWArcInner<T>>,
priv nf: NotFreeze,
}

impl<T:Freeze + Send> Clone for RWArc<T> {
/// Duplicate a rwlock-protected Arc. See arc::clone for more details.
#[inline]
fn clone(&self) -> RWArc<T> {
RWArc { x: self.x.clone() }
RWArc { x: self.x.clone(), nf: NotFreeze }
}

}
Expand All @@ -348,7 +351,7 @@ impl<T:Freeze + Send> RWArc<T> {
lock: RWLock::new_with_condvars(num_condvars),
failed: false, data: user_data
};
RWArc { x: UnsafeArc::new(data), }
RWArc { x: UnsafeArc::new(data), nf: NotFreeze }
}

/**
Expand Down
1 change: 0 additions & 1 deletion src/libextra/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ struct Chunk {
// different chunks than objects without destructors. This reduces
// overhead when initializing plain-old-data and means we don't need
// to waste time running the destructors of POD.
#[no_freeze]
pub struct Arena {
// The head is separated out from the list as a unbenchmarked
// microoptimization, to avoid needing to case on the list to
Expand Down
20 changes: 10 additions & 10 deletions src/libextra/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@

use std::borrow;
use std::comm;
use std::unstable::sync::Exclusive;
use std::kinds::NotPod;
use std::sync::arc::UnsafeArc;
use std::sync::atomics;
use std::unstable::finally::Finally;
use std::unstable::sync::Exclusive;
use std::util;
use std::util::NonCopyable;

/****************************************************************************
* Internals
Expand Down Expand Up @@ -179,7 +179,7 @@ pub struct Condvar<'a> {
// See the comment in write_cond for more detail.
priv order: ReacquireOrderLock<'a>,
// Make sure condvars are non-copyable.
priv token: util::NonCopyable,
priv token: NotPod,
}

impl<'a> Condvar<'a> {
Expand Down Expand Up @@ -325,7 +325,7 @@ impl Sem<~[WaitQueue]> {
blk(&Condvar {
sem: self,
order: Nothing,
token: NonCopyable
token: NotPod
})
})
}
Expand Down Expand Up @@ -565,7 +565,7 @@ impl RWLock {
(&self.order_lock).release();
let opt_lock = Just(&self.order_lock);
blk(&Condvar { sem: cond.sem, order: opt_lock,
token: NonCopyable })
token: NotPod })
})
}

Expand Down Expand Up @@ -600,7 +600,7 @@ impl RWLock {
(&self.access_lock).acquire();
(&self.order_lock).release();
(|| {
blk(RWLockWriteMode { lock: self, token: NonCopyable })
blk(RWLockWriteMode { lock: self, token: NotPod })
}).finally(|| {
let writer_or_last_reader;
// Check if we're releasing from read mode or from write mode.
Expand Down Expand Up @@ -653,16 +653,16 @@ impl RWLock {
(&self.access_lock).release();
}
}
RWLockReadMode { lock: token.lock, token: NonCopyable }
RWLockReadMode { lock: token.lock, token: NotPod }
}
}

/// The "write permission" token used for rwlock.write_downgrade().
pub struct RWLockWriteMode<'a> { priv lock: &'a RWLock, priv token: NonCopyable }
pub struct RWLockWriteMode<'a> { priv lock: &'a RWLock, priv token: NotPod }
/// The "read permission" token used for rwlock.write_downgrade().
pub struct RWLockReadMode<'a> { priv lock: &'a RWLock,
priv token: NonCopyable }
priv token: NotPod }

impl<'a> RWLockWriteMode<'a> {
/// Access the pre-downgrade rwlock in write mode.
Expand All @@ -673,7 +673,7 @@ impl<'a> RWLockWriteMode<'a> {
// access lock. See comment in RWLock::write_cond for why.
blk(&Condvar { sem: &self.lock.access_lock,
order: Just(&self.lock.order_lock),
token: NonCopyable })
token: NotPod })
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ lets_do_this! {
SizedTraitLangItem, "sized", sized_trait;
PodTraitLangItem, "pod", pod_trait;

NotPodLangItem, "not_pod", notpod_struct;
NotFreezeLangItem, "not_freeze", notfreeze_struct;
NotSend, "not_send", notsend_struct;

DropTraitLangItem, "drop", drop_trait;

AddTraitLangItem, "add", add_trait;
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -923,8 +923,8 @@ static other_attrs: &'static [&'static str] = &[
"thread_local", // for statics
"allow", "deny", "forbid", "warn", // lint options
"deprecated", "experimental", "unstable", "stable", "locked", "frozen", //item stability
"crate_map", "cfg", "doc", "export_name", "link_section", "no_freeze",
"no_mangle", "no_send", "static_assert", "unsafe_no_drop_flag", "packed",
"crate_map", "cfg", "doc", "export_name", "link_section",
"no_mangle", "static_assert", "unsafe_no_drop_flag", "packed",
"simd", "repr", "deriving", "unsafe_destructor", "link", "phase",
"macro_export",

Expand Down
31 changes: 15 additions & 16 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2062,13 +2062,21 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
}

ty_struct(did, ref substs) => {
let flds = struct_fields(cx, did, substs);
let mut res =
TypeContents::union(flds, |f| tc_mt(cx, f.mt, cache));
if ty::has_dtor(cx, did) {
res = res | TC::OwnsDtor;
if Some(did) == cx.lang_items.notfreeze_struct() {
TC::ReachesMutable
} else if Some(did) == cx.lang_items.notsend_struct() {
TC::ReachesNonsendAnnot
} else if Some(did) == cx.lang_items.notpod_struct() {
TC::OwnsOwned
} else {
let flds = struct_fields(cx, did, substs);
let mut res =
TypeContents::union(flds, |f| tc_mt(cx, f.mt, cache));
if ty::has_dtor(cx, did) {
res = res | TC::OwnsDtor;
}
res
}
apply_attributes(cx, did, res)
}

ty_tup(ref tys) => {
Expand All @@ -2083,7 +2091,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
tc_ty(cx, *arg_ty, cache)
})
});
apply_attributes(cx, did, res)
res
}

ty_param(p) => {
Expand Down Expand Up @@ -2145,15 +2153,6 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
mc | tc_ty(cx, mt.ty, cache)
}

fn apply_attributes(cx: ctxt,
did: ast::DefId,
tc: TypeContents)
-> TypeContents {
tc |
TC::ReachesMutable.when(has_attr(cx, did, "no_freeze")) |
TC::ReachesNonsendAnnot.when(has_attr(cx, did, "no_send"))
}

fn borrowed_contents(region: ty::Region,
mutbl: ast::Mutability)
-> TypeContents {
Expand Down
13 changes: 8 additions & 5 deletions src/libstd/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,23 @@
//! Types dealing with dynamic mutability
use prelude::*;
use kinds::NotFreeze;
use cast;
use util::NonCopyable;
use kinds::NotPod;

/// A mutable memory location that admits only `Pod` data.
#[no_freeze]
#[deriving(Clone)]
pub struct Cell<T> {
priv value: T,
priv nf: NotFreeze,
}

impl<T: ::kinds::Pod> Cell<T> {
/// Creates a new `Cell` containing the given value.
pub fn new(value: T) -> Cell<T> {
Cell {
value: value,
nf: NotFreeze,
}
}

Expand All @@ -45,11 +47,11 @@ impl<T: ::kinds::Pod> Cell<T> {
}

/// A mutable memory location with dynamically checked borrow rules
#[no_freeze]
pub struct RefCell<T> {
priv value: T,
priv borrow: BorrowFlag,
priv nc: NonCopyable
priv nc: NotPod,
priv nf: NotFreeze,
}

// Values [1, MAX-1] represent the number of `Ref` active
Expand All @@ -64,7 +66,8 @@ impl<T> RefCell<T> {
RefCell {
value: value,
borrow: UNUSED,
nc: NonCopyable
nc: NotPod,
nf: NotFreeze,
}
}

Expand Down
15 changes: 7 additions & 8 deletions src/libstd/comm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ use clone::Clone;
use container::Container;
use int;
use iter::Iterator;
use kinds::Send;
use kinds::{Send, NotFreeze};
use ops::Drop;
use option::{Option, Some, None};
use result::{Ok, Err};
Expand Down Expand Up @@ -297,9 +297,9 @@ impl<T: Send> Consumer<T>{

/// The receiving-half of Rust's channel type. This half can only be owned by
/// one task
#[no_freeze] // can't share ports in an arc
pub struct Port<T> {
priv queue: Consumer<T>,
priv nf: NotFreeze,
}

/// An iterator over messages received on a port, this iterator will block
Expand All @@ -311,17 +311,16 @@ pub struct Messages<'a, T> {

/// The sending-half of Rust's channel type. This half can only be owned by one
/// task
#[no_freeze] // can't share chans in an arc
pub struct Chan<T> {
priv queue: spsc::Producer<T, Packet>,
priv nf: NotFreeze,
}

/// The sending-half of Rust's channel type. This half can be shared among many
/// tasks by creating copies of itself through the `clone` method.
#[no_freeze] // technically this implementation is shareable, but it shouldn't
// be required to be shareable in an arc
pub struct SharedChan<T> {
priv queue: mpsc::Producer<T, Packet>,
priv nf: NotFreeze,
}

/// This enumeration is the list of the possible reasons that try_recv could not
Expand Down Expand Up @@ -545,7 +544,7 @@ impl<T: Send> Chan<T> {
// maximum buffer size
let (c, p) = spsc::queue(128, Packet::new());
let c = SPSC(c);
(Port { queue: c }, Chan { queue: p })
(Port { queue: c, nf: NotFreeze }, Chan { queue: p, nf: NotFreeze })
}

/// Sends a value along this channel to be received by the corresponding
Expand Down Expand Up @@ -640,7 +639,7 @@ impl<T: Send> SharedChan<T> {
pub fn new() -> (Port<T>, SharedChan<T>) {
let (c, p) = mpsc::queue(Packet::new());
let c = MPSC(c);
(Port { queue: c }, SharedChan { queue: p })
(Port { queue: c, nf: NotFreeze }, SharedChan { queue: p, nf: NotFreeze })
}

/// Equivalent method to `send` on the `Chan` type (using the same
Expand Down Expand Up @@ -706,7 +705,7 @@ impl<T: Send> SharedChan<T> {
impl<T: Send> Clone for SharedChan<T> {
fn clone(&self) -> SharedChan<T> {
unsafe { (*self.queue.packet()).channels.fetch_add(1, SeqCst); }
SharedChan { queue: self.queue.clone() }
SharedChan { queue: self.queue.clone(), nf: NotFreeze }
}
}

Expand Down
8 changes: 5 additions & 3 deletions src/libstd/comm/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
use cast;
use comm;
use iter::Iterator;
use kinds::Send;
use kinds::{Send, NotFreeze, NotSend};
use ops::Drop;
use option::{Some, None, Option};
use ptr::RawPtr;
Expand Down Expand Up @@ -77,12 +77,12 @@ macro_rules! select {

/// The "port set" of the select interface. This structure is used to manage a
/// set of ports which are being selected over.
#[no_freeze]
#[no_send]
pub struct Select {
priv head: *mut Packet,
priv tail: *mut Packet,
priv next_id: uint,
priv nf: NotFreeze,
priv ns: NotSend,
}

/// A handle to a port which is currently a member of a `Select` set of ports.
Expand All @@ -107,6 +107,8 @@ impl Select {
head: 0 as *mut Packet,
tail: 0 as *mut Packet,
next_id: 1,
nf: NotFreeze,
ns: NotSend,
}
}

Expand Down
Loading

0 comments on commit 6ca9ca8

Please sign in to comment.