diff --git a/mk/crates.mk b/mk/crates.mk index e02e4fb8706e8..ea573b9db8d21 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -49,25 +49,27 @@ # automatically generated for all stage/host/target combinations. ################################################################################ -TARGET_CRATES := std extra green rustuv native flate arena glob term semver uuid +TARGET_CRATES := std extra green rustuv native flate arena glob term semver uuid serialize sync HOST_CRATES := syntax rustc rustdoc CRATES := $(TARGET_CRATES) $(HOST_CRATES) TOOLS := compiletest rustdoc rustc DEPS_std := native:rustrt -DEPS_extra := std term +DEPS_extra := std serialize sync term DEPS_green := std DEPS_rustuv := std native:uv native:uv_support DEPS_native := std -DEPS_syntax := std extra term -DEPS_rustc := syntax native:rustllvm flate arena -DEPS_rustdoc := rustc native:sundown +DEPS_syntax := std extra term serialize +DEPS_rustc := syntax native:rustllvm flate arena serialize sync +DEPS_rustdoc := rustc native:sundown serialize sync DEPS_flate := std native:miniz DEPS_arena := std extra DEPS_glob := std +DEPS_serialize := std DEPS_term := std DEPS_semver := std -DEPS_uuid := std extra +DEPS_uuid := std serialize +DEPS_sync := std TOOL_DEPS_compiletest := extra green rustuv TOOL_DEPS_rustdoc := rustdoc green rustuv diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md index c3bdbe3a3ee89..387f481025df7 100644 --- a/src/doc/guide-tasks.md +++ b/src/doc/guide-tasks.md @@ -39,7 +39,7 @@ data through the global _exchange heap_. While Rust's type system provides the building blocks needed for safe and efficient tasks, all of the task functionality itself is implemented -in the standard and extra libraries, which are still under development +in the standard and sync libraries, which are still under development and do not always present a consistent or complete interface. For your reference, these are the standard modules involved in Rust @@ -47,18 +47,43 @@ concurrency at this writing: * [`std::task`] - All code relating to tasks and task scheduling, * [`std::comm`] - The message passing interface, -* [`extra::comm`] - Additional messaging types based on `std::comm`, -* [`extra::sync`] - More exotic synchronization tools, including locks, -* [`extra::arc`] - The Arc (atomically reference counted) type, - for safely sharing immutable data, -* [`extra::future`] - A type representing values that may be computed concurrently and retrieved at a later time. +* [`sync::DuplexStream`] - An extension of `pipes::stream` that allows both sending and receiving, +* [`sync::SyncChan`] - An extension of `pipes::stream` that provides synchronous message sending, +* [`sync::SyncPort`] - An extension of `pipes::stream` that acknowledges each message received, +* [`sync::rendezvous`] - Creates a stream whose channel, upon sending a message, blocks until the + message is received. +* [`sync::Arc`] - The Arc (atomically reference counted) type, for safely sharing immutable data, +* [`sync::RWArc`] - A dual-mode Arc protected by a reader-writer lock, +* [`sync::MutexArc`] - An Arc with mutable data protected by a blocking mutex, +* [`sync::Semaphore`] - A counting, blocking, bounded-waiting semaphore, +* [`sync::Mutex`] - A blocking, bounded-waiting, mutual exclusion lock with an associated + FIFO condition variable, +* [`sync::RWLock`] - A blocking, no-starvation, reader-writer lock with an associated condvar, +* [`sync::Barrier`] - A barrier enables multiple tasks to synchronize the beginning + of some computation, +* [`sync::TaskPool`] - A task pool abstraction, +* [`sync::Future`] - A type encapsulating the result of a computation which may not be complete, +* [`sync::one`] - A "once initialization" primitive +* [`sync::mutex`] - A proper mutex implementation regardless of the "flavor of task" which is + acquiring the lock. [`std::task`]: std/task/index.html [`std::comm`]: std/comm/index.html -[`extra::comm`]: extra/comm/index.html -[`extra::sync`]: extra/sync/index.html -[`extra::arc`]: extra/arc/index.html -[`extra::future`]: extra/future/index.html +[`sync::DuplexStream`]: sync/struct.DuplexStream.html +[`sync::SyncChan`]: sync/struct.SyncChan.html +[`sync::SyncPort`]: sync/struct.SyncPort.html +[`sync::rendezvous`]: sync/fn.rendezvous.html +[`sync::Arc`]: sync/struct.Arc.html +[`sync::RWArc`]: sync/struct.RWArc.html +[`sync::MutexArc`]: sync/struct.MutexArc.html +[`sync::Semaphore`]: sync/struct.Semaphore.html +[`sync::Mutex`]: sync/struct.Mutex.html +[`sync::RWLock`]: sync/struct.RWLock.html +[`sync::Barrier`]: sync/struct.Barrier.html +[`sync::TaskPool`]: sync/struct.TaskPool.html +[`sync::Future`]: sync/struct.Future.html +[`sync::one`]: sync/one/index.html +[`sync::mutex`]: sync/mutex/index.html # Basics @@ -254,21 +279,25 @@ let result = ports.iter().fold(0, |accum, port| accum + port.recv() ); ~~~ ## Backgrounding computations: Futures -With `extra::future`, rust has a mechanism for requesting a computation and getting the result +With `sync::Future`, rust has a mechanism for requesting a computation and getting the result later. The basic example below illustrates this. ~~~ +# extern mod sync; + +# fn main() { # fn make_a_sandwich() {}; fn fib(n: u64) -> u64 { // lengthy computation returning an uint 12586269025 } -let mut delayed_fib = extra::future::Future::spawn(proc() fib(50)); +let mut delayed_fib = sync::Future::spawn(proc() fib(50)); make_a_sandwich(); println!("fib(50) = {:?}", delayed_fib.get()) +# } ~~~ The call to `future::spawn` returns immediately a `future` object regardless of how long it @@ -281,6 +310,7 @@ Here is another example showing how futures allow you to background computations be distributed on the available cores. ~~~ +# extern mod sync; # use std::vec; fn partial_sum(start: uint) -> f64 { let mut local_sum = 0f64; @@ -291,7 +321,7 @@ fn partial_sum(start: uint) -> f64 { } fn main() { - let mut futures = vec::from_fn(1000, |ind| extra::future::Future::spawn( proc() { partial_sum(ind) })); + let mut futures = vec::from_fn(1000, |ind| sync::Future::spawn( proc() { partial_sum(ind) })); let mut final_res = 0f64; for ft in futures.mut_iter() { @@ -309,16 +339,17 @@ add up to a significant amount of wasted memory and would require copying the sa necessary. To tackle this issue, one can use an Atomically Reference Counted wrapper (`Arc`) as implemented in -the `extra` library of Rust. With an Arc, the data will no longer be copied for each task. The Arc +the `sync` library of Rust. With an Arc, the data will no longer be copied for each task. The Arc acts as a reference to the shared data and only this reference is shared and cloned. Here is a small example showing how to use Arcs. We wish to run concurrently several computations on a single large vector of floats. Each task needs the full vector to perform its duty. ~~~ +# extern mod sync; # use std::vec; # use std::rand; -use extra::arc::Arc; +use sync::Arc; fn pnorm(nums: &~[f64], p: uint) -> f64 { nums.iter().fold(0.0, |a,b| a+(*b).powf(&(p as f64)) ).powf(&(1.0 / (p as f64))) @@ -348,23 +379,29 @@ at the power given as argument and takes the inverse power of this value). The A created by the line ~~~ -# use extra::arc::Arc; +# extern mod sync; +# use sync::Arc; # use std::vec; # use std::rand; +# fn main() { # let numbers = vec::from_fn(1000000, |_| rand::random::()); let numbers_arc=Arc::new(numbers); +# } ~~~ and a clone of it is sent to each task ~~~ -# use extra::arc::Arc; +# extern mod sync; +# use sync::Arc; # use std::vec; # use std::rand; +# fn main() { # let numbers=vec::from_fn(1000000, |_| rand::random::()); # let numbers_arc = Arc::new(numbers); # let (port, chan) = Chan::new(); chan.send(numbers_arc.clone()); +# } ~~~ copying only the wrapper and not its contents. @@ -372,15 +409,18 @@ copying only the wrapper and not its contents. Each task recovers the underlying data by ~~~ -# use extra::arc::Arc; +# extern mod sync; +# use sync::Arc; # use std::vec; # use std::rand; +# fn main() { # let numbers=vec::from_fn(1000000, |_| rand::random::()); # let numbers_arc=Arc::new(numbers); # let (port, chan) = Chan::new(); # chan.send(numbers_arc.clone()); # let local_arc : Arc<~[f64]> = port.recv(); let task_numbers = local_arc.get(); +# } ~~~ and can use it as if it were local. @@ -450,7 +490,7 @@ proceed). A very common thing to do is to spawn a child task where the parent and child both need to exchange messages with each other. The -function `extra::comm::DuplexStream()` supports this pattern. We'll +function `sync::comm::DuplexStream()` supports this pattern. We'll look briefly at how to use it. To see how `DuplexStream()` works, we will create a child task @@ -458,17 +498,19 @@ that repeatedly receives a `uint` message, converts it to a string, and sends the string in response. The child terminates when it receives `0`. Here is the function that implements the child task: -~~~{.ignore .linked-failure} -# use extra::comm::DuplexStream; -# use std::uint; -fn stringifier(channel: &DuplexStream<~str, uint>) { - let mut value: uint; - loop { - value = channel.recv(); - channel.send(uint::to_str(value)); - if value == 0 { break; } +~~~ +# extern mod sync; +# fn main() { +# use sync::DuplexStream; + fn stringifier(channel: &DuplexStream<~str, uint>) { + let mut value: uint; + loop { + value = channel.recv(); + channel.send(value.to_str()); + if value == 0 { break; } + } } -} +# } ~~~~ The implementation of `DuplexStream` supports both sending and @@ -481,15 +523,15 @@ response itself is simply the stringified version of the received value, Here is the code for the parent task: -~~~{.ignore .linked-failure} +~~~ +# extern mod sync; # use std::task::spawn; -# use std::uint; -# use extra::comm::DuplexStream; +# use sync::DuplexStream; # fn stringifier(channel: &DuplexStream<~str, uint>) { # let mut value: uint; # loop { # value = channel.recv(); -# channel.send(uint::to_str(value)); +# channel.send(value.to_str()); # if value == 0u { break; } # } # } diff --git a/src/doc/index.md b/src/doc/index.md index 9915d67bfcad3..54b8b484693a9 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -41,8 +41,10 @@ li {list-style-type: none; } * [The `flate` compression library](flate/index.html) * [The `glob` file path matching library](glob/index.html) * [The `semver` version collation library](semver/index.html) +* [The `serialize` value encoding/decoding library](serialize/index.html) +* [The `sync` library for concurrency-enabled mechanisms and primitives](sync/index.html) * [The `term` terminal-handling library](term/index.html) -* [The UUID library](uuid/index.html) +* [The `uuid` 128-bit universally unique identifier library](uuid/index.html) # Tooling diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index a7696b4540560..75a5840a1ef69 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -509,7 +509,7 @@ fn angle(vector: (f64, f64)) -> f64 { let pi = f64::consts::PI; match vector { (0.0, y) if y < 0.0 => 1.5 * pi, - (0.0, y) => 0.5 * pi, + (0.0, _) => 0.5 * pi, (x, y) => atan(y / x) } } @@ -519,7 +519,9 @@ A variable name in a pattern matches any value, *and* binds that name to the value of the matched value inside of the arm's action. Thus, `(0.0, y)` matches any tuple whose first element is zero, and binds `y` to the second element. `(x, y)` matches any two-element tuple, and binds both -elements to variables. +elements to variables. `(0.0,_)` matches any tuple whose first element is zero +and does not bind anything to the second element. + A subpattern can also be bound to a variable, using `variable @ pattern`. For example: diff --git a/src/etc/licenseck.py b/src/etc/licenseck.py index afbf34d07535d..e214a40e3d134 100644 --- a/src/etc/licenseck.py +++ b/src/etc/licenseck.py @@ -41,7 +41,7 @@ "libstd/sync/mpsc_queue.rs", # BSD "libstd/sync/spsc_queue.rs", # BSD "libstd/sync/mpmc_bounded_queue.rs", # BSD - "libextra/sync/mpsc_intrusive.rs", # BSD + "libsync/sync/mpsc_intrusive.rs", # BSD ] def check_license(name, contents): diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index ee80fa1c4c46e..88df73845d03d 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -30,6 +30,8 @@ use std::iter; use container::Deque; +use serialize::{Encodable, Decodable, Encoder, Decoder}; + /// A doubly-linked list. pub struct DList { priv length: uint, @@ -628,6 +630,31 @@ impl Clone for DList { } } +impl< + S: Encoder, + T: Encodable +> Encodable for DList { + fn encode(&self, s: &mut S) { + s.emit_seq(self.len(), |s| { + for (i, e) in self.iter().enumerate() { + s.emit_seq_elt(i, |s| e.encode(s)); + } + }) + } +} + +impl> Decodable for DList { + fn decode(d: &mut D) -> DList { + let mut list = DList::new(); + d.read_seq(|d, len| { + for i in range(0u, len) { + list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))); + } + }); + list + } +} + #[cfg(test)] mod tests { use container::Deque; diff --git a/src/libextra/json.rs b/src/libextra/json.rs index ef8e0999521b8..8b082bf3056d6 100644 --- a/src/libextra/json.rs +++ b/src/libextra/json.rs @@ -51,17 +51,18 @@ A simple JSON document encoding a person, his/her age, address and phone numbers Rust provides a mechanism for low boilerplate encoding & decoding of values to and from JSON via the serialization API. -To be able to encode a piece of data, it must implement the `extra::serialize::Encodable` trait. -To be able to decode a piece of data, it must implement the `extra::serialize::Decodable` trait. +To be able to encode a piece of data, it must implement the `serialize::Encodable` trait. +To be able to decode a piece of data, it must implement the `serialize::Decodable` trait. The Rust compiler provides an annotation to automatically generate the code for these traits: `#[deriving(Decodable, Encodable)]` To encode using Encodable : ```rust +extern mod serialize; use extra::json; use std::io; -use extra::serialize::Encodable; +use serialize::Encodable; #[deriving(Encodable)] pub struct TestStruct { @@ -125,7 +126,8 @@ fn main() { To decode a json string using `Decodable` trait : ```rust -use extra::serialize::Decodable; +extern mod serialize; +use serialize::Decodable; #[deriving(Decodable)] pub struct MyStruct { @@ -150,8 +152,9 @@ Create a struct called TestStruct1 and serialize and deserialize it to and from using the serialization API, using the derived serialization code. ```rust +extern mod serialize; use extra::json; -use extra::serialize::{Encodable, Decodable}; +use serialize::{Encodable, Decodable}; #[deriving(Decodable, Encodable)] //generate Decodable, Encodable impl. pub struct TestStruct1 { @@ -181,9 +184,10 @@ This example use the ToJson impl to unserialize the json string. Example of `ToJson` trait implementation for TestStruct1. ```rust +extern mod serialize; use extra::json; use extra::json::ToJson; -use extra::serialize::{Encodable, Decodable}; +use serialize::{Encodable, Decodable}; use extra::treemap::TreeMap; #[deriving(Decodable, Encodable)] // generate Decodable, Encodable impl. @@ -312,7 +316,7 @@ impl<'a> Encoder<'a> { } /// Encode the specified struct into a json [u8] - pub fn buffer_encode>>(to_encode_object: &T) -> ~[u8] { + pub fn buffer_encode>>(to_encode_object: &T) -> ~[u8] { //Serialize the object in a string using a writer let mut m = MemWriter::new(); { @@ -323,7 +327,7 @@ impl<'a> Encoder<'a> { } /// Encode the specified struct into a json str - pub fn str_encode>>(to_encode_object: &T) -> ~str { + pub fn str_encode>>(to_encode_object: &T) -> ~str { let buff:~[u8] = Encoder::buffer_encode(to_encode_object); str::from_utf8_owned(buff).unwrap() } @@ -684,7 +688,7 @@ impl serialize::Encodable for Json { } } -impl Json{ +impl Json { /// Encodes a json value into a io::writer. Uses a single line. pub fn to_writer(&self, wr: &mut io::Writer) -> io::IoResult<()> { let mut encoder = Encoder::new(wr); diff --git a/src/libextra/lib.rs b/src/libextra/lib.rs index d198fd44450c4..37b4d3cc524be 100644 --- a/src/libextra/lib.rs +++ b/src/libextra/lib.rs @@ -34,17 +34,27 @@ Rust extras are part of the standard Rust distribution. #[deny(non_camel_case_types)]; #[deny(missing_doc)]; -// Utility modules +extern mod sync; +#[cfg(not(stage0))] +extern mod serialize; + +#[cfg(stage0)] +pub mod serialize { + #[allow(missing_doc)]; + // Temp re-export until after a snapshot + extern mod serialize = "serialize"; + pub use self::serialize::{Encoder, Decoder, Encodable, Decodable, + EncoderHelpers, DecoderHelpers}; +} -pub mod c_vec; +#[cfg(stage0)] +macro_rules! if_ok ( + ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) }) +) -// Concurrency +// Utility modules -pub mod sync; -pub mod arc; -pub mod comm; -pub mod future; -pub mod task_pool; +pub mod c_vec; // Collections @@ -63,7 +73,6 @@ pub mod lru_cache; // And ... other stuff pub mod url; -pub mod ebml; pub mod getopts; pub mod json; pub mod tempfile; @@ -86,7 +95,6 @@ mod unicode; // Compiler support modules pub mod test; -pub mod serialize; // A curious inner-module that's not exported that contains the binding // 'extra' so that macro-expanded references to extra::serialize and such diff --git a/src/libextra/ringbuf.rs b/src/libextra/ringbuf.rs index 4da35942935f1..17631f5bdff01 100644 --- a/src/libextra/ringbuf.rs +++ b/src/libextra/ringbuf.rs @@ -19,6 +19,8 @@ use std::iter::{Rev, RandomAccessIterator}; use container::Deque; +use serialize::{Encodable, Decodable, Encoder, Decoder}; + static INITIAL_CAPACITY: uint = 8u; // 2^3 static MINIMUM_CAPACITY: uint = 2u; @@ -402,6 +404,31 @@ impl Extendable for RingBuf { } } +impl< + S: Encoder, + T: Encodable +> Encodable for RingBuf { + fn encode(&self, s: &mut S) { + s.emit_seq(self.len(), |s| { + for (i, e) in self.iter().enumerate() { + s.emit_seq_elt(i, |s| e.encode(s)); + } + }) + } +} + +impl> Decodable for RingBuf { + fn decode(d: &mut D) -> RingBuf { + let mut deque = RingBuf::new(); + d.read_seq(|d, len| { + for i in range(0u, len) { + deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))); + } + }); + deque + } +} + #[cfg(test)] mod tests { use container::Deque; diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs index 6605ea00c4413..449e72dd0ec81 100644 --- a/src/libextra/treemap.rs +++ b/src/libextra/treemap.rs @@ -17,6 +17,8 @@ use std::iter::{Peekable}; use std::cmp::Ordering; use std::ptr; +use serialize::{Encodable, Decodable, Encoder, Decoder}; + // This is implemented as an AA tree, which is a simplified variation of // a red-black tree where red (horizontal) nodes can only be added // as a right child. The time complexity is the same, and re-balancing @@ -1004,6 +1006,71 @@ impl Extendable for TreeSet { } } +impl< + E: Encoder, + K: Encodable + Eq + TotalOrd, + V: Encodable + Eq +> Encodable for TreeMap { + fn encode(&self, e: &mut E) { + e.emit_map(self.len(), |e| { + let mut i = 0; + for (key, val) in self.iter() { + e.emit_map_elt_key(i, |e| key.encode(e)); + e.emit_map_elt_val(i, |e| val.encode(e)); + i += 1; + } + }) + } +} + +impl< + D: Decoder, + K: Decodable + Eq + TotalOrd, + V: Decodable + Eq +> Decodable for TreeMap { + fn decode(d: &mut D) -> TreeMap { + d.read_map(|d, len| { + let mut map = TreeMap::new(); + for i in range(0u, len) { + let key = d.read_map_elt_key(i, |d| Decodable::decode(d)); + let val = d.read_map_elt_val(i, |d| Decodable::decode(d)); + map.insert(key, val); + } + map + }) + } +} + +impl< + S: Encoder, + T: Encodable + Eq + TotalOrd +> Encodable for TreeSet { + fn encode(&self, s: &mut S) { + s.emit_seq(self.len(), |s| { + let mut i = 0; + for e in self.iter() { + s.emit_seq_elt(i, |s| e.encode(s)); + i += 1; + } + }) + } +} + +impl< + D: Decoder, + T: Decodable + Eq + TotalOrd +> Decodable for TreeSet { + fn decode(d: &mut D) -> TreeSet { + d.read_seq(|d, len| { + let mut set = TreeSet::new(); + for i in range(0u, len) { + set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))); + } + set + }) + } +} + #[cfg(test)] mod test_treemap { diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs index 4d8e7e50dcfd5..d16edb7aa1e79 100644 --- a/src/libextra/workcache.rs +++ b/src/libextra/workcache.rs @@ -13,7 +13,7 @@ use json; use json::ToJson; use serialize::{Encoder, Encodable, Decoder, Decodable}; -use arc::{Arc,RWArc}; +use sync::{Arc,RWArc}; use treemap::TreeMap; use std::str; use std::io; diff --git a/src/libnative/io/file.rs b/src/libnative/io/file.rs index cc5b0770d4d20..25fb2809e764a 100644 --- a/src/libnative/io/file.rs +++ b/src/libnative/io/file.rs @@ -10,6 +10,7 @@ //! Blocking posix-based file I/O +use std::sync::arc::UnsafeArc; use std::c_str::CString; use std::io::IoError; use std::io; @@ -55,9 +56,13 @@ pub fn keep_going(data: &[u8], f: |*u8, uint| -> i64) -> i64 { pub type fd_t = libc::c_int; +struct Inner { + fd: fd_t, + close_on_drop: bool, +} + pub struct FileDesc { - priv fd: fd_t, - priv close_on_drop: bool, + priv inner: UnsafeArc } impl FileDesc { @@ -70,7 +75,10 @@ impl FileDesc { /// Note that all I/O operations done on this object will be *blocking*, but /// they do not require the runtime to be active. pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc { - FileDesc { fd: fd, close_on_drop: close_on_drop } + FileDesc { inner: UnsafeArc::new(Inner { + fd: fd, + close_on_drop: close_on_drop + }) } } // FIXME(#10465) these functions should not be public, but anything in @@ -80,7 +88,7 @@ impl FileDesc { #[cfg(windows)] type rlen = libc::c_uint; #[cfg(not(windows))] type rlen = libc::size_t; let ret = retry(|| unsafe { - libc::read(self.fd, + libc::read(self.fd(), buf.as_ptr() as *mut libc::c_void, buf.len() as rlen) as libc::c_int }); @@ -97,7 +105,7 @@ impl FileDesc { #[cfg(not(windows))] type wlen = libc::size_t; let ret = keep_going(buf, |buf, len| { unsafe { - libc::write(self.fd, buf as *libc::c_void, len as wlen) as i64 + libc::write(self.fd(), buf as *libc::c_void, len as wlen) as i64 } }); if ret < 0 { @@ -107,7 +115,11 @@ impl FileDesc { } } - pub fn fd(&self) -> fd_t { self.fd } + pub fn fd(&self) -> fd_t { + // This unsafety is fine because we're just reading off the file + // descriptor, no one is modifying this. + unsafe { (*self.inner.get()).fd } + } } impl io::Reader for FileDesc { @@ -130,7 +142,7 @@ impl rtio::RtioFileStream for FileDesc { self.inner_write(buf) } fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result { - return os_pread(self.fd, buf.as_ptr(), buf.len(), offset); + return os_pread(self.fd(), buf.as_ptr(), buf.len(), offset); #[cfg(windows)] fn os_pread(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult { @@ -162,7 +174,7 @@ impl rtio::RtioFileStream for FileDesc { } } fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError> { - return os_pwrite(self.fd, buf.as_ptr(), buf.len(), offset); + return os_pwrite(self.fd(), buf.as_ptr(), buf.len(), offset); #[cfg(windows)] fn os_pwrite(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<()> { @@ -197,7 +209,7 @@ impl rtio::RtioFileStream for FileDesc { io::SeekCur => libc::FILE_CURRENT, }; unsafe { - let handle = libc::get_osfhandle(self.fd) as libc::HANDLE; + let handle = libc::get_osfhandle(self.fd()) as libc::HANDLE; let mut newpos = 0; match libc::SetFilePointerEx(handle, pos, &mut newpos, whence) { 0 => Err(super::last_error()), @@ -212,7 +224,7 @@ impl rtio::RtioFileStream for FileDesc { io::SeekEnd => libc::SEEK_END, io::SeekCur => libc::SEEK_CUR, }; - let n = unsafe { libc::lseek(self.fd, pos as libc::off_t, whence) }; + let n = unsafe { libc::lseek(self.fd(), pos as libc::off_t, whence) }; if n < 0 { Err(super::last_error()) } else { @@ -220,7 +232,7 @@ impl rtio::RtioFileStream for FileDesc { } } fn tell(&self) -> Result { - let n = unsafe { libc::lseek(self.fd, 0, libc::SEEK_CUR) }; + let n = unsafe { libc::lseek(self.fd(), 0, libc::SEEK_CUR) }; if n < 0 { Err(super::last_error()) } else { @@ -228,7 +240,7 @@ impl rtio::RtioFileStream for FileDesc { } } fn fsync(&mut self) -> Result<(), IoError> { - return os_fsync(self.fd); + return os_fsync(self.fd()); #[cfg(windows)] fn os_fsync(fd: c_int) -> IoResult<()> { @@ -247,7 +259,7 @@ impl rtio::RtioFileStream for FileDesc { #[cfg(not(windows))] fn datasync(&mut self) -> Result<(), IoError> { - return super::mkerr_libc(os_datasync(self.fd)); + return super::mkerr_libc(os_datasync(self.fd())); #[cfg(target_os = "macos")] fn os_datasync(fd: c_int) -> c_int { @@ -270,7 +282,7 @@ impl rtio::RtioFileStream for FileDesc { Ok(_) => {}, Err(e) => return Err(e), }; let ret = unsafe { - let handle = libc::get_osfhandle(self.fd) as libc::HANDLE; + let handle = libc::get_osfhandle(self.fd()) as libc::HANDLE; match libc::SetEndOfFile(handle) { 0 => Err(super::last_error()), _ => Ok(()) @@ -282,7 +294,7 @@ impl rtio::RtioFileStream for FileDesc { #[cfg(unix)] fn truncate(&mut self, offset: i64) -> Result<(), IoError> { super::mkerr_libc(retry(|| unsafe { - libc::ftruncate(self.fd, offset as libc::off_t) + libc::ftruncate(self.fd(), offset as libc::off_t) })) } } @@ -294,6 +306,9 @@ impl rtio::RtioPipe for FileDesc { fn write(&mut self, buf: &[u8]) -> Result<(), IoError> { self.inner_write(buf) } + fn clone(&self) -> ~rtio::RtioPipe { + ~FileDesc { inner: self.inner.clone() } as ~rtio::RtioPipe + } } impl rtio::RtioTTY for FileDesc { @@ -312,7 +327,7 @@ impl rtio::RtioTTY for FileDesc { fn isatty(&self) -> bool { false } } -impl Drop for FileDesc { +impl Drop for Inner { fn drop(&mut self) { // closing stdio file handles makes no sense, so never do it. Also, note // that errors are ignored when closing a file descriptor. The reason diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index dd916c8f3c4b9..32cd6337f993d 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -14,6 +14,7 @@ use std::io; use std::libc; use std::mem; use std::rt::rtio; +use std::sync::arc::UnsafeArc; use std::unstable::intrinsics; use super::{IoResult, retry}; @@ -108,10 +109,27 @@ fn setsockopt(fd: sock_t, opt: libc::c_int, val: libc::c_int, let ret = libc::setsockopt(fd, opt, val, payload, mem::size_of::() as libc::socklen_t); - super::mkerr_libc(ret) + if ret != 0 { + Err(last_error()) + } else { + Ok(()) + } } } +#[cfg(windows)] +fn last_error() -> io::IoError { + extern "system" { + fn WSAGetLastError() -> libc::c_int; + } + super::translate_error(unsafe { WSAGetLastError() }, true) +} + +#[cfg(not(windows))] +fn last_error() -> io::IoError { + super::last_error() +} + #[cfg(windows)] unsafe fn close(sock: sock_t) { let _ = libc::closesocket(sock); } #[cfg(unix)] unsafe fn close(sock: sock_t) { let _ = libc::close(sock); } @@ -128,7 +146,7 @@ fn sockname(fd: sock_t, storage as *mut libc::sockaddr, &mut len as *mut libc::socklen_t); if ret != 0 { - return Err(super::last_error()) + return Err(last_error()) } } return sockaddr_to_addr(&storage, len as uint); @@ -222,7 +240,11 @@ pub fn init() { //////////////////////////////////////////////////////////////////////////////// pub struct TcpStream { - priv fd: sock_t, + priv inner: UnsafeArc, +} + +struct Inner { + fd: sock_t, } impl TcpStream { @@ -231,27 +253,31 @@ impl TcpStream { socket(addr, libc::SOCK_STREAM).and_then(|fd| { let (addr, len) = addr_to_sockaddr(addr); let addrp = &addr as *libc::sockaddr_storage; - let ret = TcpStream { fd: fd }; + let inner = Inner { fd: fd }; + let ret = TcpStream { inner: UnsafeArc::new(inner) }; match retry(|| { libc::connect(fd, addrp as *libc::sockaddr, len as libc::socklen_t) }) { - -1 => Err(super::last_error()), + -1 => Err(last_error()), _ => Ok(ret), } }) } } - pub fn fd(&self) -> sock_t { self.fd } + pub fn fd(&self) -> sock_t { + // This unsafety is fine because it's just a read-only arc + unsafe { (*self.inner.get()).fd } + } fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> { - setsockopt(self.fd, libc::IPPROTO_TCP, libc::TCP_NODELAY, + setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as libc::c_int) } fn set_keepalive(&mut self, seconds: Option) -> IoResult<()> { - let ret = setsockopt(self.fd, libc::SOL_SOCKET, libc::SO_KEEPALIVE, + let ret = setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_KEEPALIVE, seconds.is_some() as libc::c_int); match seconds { Some(n) => ret.and_then(|()| self.set_tcp_keepalive(n)), @@ -261,12 +287,12 @@ impl TcpStream { #[cfg(target_os = "macos")] fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> { - setsockopt(self.fd, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, + setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, seconds as libc::c_int) } #[cfg(target_os = "freebsd")] fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> { - setsockopt(self.fd, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, + setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, seconds as libc::c_int) } #[cfg(not(target_os = "macos"), not(target_os = "freebsd"))] @@ -282,7 +308,7 @@ impl rtio::RtioTcpStream for TcpStream { fn read(&mut self, buf: &mut [u8]) -> IoResult { let ret = retry(|| { unsafe { - libc::recv(self.fd, + libc::recv(self.fd(), buf.as_ptr() as *mut libc::c_void, buf.len() as wrlen, 0) as libc::c_int @@ -291,7 +317,7 @@ impl rtio::RtioTcpStream for TcpStream { if ret == 0 { Err(io::standard_error(io::EndOfFile)) } else if ret < 0 { - Err(super::last_error()) + Err(last_error()) } else { Ok(ret as uint) } @@ -299,20 +325,20 @@ impl rtio::RtioTcpStream for TcpStream { fn write(&mut self, buf: &[u8]) -> IoResult<()> { let ret = keep_going(buf, |buf, len| { unsafe { - libc::send(self.fd, + libc::send(self.fd(), buf as *mut libc::c_void, len as wrlen, 0) as i64 } }); if ret < 0 { - Err(super::last_error()) + Err(last_error()) } else { Ok(()) } } fn peer_name(&mut self) -> IoResult { - sockname(self.fd, libc::getpeername) + sockname(self.fd(), libc::getpeername) } fn control_congestion(&mut self) -> IoResult<()> { self.set_nodelay(false) @@ -326,15 +352,19 @@ impl rtio::RtioTcpStream for TcpStream { fn letdie(&mut self) -> IoResult<()> { self.set_keepalive(None) } + + fn clone(&self) -> ~rtio::RtioTcpStream { + ~TcpStream { inner: self.inner.clone() } as ~rtio::RtioTcpStream + } } impl rtio::RtioSocket for TcpStream { fn socket_name(&mut self) -> IoResult { - sockname(self.fd, libc::getsockname) + sockname(self.fd(), libc::getsockname) } } -impl Drop for TcpStream { +impl Drop for Inner { fn drop(&mut self) { unsafe { close(self.fd); } } } @@ -343,7 +373,7 @@ impl Drop for TcpStream { //////////////////////////////////////////////////////////////////////////////// pub struct TcpListener { - priv fd: sock_t, + priv inner: UnsafeArc, } impl TcpListener { @@ -352,7 +382,8 @@ impl TcpListener { socket(addr, libc::SOCK_STREAM).and_then(|fd| { let (addr, len) = addr_to_sockaddr(addr); let addrp = &addr as *libc::sockaddr_storage; - let ret = TcpListener { fd: fd }; + let inner = Inner { fd: fd }; + let ret = TcpListener { inner: UnsafeArc::new(inner) }; // On platforms with Berkeley-derived sockets, this allows // to quickly rebind a socket, without needing to wait for // the OS to clean up the previous one. @@ -366,18 +397,21 @@ impl TcpListener { } match libc::bind(fd, addrp as *libc::sockaddr, len as libc::socklen_t) { - -1 => Err(super::last_error()), + -1 => Err(last_error()), _ => Ok(ret), } }) } } - pub fn fd(&self) -> sock_t { self.fd } + pub fn fd(&self) -> sock_t { + // This is just a read-only arc so the unsafety is fine + unsafe { (*self.inner.get()).fd } + } pub fn native_listen(self, backlog: int) -> IoResult { - match unsafe { libc::listen(self.fd, backlog as libc::c_int) } { - -1 => Err(super::last_error()), + match unsafe { libc::listen(self.fd(), backlog as libc::c_int) } { + -1 => Err(last_error()), _ => Ok(TcpAcceptor { listener: self }) } } @@ -391,20 +425,16 @@ impl rtio::RtioTcpListener for TcpListener { impl rtio::RtioSocket for TcpListener { fn socket_name(&mut self) -> IoResult { - sockname(self.fd, libc::getsockname) + sockname(self.fd(), libc::getsockname) } } -impl Drop for TcpListener { - fn drop(&mut self) { unsafe { close(self.fd); } } -} - pub struct TcpAcceptor { priv listener: TcpListener, } impl TcpAcceptor { - pub fn fd(&self) -> sock_t { self.listener.fd } + pub fn fd(&self) -> sock_t { self.listener.fd() } pub fn native_accept(&mut self) -> IoResult { unsafe { @@ -417,8 +447,8 @@ impl TcpAcceptor { storagep as *mut libc::sockaddr, &mut size as *mut libc::socklen_t) as libc::c_int }) as sock_t { - -1 => Err(super::last_error()), - fd => Ok(TcpStream { fd: fd }) + -1 => Err(last_error()), + fd => Ok(TcpStream { inner: UnsafeArc::new(Inner { fd: fd })}) } } } @@ -444,7 +474,7 @@ impl rtio::RtioTcpAcceptor for TcpAcceptor { //////////////////////////////////////////////////////////////////////////////// pub struct UdpSocket { - priv fd: sock_t, + priv inner: UnsafeArc, } impl UdpSocket { @@ -453,25 +483,29 @@ impl UdpSocket { socket(addr, libc::SOCK_DGRAM).and_then(|fd| { let (addr, len) = addr_to_sockaddr(addr); let addrp = &addr as *libc::sockaddr_storage; - let ret = UdpSocket { fd: fd }; + let inner = Inner { fd: fd }; + let ret = UdpSocket { inner: UnsafeArc::new(inner) }; match libc::bind(fd, addrp as *libc::sockaddr, len as libc::socklen_t) { - -1 => Err(super::last_error()), + -1 => Err(last_error()), _ => Ok(ret), } }) } } - pub fn fd(&self) -> sock_t { self.fd } + pub fn fd(&self) -> sock_t { + // unsafety is fine because it's just a read-only arc + unsafe { (*self.inner.get()).fd } + } pub fn set_broadcast(&mut self, on: bool) -> IoResult<()> { - setsockopt(self.fd, libc::SOL_SOCKET, libc::SO_BROADCAST, + setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_BROADCAST, on as libc::c_int) } pub fn set_multicast_loop(&mut self, on: bool) -> IoResult<()> { - setsockopt(self.fd, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, + setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, on as libc::c_int) } @@ -484,14 +518,14 @@ impl UdpSocket { // interface == INADDR_ANY imr_interface: libc::in_addr { s_addr: 0x0 }, }; - setsockopt(self.fd, libc::IPPROTO_IP, opt, mreq) + setsockopt(self.fd(), libc::IPPROTO_IP, opt, mreq) } In6Addr(addr) => { let mreq = libc::ip6_mreq { ipv6mr_multiaddr: addr, ipv6mr_interface: 0, }; - setsockopt(self.fd, libc::IPPROTO_IPV6, opt, mreq) + setsockopt(self.fd(), libc::IPPROTO_IPV6, opt, mreq) } } } @@ -514,14 +548,14 @@ impl rtio::RtioUdpSocket for UdpSocket { let mut addrlen: libc::socklen_t = mem::size_of::() as libc::socklen_t; let ret = retry(|| { - libc::recvfrom(self.fd, + libc::recvfrom(self.fd(), buf.as_ptr() as *mut libc::c_void, buf.len() as msglen_t, 0, storagep as *mut libc::sockaddr, &mut addrlen) as libc::c_int }); - if ret < 0 { return Err(super::last_error()) } + if ret < 0 { return Err(last_error()) } sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| { Ok((ret as uint, addr)) }) @@ -532,7 +566,7 @@ impl rtio::RtioUdpSocket for UdpSocket { let dstp = &dst as *libc::sockaddr_storage; unsafe { let ret = retry(|| { - libc::sendto(self.fd, + libc::sendto(self.fd(), buf.as_ptr() as *libc::c_void, buf.len() as msglen_t, 0, @@ -540,7 +574,7 @@ impl rtio::RtioUdpSocket for UdpSocket { len as libc::socklen_t) as libc::c_int }); match ret { - -1 => Err(super::last_error()), + -1 => Err(last_error()), n if n as uint != buf.len() => { Err(io::IoError { kind: io::OtherIoError, @@ -582,11 +616,11 @@ impl rtio::RtioUdpSocket for UdpSocket { } fn multicast_time_to_live(&mut self, ttl: int) -> IoResult<()> { - setsockopt(self.fd, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, + setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, ttl as libc::c_int) } fn time_to_live(&mut self, ttl: int) -> IoResult<()> { - setsockopt(self.fd, libc::IPPROTO_IP, libc::IP_TTL, ttl as libc::c_int) + setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_TTL, ttl as libc::c_int) } fn hear_broadcasts(&mut self) -> IoResult<()> { @@ -595,8 +629,8 @@ impl rtio::RtioUdpSocket for UdpSocket { fn ignore_broadcasts(&mut self) -> IoResult<()> { self.set_broadcast(false) } -} -impl Drop for UdpSocket { - fn drop(&mut self) { unsafe { close(self.fd) } } + fn clone(&self) -> ~rtio::RtioUdpSocket { + ~UdpSocket { inner: self.inner.clone() } as ~rtio::RtioUdpSocket + } } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index e224a06818af1..aea9b65087dc6 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -331,7 +331,7 @@ pub mod write { } unsafe fn configure_llvm(sess: Session) { - use extra::sync::one::{Once, ONCE_INIT}; + use sync::one::{Once, ONCE_INIT}; static mut INIT: Once = ONCE_INIT; // Copy what clang does by turning on loop vectorization at O2 and diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs index ed4455c2f89a1..15056d9d2d842 100644 --- a/src/librustc/front/feature_gate.rs +++ b/src/librustc/front/feature_gate.rs @@ -49,6 +49,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("trace_macros", Active), ("simd", Active), ("default_type_params", Active), + ("quote", Active), // These are used to test this portion of the compiler, they don't actually // mean anything @@ -189,24 +190,35 @@ impl Visitor<()> for Context { fn visit_mac(&mut self, macro: &ast::Mac, _: ()) { let ast::MacInvocTT(ref path, _, _) = macro.node; + let id = path.segments.last().unwrap().identifier; + let quotes = ["quote_tokens", "quote_expr", "quote_ty", + "quote_item", "quote_pat", "quote_stmt"]; + let msg = " is not stable enough for use and are subject to change"; - if path.segments.last().unwrap().identifier == self.sess.ident_of("macro_rules") { + + if id == self.sess.ident_of("macro_rules") { self.gate_feature("macro_rules", path.span, "macro definitions are \ not stable enough for use and are subject to change"); } - else if path.segments.last().unwrap().identifier == self.sess.ident_of("asm") { + else if id == self.sess.ident_of("asm") { self.gate_feature("asm", path.span, "inline assembly is not \ stable enough for use and is subject to change"); } - else if path.segments.last().unwrap().identifier == self.sess.ident_of("log_syntax") { + else if id == self.sess.ident_of("log_syntax") { self.gate_feature("log_syntax", path.span, "`log_syntax!` is not \ stable enough for use and is subject to change"); } - else if path.segments.last().unwrap().identifier == self.sess.ident_of("trace_macros") { + else if id == self.sess.ident_of("trace_macros") { self.gate_feature("trace_macros", path.span, "`trace_macros` is not \ stable enough for use and is subject to change"); + } else { + for "e in quotes.iter() { + if id == self.sess.ident_of(quote) { + self.gate_feature("quote", path.span, quote + msg); + } + } } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 36f44c8870dcc..52ddc8c810888 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -28,11 +28,15 @@ This API is completely unstable and subject to change. html_root_url = "http://static.rust-lang.org/doc/master")]; #[feature(macro_rules, globs, struct_variant, managed_boxes)]; +#[allow(unknown_features)]; // Note: remove it after a snapshot. +#[feature(quote)]; extern mod extra; extern mod flate; extern mod arena; extern mod syntax; +extern mod serialize; +extern mod sync; use back::link; use driver::session; diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 1a65b326bbdea..8a6ba824dcb27 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -18,8 +18,8 @@ use middle::ty; use middle::typeck; use std::vec; +use reader = serialize::ebml::reader; use std::rc::Rc; -use reader = extra::ebml::reader; use syntax::ast; use syntax::ast_map; use syntax::diagnostic::expect; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 8ba98e84dfa50..d18017d00439b 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -31,9 +31,9 @@ use std::io::extensions::u64_from_be_bytes; use std::option; use std::rc::Rc; use std::vec; -use extra::ebml::reader; -use extra::ebml; -use extra::serialize::Decodable; +use serialize::ebml::reader; +use serialize::ebml; +use serialize::Decodable; use syntax::ast_map; use syntax::attr; use syntax::parse::token::{IdentInterner, special_idents}; diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index d56d211b713ee..ba33f57309f8e 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -22,7 +22,7 @@ use middle::ty; use middle::typeck; use middle; -use extra::serialize::Encodable; +use serialize::Encodable; use std::cast; use std::cell::{Cell, RefCell}; use std::hashmap::{HashMap, HashSet}; @@ -45,7 +45,7 @@ use syntax::parse::token; use syntax::visit::Visitor; use syntax::visit; use syntax; -use writer = extra::ebml::writer; +use writer = serialize::ebml::writer; // used by astencode: type abbrev_map = @RefCell>; diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 29ea3475d3441..8adbd37462b94 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -37,12 +37,12 @@ use std::cast; use std::io::Seek; use std::rc::Rc; -use extra::ebml::reader; -use extra::ebml; -use extra::serialize; -use extra::serialize::{Encoder, Encodable, EncoderHelpers, DecoderHelpers}; -use extra::serialize::{Decoder, Decodable}; -use writer = extra::ebml::writer; +use serialize::ebml::reader; +use serialize::ebml; +use serialize; +use serialize::{Encoder, Encodable, EncoderHelpers, DecoderHelpers}; +use serialize::{Decoder, Decodable}; +use writer = serialize::ebml::writer; #[cfg(test)] use syntax::parse; #[cfg(test)] use syntax::print::pprust; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 1ebe4a03cfdd2..5b4a961761277 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2660,7 +2660,7 @@ pub fn trans_crate(sess: session::Session, output: &Path) -> CrateTranslation { // Before we touch LLVM, make sure that multithreading is enabled. unsafe { - use extra::sync::one::{Once, ONCE_INIT}; + use sync::one::{Once, ONCE_INIT}; static mut INIT: Once = ONCE_INIT; static mut POISONED: bool = false; INIT.doit(|| { diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 1bfbb3f99b199..99eccb8f40b99 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -30,7 +30,7 @@ use middle::trans::machine::*; use middle::trans::reflect; use middle::trans::tvec; use middle::trans::type_::Type; -use middle::trans::type_of::type_of; +use middle::trans::type_of::{type_of, sizing_type_of}; use middle::ty; use util::ppaux::ty_to_short_str; use util::ppaux; @@ -100,23 +100,29 @@ pub fn lazily_emit_all_tydesc_glue(ccx: @CrateContext, lazily_emit_tydesc_glue(ccx, abi::tydesc_field_visit_glue, static_ti); } -fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { +fn get_glue_type(ccx: &CrateContext, field: uint, t: ty::t) -> ty::t { + let tcx = ccx.tcx; if field == abi::tydesc_field_drop_glue { if !ty::type_needs_drop(tcx, t) { - return ty::mk_nil(); + return ty::mk_i8(); } match ty::get(t).sty { - ty::ty_box(typ) - if !ty::type_needs_drop(tcx, typ) => - return ty::mk_box(tcx, ty::mk_nil()), - - ty::ty_uniq(typ) - if !ty::type_needs_drop(tcx, typ) => - return ty::mk_uniq(tcx, ty::mk_nil()), + ty::ty_box(typ) if !ty::type_needs_drop(tcx, typ) => + return ty::mk_box(tcx, ty::mk_i8()), + + ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ) => { + let llty = sizing_type_of(ccx, typ); + // Unique boxes do not allocate for zero-size types. The standard library may assume + // that `free` is never called on the pointer returned for `~ZeroSizeType`. + if llsize_of_alloc(ccx, llty) == 0 { + return ty::mk_i8(); + } else { + return ty::mk_uniq(tcx, ty::mk_i8()); + } + } - ty::ty_vec(mt, ty::vstore_uniq) - if !ty::type_needs_drop(tcx, mt.ty) => - return ty::mk_uniq(tcx, ty::mk_nil()), + ty::ty_vec(mt, ty::vstore_uniq) if !ty::type_needs_drop(tcx, mt.ty) => + return ty::mk_uniq(tcx, ty::mk_i8()), _ => {} } @@ -128,7 +134,7 @@ fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { pub fn lazily_emit_tydesc_glue(ccx: @CrateContext, field: uint, ti: @tydesc_info) { let _icx = push_ctxt("lazily_emit_tydesc_glue"); - let simpl = simplified_glue_type(ccx.tcx, field, ti.ty); + let simpl = get_glue_type(ccx, field, ti.ty); if simpl != ti.ty { let _icx = push_ctxt("lazily_emit_simplified_tydesc_glue"); let simpl_ti = get_tydesc(ccx, simpl); @@ -204,7 +210,7 @@ pub fn call_tydesc_glue_full(bcx: &Block, v: ValueRef, tydesc: ValueRef, PointerCast(bcx, v, Type::i8p()) } else { let ty = static_ti.unwrap().ty; - let simpl = simplified_glue_type(ccx.tcx, field, ty); + let simpl = get_glue_type(ccx, field, ty); if simpl != ty { PointerCast(bcx, v, type_of(ccx, simpl).ptr_to()) } else { diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 5ca879fea4a67..06776fc672eb0 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -15,7 +15,7 @@ // each trait in the system to its implementations. -use metadata::csearch::{each_impl, get_impl_trait}; +use metadata::csearch::{each_impl, get_impl_trait, each_implementation_for_trait}; use metadata::csearch; use middle::ty::get; use middle::ty::{ImplContainer, lookup_item_type, subst}; @@ -434,7 +434,7 @@ impl CoherenceChecker { pub fn check_implementation_coherence_of(&self, trait_def_id: DefId) { // Unify pairs of polytypes. - self.iter_impls_of_trait(trait_def_id, |a| { + self.iter_impls_of_trait_local(trait_def_id, |a| { let implementation_a = a; let polytype_a = self.get_self_type_for_implementation(implementation_a); @@ -452,12 +452,19 @@ impl CoherenceChecker { if self.polytypes_unify(polytype_a.clone(), polytype_b) { let session = self.crate_context.tcx.sess; session.span_err( - self.span_of_impl(implementation_b), + self.span_of_impl(implementation_a), format!("conflicting implementations for trait `{}`", ty::item_path_str(self.crate_context.tcx, trait_def_id))); - session.span_note(self.span_of_impl(implementation_a), - "note conflicting implementation here"); + if implementation_b.did.crate == LOCAL_CRATE { + session.span_note(self.span_of_impl(implementation_b), + "note conflicting implementation here"); + } else { + let crate_store = self.crate_context.tcx.sess.cstore; + let cdata = crate_store.get_crate_data(implementation_b.did.crate); + session.note( + "conflicting implementation in crate `" + cdata.name + "`"); + } } } }) @@ -465,6 +472,21 @@ impl CoherenceChecker { } pub fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |@Impl|) { + self.iter_impls_of_trait_local(trait_def_id, |x| f(x)); + + if trait_def_id.crate == LOCAL_CRATE { + return; + } + + let crate_store = self.crate_context.tcx.sess.cstore; + csearch::each_implementation_for_trait(crate_store, trait_def_id, |impl_def_id| { + let implementation = @csearch::get_impl(self.crate_context.tcx, impl_def_id); + let _ = lookup_item_type(self.crate_context.tcx, implementation.did); + f(implementation); + }); + } + + pub fn iter_impls_of_trait_local(&self, trait_def_id: DefId, f: |@Impl|) { let trait_impls = self.crate_context.tcx.trait_impls.borrow(); match trait_impls.get().find(&trait_def_id) { Some(impls) => { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 65696528a6fa1..f01e420030f6d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -41,7 +41,7 @@ use std::io::{fs, File, BufferedWriter}; use std::str; use std::vec; -use extra::arc::Arc; +use sync::Arc; use extra::json::ToJson; use syntax::ast; use syntax::attr; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index fe989279e7147..7256e8923fa87 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -18,6 +18,8 @@ extern mod syntax; extern mod rustc; extern mod extra; +extern mod serialize; +extern mod sync; use std::local_data; use std::io; @@ -26,7 +28,7 @@ use std::str; use extra::getopts; use extra::getopts::groups; use extra::json; -use extra::serialize::{Decodable, Encodable}; +use serialize::{Decodable, Encodable}; use extra::time; pub mod clean; diff --git a/src/librustuv/access.rs b/src/librustuv/access.rs new file mode 100644 index 0000000000000..9d06593a6eafd --- /dev/null +++ b/src/librustuv/access.rs @@ -0,0 +1,109 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// An exclusive access primitive +/// +/// This primitive is used to gain exclusive access to read() and write() in uv. +/// It is assumed that all invocations of this struct happen on the same thread +/// (the uv event loop). + +use std::cast; +use std::sync::arc::UnsafeArc; +use std::rt::task::{BlockedTask, Task}; +use std::rt::local::Local; + +use homing::HomingMissile; + +pub struct Access { + priv inner: UnsafeArc, +} + +pub struct Guard<'a> { + priv access: &'a mut Access, + priv missile: Option, +} + +struct Inner { + queue: ~[BlockedTask], + held: bool, +} + +impl Access { + pub fn new() -> Access { + Access { + inner: UnsafeArc::new(Inner { + queue: ~[], + held: false, + }) + } + } + + pub fn grant<'a>(&'a mut self, missile: HomingMissile) -> Guard<'a> { + // This unsafety is actually OK because the homing missile argument + // guarantees that we're on the same event loop as all the other objects + // attempting to get access granted. + let inner: &mut Inner = unsafe { cast::transmute(self.inner.get()) }; + + if inner.held { + let t: ~Task = Local::take(); + t.deschedule(1, |task| { + inner.queue.push(task); + Ok(()) + }); + assert!(inner.held); + } else { + inner.held = true; + } + + Guard { access: self, missile: Some(missile) } + } +} + +impl Clone for Access { + fn clone(&self) -> Access { + Access { inner: self.inner.clone() } + } +} + +#[unsafe_destructor] +impl<'a> Drop for Guard<'a> { + fn drop(&mut self) { + // This guard's homing missile is still armed, so we're guaranteed to be + // on the same I/O event loop, so this unsafety should be ok. + assert!(self.missile.is_some()); + let inner: &mut Inner = unsafe { + cast::transmute(self.access.inner.get()) + }; + + match inner.queue.shift() { + // Here we have found a task that was waiting for access, and we + // current have the "access lock" we need to relinquish access to + // this sleeping task. + // + // To do so, we first drop out homing missile and we then reawaken + // the task. In reawakening the task, it will be immediately + // scheduled on this scheduler. Because we might be woken up on some + // other scheduler, we drop our homing missile before we reawaken + // the task. + Some(task) => { + drop(self.missile.take()); + let _ = task.wake().map(|t| t.reawaken()); + } + None => { inner.held = false; } + } + } +} + +impl Drop for Inner { + fn drop(&mut self) { + assert!(!self.held); + assert_eq!(self.queue.len(), 0); + } +} diff --git a/src/librustuv/homing.rs b/src/librustuv/homing.rs index a2f3457a9430c..25c929c995de7 100644 --- a/src/librustuv/homing.rs +++ b/src/librustuv/homing.rs @@ -125,8 +125,8 @@ pub trait HomingIO { /// After a homing operation has been completed, this will return the current /// task back to its appropriate home (if applicable). The field is used to /// assert that we are where we think we are. -struct HomingMissile { - io_home: uint, +pub struct HomingMissile { + priv io_home: uint, } impl HomingMissile { diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs index 39d6f851e1722..b463bb7fd733d 100644 --- a/src/librustuv/lib.rs +++ b/src/librustuv/lib.rs @@ -68,8 +68,10 @@ pub use self::tty::TtyWatcher; mod macros; -mod queue; +mod access; mod homing; +mod queue; +mod rc; /// The implementation of `rtio` for libuv pub mod uvio; diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index 5461fc6272d35..7660d2c4f2b3e 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -19,7 +19,9 @@ use std::rt::rtio; use std::rt::task::BlockedTask; use std::unstable::intrinsics; +use access::Access; use homing::{HomingIO, HomeHandle}; +use rc::Refcount; use stream::StreamWatcher; use super::{Loop, Request, UvError, Buf, status_to_io_result, uv_error_to_io_error, UvHandle, slice_to_uv_buf, @@ -152,6 +154,14 @@ pub struct TcpWatcher { handle: *uvll::uv_tcp_t, stream: StreamWatcher, home: HomeHandle, + priv refcount: Refcount, + + // libuv can't support concurrent reads and concurrent writes of the same + // stream object, so we use these access guards in order to arbitrate among + // multiple concurrent reads and writes. Note that libuv *can* read and + // write simultaneously, it just can't read and read simultaneously. + priv read_access: Access, + priv write_access: Access, } pub struct TcpListener { @@ -183,6 +193,9 @@ impl TcpWatcher { home: home, handle: handle, stream: StreamWatcher::new(handle), + refcount: Refcount::new(), + read_access: Access::new(), + write_access: Access::new(), } } @@ -238,12 +251,14 @@ impl rtio::RtioSocket for TcpWatcher { impl rtio::RtioTcpStream for TcpWatcher { fn read(&mut self, buf: &mut [u8]) -> Result { - let _m = self.fire_homing_missile(); + let m = self.fire_homing_missile(); + let _g = self.read_access.grant(m); self.stream.read(buf).map_err(uv_error_to_io_error) } fn write(&mut self, buf: &[u8]) -> Result<(), IoError> { - let _m = self.fire_homing_missile(); + let m = self.fire_homing_missile(); + let _g = self.write_access.grant(m); self.stream.write(buf).map_err(uv_error_to_io_error) } @@ -280,6 +295,17 @@ impl rtio::RtioTcpStream for TcpWatcher { uvll::uv_tcp_keepalive(self.handle, 0 as c_int, 0 as c_uint) }) } + + fn clone(&self) -> ~rtio::RtioTcpStream { + ~TcpWatcher { + handle: self.handle, + stream: StreamWatcher::new(self.handle), + home: self.home.clone(), + refcount: self.refcount.clone(), + write_access: self.write_access.clone(), + read_access: self.read_access.clone(), + } as ~rtio::RtioTcpStream + } } impl UvHandle for TcpWatcher { @@ -289,7 +315,9 @@ impl UvHandle for TcpWatcher { impl Drop for TcpWatcher { fn drop(&mut self) { let _m = self.fire_homing_missile(); - self.close(); + if self.refcount.decrement() { + self.close(); + } } } @@ -415,6 +443,11 @@ impl rtio::RtioTcpAcceptor for TcpAcceptor { pub struct UdpWatcher { handle: *uvll::uv_udp_t, home: HomeHandle, + + // See above for what these fields are + priv refcount: Refcount, + priv read_access: Access, + priv write_access: Access, } impl UdpWatcher { @@ -423,6 +456,9 @@ impl UdpWatcher { let udp = UdpWatcher { handle: unsafe { uvll::malloc_handle(uvll::UV_UDP) }, home: io.make_handle(), + refcount: Refcount::new(), + read_access: Access::new(), + write_access: Access::new(), }; assert_eq!(unsafe { uvll::uv_udp_init(io.uv_loop(), udp.handle) @@ -463,7 +499,8 @@ impl rtio::RtioUdpSocket for UdpWatcher { buf: Option, result: Option<(ssize_t, Option)>, } - let _m = self.fire_homing_missile(); + let m = self.fire_homing_missile(); + let _g = self.read_access.grant(m); let a = match unsafe { uvll::uv_udp_recv_start(self.handle, alloc_cb, recv_cb) @@ -533,7 +570,8 @@ impl rtio::RtioUdpSocket for UdpWatcher { fn sendto(&mut self, buf: &[u8], dst: ip::SocketAddr) -> Result<(), IoError> { struct Ctx { task: Option, result: c_int } - let _m = self.fire_homing_missile(); + let m = self.fire_homing_missile(); + let _g = self.write_access.grant(m); let mut req = Request::new(uvll::UV_UDP_SEND); let buf = slice_to_uv_buf(buf); @@ -636,13 +674,25 @@ impl rtio::RtioUdpSocket for UdpWatcher { 0 as c_int) }) } + + fn clone(&self) -> ~rtio::RtioUdpSocket { + ~UdpWatcher { + handle: self.handle, + home: self.home.clone(), + refcount: self.refcount.clone(), + write_access: self.write_access.clone(), + read_access: self.read_access.clone(), + } as ~rtio::RtioUdpSocket + } } impl Drop for UdpWatcher { fn drop(&mut self) { // Send ourselves home to close this handle (blocking while doing so). let _m = self.fire_homing_missile(); - self.close(); + if self.refcount.decrement() { + self.close(); + } } } diff --git a/src/librustuv/pipe.rs b/src/librustuv/pipe.rs index a021a13e2d98d..c312f112d28b4 100644 --- a/src/librustuv/pipe.rs +++ b/src/librustuv/pipe.rs @@ -14,7 +14,9 @@ use std::libc; use std::rt::rtio::{RtioPipe, RtioUnixListener, RtioUnixAcceptor}; use std::rt::task::BlockedTask; +use access::Access; use homing::{HomingIO, HomeHandle}; +use rc::Refcount; use stream::StreamWatcher; use super::{Loop, UvError, UvHandle, Request, uv_error_to_io_error, wait_until_woken_after, wakeup}; @@ -25,6 +27,11 @@ pub struct PipeWatcher { stream: StreamWatcher, home: HomeHandle, priv defused: bool, + priv refcount: Refcount, + + // see comments in TcpWatcher for why these exist + priv write_access: Access, + priv read_access: Access, } pub struct PipeListener { @@ -61,6 +68,9 @@ impl PipeWatcher { stream: StreamWatcher::new(handle), home: home, defused: false, + refcount: Refcount::new(), + read_access: Access::new(), + write_access: Access::new(), } } @@ -118,14 +128,27 @@ impl PipeWatcher { impl RtioPipe for PipeWatcher { fn read(&mut self, buf: &mut [u8]) -> Result { - let _m = self.fire_homing_missile(); + let m = self.fire_homing_missile(); + let _g = self.read_access.grant(m); self.stream.read(buf).map_err(uv_error_to_io_error) } fn write(&mut self, buf: &[u8]) -> Result<(), IoError> { - let _m = self.fire_homing_missile(); + let m = self.fire_homing_missile(); + let _g = self.write_access.grant(m); self.stream.write(buf).map_err(uv_error_to_io_error) } + + fn clone(&self) -> ~RtioPipe { + ~PipeWatcher { + stream: StreamWatcher::new(self.stream.handle), + defused: false, + home: self.home.clone(), + refcount: self.refcount.clone(), + read_access: self.read_access.clone(), + write_access: self.write_access.clone(), + } as ~RtioPipe + } } impl HomingIO for PipeWatcher { @@ -138,8 +161,8 @@ impl UvHandle for PipeWatcher { impl Drop for PipeWatcher { fn drop(&mut self) { - if !self.defused { - let _m = self.fire_homing_missile(); + let _m = self.fire_homing_missile(); + if !self.defused && self.refcount.decrement() { self.close(); } } diff --git a/src/librustuv/rc.rs b/src/librustuv/rc.rs new file mode 100644 index 0000000000000..f43cf72236109 --- /dev/null +++ b/src/librustuv/rc.rs @@ -0,0 +1,49 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// Simple refcount structure for cloning handles +/// +/// This is meant to be an unintrusive solution to cloning handles in rustuv. +/// The handles themselves shouldn't be sharing memory because there are bits of +/// state in the rust objects which shouldn't be shared across multiple users of +/// the same underlying uv object, hence Rc is not used and this simple counter +/// should suffice. + +use std::sync::arc::UnsafeArc; + +pub struct Refcount { + priv rc: UnsafeArc, +} + +impl Refcount { + /// Creates a new refcount of 1 + pub fn new() -> Refcount { + Refcount { rc: UnsafeArc::new(1) } + } + + fn increment(&self) { + unsafe { *self.rc.get() += 1; } + } + + /// Returns whether the refcount just hit 0 or not + pub fn decrement(&self) -> bool { + unsafe { + *self.rc.get() -= 1; + *self.rc.get() == 0 + } + } +} + +impl Clone for Refcount { + fn clone(&self) -> Refcount { + self.increment(); + Refcount { rc: self.rc.clone() } + } +} diff --git a/src/libextra/ebml.rs b/src/libserialize/ebml.rs similarity index 97% rename from src/libextra/ebml.rs rename to src/libserialize/ebml.rs index 1900313ab6c8e..9d1c099c6f0fb 100644 --- a/src/libextra/ebml.rs +++ b/src/libserialize/ebml.rs @@ -83,15 +83,19 @@ pub enum EbmlEncoderTag { pub mod reader { use std::char; - use super::*; - - use serialize; use std::cast::transmute; use std::int; use std::option::{None, Option, Some}; use std::io::extensions::u64_from_be_bytes; + use serialize; + + use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey, + EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8, + EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint, + EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc }; + // ebml reading pub struct Res { @@ -588,8 +592,6 @@ pub mod reader { } pub mod writer { - use super::*; - use std::cast; use std::clone::Clone; use std::io; @@ -597,6 +599,13 @@ pub mod writer { use std::io::MemWriter; use std::io::extensions::u64_to_be_bytes; + use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey, + EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8, + EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint, + EsOpaque, EsLabel, EbmlEncoderTag }; + + use serialize; + // ebml writing pub struct Encoder<'a> { // FIXME(#5665): this should take a trait object. Note that if you @@ -775,7 +784,7 @@ pub mod writer { } } - impl<'a> ::serialize::Encoder for Encoder<'a> { + impl<'a> serialize::Encoder for Encoder<'a> { fn emit_nil(&mut self) {} fn emit_uint(&mut self, v: uint) { @@ -952,8 +961,7 @@ pub mod writer { mod tests { use ebml::reader; use ebml::writer; - use serialize::Encodable; - use serialize; + use {Encodable, Decodable}; use std::io::MemWriter; use std::option::{None, Option, Some}; @@ -1017,7 +1025,7 @@ mod tests { } let ebml_doc = reader::Doc(wr.get_ref()); let mut deser = reader::Decoder(ebml_doc); - let v1 = serialize::Decodable::decode(&mut deser); + let v1 = Decodable::decode(&mut deser); debug!("v1 == {:?}", v1); assert_eq!(v, v1); } @@ -1031,7 +1039,7 @@ mod tests { #[cfg(test)] mod bench { use ebml::reader; - use test::BenchHarness; + use extra::test::BenchHarness; #[bench] pub fn vuint_at_A_aligned(bh: &mut BenchHarness) { diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs new file mode 100644 index 0000000000000..5f473b253697c --- /dev/null +++ b/src/libserialize/lib.rs @@ -0,0 +1,33 @@ +// Copyright 2012-2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Support code for encoding and decoding types. + +/* +Core encoding and decoding interfaces. +*/ + +#[crate_id = "serialize#0.10-pre"]; +#[crate_type = "rlib"]; +#[crate_type = "dylib"]; +#[license = "MIT/ASL2"]; +#[allow(missing_doc)]; +#[forbid(non_camel_case_types)]; +#[feature(macro_rules,managed_boxes)]; + +// test harness access +#[cfg(test)] +extern mod extra; + +pub use self::serialize::{Decoder, Encoder, Decodable, Encodable, + DecoderHelpers, EncoderHelpers}; + +mod serialize; +pub mod ebml; diff --git a/src/libextra/serialize.rs b/src/libserialize/serialize.rs similarity index 86% rename from src/libextra/serialize.rs rename to src/libserialize/serialize.rs index 9b1b1e0548e07..c4f0a7a1830f3 100644 --- a/src/libextra/serialize.rs +++ b/src/libserialize/serialize.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -14,18 +14,10 @@ Core encoding and decoding interfaces. */ -#[allow(missing_doc)]; -#[forbid(non_camel_case_types)]; - - use std::hashmap::{HashMap, HashSet}; use std::rc::Rc; use std::trie::{TrieMap, TrieSet}; use std::vec; -use ringbuf::RingBuf; -use container::Deque; -use dlist::DList; -use treemap::{TreeMap, TreeSet}; pub trait Encoder { // Primitive types: @@ -614,56 +606,6 @@ impl< } } -impl< - S: Encoder, - T: Encodable -> Encodable for DList { - fn encode(&self, s: &mut S) { - s.emit_seq(self.len(), |s| { - for (i, e) in self.iter().enumerate() { - s.emit_seq_elt(i, |s| e.encode(s)); - } - }) - } -} - -impl> Decodable for DList { - fn decode(d: &mut D) -> DList { - let mut list = DList::new(); - d.read_seq(|d, len| { - for i in range(0u, len) { - list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))); - } - }); - list - } -} - -impl< - S: Encoder, - T: Encodable -> Encodable for RingBuf { - fn encode(&self, s: &mut S) { - s.emit_seq(self.len(), |s| { - for (i, e) in self.iter().enumerate() { - s.emit_seq_elt(i, |s| e.encode(s)); - } - }) - } -} - -impl> Decodable for RingBuf { - fn decode(d: &mut D) -> RingBuf { - let mut deque = RingBuf::new(); - d.read_seq(|d, len| { - for i in range(0u, len) { - deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))); - } - }); - deque - } -} - impl< E: Encoder, K: Encodable + Hash + IterBytes + Eq, @@ -782,71 +724,6 @@ impl Decodable for TrieSet { } } -impl< - E: Encoder, - K: Encodable + Eq + TotalOrd, - V: Encodable + Eq -> Encodable for TreeMap { - fn encode(&self, e: &mut E) { - e.emit_map(self.len(), |e| { - let mut i = 0; - for (key, val) in self.iter() { - e.emit_map_elt_key(i, |e| key.encode(e)); - e.emit_map_elt_val(i, |e| val.encode(e)); - i += 1; - } - }) - } -} - -impl< - D: Decoder, - K: Decodable + Eq + TotalOrd, - V: Decodable + Eq -> Decodable for TreeMap { - fn decode(d: &mut D) -> TreeMap { - d.read_map(|d, len| { - let mut map = TreeMap::new(); - for i in range(0u, len) { - let key = d.read_map_elt_key(i, |d| Decodable::decode(d)); - let val = d.read_map_elt_val(i, |d| Decodable::decode(d)); - map.insert(key, val); - } - map - }) - } -} - -impl< - S: Encoder, - T: Encodable + Eq + TotalOrd -> Encodable for TreeSet { - fn encode(&self, s: &mut S) { - s.emit_seq(self.len(), |s| { - let mut i = 0; - for e in self.iter() { - s.emit_seq_elt(i, |s| e.encode(s)); - i += 1; - } - }) - } -} - -impl< - D: Decoder, - T: Decodable + Eq + TotalOrd -> Decodable for TreeSet { - fn decode(d: &mut D) -> TreeSet { - d.read_seq(|d, len| { - let mut set = TreeSet::new(); - for i in range(0u, len) { - set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))); - } - set - }) - } -} - // ___________________________________________________________________________ // Helper routines // diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 83aec9d0aa639..4a43a00c5f5a9 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -18,9 +18,9 @@ use str::OwnedStr; use container::Container; use cast; use iter::Iterator; -use vec::{ImmutableVector, MutableVector, Vector}; +use vec::{ImmutableVector,MutableVector,Vector}; use to_bytes::IterBytes; -use option::{Option, Some, None}; +use option::{Option,Some,None}; /// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. #[deriving(Clone, Eq, Ord, TotalOrd, TotalEq)] diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index e19b8ae712f9a..6fab74cbc2fc2 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -10,7 +10,10 @@ //! Types dealing with dynamic mutability -use prelude::*; +use clone::{Clone,DeepClone}; +use cmp::Eq; +use ops::Drop; +use option::{None,Option,Some}; use cast; use kinds::{marker, Pod}; diff --git a/src/libstd/condition.rs b/src/libstd/condition.rs index e0dc5c8b65d69..587b444d59d5c 100644 --- a/src/libstd/condition.rs +++ b/src/libstd/condition.rs @@ -73,7 +73,9 @@ along with comparing and contrasting it with other error handling strategies. */ use local_data; -use prelude::*; +use clone::Clone; +use ops::Drop; +use option::{None, Option, Some}; use unstable::raw::Closure; #[doc(hidden)] diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index a0bdc193d980c..66ceb03082f4b 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -8,11 +8,42 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! TCP network connections +//! +//! This module contains the ability to open a TCP stream to a socket address, +//! as well as creating a socket server to accept incoming connections. The +//! destination and binding addresses can either be an IPv4 or IPv6 address. +//! +//! A TCP connection implements the `Reader` and `Writer` traits, while the TCP +//! listener (socket server) implements the `Listener` and `Acceptor` traits. + +#[deny(missing_doc)]; + +use clone::Clone; use io::net::ip::SocketAddr; -use io::{Reader, Writer, Listener, Acceptor, IoResult}; +use io::{Reader, Writer, Listener, Acceptor}; +use io::IoResult; use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener}; use rt::rtio::{RtioTcpAcceptor, RtioTcpStream}; +/// A structure which represents a TCP stream between a local socket and a +/// remote socket. +/// +/// # Example +/// +/// ```rust +/// # #[allow(unused_must_use)]; +/// use std::io::net::tcp::TcpStream; +/// use std::io::net::ip::{Ipv4Addr, SocketAddr}; +/// +/// let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 34254 }; +/// let mut stream = TcpStream::connect(addr); +/// +/// stream.write([1]); +/// let mut buf = [0]; +/// stream.read(buf); +/// drop(stream); // close the connection +/// ``` pub struct TcpStream { priv obj: ~RtioTcpStream } @@ -22,21 +53,40 @@ impl TcpStream { TcpStream { obj: s } } + /// Creates a TCP connection to a remote socket address. + /// + /// If no error is encountered, then `Ok(stream)` is returned. pub fn connect(addr: SocketAddr) -> IoResult { LocalIo::maybe_raise(|io| { io.tcp_connect(addr).map(TcpStream::new) }) } + /// Returns the socket address of the remote peer of this TCP connection. pub fn peer_name(&mut self) -> IoResult { self.obj.peer_name() } + /// Returns the socket address of the local half of this TCP connection. pub fn socket_name(&mut self) -> IoResult { self.obj.socket_name() } } +impl Clone for TcpStream { + /// Creates a new handle to this TCP stream, allowing for simultaneous reads + /// and writes of this connection. + /// + /// The underlying TCP stream will not be closed until all handles to the + /// stream have been deallocated. All handles will also follow the same + /// stream, but two concurrent reads will not receive the same data. + /// Instead, the first read will receive the first packet received, and the + /// second read will receive the second packet. + fn clone(&self) -> TcpStream { + TcpStream { obj: self.obj.clone() } + } +} + impl Reader for TcpStream { fn read(&mut self, buf: &mut [u8]) -> IoResult { self.obj.read(buf) } } @@ -45,17 +95,56 @@ impl Writer for TcpStream { fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.obj.write(buf) } } +/// A structure representing a socket server. This listener is used to create a +/// `TcpAcceptor` which can be used to accept sockets on a local port. +/// +/// # Example +/// +/// ```rust +/// # fn main() {} +/// # fn foo() { +/// # #[allow(unused_must_use, dead_code)]; +/// use std::io::net::tcp::TcpListener; +/// use std::io::net::ip::{Ipv4Addr, SocketAddr}; +/// use std::io::{Acceptor, Listener}; +/// +/// let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 80 }; +/// let listener = TcpListener::bind(addr); +/// +/// // bind the listener to the specified address +/// let mut acceptor = listener.listen(); +/// +/// // accept connections and process them +/// # fn handle_client(_: T) {} +/// for stream in acceptor.incoming() { +/// spawn(proc() { +/// handle_client(stream); +/// }); +/// } +/// +/// // close the socket server +/// drop(acceptor); +/// # } +/// ``` pub struct TcpListener { priv obj: ~RtioTcpListener } impl TcpListener { + /// Creates a new `TcpListener` which will be bound to the specified local + /// socket address. This listener is not ready for accepting connections, + /// `listen` must be called on it before that's possible. + /// + /// Binding with a port number of 0 will request that the OS assigns a port + /// to this listener. The port allocated can be queried via the + /// `socket_name` function. pub fn bind(addr: SocketAddr) -> IoResult { LocalIo::maybe_raise(|io| { io.tcp_bind(addr).map(|l| TcpListener { obj: l }) }) } + /// Returns the local socket address of this listener. pub fn socket_name(&mut self) -> IoResult { self.obj.socket_name() } @@ -67,6 +156,9 @@ impl Listener for TcpListener { } } +/// The accepting half of a TCP socket server. This structure is created through +/// a `TcpListener`'s `listen` method, and this object can be used to accept new +/// `TcpStream` instances. pub struct TcpAcceptor { priv obj: ~RtioTcpAcceptor } @@ -573,4 +665,91 @@ mod test { } let _listener = TcpListener::bind(addr); }) + + iotest!(fn tcp_clone_smoke() { + let addr = next_test_ip4(); + let mut acceptor = TcpListener::bind(addr).listen(); + + spawn(proc() { + let mut s = TcpStream::connect(addr); + let mut buf = [0, 0]; + assert_eq!(s.read(buf), Ok(1)); + assert_eq!(buf[0], 1); + s.write([2]).unwrap(); + }); + + let mut s1 = acceptor.accept().unwrap(); + let s2 = s1.clone(); + + let (p1, c1) = Chan::new(); + let (p2, c2) = Chan::new(); + spawn(proc() { + let mut s2 = s2; + p1.recv(); + s2.write([1]).unwrap(); + c2.send(()); + }); + c1.send(()); + let mut buf = [0, 0]; + assert_eq!(s1.read(buf), Ok(1)); + p2.recv(); + }) + + iotest!(fn tcp_clone_two_read() { + let addr = next_test_ip6(); + let mut acceptor = TcpListener::bind(addr).listen(); + let (p, c) = SharedChan::new(); + let c2 = c.clone(); + + spawn(proc() { + let mut s = TcpStream::connect(addr); + s.write([1]).unwrap(); + p.recv(); + s.write([2]).unwrap(); + p.recv(); + }); + + let mut s1 = acceptor.accept().unwrap(); + let s2 = s1.clone(); + + let (p, done) = Chan::new(); + spawn(proc() { + let mut s2 = s2; + let mut buf = [0, 0]; + s2.read(buf).unwrap(); + c2.send(()); + done.send(()); + }); + let mut buf = [0, 0]; + s1.read(buf).unwrap(); + c.send(()); + + p.recv(); + }) + + iotest!(fn tcp_clone_two_write() { + let addr = next_test_ip4(); + let mut acceptor = TcpListener::bind(addr).listen(); + + spawn(proc() { + let mut s = TcpStream::connect(addr); + let mut buf = [0, 1]; + s.read(buf).unwrap(); + s.read(buf).unwrap(); + }); + + let mut s1 = acceptor.accept().unwrap(); + let s2 = s1.clone(); + + let (p, done) = Chan::new(); + spawn(proc() { + let mut s2 = s2; + s2.write([1]).unwrap(); + done.send(()); + }); + s1.write([2]).unwrap(); + + p.recv(); + }) } + diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index 0ef62648afcb7..3c02f56384792 100644 --- a/src/libstd/io/net/udp.rs +++ b/src/libstd/io/net/udp.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use clone::Clone; use result::{Ok, Err}; use io::net::ip::SocketAddr; use io::{Reader, Writer, IoResult}; @@ -41,6 +42,19 @@ impl UdpSocket { } } +impl Clone for UdpSocket { + /// Creates a new handle to this UDP socket, allowing for simultaneous reads + /// and writes of the socket. + /// + /// The underlying UDP socket will not be closed until all handles to the + /// socket have been deallocated. Two concurrent reads will not receive the + /// same data. Instead, the first read will receive the first packet + /// received, and the second read will receive the second packet. + fn clone(&self) -> UdpSocket { + UdpSocket { obj: self.obj.clone() } + } +} + pub struct UdpStream { priv socket: UdpSocket, priv connectedTo: SocketAddr @@ -250,4 +264,107 @@ mod test { iotest!(fn socket_name_ip6() { socket_name(next_test_ip6()); }) + + iotest!(fn udp_clone_smoke() { + let addr1 = next_test_ip4(); + let addr2 = next_test_ip4(); + let mut sock1 = UdpSocket::bind(addr1).unwrap(); + let sock2 = UdpSocket::bind(addr2).unwrap(); + + spawn(proc() { + let mut sock2 = sock2; + let mut buf = [0, 0]; + assert_eq!(sock2.recvfrom(buf), Ok((1, addr1))); + assert_eq!(buf[0], 1); + sock2.sendto([2], addr1).unwrap(); + }); + + let sock3 = sock1.clone(); + + let (p1, c1) = Chan::new(); + let (p2, c2) = Chan::new(); + spawn(proc() { + let mut sock3 = sock3; + p1.recv(); + sock3.sendto([1], addr2).unwrap(); + c2.send(()); + }); + c1.send(()); + let mut buf = [0, 0]; + assert_eq!(sock1.recvfrom(buf), Ok((1, addr2))); + p2.recv(); + }) + + iotest!(fn udp_clone_two_read() { + let addr1 = next_test_ip4(); + let addr2 = next_test_ip4(); + let mut sock1 = UdpSocket::bind(addr1).unwrap(); + let sock2 = UdpSocket::bind(addr2).unwrap(); + let (p, c) = SharedChan::new(); + let c2 = c.clone(); + + spawn(proc() { + let mut sock2 = sock2; + sock2.sendto([1], addr1).unwrap(); + p.recv(); + sock2.sendto([2], addr1).unwrap(); + p.recv(); + }); + + let sock3 = sock1.clone(); + + let (p, done) = Chan::new(); + spawn(proc() { + let mut sock3 = sock3; + let mut buf = [0, 0]; + sock3.recvfrom(buf).unwrap(); + c2.send(()); + done.send(()); + }); + let mut buf = [0, 0]; + sock1.recvfrom(buf).unwrap(); + c.send(()); + + p.recv(); + }) + + iotest!(fn udp_clone_two_write() { + let addr1 = next_test_ip4(); + let addr2 = next_test_ip4(); + let mut sock1 = UdpSocket::bind(addr1).unwrap(); + let sock2 = UdpSocket::bind(addr2).unwrap(); + + let (p, c) = SharedChan::new(); + + spawn(proc() { + let mut sock2 = sock2; + let mut buf = [0, 1]; + + for _ in p.iter() { + match sock2.recvfrom(buf) { + Ok(..) => {} + Err(e) => fail!("failed receive: {}", e), + } + } + }); + + let sock3 = sock1.clone(); + + let (p, done) = Chan::new(); + let c2 = c.clone(); + spawn(proc() { + let mut sock3 = sock3; + match sock3.sendto([1], addr2) { + Ok(..) => c2.send(()), + Err(..) => {} + } + done.send(()); + }); + match sock1.sendto([2], addr2) { + Ok(..) => c.send(()), + Err(..) => {} + } + + p.recv(); + }) } diff --git a/src/libstd/io/net/unix.rs b/src/libstd/io/net/unix.rs index ce95b987663f7..3c7db9c868618 100644 --- a/src/libstd/io/net/unix.rs +++ b/src/libstd/io/net/unix.rs @@ -25,6 +25,7 @@ instances as clients. use prelude::*; use c_str::ToCStr; +use clone::Clone; use rt::rtio::{IoFactory, LocalIo, RtioUnixListener}; use rt::rtio::{RtioUnixAcceptor, RtioPipe}; use io::pipe::PipeStream; @@ -62,6 +63,12 @@ impl UnixStream { } } +impl Clone for UnixStream { + fn clone(&self) -> UnixStream { + UnixStream { obj: self.obj.clone() } + } +} + impl Reader for UnixStream { fn read(&mut self, buf: &mut [u8]) -> IoResult { self.obj.read(buf) } } @@ -228,4 +235,93 @@ mod tests { let _acceptor = UnixListener::bind(&path).listen(); assert!(path.exists()); } + + #[test] + fn unix_clone_smoke() { + let addr = next_test_unix(); + let mut acceptor = UnixListener::bind(&addr).listen(); + + spawn(proc() { + let mut s = UnixStream::connect(&addr); + let mut buf = [0, 0]; + assert_eq!(s.read(buf), Ok(1)); + assert_eq!(buf[0], 1); + s.write([2]).unwrap(); + }); + + let mut s1 = acceptor.accept().unwrap(); + let s2 = s1.clone(); + + let (p1, c1) = Chan::new(); + let (p2, c2) = Chan::new(); + spawn(proc() { + let mut s2 = s2; + p1.recv(); + s2.write([1]).unwrap(); + c2.send(()); + }); + c1.send(()); + let mut buf = [0, 0]; + assert_eq!(s1.read(buf), Ok(1)); + p2.recv(); + } + + #[test] + fn unix_clone_two_read() { + let addr = next_test_unix(); + let mut acceptor = UnixListener::bind(&addr).listen(); + let (p, c) = SharedChan::new(); + let c2 = c.clone(); + + spawn(proc() { + let mut s = UnixStream::connect(&addr); + s.write([1]).unwrap(); + p.recv(); + s.write([2]).unwrap(); + p.recv(); + }); + + let mut s1 = acceptor.accept().unwrap(); + let s2 = s1.clone(); + + let (p, done) = Chan::new(); + spawn(proc() { + let mut s2 = s2; + let mut buf = [0, 0]; + s2.read(buf).unwrap(); + c2.send(()); + done.send(()); + }); + let mut buf = [0, 0]; + s1.read(buf).unwrap(); + c.send(()); + + p.recv(); + } + + #[test] + fn unix_clone_two_write() { + let addr = next_test_unix(); + let mut acceptor = UnixListener::bind(&addr).listen(); + + spawn(proc() { + let mut s = UnixStream::connect(&addr); + let mut buf = [0, 1]; + s.read(buf).unwrap(); + s.read(buf).unwrap(); + }); + + let mut s1 = acceptor.accept().unwrap(); + let s2 = s1.clone(); + + let (p, done) = Chan::new(); + spawn(proc() { + let mut s2 = s2; + s2.write([1]).unwrap(); + done.send(()); + }); + s1.write([2]).unwrap(); + + p.recv(); + } } diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs index ca85707149b92..83250bdae7361 100644 --- a/src/libstd/io/pipe.rs +++ b/src/libstd/io/pipe.rs @@ -51,6 +51,12 @@ impl PipeStream { } } +impl Clone for PipeStream { + fn clone(&self) -> PipeStream { + PipeStream { obj: self.obj.clone() } + } +} + impl Reader for PipeStream { fn read(&mut self, buf: &mut [u8]) -> IoResult { self.obj.read(buf) } } diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs index 11a7b5dd19171..057d618f44490 100644 --- a/src/libstd/libc.rs +++ b/src/libstd/libc.rs @@ -960,6 +960,8 @@ pub mod types { } pub mod extra { use ptr; + use libc::consts::os::extra::{MAX_PROTOCOL_CHAIN, + WSAPROTOCOL_LEN}; use libc::types::common::c95::c_void; use libc::types::os::arch::c95::{c_char, c_int, c_uint, size_t}; use libc::types::os::arch::c95::{c_long, c_ulong}; @@ -1106,6 +1108,47 @@ pub mod types { } pub type LPFILETIME = *mut FILETIME; + + pub struct GUID { + Data1: DWORD, + Data2: DWORD, + Data3: DWORD, + Data4: [BYTE, ..8], + } + + struct WSAPROTOCOLCHAIN { + ChainLen: c_int, + ChainEntries: [DWORD, ..MAX_PROTOCOL_CHAIN], + } + + pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN; + + pub struct WSAPROTOCOL_INFO { + dwServiceFlags1: DWORD, + dwServiceFlags2: DWORD, + dwServiceFlags3: DWORD, + dwServiceFlags4: DWORD, + dwProviderFlags: DWORD, + ProviderId: GUID, + dwCatalogEntryId: DWORD, + ProtocolChain: WSAPROTOCOLCHAIN, + iVersion: c_int, + iAddressFamily: c_int, + iMaxSockAddr: c_int, + iMinSockAddr: c_int, + iSocketType: c_int, + iProtocol: c_int, + iProtocolMaxOffset: c_int, + iNetworkByteOrder: c_int, + iSecurityScheme: c_int, + dwMessageSize: DWORD, + dwProviderReserved: DWORD, + szProtocol: [u8, ..WSAPROTOCOL_LEN+1], + } + + pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO; + + pub type GROUP = c_uint; } } } @@ -1721,6 +1764,10 @@ pub mod consts { pub static FILE_BEGIN: DWORD = 0; pub static FILE_CURRENT: DWORD = 1; pub static FILE_END: DWORD = 2; + + pub static MAX_PROTOCOL_CHAIN: DWORD = 7; + pub static WSAPROTOCOL_LEN: DWORD = 255; + pub static INVALID_SOCKET: DWORD = !0; } pub mod sysconf { } @@ -4098,6 +4145,8 @@ pub mod funcs { lpFrequency: *mut LARGE_INTEGER) -> BOOL; pub fn QueryPerformanceCounter( lpPerformanceCount: *mut LARGE_INTEGER) -> BOOL; + + pub fn GetCurrentProcessId() -> DWORD; } } diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs index 719cf2450c505..5c3ca07f128c4 100644 --- a/src/libstd/local_data.rs +++ b/src/libstd/local_data.rs @@ -41,7 +41,9 @@ local_data::get(key_vector, |opt| assert_eq!(*opt.unwrap(), ~[4])); // magic. use cast; -use prelude::*; +use option::{None,Option,Some}; +use vec::{ImmutableVector,MutableVector,OwnedVector}; +use iter::{Iterator}; use rt::task::{Task, LocalStorage}; use util::replace; diff --git a/src/libstd/option.rs b/src/libstd/option.rs index 39b516aeb12a7..7bb29fdfacf65 100644 --- a/src/libstd/option.rs +++ b/src/libstd/option.rs @@ -480,7 +480,6 @@ mod tests { use iter::range; use str::StrSlice; - use util; use kinds::marker; use vec::ImmutableVector; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 541db01f1484f..35fa4593a641f 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -28,20 +28,30 @@ #[allow(missing_doc)]; -use clone::Clone; -use container::Container; #[cfg(target_os = "macos")] +#[cfg(windows)] use iter::range; + +use clone::Clone; +use container::Container; use libc; use libc::{c_char, c_void, c_int}; -use option::{Some, None}; +use option::{Some, None, Option}; use os; -use prelude::*; +use ops::Drop; +use result::{Err, Ok, Result}; use ptr; use str; +use str::{Str, StrSlice}; +use cmp::Equiv; use fmt; use unstable::finally::Finally; use sync::atomics::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; +use path::{Path, GenericPath}; +use iter::Iterator; +use vec::{Vector, CloneableVector, ImmutableVector, MutableVector, OwnedVector}; +use ptr::RawPtr; +use c_str::ToCStr; /// Delegates to the libc close() function, returning the same return value. pub fn close(fd: int) -> int { @@ -396,6 +406,8 @@ pub fn self_exe_name() -> Option { #[cfg(windows)] fn load_self() -> Option<~[u8]> { + use str::OwnedStr; + unsafe { use os::win32::fill_utf16_buf_and_decode; fill_utf16_buf_and_decode(|buf, sz| { diff --git a/src/libstd/reference.rs b/src/libstd/reference.rs index 91f03f02892e3..7584d07ed6423 100644 --- a/src/libstd/reference.rs +++ b/src/libstd/reference.rs @@ -11,7 +11,7 @@ //! Utilities for references #[cfg(not(test))] -use prelude::*; +use cmp::{Eq,Ord,Ordering,TotalEq,TotalOrd}; // Equality for region pointers #[cfg(not(test))] diff --git a/src/libstd/result.rs b/src/libstd/result.rs index 846bba7533fed..81c337198ca75 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -20,6 +20,7 @@ use to_str::ToStr; /// `Result` is a type that represents either success (`Ok`) or failure (`Err`). #[deriving(Clone, DeepClone, Eq, Ord, TotalEq, TotalOrd, ToStr)] +#[deny(unused_must_use)] #[must_use] pub enum Result { /// Contains the success value diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs index 35b1e21df0677..8d02048d55cf0 100644 --- a/src/libstd/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -203,6 +203,7 @@ pub trait RtioTcpStream : RtioSocket { fn nodelay(&mut self) -> Result<(), IoError>; fn keepalive(&mut self, delay_in_seconds: uint) -> Result<(), IoError>; fn letdie(&mut self) -> Result<(), IoError>; + fn clone(&self) -> ~RtioTcpStream; } pub trait RtioSocket { @@ -224,6 +225,8 @@ pub trait RtioUdpSocket : RtioSocket { fn hear_broadcasts(&mut self) -> Result<(), IoError>; fn ignore_broadcasts(&mut self) -> Result<(), IoError>; + + fn clone(&self) -> ~RtioUdpSocket; } pub trait RtioTimer { @@ -253,6 +256,7 @@ pub trait RtioProcess { pub trait RtioPipe { fn read(&mut self, buf: &mut [u8]) -> Result; fn write(&mut self, buf: &[u8]) -> Result<(), IoError>; + fn clone(&self) -> ~RtioPipe; } pub trait RtioUnixListener { diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 04e42b3eedfc5..1b880bc43ee82 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -20,7 +20,13 @@ use io::process; use io; use libc::{pid_t, c_int}; use libc; -use prelude::*; +use option::{None,Option,Some}; +use task::spawn; +use path::{Path,GenericPath}; +use result::Ok; +use str::Str; +use vec::Vector; +use clone::Clone; /** * A value representing a child process. diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs index ef0930fabf1cd..7530c5e338aad 100644 --- a/src/libstd/trie.rs +++ b/src/libstd/trie.rs @@ -10,12 +10,16 @@ //! Ordered containers with integer keys, implemented as radix tries (`TrieSet` and `TrieMap` types) -use prelude::*; +use option::{None,Option,Some}; +use container::{Container,Map,Mutable,MutableMap}; +use iter::{Extendable,FromIterator,Iterator}; use mem; use uint; use util::replace; use unstable::intrinsics::init; use vec; +use ptr::RawPtr; +use vec::{ImmutableVector,Items,MutableVector,MutItems,OwnedVector}; // FIXME: #5244: need to manually update the TrieNode constructor static SHIFT: uint = 4; diff --git a/src/libstd/unit.rs b/src/libstd/unit.rs index 786a7f42bb394..d62fcca63a49e 100644 --- a/src/libstd/unit.rs +++ b/src/libstd/unit.rs @@ -11,7 +11,8 @@ //! Functions for the unit type. #[cfg(not(test))] -use prelude::*; +use default::Default; +use cmp::{Eq,Equal,Ord,Ordering,TotalEq,TotalOrd}; #[cfg(not(test))] impl Eq for () { diff --git a/src/libstd/unstable/mutex.rs b/src/libstd/unstable/mutex.rs index 4804de756876f..82957cd93ceb8 100644 --- a/src/libstd/unstable/mutex.rs +++ b/src/libstd/unstable/mutex.rs @@ -380,7 +380,6 @@ mod test { use super::{Mutex, MUTEX_INIT}; use rt::thread::Thread; - use task; #[test] fn somke_lock() { diff --git a/src/libstd/util.rs b/src/libstd/util.rs index c075f9b4ba84f..715a10b9112f9 100644 --- a/src/libstd/util.rs +++ b/src/libstd/util.rs @@ -69,7 +69,6 @@ impl Void { mod tests { use super::*; use prelude::*; - use mem::size_of; #[test] fn identity_crisis() { diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 4a6a4d54ae3e4..d53c2dceba248 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -4253,7 +4253,7 @@ mod tests { let h = x.mut_last(); assert_eq!(*h.unwrap(), 5); - let mut y: &mut [int] = []; + let y: &mut [int] = []; assert!(y.mut_last().is_none()); } } diff --git a/src/libstd/vec_ng.rs b/src/libstd/vec_ng.rs index e503497d95dff..c49a7302e729d 100644 --- a/src/libstd/vec_ng.rs +++ b/src/libstd/vec_ng.rs @@ -11,12 +11,16 @@ // Migrate documentation over from `std::vec` when it is removed. #[doc(hidden)]; -use prelude::*; +use ops::Drop; +use option::{None, Option, Some}; +use clone::Clone; +use iter::{DoubleEndedIterator, Iterator}; +use num::CheckedMul; use container::Container; use mem::size_of; use cast::{forget, transmute}; use rt::global_heap::{malloc_raw, realloc_raw}; -use vec::Items; +use vec::{ImmutableVector, Items, MutableVector}; use unstable::raw::Slice; use ptr::{offset, read_ptr}; use libc::{free, c_void}; diff --git a/src/libextra/arc.rs b/src/libsync/arc.rs similarity index 99% rename from src/libextra/arc.rs rename to src/libsync/arc.rs index 7f8d64053d51c..0e53ecd416a7a 100644 --- a/src/libextra/arc.rs +++ b/src/libsync/arc.rs @@ -18,7 +18,7 @@ * With simple pipes, without Arc, a copy would have to be made for each task. * * ```rust - * use extra::arc::Arc; + * use sync::Arc; * use std::{rand, vec}; * * let numbers = vec::from_fn(100, |i| (i as f32) * rand::random()); @@ -38,7 +38,7 @@ * ``` */ -#[allow(missing_doc)]; +#[allow(missing_doc, dead_code)]; use sync; @@ -424,7 +424,7 @@ impl RWArc { * # Example * * ```rust - * use extra::arc::RWArc; + * use sync::RWArc; * * let arc = RWArc::new(1); * arc.write_downgrade(|mut write_token| { @@ -605,7 +605,7 @@ impl Clone for CowArc { #[cfg(test)] mod tests { - use arc::*; + use super::{Arc, RWArc, MutexArc, CowArc}; use std::task; diff --git a/src/libextra/comm.rs b/src/libsync/comm.rs similarity index 100% rename from src/libextra/comm.rs rename to src/libsync/comm.rs diff --git a/src/libextra/future.rs b/src/libsync/future.rs similarity index 99% rename from src/libextra/future.rs rename to src/libsync/future.rs index b9121290f33f4..479174d17afb0 100644 --- a/src/libextra/future.rs +++ b/src/libsync/future.rs @@ -15,7 +15,7 @@ * # Example * * ```rust - * use extra::future::Future; + * use sync::Future; * # fn fib(n: uint) -> uint {42}; * # fn make_a_sandwich() {}; * let mut delayed_fib = Future::spawn(proc() { fib(5000) }); diff --git a/src/libsync/lib.rs b/src/libsync/lib.rs new file mode 100644 index 0000000000000..de1b0f91d6dc5 --- /dev/null +++ b/src/libsync/lib.rs @@ -0,0 +1,31 @@ +// Copyright 2012-2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * Concurrency-enabled mechanisms and primitives. + */ + +#[crate_id = "sync#0.10-pre"]; +#[crate_type = "rlib"]; +#[crate_type = "dylib"]; +#[license = "MIT/ASL2"]; + +pub use arc::{Arc, MutexArc, RWArc, RWWriteMode, RWReadMode, Condvar}; +pub use sync::{Mutex, RWLock, Condvar, Semaphore, RWLockWriteMode, + RWLockReadMode, Barrier, one, mutex}; +pub use comm::{DuplexStream, SyncChan, SyncPort, rendezvous}; +pub use task_pool::TaskPool; +pub use future::Future; + +mod arc; +mod sync; +mod comm; +mod task_pool; +mod future; diff --git a/src/libextra/sync/mod.rs b/src/libsync/sync/mod.rs similarity index 99% rename from src/libextra/sync/mod.rs rename to src/libsync/sync/mod.rs index 03bf1101f1f29..cfff31e08d4b3 100644 --- a/src/libextra/sync/mod.rs +++ b/src/libsync/sync/mod.rs @@ -588,7 +588,7 @@ impl RWLock { * # Example * * ```rust - * use extra::sync::RWLock; + * use sync::RWLock; * * let lock = RWLock::new(); * lock.write_downgrade(|mut write_token| { @@ -695,7 +695,7 @@ impl<'a> RWLockReadMode<'a> { /// of some computation. /// /// ```rust -/// use extra::sync::Barrier; +/// use sync::Barrier; /// /// let barrier = Barrier::new(10); /// for _ in range(0, 10) { @@ -759,7 +759,7 @@ impl Barrier { #[cfg(test)] mod tests { - use sync::*; + use sync::{Semaphore, Mutex, RWLock, Barrier, Condvar}; use std::cast; use std::result; diff --git a/src/libextra/sync/mpsc_intrusive.rs b/src/libsync/sync/mpsc_intrusive.rs similarity index 100% rename from src/libextra/sync/mpsc_intrusive.rs rename to src/libsync/sync/mpsc_intrusive.rs diff --git a/src/libextra/sync/mutex.rs b/src/libsync/sync/mutex.rs similarity index 99% rename from src/libextra/sync/mutex.rs rename to src/libsync/sync/mutex.rs index 7ea98c0741a29..f1a81d65c1da5 100644 --- a/src/libextra/sync/mutex.rs +++ b/src/libsync/sync/mutex.rs @@ -83,7 +83,7 @@ pub static NATIVE_BLOCKED: uint = 1 << 2; /// # Example /// /// ```rust -/// use extra::sync::mutex::Mutex; +/// use sync::mutex::Mutex; /// /// let mut m = Mutex::new(); /// let guard = m.lock(); @@ -113,7 +113,7 @@ enum Flavor { /// # Example /// /// ```rust -/// use extra::sync::mutex::{StaticMutex, MUTEX_INIT}; +/// use sync::mutex::{StaticMutex, MUTEX_INIT}; /// /// static mut LOCK: StaticMutex = MUTEX_INIT; /// diff --git a/src/libextra/sync/one.rs b/src/libsync/sync/one.rs similarity index 99% rename from src/libextra/sync/one.rs rename to src/libsync/sync/one.rs index 826955d93e8d3..93d818b704dc9 100644 --- a/src/libextra/sync/one.rs +++ b/src/libsync/sync/one.rs @@ -30,7 +30,7 @@ use sync::mutex::{StaticMutex, MUTEX_INIT}; /// # Example /// /// ```rust -/// use extra::sync::one::{Once, ONCE_INIT}; +/// use sync::one::{Once, ONCE_INIT}; /// /// static mut START: Once = ONCE_INIT; /// unsafe { diff --git a/src/libextra/task_pool.rs b/src/libsync/task_pool.rs similarity index 100% rename from src/libextra/task_pool.rs rename to src/libsync/task_pool.rs diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 228329cbda12a..abfd119acbb99 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -22,7 +22,7 @@ use std::hashmap::HashMap; use std::option::Option; use std::rc::Rc; use std::to_str::ToStr; -use extra::serialize::{Encodable, Decodable, Encoder, Decoder}; +use serialize::{Encodable, Decodable, Encoder, Decoder}; /// A pointer abstraction. FIXME(eddyb) #10676 use Rc in the future. pub type P = @T; @@ -1204,6 +1204,7 @@ pub enum InlinedItem { #[cfg(test)] mod test { + use serialize; use extra; use codemap::*; use super::*; @@ -1230,6 +1231,6 @@ mod test { }, }; // doesn't matter which encoder we use.... - let _f = (@e as @extra::serialize::Encodable); + let _f = (@e as @serialize::Encodable); } } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 2ada3ac16ea66..a6c1a373d887f 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -23,7 +23,7 @@ source code snippets, etc. use std::cell::RefCell; use std::cmp; -use extra::serialize::{Encodable, Decodable, Encoder, Decoder}; +use serialize::{Encodable, Decodable, Encoder, Decoder}; pub trait Pos { fn from_uint(n: uint) -> Self; diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 019a4dfe7cca4..ad7b3a2e950ae 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -28,12 +28,12 @@ pub fn expand_deriving_decodable(cx: &ExtCtxt, let trait_def = TraitDef { cx: cx, span: span, - path: Path::new_(~["extra", "serialize", "Decodable"], None, + path: Path::new_(~["serialize", "Decodable"], None, ~[~Literal(Path::new_local("__D"))], true), additional_bounds: ~[], generics: LifetimeBounds { lifetimes: ~[], - bounds: ~[("__D", ~[Path::new(~["extra", "serialize", "Decoder"])])], + bounds: ~[("__D", ~[Path::new(~["serialize", "Decoder"])])], }, methods: ~[ MethodDef { @@ -56,8 +56,7 @@ pub fn expand_deriving_decodable(cx: &ExtCtxt, fn decodable_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { let decoder = substr.nonself_args[0]; - let recurse = ~[cx.ident_of("extra"), - cx.ident_of("serialize"), + let recurse = ~[cx.ident_of("serialize"), cx.ident_of("Decodable"), cx.ident_of("decode")]; // throw an underscore in front to suppress unused variable warnings diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index c50c9f18389c2..66b744ecbcb4a 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -22,7 +22,7 @@ For example, a type like: would generate two implementations like: -impl Encodable for Node { +impl Encodable for Node { fn encode(&self, s: &S) { s.emit_struct("Node", 1, || { s.emit_field("id", 0, || s.emit_uint(self.id)) @@ -89,12 +89,12 @@ pub fn expand_deriving_encodable(cx: &ExtCtxt, let trait_def = TraitDef { cx: cx, span: span, - path: Path::new_(~["extra", "serialize", "Encodable"], None, + path: Path::new_(~["serialize", "Encodable"], None, ~[~Literal(Path::new_local("__E"))], true), additional_bounds: ~[], generics: LifetimeBounds { lifetimes: ~[], - bounds: ~[("__E", ~[Path::new(~["extra", "serialize", "Encoder"])])], + bounds: ~[("__E", ~[Path::new(~["serialize", "Encoder"])])], }, methods: ~[ MethodDef { diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 8eaff592765b2..992ee3175edd9 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -204,7 +204,7 @@ pub struct TraitDef<'a> { /// other than the current trait additional_bounds: ~[Ty<'a>], - /// Any extra lifetimes and/or bounds, e.g. `D: extra::serialize::Decoder` + /// Any extra lifetimes and/or bounds, e.g. `D: serialize::Decoder` generics: LifetimeBounds<'a>, methods: ~[MethodDef<'a>] diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index e2460b0171a20..3f305a4eb0e64 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -27,10 +27,13 @@ This API is completely unstable and subject to change. html_root_url = "http://static.rust-lang.org/doc/master")]; #[feature(macro_rules, globs, managed_boxes)]; +#[allow(unknown_features)];// Note: remove it after a snapshot. +#[feature(quote)]; #[deny(non_camel_case_types)]; extern mod extra; +extern mod serialize; extern mod term; pub mod util { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 328f0e7f22187..faebd97e7c270 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -284,7 +284,7 @@ pub fn maybe_aborted(result: T, mut p: Parser) -> T { #[cfg(test)] mod test { use super::*; - use extra::serialize::Encodable; + use serialize::Encodable; use extra; use std::io; use std::io::MemWriter; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index f1dd844fc7c68..090774ec76ff2 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -15,7 +15,7 @@ use parse::token; use util::interner::{RcStr, StrInterner}; use util::interner; -use extra::serialize::{Decodable, Decoder, Encodable, Encoder}; +use serialize::{Decodable, Decoder, Encodable, Encoder}; use std::cast; use std::char; use std::fmt; diff --git a/src/libuuid/lib.rs b/src/libuuid/lib.rs index 60e69af324e1a..1951c52237f5f 100644 --- a/src/libuuid/lib.rs +++ b/src/libuuid/lib.rs @@ -59,7 +59,10 @@ Examples of string representations: #[crate_type = "dylib"]; #[license = "MIT/ASL2"]; +// test harness access +#[cfg(test)] extern mod extra; +extern mod serialize; use std::str; use std::vec; @@ -73,7 +76,7 @@ use std::cmp::Eq; use std::cast::{transmute,transmute_copy}; use std::to_bytes::{IterBytes, Cb}; -use extra::serialize::{Encoder, Encodable, Decoder, Decodable}; +use serialize::{Encoder, Encodable, Decoder, Decodable}; /// A 128-bit (16 byte) buffer containing the ID pub type UuidBytes = [u8, ..16]; @@ -784,8 +787,8 @@ mod test { #[test] fn test_serialize_round_trip() { - use extra::ebml; - use extra::serialize::{Encodable, Decodable}; + use serialize::ebml; + use serialize::{Encodable, Decodable}; let u = Uuid::new_v4(); let mut wr = MemWriter::new(); diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs index e5bf8574366c8..2867e0f814306 100644 --- a/src/test/auxiliary/macro_crate_test.rs +++ b/src/test/auxiliary/macro_crate_test.rs @@ -10,7 +10,7 @@ // force-host -#[feature(globs, macro_registrar, macro_rules)]; +#[feature(globs, macro_registrar, macro_rules, quote)]; extern mod syntax; diff --git a/src/test/auxiliary/trait_impl_conflict.rs b/src/test/auxiliary/trait_impl_conflict.rs new file mode 100644 index 0000000000000..990bc21604959 --- /dev/null +++ b/src/test/auxiliary/trait_impl_conflict.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait Foo { +} + +impl Foo for int { +} diff --git a/src/test/bench/msgsend-ring-mutex-arcs.rs b/src/test/bench/msgsend-ring-mutex-arcs.rs index b1b2300466a5e..4b505ec811762 100644 --- a/src/test/bench/msgsend-ring-mutex-arcs.rs +++ b/src/test/bench/msgsend-ring-mutex-arcs.rs @@ -16,15 +16,17 @@ // This also serves as a pipes test, because Arcs are implemented with pipes. extern mod extra; +extern mod sync; -use extra::arc; -use extra::future::Future; +use sync::Arc; +use sync::MutexArc; +use sync::Future; use extra::time; use std::os; use std::uint; // A poor man's pipe. -type pipe = arc::MutexArc<~[uint]>; +type pipe = MutexArc<~[uint]>; fn send(p: &pipe, msg: uint) { unsafe { @@ -46,7 +48,7 @@ fn recv(p: &pipe) -> uint { } fn init() -> (pipe,pipe) { - let m = arc::MutexArc::new(~[]); + let m = MutexArc::new(~[]); ((&m).clone(), m) } diff --git a/src/test/bench/msgsend-ring-rw-arcs.rs b/src/test/bench/msgsend-ring-rw-arcs.rs index d7bd0f2f6bd3d..23b4f00b280da 100644 --- a/src/test/bench/msgsend-ring-rw-arcs.rs +++ b/src/test/bench/msgsend-ring-rw-arcs.rs @@ -16,15 +16,16 @@ // This also serves as a pipes test, because Arcs are implemented with pipes. extern mod extra; +extern mod sync; -use extra::arc; -use extra::future::Future; +use sync::RWArc; +use sync::Future; use extra::time; use std::os; use std::uint; // A poor man's pipe. -type pipe = arc::RWArc<~[uint]>; +type pipe = RWArc<~[uint]>; fn send(p: &pipe, msg: uint) { p.write_cond(|state, cond| { @@ -42,7 +43,7 @@ fn recv(p: &pipe) -> uint { } fn init() -> (pipe,pipe) { - let x = arc::RWArc::new(~[]); + let x = RWArc::new(~[]); ((&x).clone(), x) } diff --git a/src/test/bench/shootout-binarytrees.rs b/src/test/bench/shootout-binarytrees.rs index da658e6d041f7..c0e22f207b8f9 100644 --- a/src/test/bench/shootout-binarytrees.rs +++ b/src/test/bench/shootout-binarytrees.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod extra; +extern mod sync; extern mod arena; use std::iter::range_step; -use extra::future::Future; +use sync::Future; use arena::TypedArena; enum Tree<'a> { diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index d68ca4e0abbae..9de62aaf960e8 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -10,15 +10,15 @@ // xfail-test arcs no longer unwrap -extern mod extra; +extern mod sync; use std::from_str::FromStr; use std::iter::count; use std::num::min; use std::os; use std::vec::from_elem; -use extra::arc::Arc; -use extra::arc::RWArc; +use sync::Arc; +use sync::RWArc; fn A(i: uint, j: uint) -> f64 { ((i + j) * (i + j + 1) / 2 + i + 1) as f64 diff --git a/src/test/compile-fail/arc-cant-nest-rw-arc-3177.rs b/src/test/compile-fail/arc-cant-nest-rw-arc-3177.rs index 49412b3aafdea..5c55f10ab4f2a 100644 --- a/src/test/compile-fail/arc-cant-nest-rw-arc-3177.rs +++ b/src/test/compile-fail/arc-cant-nest-rw-arc-3177.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod extra; -use extra::arc::RWArc; +extern mod sync; +use sync::RWArc; fn main() { let arc1 = RWArc::new(true); diff --git a/src/test/compile-fail/arc-rw-cond-shouldnt-escape.rs b/src/test/compile-fail/arc-rw-cond-shouldnt-escape.rs index c31a7bb244c72..c9cd132788225 100644 --- a/src/test/compile-fail/arc-rw-cond-shouldnt-escape.rs +++ b/src/test/compile-fail/arc-rw-cond-shouldnt-escape.rs @@ -9,10 +9,10 @@ // except according to those terms. // error-pattern: lifetime of return value does not outlive the function call -extern mod extra; -use extra::arc; +extern mod sync; +use sync::RWArc; fn main() { - let x = ~arc::RWArc::new(1); + let x = ~RWArc::new(1); let mut y = None; x.write_cond(|_one, cond| y = Some(cond)); y.unwrap().wait(); diff --git a/src/test/compile-fail/arc-rw-read-mode-shouldnt-escape.rs b/src/test/compile-fail/arc-rw-read-mode-shouldnt-escape.rs index 716dfe2c8b5c5..dfdbd882acff6 100644 --- a/src/test/compile-fail/arc-rw-read-mode-shouldnt-escape.rs +++ b/src/test/compile-fail/arc-rw-read-mode-shouldnt-escape.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod extra; -use extra::arc; +extern mod sync; +use sync::RWArc; fn main() { - let x = ~arc::RWArc::new(1); + let x = ~RWArc::new(1); let mut y = None; x.write_downgrade(|write_mode| { y = Some(x.downgrade(write_mode)); diff --git a/src/test/compile-fail/arc-rw-state-shouldnt-escape.rs b/src/test/compile-fail/arc-rw-state-shouldnt-escape.rs index 7c129ae0dcaad..4bb7653d23e5c 100644 --- a/src/test/compile-fail/arc-rw-state-shouldnt-escape.rs +++ b/src/test/compile-fail/arc-rw-state-shouldnt-escape.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod extra; -use extra::arc; +extern mod sync; +use sync::RWArc; fn main() { - let x = ~arc::RWArc::new(1); + let x = ~RWArc::new(1); let mut y = None; //~ ERROR lifetime of variable does not enclose its declaration x.write(|one| y = Some(one)); *y.unwrap() = 2; diff --git a/src/test/compile-fail/arc-rw-write-mode-cond-shouldnt-escape.rs b/src/test/compile-fail/arc-rw-write-mode-cond-shouldnt-escape.rs index 674cd5708889c..1410308107e94 100644 --- a/src/test/compile-fail/arc-rw-write-mode-cond-shouldnt-escape.rs +++ b/src/test/compile-fail/arc-rw-write-mode-cond-shouldnt-escape.rs @@ -9,10 +9,10 @@ // except according to those terms. // error-pattern: lifetime of variable does not enclose its declaration -extern mod extra; -use extra::arc; +extern mod sync; +use sync::RWArc; fn main() { - let x = ~arc::RWArc::new(1); + let x = ~RWArc::new(1); let mut y = None; x.write_downgrade(|write_mode| { (&write_mode).write_cond(|_one, cond| { diff --git a/src/test/compile-fail/arc-rw-write-mode-shouldnt-escape.rs b/src/test/compile-fail/arc-rw-write-mode-shouldnt-escape.rs index 213bf48a08750..68226d96a18ef 100644 --- a/src/test/compile-fail/arc-rw-write-mode-shouldnt-escape.rs +++ b/src/test/compile-fail/arc-rw-write-mode-shouldnt-escape.rs @@ -9,10 +9,10 @@ // except according to those terms. // error-pattern: lifetime of variable does not enclose its declaration -extern mod extra; -use extra::arc; +extern mod sync; +use sync::RWArc; fn main() { - let x = ~arc::RWArc::new(1); + let x = ~RWArc::new(1); let mut y = None; x.write_downgrade(|write_mode| y = Some(write_mode)); y.unwrap(); diff --git a/src/test/compile-fail/conflicting-implementations-aux.rs b/src/test/compile-fail/conflicting-implementations-aux.rs new file mode 100644 index 0000000000000..e39059124a091 --- /dev/null +++ b/src/test/compile-fail/conflicting-implementations-aux.rs @@ -0,0 +1,24 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #3512 - conflicting trait impls in different crates should give a +// 'conflicting implementations' error message. + +// aux-build:trait_impl_conflict.rs +extern mod trait_impl_conflict; +use trait_impl_conflict::Foo; + +impl Foo for A { +//~^ ERROR conflicting implementations for trait `trait_impl_conflict::Foo` +//~^^ ERROR cannot provide an extension implementation where both trait and type are not defined in this crate +} + +fn main() { +} diff --git a/src/test/compile-fail/functional-struct-update-noncopyable.rs b/src/test/compile-fail/functional-struct-update-noncopyable.rs index 00945ea84693c..f2c9ba5822893 100644 --- a/src/test/compile-fail/functional-struct-update-noncopyable.rs +++ b/src/test/compile-fail/functional-struct-update-noncopyable.rs @@ -11,8 +11,8 @@ // issue 7327 // xfail-fast #7103 -extern mod extra; -use extra::arc::Arc; +extern mod sync; +use sync::Arc; struct A { y: Arc, x: Arc } diff --git a/src/test/compile-fail/future_not_copyable.rs b/src/test/compile-fail/future_not_copyable.rs index aef5d0f9b04a6..69a90275ec78b 100644 --- a/src/test/compile-fail/future_not_copyable.rs +++ b/src/test/compile-fail/future_not_copyable.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod extra; +extern mod sync; -use extra::future::Future; +use sync::Future; fn main() { let f = Future::from_value(()); diff --git a/src/test/compile-fail/mutex-arc-nested.rs b/src/test/compile-fail/mutex-arc-nested.rs index 24a141c4799d5..cdfdd29410e76 100644 --- a/src/test/compile-fail/mutex-arc-nested.rs +++ b/src/test/compile-fail/mutex-arc-nested.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod extra; +extern mod sync; use std::task; -use extra::arc::{MutexArc}; +use sync::MutexArc; fn test_mutex_arc_nested() { let arc = ~MutexArc::new(1); diff --git a/src/test/compile-fail/no-capture-arc.rs b/src/test/compile-fail/no-capture-arc.rs index 5ae38e69ec0e3..cc529abd6f94f 100644 --- a/src/test/compile-fail/no-capture-arc.rs +++ b/src/test/compile-fail/no-capture-arc.rs @@ -10,14 +10,14 @@ // error-pattern: use of moved value -extern mod extra; -use extra::arc; +extern mod sync; +use sync::Arc; use std::task; fn main() { let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let arc_v = arc::Arc::new(v); + let arc_v = Arc::new(v); task::spawn(proc() { let v = arc_v.get(); diff --git a/src/test/compile-fail/no-reuse-move-arc.rs b/src/test/compile-fail/no-reuse-move-arc.rs index c6c0ba41ab91a..204a0e1cdd4a0 100644 --- a/src/test/compile-fail/no-reuse-move-arc.rs +++ b/src/test/compile-fail/no-reuse-move-arc.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod extra; -use extra::arc; +extern mod sync; +use sync::Arc; use std::task; fn main() { let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let arc_v = arc::Arc::new(v); + let arc_v = Arc::new(v); task::spawn(proc() { let v = arc_v.get(); diff --git a/src/test/compile-fail/once-cant-call-twice-on-heap.rs b/src/test/compile-fail/once-cant-call-twice-on-heap.rs index 8d5e2229b2e5d..a7e4f8de43704 100644 --- a/src/test/compile-fail/once-cant-call-twice-on-heap.rs +++ b/src/test/compile-fail/once-cant-call-twice-on-heap.rs @@ -12,8 +12,8 @@ // This program would segfault if it were legal. #[feature(once_fns)]; -extern mod extra; -use extra::arc; +extern mod sync; +use sync::Arc; fn foo(blk: proc()) { blk(); @@ -21,7 +21,7 @@ fn foo(blk: proc()) { } fn main() { - let x = arc::Arc::new(true); + let x = Arc::new(true); foo(proc() { assert!(*x.get()); drop(x); diff --git a/src/test/compile-fail/once-cant-call-twice-on-stack.rs b/src/test/compile-fail/once-cant-call-twice-on-stack.rs index 71293555d499d..8b168dd67870e 100644 --- a/src/test/compile-fail/once-cant-call-twice-on-stack.rs +++ b/src/test/compile-fail/once-cant-call-twice-on-stack.rs @@ -12,8 +12,8 @@ // This program would segfault if it were legal. #[feature(once_fns)]; -extern mod extra; -use extra::arc; +extern mod sync; +use sync::Arc; fn foo(blk: once ||) { blk(); @@ -21,7 +21,7 @@ fn foo(blk: once ||) { } fn main() { - let x = arc::Arc::new(true); + let x = Arc::new(true); foo(|| { assert!(*x.get()); drop(x); diff --git a/src/test/compile-fail/once-cant-move-out-of-non-once-on-stack.rs b/src/test/compile-fail/once-cant-move-out-of-non-once-on-stack.rs index 7206b9bdb88eb..4fa6b6af7949e 100644 --- a/src/test/compile-fail/once-cant-move-out-of-non-once-on-stack.rs +++ b/src/test/compile-fail/once-cant-move-out-of-non-once-on-stack.rs @@ -11,8 +11,8 @@ // Testing guarantees provided by once functions. // This program would segfault if it were legal. -extern mod extra; -use extra::arc; +extern mod sync; +use sync::Arc; fn foo(blk: ||) { blk(); @@ -20,7 +20,7 @@ fn foo(blk: ||) { } fn main() { - let x = arc::Arc::new(true); + let x = Arc::new(true); foo(|| { assert!(*x.get()); drop(x); //~ ERROR cannot move out of captured outer variable diff --git a/src/test/compile-fail/qquote-1.rs b/src/test/compile-fail/qquote-1.rs index f55fcfc204b2f..6dcbf3df9d653 100644 --- a/src/test/compile-fail/qquote-1.rs +++ b/src/test/compile-fail/qquote-1.rs @@ -9,6 +9,7 @@ // except according to those terms. // xfail-test Can't use syntax crate here +#[feature(quote)]; extern mod extra; extern mod syntax; diff --git a/src/test/compile-fail/qquote-2.rs b/src/test/compile-fail/qquote-2.rs index 262abc045a411..0e5c852fd6ecb 100644 --- a/src/test/compile-fail/qquote-2.rs +++ b/src/test/compile-fail/qquote-2.rs @@ -9,6 +9,7 @@ // except according to those terms. // xfail-test Can't use syntax crate here +#[feature(quote)]; extern mod extra; extern mod syntax; diff --git a/src/test/compile-fail/sync-cond-shouldnt-escape.rs b/src/test/compile-fail/sync-cond-shouldnt-escape.rs index 4df08b28eb896..06b8ad6259b6b 100644 --- a/src/test/compile-fail/sync-cond-shouldnt-escape.rs +++ b/src/test/compile-fail/sync-cond-shouldnt-escape.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: lifetime of variable does not enclose its declaration -extern mod extra; -use extra::sync; +extern mod sync; +use sync::Mutex; fn main() { let m = ~sync::Mutex::new(); diff --git a/src/test/compile-fail/sync-rwlock-cond-shouldnt-escape.rs b/src/test/compile-fail/sync-rwlock-cond-shouldnt-escape.rs index d59eaf62abf84..52466c122dd7f 100644 --- a/src/test/compile-fail/sync-rwlock-cond-shouldnt-escape.rs +++ b/src/test/compile-fail/sync-rwlock-cond-shouldnt-escape.rs @@ -9,10 +9,10 @@ // except according to those terms. // error-pattern: lifetime of method receiver does not outlive the method call -extern mod extra; -use extra::sync; +extern mod sync; +use sync::RWLock; fn main() { - let x = ~sync::RWLock::new(); + let x = ~RWLock::new(); let mut y = None; x.write_cond(|cond| { y = Some(cond); diff --git a/src/test/compile-fail/sync-rwlock-read-mode-shouldnt-escape.rs b/src/test/compile-fail/sync-rwlock-read-mode-shouldnt-escape.rs index 0078841acb139..0201f9dd51cbf 100644 --- a/src/test/compile-fail/sync-rwlock-read-mode-shouldnt-escape.rs +++ b/src/test/compile-fail/sync-rwlock-read-mode-shouldnt-escape.rs @@ -9,10 +9,10 @@ // except according to those terms. // error-pattern: cannot infer an appropriate lifetime -extern mod extra; -use extra::sync; +extern mod sync; +use sync::RWLock; fn main() { - let x = ~sync::RWLock::new(); + let x = ~RWLock::new(); let mut y = None; x.write_downgrade(|write_mode| { y = Some(x.downgrade(write_mode)); diff --git a/src/test/compile-fail/sync-rwlock-write-mode-cond-shouldnt-escape.rs b/src/test/compile-fail/sync-rwlock-write-mode-cond-shouldnt-escape.rs index cbe5181d46f24..71a9dd100c395 100644 --- a/src/test/compile-fail/sync-rwlock-write-mode-cond-shouldnt-escape.rs +++ b/src/test/compile-fail/sync-rwlock-write-mode-cond-shouldnt-escape.rs @@ -9,10 +9,10 @@ // except according to those terms. // error-pattern: lifetime of variable does not enclose its declaration -extern mod extra; -use extra::sync; +extern mod sync; +use sync::RWLock; fn main() { - let x = ~sync::RWLock::new(); + let x = ~RWLock::new(); let mut y = None; x.write_downgrade(|write_mode| { (&write_mode).write_cond(|cond| { diff --git a/src/test/compile-fail/sync-rwlock-write-mode-shouldnt-escape.rs b/src/test/compile-fail/sync-rwlock-write-mode-shouldnt-escape.rs index 6e9216830750b..53966bf48a493 100644 --- a/src/test/compile-fail/sync-rwlock-write-mode-shouldnt-escape.rs +++ b/src/test/compile-fail/sync-rwlock-write-mode-shouldnt-escape.rs @@ -9,10 +9,10 @@ // except according to those terms. // error-pattern: lifetime of variable does not enclose its declaration -extern mod extra; -use extra::sync; +extern mod sync; +use sync::RWLock; fn main() { - let x = ~sync::RWLock::new(); + let x = ~RWLock::new(); let mut y = None; x.write_downgrade(|write_mode| { y = Some(write_mode); diff --git a/src/test/run-fail/issue-2444.rs b/src/test/run-fail/issue-2444.rs index c1357988f7db5..16f54e929236a 100644 --- a/src/test/run-fail/issue-2444.rs +++ b/src/test/run-fail/issue-2444.rs @@ -10,10 +10,10 @@ // error-pattern:explicit failure -extern mod extra; -use extra::arc; +extern mod sync; +use sync::Arc; -enum e { e(arc::Arc) } +enum e { e(Arc) } fn foo() -> e {fail!();} diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs index 05225eb0e7ada..dc67ff21585dc 100644 --- a/src/test/run-pass-fulldeps/qquote.rs +++ b/src/test/run-pass-fulldeps/qquote.rs @@ -10,6 +10,7 @@ // xfail-pretty // xfail-test +#[feature(quote)]; extern mod extra; extern mod syntax; diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs index dc95faa198647..7429ac45904cc 100644 --- a/src/test/run-pass-fulldeps/quote-tokens.rs +++ b/src/test/run-pass-fulldeps/quote-tokens.rs @@ -9,7 +9,7 @@ // except according to those terms. // xfail-test - +#[feature(quote)]; #[feature(managed_boxes)]; extern mod syntax; diff --git a/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs b/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs index a8b7dc3d382f3..0411c0b1cea3f 100644 --- a/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs +++ b/src/test/run-pass-fulldeps/quote-unused-sp-no-warning.rs @@ -10,7 +10,7 @@ // xfail-fast // xfail-android - +#[feature(quote)]; #[deny(unused_variable)]; extern mod syntax; diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs index f3af7d652cde4..027b329b17831 100644 --- a/src/test/run-pass/auto-encode.rs +++ b/src/test/run-pass/auto-encode.rs @@ -26,7 +26,7 @@ use EBWriter = extra::ebml::writer; use std::cmp::Eq; use std::cmp; use std::io; -use extra::serialize::{Decodable, Encodable}; +use serialize::{Decodable, Encodable}; use extra::time; fn test_ebml<'a, A: diff --git a/src/test/run-pass/bind-by-move.rs b/src/test/run-pass/bind-by-move.rs index a7a4aa9885e6e..3a86357bdaad1 100644 --- a/src/test/run-pass/bind-by-move.rs +++ b/src/test/run-pass/bind-by-move.rs @@ -9,12 +9,12 @@ // except according to those terms. // xfail-fast -extern mod extra; -use extra::arc; -fn dispose(_x: arc::Arc) { } +extern mod sync; +use sync::Arc; +fn dispose(_x: Arc) { } pub fn main() { - let p = arc::Arc::new(true); + let p = Arc::new(true); let x = Some(p); match x { Some(z) => { dispose(z); }, diff --git a/src/test/run-pass/deriving-encodable-decodable.rs b/src/test/run-pass/deriving-encodable-decodable.rs index 444790bcce99c..dedacd92535a5 100644 --- a/src/test/run-pass/deriving-encodable-decodable.rs +++ b/src/test/run-pass/deriving-encodable-decodable.rs @@ -16,14 +16,14 @@ #[feature(struct_variant, managed_boxes)]; -extern mod extra; +extern mod serialize; use std::io::MemWriter; use std::rand::{random, Rand}; -use extra::serialize::{Encodable, Decodable}; -use extra::ebml; -use extra::ebml::writer::Encoder; -use extra::ebml::reader::Decoder; +use serialize::{Encodable, Decodable}; +use serialize::ebml; +use serialize::ebml::writer::Encoder; +use serialize::ebml::reader::Decoder; #[deriving(Encodable, Decodable, Eq, Rand)] struct A; diff --git a/src/test/run-pass/deriving-global.rs b/src/test/run-pass/deriving-global.rs index ce51e2dcd7059..a7a3784877c59 100644 --- a/src/test/run-pass/deriving-global.rs +++ b/src/test/run-pass/deriving-global.rs @@ -11,7 +11,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod extra; // {En,De}codable +extern mod serialize; // {En,De}codable mod submod { // if any of these are implemented without global calls for any // function calls, then being in a submodule will (correctly) diff --git a/src/test/run-pass/issue-4016.rs b/src/test/run-pass/issue-4016.rs index c1f40d302c865..87a52de2269d2 100644 --- a/src/test/run-pass/issue-4016.rs +++ b/src/test/run-pass/issue-4016.rs @@ -9,10 +9,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-fast + extern mod extra; +extern mod serialize; use extra::json; -use extra::serialize::Decodable; +use serialize::Decodable; trait JD : Decodable { } diff --git a/src/test/run-pass/issue-4036.rs b/src/test/run-pass/issue-4036.rs index 5665bff571e4c..b746e524d7f0c 100644 --- a/src/test/run-pass/issue-4036.rs +++ b/src/test/run-pass/issue-4036.rs @@ -8,15 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-fast + // Issue #4036: Test for an issue that arose around fixing up type inference // byproducts in vtable records. extern mod extra; -use self::extra::json; -use self::extra::serialize; +extern mod serialize; +use extra::json; +use serialize::Decodable; pub fn main() { let json = json::from_str("[1]").unwrap(); let mut decoder = json::Decoder::new(json); - let _x: ~[int] = serialize::Decodable::decode(&mut decoder); + let _x: ~[int] = Decodable::decode(&mut decoder); } diff --git a/src/test/run-pass/once-move-out-on-heap.rs b/src/test/run-pass/once-move-out-on-heap.rs index bc56712ee3bc1..0ccf7b8f8a3e1 100644 --- a/src/test/run-pass/once-move-out-on-heap.rs +++ b/src/test/run-pass/once-move-out-on-heap.rs @@ -13,15 +13,15 @@ // xfail-fast #[feature(once_fns)]; -extern mod extra; -use extra::arc; +extern mod sync; +use sync::Arc; fn foo(blk: proc()) { blk(); } pub fn main() { - let x = arc::Arc::new(true); + let x = Arc::new(true); foo(proc() { assert!(*x.get()); drop(x); diff --git a/src/test/run-pass/once-move-out-on-stack.rs b/src/test/run-pass/once-move-out-on-stack.rs index 07dd5175a0fae..e732d0c76a663 100644 --- a/src/test/run-pass/once-move-out-on-stack.rs +++ b/src/test/run-pass/once-move-out-on-stack.rs @@ -13,15 +13,15 @@ // xfail-fast #[feature(once_fns)]; -extern mod extra; -use extra::arc; +extern mod sync; +use sync::Arc; fn foo(blk: once ||) { blk(); } pub fn main() { - let x = arc::Arc::new(true); + let x = Arc::new(true); foo(|| { assert!(*x.get()); drop(x); diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs index 2bf18e1ae1d5f..454da6d2aaa07 100644 --- a/src/test/run-pass/trait-bounds-in-arc.rs +++ b/src/test/run-pass/trait-bounds-in-arc.rs @@ -15,9 +15,9 @@ // xfail-fast -extern mod extra; +extern mod sync; -use extra::arc; +use sync::Arc; use std::task; trait Pet { @@ -65,7 +65,7 @@ pub fn main() { let dogge1 = Dogge { bark_decibels: 100, tricks_known: 42, name: ~"alan_turing" }; let dogge2 = Dogge { bark_decibels: 55, tricks_known: 11, name: ~"albert_einstein" }; let fishe = Goldfyshe { swim_speed: 998, name: ~"alec_guinness" }; - let arc = arc::Arc::new(~[~catte as ~Pet:Freeze+Send, + let arc = Arc::new(~[~catte as ~Pet:Freeze+Send, ~dogge1 as ~Pet:Freeze+Send, ~fishe as ~Pet:Freeze+Send, ~dogge2 as ~Pet:Freeze+Send]); @@ -83,21 +83,21 @@ pub fn main() { p3.recv(); } -fn check_legs(arc: arc::Arc<~[~Pet:Freeze+Send]>) { +fn check_legs(arc: Arc<~[~Pet:Freeze+Send]>) { let mut legs = 0; for pet in arc.get().iter() { legs += pet.num_legs(); } assert!(legs == 12); } -fn check_names(arc: arc::Arc<~[~Pet:Freeze+Send]>) { +fn check_names(arc: Arc<~[~Pet:Freeze+Send]>) { for pet in arc.get().iter() { pet.name(|name| { assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8); }) } } -fn check_pedigree(arc: arc::Arc<~[~Pet:Freeze+Send]>) { +fn check_pedigree(arc: Arc<~[~Pet:Freeze+Send]>) { for pet in arc.get().iter() { assert!(pet.of_good_pedigree()); }