From 228e83888bf3d0e14d0bc00ddd0040bb71e24a87 Mon Sep 17 00:00:00 2001 From: Benjamin Herr Date: Fri, 1 Mar 2013 21:27:08 +0100 Subject: [PATCH 01/10] `std::net::tcp` docs: Use current syntax and types Doesn't touch non-comment lines. This changes various type_names to TypeNames and fixes the example for `tcp::accept` that was still using the old `match` syntax and `{|args| ...}` closures. --- src/libstd/net_tcp.rs | 152 +++++++++++++++++++++--------------------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index dcbf7e60d89..4266cab0a05 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -43,7 +43,7 @@ extern mod rustrt { /** * Encapsulates an open TCP/IP connection through libuv * - * `tcp_socket` is non-copyable/sendable and automagically handles closing the + * `TcpSocket` is non-copyable/sendable and automagically handles closing the * underlying libuv data structures when it goes out of scope. This is the * data structure that is used for read/write operations over a TCP stream. */ @@ -66,10 +66,10 @@ pub fn TcpSocket(socket_data: @TcpSocketData) -> TcpSocket { } /** - * A buffered wrapper for `net::tcp::tcp_socket` + * A buffered wrapper for `net::tcp::TcpSocket` * * It is created with a call to `net::tcp::socket_buf()` and has impls that - * satisfy both the `io::reader` and `io::writer` traits. + * satisfy both the `io::Reader` and `io::Writer` traits. */ pub struct TcpSocketBuf { data: @TcpBufferedSocketData, @@ -89,7 +89,7 @@ pub struct TcpErrData { err_msg: ~str, } -/// Details returned as part of a `result::err` result from `tcp::listen` +/// Details returned as part of a `Result::Err` result from `tcp::listen` pub enum TcpListenErrData { /** * Some unplanned-for error. The first and second fields correspond @@ -116,7 +116,7 @@ pub enum TcpListenErrData { */ AccessDenied } -/// Details returned as part of a `result::err` result from `tcp::connect` +/// Details returned as part of a `Result::Err` result from `tcp::connect` pub enum TcpConnectErrData { /** * Some unplanned-for error. The first and second fields correspond @@ -139,9 +139,9 @@ pub enum TcpConnectErrData { * # Returns * * A `result` that, if the operation succeeds, contains a - * `net::net::tcp_socket` that can be used to send and receive data to/from + * `net::net::TcpSocket` that can be used to send and receive data to/from * the remote host. In the event of failure, a - * `net::tcp::tcp_connect_err_data` instance will be returned + * `net::tcp::TcpConnectErrData` instance will be returned */ pub fn connect(input_ip: ip::IpAddr, port: uint, iotask: &IoTask) @@ -288,14 +288,14 @@ pub fn connect(input_ip: ip::IpAddr, port: uint, * * # Arguments * - * * sock - a `tcp_socket` to write to + * * sock - a `TcpSocket` to write to * * raw_write_data - a vector of `~[u8]` that will be written to the stream. * This value must remain valid for the duration of the `write` call * * # Returns * - * A `result` object with a `nil` value as the `ok` variant, or a - * `tcp_err_data` value as the `err` variant + * A `Result` object with a `()` value as the `Ok` variant, or a + * `TcpErrData` value as the `Err` variant */ pub fn write(sock: &TcpSocket, raw_write_data: ~[u8]) -> result::Result<(), TcpErrData> { @@ -306,7 +306,7 @@ pub fn write(sock: &TcpSocket, raw_write_data: ~[u8]) } /** - * Write binary data to tcp stream; Returns a `future::future` value + * Write binary data to tcp stream; Returns a `future::Future` value * immediately * * # Safety @@ -314,27 +314,27 @@ pub fn write(sock: &TcpSocket, raw_write_data: ~[u8]) * This function can produce unsafe results if: * * 1. the call to `write_future` is made - * 2. the `future::future` value returned is never resolved via - * `future::get` - * 3. and then the `tcp_socket` passed in to `write_future` leaves + * 2. the `future::Future` value returned is never resolved via + * `Future::get` + * 3. and then the `TcpSocket` passed in to `write_future` leaves * scope and is destructed before the task that runs the libuv write * operation completes. * * As such: If using `write_future`, always be sure to resolve the returned - * `future` so as to ensure libuv doesn't try to access a released write + * `Future` so as to ensure libuv doesn't try to access a released write * handle. Otherwise, use the blocking `tcp::write` function instead. * * # Arguments * - * * sock - a `tcp_socket` to write to + * * sock - a `TcpSocket` to write to * * raw_write_data - a vector of `~[u8]` that will be written to the stream. * This value must remain valid for the duration of the `write` call * * # Returns * - * A `future` value that, once the `write` operation completes, resolves to a - * `result` object with a `nil` value as the `ok` variant, or a `tcp_err_data` - * value as the `err` variant + * A `Future` value that, once the `write` operation completes, resolves to a + * `Result` object with a `nil` value as the `Ok` variant, or a `TcpErrData` + * value as the `Err` variant */ pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8]) -> future::Future> { @@ -353,14 +353,14 @@ pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8]) * * # Arguments * - * * sock -- a `net::tcp::tcp_socket` for the connection to read from + * * sock -- a `net::tcp::TcpSocket` for the connection to read from * * # Returns * - * * A `result` instance that will either contain a - * `core::comm::port` that the user can read (and - * optionally, loop on) from until `read_stop` is called, or a - * `tcp_err_data` record + * * A `Result` instance that will either contain a + * `core::comm::Port>` that the user can read + * (and * optionally, loop on) from until `read_stop` is called, or a + * `TcpErrData` record */ pub fn read_start(sock: &TcpSocket) -> result::Result<@Port< @@ -376,7 +376,7 @@ pub fn read_start(sock: &TcpSocket) * * # Arguments * - * * `sock` - a `net::tcp::tcp_socket` that you wish to stop reading on + * * `sock` - a `net::tcp::TcpSocket` that you wish to stop reading on */ pub fn read_stop(sock: &TcpSocket) -> result::Result<(), TcpErrData> { @@ -387,17 +387,17 @@ pub fn read_stop(sock: &TcpSocket) -> } /** - * Reads a single chunk of data from `tcp_socket`; block until data/error + * Reads a single chunk of data from `TcpSocket`; block until data/error * recv'd * * Does a blocking read operation for a single chunk of data from a - * `tcp_socket` until a data arrives or an error is received. The provided + * `TcpSocket` until a data arrives or an error is received. The provided * `timeout_msecs` value is used to raise an error if the timeout period * passes without any data received. * * # Arguments * - * * `sock` - a `net::tcp::tcp_socket` that you wish to read from + * * `sock` - a `net::tcp::TcpSocket` that you wish to read from * * `timeout_msecs` - a `uint` value, in msecs, to wait before dropping the * read attempt. Pass `0u` to wait indefinitely */ @@ -408,12 +408,12 @@ pub fn read(sock: &TcpSocket, timeout_msecs: uint) } /** - * Reads a single chunk of data; returns a `future::future<~[u8]>` + * Reads a single chunk of data; returns a `future::Future<~[u8]>` * immediately * * Does a non-blocking read operation for a single chunk of data from a - * `tcp_socket` and immediately returns a `future` value representing the - * result. When resolving the returned `future`, it will block until data + * `TcpSocket` and immediately returns a `Future` value representing the + * result. When resolving the returned `Future`, it will block until data * arrives or an error is received. The provided `timeout_msecs` * value is used to raise an error if the timeout period passes without any * data received. @@ -421,18 +421,18 @@ pub fn read(sock: &TcpSocket, timeout_msecs: uint) * # Safety * * This function can produce unsafe results if the call to `read_future` is - * made, the `future::future` value returned is never resolved via - * `future::get`, and then the `tcp_socket` passed in to `read_future` leaves + * made, the `future::Future` value returned is never resolved via + * `Future::get`, and then the `TcpSocket` passed in to `read_future` leaves * scope and is destructed before the task that runs the libuv read * operation completes. * * As such: If using `read_future`, always be sure to resolve the returned - * `future` so as to ensure libuv doesn't try to access a released read + * `Future` so as to ensure libuv doesn't try to access a released read * handle. Otherwise, use the blocking `tcp::read` function instead. * * # Arguments * - * * `sock` - a `net::tcp::tcp_socket` that you wish to read from + * * `sock` - a `net::tcp::TcpSocket` that you wish to read from * * `timeout_msecs` - a `uint` value, in msecs, to wait before dropping the * read attempt. Pass `0u` to wait indefinitely */ @@ -445,7 +445,7 @@ fn read_future(sock: &TcpSocket, timeout_msecs: uint) } /** - * Bind an incoming client connection to a `net::tcp::tcp_socket` + * Bind an incoming client connection to a `net::tcp::TcpSocket` * * # Notes * @@ -461,7 +461,7 @@ fn read_future(sock: &TcpSocket, timeout_msecs: uint) * * This implies that a port/chan pair must be used to make sure that the * `new_connect_cb` call blocks until an attempt to create a - * `net::tcp::tcp_socket` is completed. + * `net::tcp::TcpSocket` is completed. * * # Example * @@ -469,49 +469,49 @@ fn read_future(sock: &TcpSocket, timeout_msecs: uint) * a task spawned by the `new_connect_cb` passed into `listen` * * ~~~~~~~~~~~ - * net::tcp::listen(remote_ip, remote_port, backlog) + * do net::tcp::listen(remote_ip, remote_port, backlog, iotask, * // this callback is ran once after the connection is successfully * // set up - * {|kill_ch| + * |kill_ch| { * // pass the kill_ch to your main loop or wherever you want * // to be able to externally kill the server from - * } + * }) * // this callback is ran when a new connection arrives - * {|new_conn, kill_ch| - * let cont_po = core::comm::port::>(); - * let cont_ch = core::comm::chan(cont_po); - * task::spawn {|| + * |new_conn, kill_ch| { + * let (cont_po, cont_ch) = comm::stream::>(); + * do task::spawn { * let accept_result = net::tcp::accept(new_conn); - * if accept_result.is_err() { - * core::comm::send(cont_ch, result::get_err(accept_result)); - * // fail? - * } - * else { - * let sock = result::get(accept_result); - * core::comm::send(cont_ch, true); - * // do work here + * match accept_result { + * Err(accept_error) => { + * cont_ch.send(Some(accept_error)); + * // fail? + * }, + * Ok(sock) => { + * cont_ch.send(None); + * // do work here + * } * } * }; - * match core::comm::recv(cont_po) { + * match cont_po.recv() { * // shut down listen() - * Some(err_data) { core::comm::send(kill_chan, Some(err_data)) } + * Some(err_data) => kill_ch.send(Some(err_data)), * // wait for next connection - * None {} + * None => () * } * }; * ~~~~~~~~~~~ * * # Arguments * - * * `new_conn` - an opaque value used to create a new `tcp_socket` + * * `new_conn` - an opaque value used to create a new `TcpSocket` * * # Returns * - * On success, this function will return a `net::tcp::tcp_socket` as the - * `ok` variant of a `result`. The `net::tcp::tcp_socket` is anchored within + * On success, this function will return a `net::tcp::TcpSocket` as the + * `Ok` variant of a `Result`. The `net::tcp::TcpSocket` is anchored within * the task that `accept` was called within for its lifetime. On failure, - * this function will return a `net::tcp::tcp_err_data` record - * as the `err` variant of a `result`. + * this function will return a `net::tcp::TcpErrData` record + * as the `Err` variant of a `Result`. */ pub fn accept(new_conn: TcpNewConnection) -> result::Result { @@ -600,27 +600,27 @@ pub fn accept(new_conn: TcpNewConnection) * * # Arguments * - * * `host_ip` - a `net::ip::ip_addr` representing a unique IP + * * `host_ip` - a `net::ip::IpAddr` representing a unique IP * (versions 4 or 6) * * `port` - a uint representing the port to listen on * * `backlog` - a uint representing the number of incoming connections * to cache in memory - * * `hl_loop` - a `uv::hl::high_level_loop` that the tcp request will run on + * * `hl_loop` - a `uv_iotask::IoTask` that the tcp request will run on * * `on_establish_cb` - a callback that is evaluated if/when the listener * is successfully established. it takes no parameters * * `new_connect_cb` - a callback to be evaluated, on the libuv thread, * whenever a client attempts to conect on the provided ip/port. the * callback's arguments are: * * `new_conn` - an opaque type that can be passed to - * `net::tcp::accept` in order to be converted to a `tcp_socket`. - * * `kill_ch` - channel of type `core::comm::chan>`. + * `net::tcp::accept` in order to be converted to a `TcpSocket`. + * * `kill_ch` - channel of type `core::comm::Chan>`. * this channel can be used to send a message to cause `listen` to begin * closing the underlying libuv data structures. * * # returns * - * a `result` instance containing empty data of type `()` on a - * successful/normal shutdown, and a `tcp_listen_err_data` enum in the event + * a `Result` instance containing empty data of type `()` on a + * successful/normal shutdown, and a `TcpListenErrData` enum in the event * of listen exiting because of an error */ pub fn listen(host_ip: ip::IpAddr, port: uint, backlog: uint, @@ -799,19 +799,19 @@ fn listen_common(host_ip: ip::IpAddr, port: uint, backlog: uint, /** - * Convert a `net::tcp::tcp_socket` to a `net::tcp::tcp_socket_buf`. + * Convert a `net::tcp::TcpSocket` to a `net::tcp::TcpSocketBuf`. * - * This function takes ownership of a `net::tcp::tcp_socket`, returning it - * stored within a buffered wrapper, which can be converted to a `io::reader` - * or `io::writer` + * This function takes ownership of a `net::tcp::TcpSocket`, returning it + * stored within a buffered wrapper, which can be converted to a `io::Reader` + * or `io::Writer` * * # Arguments * - * * `sock` -- a `net::tcp::tcp_socket` that you want to buffer + * * `sock` -- a `net::tcp::TcpSocket` that you want to buffer * * # Returns * - * A buffered wrapper that you can cast as an `io::reader` or `io::writer` + * A buffered wrapper that you can cast as an `io::Reader` or `io::Writer` */ pub fn socket_buf(sock: TcpSocket) -> TcpSocketBuf { TcpSocketBuf(@TcpBufferedSocketData { @@ -819,7 +819,7 @@ pub fn socket_buf(sock: TcpSocket) -> TcpSocketBuf { }) } -/// Convenience methods extending `net::tcp::tcp_socket` +/// Convenience methods extending `net::tcp::TcpSocket` pub impl TcpSocket { pub fn read_start() -> result::Result<@Port< result::Result<~[u8], TcpErrData>>, TcpErrData> { @@ -862,7 +862,7 @@ pub impl TcpSocket { } } -/// Implementation of `io::reader` trait for a buffered `net::tcp::tcp_socket` +/// Implementation of `io::Reader` trait for a buffered `net::tcp::TcpSocket` impl io::Reader for TcpSocketBuf { fn read(&self, buf: &mut [u8], len: uint) -> uint { if len == 0 { return 0 } @@ -962,7 +962,7 @@ impl io::Reader for TcpSocketBuf { } } -/// Implementation of `io::reader` trait for a buffered `net::tcp::tcp_socket` +/// Implementation of `io::Reader` trait for a buffered `net::tcp::TcpSocket` impl io::Writer for TcpSocketBuf { pub fn write(&self, data: &[const u8]) { unsafe { From ae89328b2a59c978edd3be22e7b7642741d27aad Mon Sep 17 00:00:00 2001 From: Benjamin Herr Date: Fri, 1 Mar 2013 22:46:00 +0100 Subject: [PATCH 02/10] Contributing.md: remove spurious verb --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c6e9478713d..d934e38c35d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,7 +11,7 @@ You're not off the hook even if you just stick to documentation; code examples i Pull requests will be treated as "review requests", and we will give feedback we expect to see corrected on [style](https://github.com/mozilla/rust/wiki/Note-style-guide) and substance before pulling. Changes contributed via pull request should focus on a single issue at a time, like any other. -We will not look accept pull-requests that try to "sneak" unrelated changes in. +We will not accept pull-requests that try to "sneak" unrelated changes in. Normally, all pull requests must include regression tests (see [Note-testsuite](https://github.com/mozilla/rust/wiki/Note-testsuite)) that test your change. Occasionally, a change will be very difficult to test for. From bcf626812b88f63932c541f81c7f68360e31a7c1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 27 Feb 2013 19:53:31 -0800 Subject: [PATCH 03/10] Rename core::private to core::unstable. #4743 --- src/libcore/at_vec.rs | 2 +- src/libcore/comm.rs | 6 +++--- src/libcore/core.rc | 8 ++++++-- src/libcore/num/f32.rs | 2 +- src/libcore/num/f64.rs | 2 +- src/libcore/os.rs | 5 ++--- src/libcore/pipes.rs | 4 ++-- src/libcore/prelude.rs | 2 +- src/libcore/ptr.rs | 2 +- src/libcore/rt.rs | 2 +- src/libcore/task/spawn.rs | 14 +++++++------- src/libcore/{private.rs => unstable.rs} | 16 ++++++++-------- src/libcore/{private => unstable}/at_exit.rs | 0 .../{private => unstable}/exchange_alloc.rs | 2 +- src/libcore/{private => unstable}/extfmt.rs | 0 src/libcore/{private => unstable}/finally.rs | 0 src/libcore/{private => unstable}/global.rs | 10 +++++----- src/libcore/{private => unstable}/intrinsics.rs | 0 src/libcore/{private => unstable}/weak_task.rs | 6 +++--- src/libcore/vec.rs | 8 ++++---- src/libstd/arc.rs | 6 +++--- src/libstd/sync.rs | 2 +- src/libstd/uv_global_loop.rs | 4 ++-- src/libsyntax/ext/fmt.rs | 4 ++-- .../compile-fail/noncopyable-match-pattern.rs | 2 +- .../run-pass/alt-ref-binding-in-guard-3256.rs | 2 +- src/test/run-pass/foreign-call-no-runtime.rs | 2 +- src/test/run-pass/type-use-i1-versus-i8.rs | 2 +- 28 files changed, 59 insertions(+), 56 deletions(-) rename src/libcore/{private.rs => unstable.rs} (97%) rename src/libcore/{private => unstable}/at_exit.rs (100%) rename src/libcore/{private => unstable}/exchange_alloc.rs (97%) rename src/libcore/{private => unstable}/extfmt.rs (100%) rename src/libcore/{private => unstable}/finally.rs (100%) rename src/libcore/{private => unstable}/global.rs (97%) rename src/libcore/{private => unstable}/intrinsics.rs (100%) rename src/libcore/{private => unstable}/weak_task.rs (97%) diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs index ab604d1f0b6..d89481766c0 100644 --- a/src/libcore/at_vec.rs +++ b/src/libcore/at_vec.rs @@ -183,7 +183,7 @@ pub mod raw { use at_vec::{capacity, rustrt}; use cast::transmute; use libc; - use private::intrinsics::{move_val_init}; + use unstable::intrinsics::{move_val_init}; use ptr::addr_of; use ptr; use sys; diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs index 238207f12b6..94272f63e67 100644 --- a/src/libcore/comm.rs +++ b/src/libcore/comm.rs @@ -12,7 +12,7 @@ use either::{Either, Left, Right}; use kinds::Owned; use option; use option::{Option, Some, None, unwrap}; -use private; +use unstable; use vec; use pipes::{recv, try_recv, wait_many, peek, PacketHeader}; @@ -242,7 +242,7 @@ impl Peekable for PortSet { } /// A channel that can be shared between many senders. -pub type SharedChan = private::Exclusive>; +pub type SharedChan = unstable::Exclusive>; impl GenericChan for SharedChan { fn send(x: T) { @@ -268,7 +268,7 @@ impl GenericSmartChan for SharedChan { /// Converts a `chan` into a `shared_chan`. pub fn SharedChan(c: Chan) -> SharedChan { - private::exclusive(c) + unstable::exclusive(c) } /// Receive a message from one of two endpoints. diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 3e514ce249f..525887f8cb3 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -228,8 +228,12 @@ pub const debug : u32 = 4_u32; // The runtime interface used by the compiler #[cfg(notest)] pub mod rt; // Private APIs -pub mod private; - +pub mod unstable; +// NOTE: Remove after snapshot +#[cfg(stage0)] +pub mod private { + pub use super::unstable::extfmt; +} /* For internal use, not exported */ diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index c4f2704ab9f..d4808bd111f 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -18,7 +18,7 @@ use num::strconv; use num; use ops; use option::Option; -use private::intrinsics::floorf32; +use unstable::intrinsics::floorf32; use from_str; use to_str; diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 8f3771312e4..5362a65f7ce 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -19,7 +19,7 @@ use num::strconv; use num; use ops; use option::Option; -use private::intrinsics::floorf64; +use unstable::intrinsics::floorf64; use to_str; use from_str; diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 8b6d27496d9..5ede0c550ff 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -35,7 +35,6 @@ use libc::{mode_t, pid_t, FILE}; use option; use option::{Some, None}; use prelude::*; -use private; use ptr; use str; use task; @@ -145,8 +144,8 @@ This uses a per-runtime lock to serialize access. FIXME #4726: It would probably be appropriate to make this a real global */ fn with_env_lock(f: &fn() -> T) -> T { - use private::global::global_data_clone_create; - use private::{Exclusive, exclusive}; + use unstable::global::global_data_clone_create; + use unstable::{Exclusive, exclusive}; struct SharedValue(()); type ValueMutex = Exclusive; diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index 77554656913..58ab2ce78f5 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -91,9 +91,9 @@ use libc; use option; use option::{None, Option, Some, unwrap}; use pipes; -use private::intrinsics; +use unstable::intrinsics; use ptr; -use private; +use unstable; use task; use vec; diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index d0a16f7875b..422d9a6eea0 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -69,7 +69,7 @@ pub use option; pub use os; pub use path; pub use comm; -pub use private; +pub use unstable; pub use ptr; pub use rand; pub use result; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 2266c2511f8..5a7b319e7ff 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -14,7 +14,7 @@ use cast; use cmp::{Eq, Ord}; use libc; use libc::{c_void, size_t}; -use private::intrinsics::{memmove32,memmove64}; +use unstable::intrinsics::{memmove32,memmove64}; use ptr; use str; use sys; diff --git a/src/libcore/rt.rs b/src/libcore/rt.rs index 5d0bad3ceb3..a4f90e37683 100644 --- a/src/libcore/rt.rs +++ b/src/libcore/rt.rs @@ -15,7 +15,7 @@ use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int}; use managed::raw::BoxRepr; use str; use sys; -use private::exchange_alloc; +use unstable::exchange_alloc; use cast::transmute; use gc::{cleanup_stack_for_failure, gc, Word}; diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index bf7209f9fc3..6cc3657a32b 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -79,7 +79,7 @@ use option; use comm::{Chan, GenericChan, GenericPort, Port, stream}; use pipes; use prelude::*; -use private; +use unstable; use ptr; use hashmap::linear::LinearSet; use task::local_data_priv::{local_get, local_set}; @@ -123,7 +123,7 @@ struct TaskGroupData { // tasks in this group. mut descendants: TaskSet, } -type TaskGroupArc = private::Exclusive>; +type TaskGroupArc = unstable::Exclusive>; type TaskGroupInner = &mut Option; @@ -153,7 +153,7 @@ struct AncestorNode { mut ancestors: AncestorList, } -enum AncestorList = Option>; +enum AncestorList = Option>; // Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety. #[inline(always)] @@ -162,7 +162,7 @@ fn access_group(x: &TaskGroupArc, blk: fn(TaskGroupInner) -> U) -> U { } #[inline(always)] -fn access_ancestors(x: &private::Exclusive, +fn access_ancestors(x: &unstable::Exclusive, blk: fn(x: &mut AncestorNode) -> U) -> U { unsafe { x.with(blk) } } @@ -458,7 +458,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool) // Main task, doing first spawn ever. Lazily initialise here. let mut members = new_taskset(); taskset_insert(&mut members, spawner); - let tasks = private::exclusive(Some(TaskGroupData { + let tasks = unstable::exclusive(Some(TaskGroupData { members: members, descendants: new_taskset(), })); @@ -482,7 +482,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool) (g, a, spawner_group.is_main) } else { // Child is in a separate group from spawner. - let g = private::exclusive(Some(TaskGroupData { + let g = unstable::exclusive(Some(TaskGroupData { members: new_taskset(), descendants: new_taskset(), })); @@ -502,7 +502,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool) }; assert new_generation < uint::max_value; // Build a new node in the ancestor list. - AncestorList(Some(private::exclusive(AncestorNode { + AncestorList(Some(unstable::exclusive(AncestorNode { generation: new_generation, parent_group: Some(spawner_group.tasks.clone()), ancestors: old_ancestors, diff --git a/src/libcore/private.rs b/src/libcore/unstable.rs similarity index 97% rename from src/libcore/private.rs rename to src/libcore/unstable.rs index d19951e76db..b7b4b563425 100644 --- a/src/libcore/private.rs +++ b/src/libcore/unstable.rs @@ -22,19 +22,19 @@ use task; use task::{TaskBuilder, atomically}; use uint; -#[path = "private/at_exit.rs"] +#[path = "unstable/at_exit.rs"] pub mod at_exit; -#[path = "private/global.rs"] +#[path = "unstable/global.rs"] pub mod global; -#[path = "private/finally.rs"] +#[path = "unstable/finally.rs"] pub mod finally; -#[path = "private/weak_task.rs"] +#[path = "unstable/weak_task.rs"] pub mod weak_task; -#[path = "private/exchange_alloc.rs"] +#[path = "unstable/exchange_alloc.rs"] pub mod exchange_alloc; -#[path = "private/intrinsics.rs"] +#[path = "unstable/intrinsics.rs"] pub mod intrinsics; -#[path = "private/extfmt.rs"] +#[path = "unstable/extfmt.rs"] pub mod extfmt; extern mod rustrt { @@ -312,7 +312,7 @@ pub mod tests { use cell::Cell; use comm; use option; - use private::exclusive; + use super::exclusive; use result; use task; use uint; diff --git a/src/libcore/private/at_exit.rs b/src/libcore/unstable/at_exit.rs similarity index 100% rename from src/libcore/private/at_exit.rs rename to src/libcore/unstable/at_exit.rs diff --git a/src/libcore/private/exchange_alloc.rs b/src/libcore/unstable/exchange_alloc.rs similarity index 97% rename from src/libcore/private/exchange_alloc.rs rename to src/libcore/unstable/exchange_alloc.rs index b6af9891e11..f59037445eb 100644 --- a/src/libcore/private/exchange_alloc.rs +++ b/src/libcore/unstable/exchange_alloc.rs @@ -14,7 +14,7 @@ use c_malloc = libc::malloc; use c_free = libc::free; use managed::raw::{BoxHeaderRepr, BoxRepr}; use cast::transmute; -use private::intrinsics::{atomic_xadd,atomic_xsub}; +use unstable::intrinsics::{atomic_xadd,atomic_xsub}; use ptr::null; use intrinsic::TyDesc; diff --git a/src/libcore/private/extfmt.rs b/src/libcore/unstable/extfmt.rs similarity index 100% rename from src/libcore/private/extfmt.rs rename to src/libcore/unstable/extfmt.rs diff --git a/src/libcore/private/finally.rs b/src/libcore/unstable/finally.rs similarity index 100% rename from src/libcore/private/finally.rs rename to src/libcore/unstable/finally.rs diff --git a/src/libcore/private/global.rs b/src/libcore/unstable/global.rs similarity index 97% rename from src/libcore/private/global.rs rename to src/libcore/unstable/global.rs index 77b61347250..aa28310f7ba 100644 --- a/src/libcore/private/global.rs +++ b/src/libcore/unstable/global.rs @@ -32,11 +32,11 @@ use libc::{c_void, uintptr_t}; use option::{Option, Some, None}; use ops::Drop; use pipes; -use private::{Exclusive, exclusive}; -use private::{SharedMutableState, shared_mutable_state}; -use private::{get_shared_immutable_state}; -use private::at_exit::at_exit; -use private::intrinsics::atomic_cxchg; +use unstable::{Exclusive, exclusive}; +use unstable::{SharedMutableState, shared_mutable_state}; +use unstable::{get_shared_immutable_state}; +use unstable::at_exit::at_exit; +use unstable::intrinsics::atomic_cxchg; use hashmap::linear::LinearMap; use sys::Closure; use task::spawn; diff --git a/src/libcore/private/intrinsics.rs b/src/libcore/unstable/intrinsics.rs similarity index 100% rename from src/libcore/private/intrinsics.rs rename to src/libcore/unstable/intrinsics.rs diff --git a/src/libcore/private/weak_task.rs b/src/libcore/unstable/weak_task.rs similarity index 97% rename from src/libcore/private/weak_task.rs rename to src/libcore/unstable/weak_task.rs index 8445638850c..0e1181f43db 100644 --- a/src/libcore/private/weak_task.rs +++ b/src/libcore/unstable/weak_task.rs @@ -24,9 +24,9 @@ use comm::{Port, Chan, SharedChan, GenericChan, GenericPort}; use hashmap::linear::LinearMap; use ops::Drop; use option::{Some, None, swap_unwrap}; -use private::at_exit::at_exit; -use private::finally::Finally; -use private::global::global_data_clone_create; +use unstable::at_exit::at_exit; +use unstable::finally::Finally; +use unstable::global::global_data_clone_create; use task::rt::{task_id, get_task_id}; use task::{Task, task, spawn}; diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 4d28c769b18..0d1be03638a 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -22,7 +22,7 @@ use kinds::Copy; use libc; use libc::size_t; use option::{None, Option, Some}; -use private::intrinsics; +use unstable::intrinsics; use ptr; use ptr::addr_of; use sys; @@ -2008,7 +2008,7 @@ pub mod raw { use managed; use option::{None, Some}; use option; - use private::intrinsics; + use unstable::intrinsics; use ptr::addr_of; use ptr; use sys; @@ -2622,8 +2622,8 @@ mod tests { #[test] fn test_swap_remove_noncopyable() { // Tests that we don't accidentally run destructors twice. - let mut v = ~[::private::exclusive(()), ::private::exclusive(()), - ::private::exclusive(())]; + let mut v = ~[::unstable::exclusive(()), ::unstable::exclusive(()), + ::unstable::exclusive(())]; let mut _e = v.swap_remove(0); assert (len(v) == 2); _e = v.swap_remove(1); diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index 69c5026cbd1..ea59d6a54c6 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -20,9 +20,9 @@ use core::cast; use core::cell::Cell; use core::pipes; use core::prelude::*; -use core::private::{SharedMutableState, shared_mutable_state}; -use core::private::{clone_shared_mutable_state}; -use core::private::{get_shared_mutable_state, get_shared_immutable_state}; +use core::unstable::{SharedMutableState, shared_mutable_state}; +use core::unstable::{clone_shared_mutable_state}; +use core::unstable::{get_shared_mutable_state, get_shared_immutable_state}; use core::ptr; use core::task; use core::util; diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index 39d3fd569a6..1289bc8e889 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -19,7 +19,7 @@ use core::cell::Cell; use core::option; use core::pipes; use core::prelude::*; -use core::private::{Exclusive, exclusive}; +use core::unstable::{Exclusive, exclusive}; use core::ptr; use core::task; use core::util; diff --git a/src/libstd/uv_global_loop.rs b/src/libstd/uv_global_loop.rs index 37d9b3221b2..52cfc078bac 100644 --- a/src/libstd/uv_global_loop.rs +++ b/src/libstd/uv_global_loop.rs @@ -18,9 +18,9 @@ use uv_iotask::{IoTask, spawn_iotask}; use core::either::{Left, Right}; use core::libc; use core::comm::{Port, Chan, SharedChan, select2i}; -use core::private::global::{global_data_clone_create, +use core::unstable::global::{global_data_clone_create, global_data_clone}; -use core::private::weak_task::weaken_task; +use core::unstable::weak_task::weaken_task; use core::str; use core::task::{task, SingleThreaded, spawn}; use core::task; diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index b8781130562..3861db28e1d 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -24,7 +24,7 @@ use ext::base::*; use ext::base; use ext::build; use ext::build::*; -use private::extfmt::ct::*; +use unstable::extfmt::ct::*; pub fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) -> base::MacResult { @@ -57,7 +57,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, -> @ast::expr { fn make_path_vec(cx: ext_ctxt, ident: @~str) -> ~[ast::ident] { let intr = cx.parse_sess().interner; - return ~[intr.intern(@~"private"), intr.intern(@~"extfmt"), + return ~[intr.intern(@~"unstable"), intr.intern(@~"extfmt"), intr.intern(@~"rt"), intr.intern(ident)]; } fn make_rt_path_expr(cx: ext_ctxt, sp: span, nm: @~str) -> @ast::expr { diff --git a/src/test/compile-fail/noncopyable-match-pattern.rs b/src/test/compile-fail/noncopyable-match-pattern.rs index 9f21d5a647a..d90e2f372a8 100644 --- a/src/test/compile-fail/noncopyable-match-pattern.rs +++ b/src/test/compile-fail/noncopyable-match-pattern.rs @@ -9,7 +9,7 @@ // except according to those terms. fn main() { - let x = Some(private::exclusive(false)); + let x = Some(unstable::exclusive(false)); match x { Some(copy z) => { //~ ERROR copying a value of non-copyable type do z.with |b| { assert !*b; } diff --git a/src/test/run-pass/alt-ref-binding-in-guard-3256.rs b/src/test/run-pass/alt-ref-binding-in-guard-3256.rs index 4474aec3d2e..d9c348cf993 100644 --- a/src/test/run-pass/alt-ref-binding-in-guard-3256.rs +++ b/src/test/run-pass/alt-ref-binding-in-guard-3256.rs @@ -9,7 +9,7 @@ // except according to those terms. pub fn main() { - let x = Some(private::exclusive(true)); + let x = Some(unstable::exclusive(true)); match x { Some(ref z) if z.with(|b| *b) => { do z.with |b| { assert *b; } diff --git a/src/test/run-pass/foreign-call-no-runtime.rs b/src/test/run-pass/foreign-call-no-runtime.rs index 5d400e98d41..86f23dd5210 100644 --- a/src/test/run-pass/foreign-call-no-runtime.rs +++ b/src/test/run-pass/foreign-call-no-runtime.rs @@ -1,4 +1,4 @@ -use core::private::run_in_bare_thread; +use core::unstable::run_in_bare_thread; extern { pub fn rust_dbg_call(cb: *u8, diff --git a/src/test/run-pass/type-use-i1-versus-i8.rs b/src/test/run-pass/type-use-i1-versus-i8.rs index d16b2e3e996..d180f6c7260 100644 --- a/src/test/run-pass/type-use-i1-versus-i8.rs +++ b/src/test/run-pass/type-use-i1-versus-i8.rs @@ -11,5 +11,5 @@ pub fn main() { let mut x: bool = false; // this line breaks it - private::intrinsics::move_val_init(&mut x, false); + unstable::intrinsics::move_val_init(&mut x, false); } From 332c0460290ade81edf44b55d47edcb4990a3b5a Mon Sep 17 00:00:00 2001 From: Benjamin Herr Date: Fri, 1 Mar 2013 23:48:17 +0100 Subject: [PATCH 04/10] docs/rust.md: Mention unit-like structs along with other struct types --- doc/rust.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/doc/rust.md b/doc/rust.md index 13d897a00d2..e928a5d5fb4 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1085,6 +1085,15 @@ let p = Point(10, 11); let px: int = match p { Point(x, _) => x }; ~~~~ +A _unit-like struct_ is a structure without any fields, defined by leaving off the fields list entirely. +Such types will have a single value, just like the [unit value `()`](#unit-and-boolean-literals) of the unit type. +For example: + +~~~~ +struct Cookie; +let c = [Cookie, Cookie, Cookie, Cookie]; +~~~~ + ### Enumerations An _enumeration_ is a simultaneous definition of a nominal [enumerated type](#enumerated-types) as well as a set of *constructors*, @@ -1590,7 +1599,8 @@ struct_expr : expr_path '{' ident ':' expr [ ',' ident ':' expr ] * [ ".." expr ] '}' | expr_path '(' expr - [ ',' expr ] * ')' + [ ',' expr ] * ')' | + expr_path ~~~~~~~~ There are several forms of structure expressions. @@ -1600,23 +1610,28 @@ providing the field values of a new instance of the structure. A field name can be any identifier, and is separated from its value expression by a colon. To indicate that a field is mutable, the `mut` keyword is written before its name. -A _tuple structure expression_ constists of the [path](#paths) of a [structure item](#structures), +A _tuple structure expression_ consists of the [path](#paths) of a [structure item](#structures), followed by a parenthesized list of one or more comma-separated expressions (in other words, the path of a structured item followed by a tuple expression). The structure item must be a tuple structure item. +A _unit-like structure expression_ consists only of the [path](#paths) of a [structure item](#structures). + The following are examples of structure expressions: ~~~~ # struct Point { x: float, y: float } # struct TuplePoint(float, float); # mod game { pub struct User { name: &str, age: uint, score: uint } } +# struct Cookie; fn some_fn(t: T) {} Point {x: 10f, y: 20f}; TuplePoint(10f, 20f); let u = game::User {name: "Joe", age: 35u, score: 100_000}; +some_fn::(Cookie); ~~~~ A structure expression forms a new value of the named structure type. +Note that for a given *unit-like* structure type, this will always be the same value. A structure expression can terminate with the syntax `..` followed by an expression to denote a functional update. The expression following `..` (the base) must be of the same structure type as the new structure type being formed. @@ -2643,7 +2658,10 @@ the resulting `struct` value will always be laid out in memory in the order spec The fields of a `struct` may be qualified by [visibility modifiers](#visibility-modifiers), to restrict access to implementation-private data in a structure. -A `tuple struct` type is just like a structure type, except that the fields are anonymous. +A _tuple struct_ type is just like a structure type, except that the fields are anonymous. + +A _unit-like struct_ type is like a structure type, except that it has no fields. +The one value constructed by the associated [structure expression](#structure-expression) is the only value that inhabits such a type. ### Enumerated types From 382143abd871d9b2c73df08ffd2928c44f314ab3 Mon Sep 17 00:00:00 2001 From: Benjamin Herr Date: Sat, 2 Mar 2013 01:07:01 +0100 Subject: [PATCH 05/10] doc/rust.md: Demonstrate the `f::()` syntax more often The "Generic functions" subsection mentions that generic functions are instantiated based on context, so let's also mention right away (with a link to the #paths section) that an explicit form is available. This also adds an example to the function call expression section that explicitly instantiates a generic function. --- doc/rust.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/rust.md b/doc/rust.md index 13d897a00d2..862358859e5 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -908,6 +908,11 @@ function defined above on `[1, 2]` will instantiate type parameter `T` with `int`, and require the closure parameter to have type `fn(int)`. +The type parameters can also be explicitly supplied in a trailing +[path](#paths) component after the function name. This might be necessary +if there is not sufficient context to determine the type parameters. For +example, `sys::size_of::() == 4`. + Since a parameter type is opaque to the generic function, the set of operations that can be performed on it is limited. Values of parameter type can always be moved, but they can only be copied when the @@ -2040,12 +2045,14 @@ an optional reference slot to serve as the function's output, bound to the `lval` on the right hand side of the call. If the function eventually returns, then the expression completes. -An example of a call expression: +Some examples of call expressions: ~~~~ # fn add(x: int, y: int) -> int { 0 } +# use core::from_str::FromStr::from_str; let x: int = add(1, 2); +let pi = from_str::("3.14"); ~~~~ ### Lambda expressions From 9639ca5aa88c59cedc7bbe4bd31ec7dabe8a62ec Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 1 Mar 2013 17:27:14 -0800 Subject: [PATCH 06/10] core: Move core::rt to core::unstable::lang --- src/libcore/cleanup.rs | 2 +- src/libcore/core.rc | 2 -- src/libcore/task/local_data_priv.rs | 6 +----- src/libcore/unstable.rs | 3 +++ src/libcore/{rt.rs => unstable/lang.rs} | 3 --- 5 files changed, 5 insertions(+), 11 deletions(-) rename src/libcore/{rt.rs => unstable/lang.rs} (98%) diff --git a/src/libcore/cleanup.rs b/src/libcore/cleanup.rs index 6912d6d995b..393a71562ad 100644 --- a/src/libcore/cleanup.rs +++ b/src/libcore/cleanup.rs @@ -154,7 +154,7 @@ fn debug_mem() -> bool { #[cfg(notest)] #[lang="annihilate"] pub unsafe fn annihilate() { - use rt::local_free; + use unstable::lang::local_free; use io::WriterUtil; use io; use libc; diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 525887f8cb3..c8d2da28255 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -225,8 +225,6 @@ pub const debug : u32 = 4_u32; /* Unsupported interfaces */ -// The runtime interface used by the compiler -#[cfg(notest)] pub mod rt; // Private APIs pub mod unstable; // NOTE: Remove after snapshot diff --git a/src/libcore/task/local_data_priv.rs b/src/libcore/task/local_data_priv.rs index df5a5af74ca..fc152765322 100644 --- a/src/libcore/task/local_data_priv.rs +++ b/src/libcore/task/local_data_priv.rs @@ -19,11 +19,7 @@ use prelude::*; use task::rt; use task::local_data::LocalDataKey; -#[cfg(notest)] -use rt::rust_task; -#[cfg(test)] -#[allow(non_camel_case_types)] -type rust_task = libc::c_void; +use super::rt::rust_task; pub trait LocalData { } impl LocalData for @T { } diff --git a/src/libcore/unstable.rs b/src/libcore/unstable.rs index b7b4b563425..8c0c029a90f 100644 --- a/src/libcore/unstable.rs +++ b/src/libcore/unstable.rs @@ -36,6 +36,9 @@ pub mod exchange_alloc; pub mod intrinsics; #[path = "unstable/extfmt.rs"] pub mod extfmt; +#[path = "unstable/lang.rs"] +#[cfg(notest)] +pub mod lang; extern mod rustrt { pub unsafe fn rust_create_little_lock() -> rust_little_lock; diff --git a/src/libcore/rt.rs b/src/libcore/unstable/lang.rs similarity index 98% rename from src/libcore/rt.rs rename to src/libcore/unstable/lang.rs index a4f90e37683..e74052995e6 100644 --- a/src/libcore/rt.rs +++ b/src/libcore/unstable/lang.rs @@ -20,9 +20,6 @@ use cast::transmute; use gc::{cleanup_stack_for_failure, gc, Word}; -#[allow(non_camel_case_types)] -pub type rust_task = c_void; - #[cfg(target_word_size = "32")] pub const FROZEN_BIT: uint = 0x80000000; #[cfg(target_word_size = "64")] From dcd2f735606ea952425760edce2ac55a32850341 Mon Sep 17 00:00:00 2001 From: Seth Pink Date: Sat, 2 Mar 2013 12:42:02 +1000 Subject: [PATCH 07/10] Fix some struct-tuple def prettyprint issues - Removed space between struct name and parentheses - Fixed indentation of the rest of the file (missing end) - Don't print parentheses for structs with no fields - Added test --- src/libsyntax/print/pprust.rs | 28 ++++++++++++---------------- src/test/pretty/struct-tuple.rs | 10 ++++++++++ 2 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 src/test/pretty/struct-tuple.rs diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 0f161a444bd..9bbed28b388 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -713,30 +713,26 @@ pub fn print_struct(s: @ps, ident: ast::ident, span: codemap::span) { print_ident(s, ident); - nbsp(s); print_generics(s, generics); if ast_util::struct_def_is_tuple_like(struct_def) { - popen(s); - let mut first = true; - for struct_def.fields.each |field| { - if first { - first = false; - } else { - word_space(s, ~","); - } - - match field.node.kind { - ast::named_field(*) => fail!(~"unexpected named field"), - ast::unnamed_field => { - maybe_print_comment(s, field.span.lo); - print_type(s, field.node.ty); + if !struct_def.fields.is_empty() { + popen(s); + do commasep(s, inconsistent, struct_def.fields) |s, field| { + match field.node.kind { + ast::named_field(*) => fail!(~"unexpected named field"), + ast::unnamed_field => { + maybe_print_comment(s, field.span.lo); + print_type(s, field.node.ty); + } } } + pclose(s); } - pclose(s); word(s.s, ~";"); + end(s); end(s); // close the outer-box } else { + nbsp(s); bopen(s); hardbreak_if_not_bol(s); do struct_def.dtor.iter |dtor| { diff --git a/src/test/pretty/struct-tuple.rs b/src/test/pretty/struct-tuple.rs new file mode 100644 index 00000000000..0d54848a4a9 --- /dev/null +++ b/src/test/pretty/struct-tuple.rs @@ -0,0 +1,10 @@ +// pp-exact +struct Foo; +struct Bar(int, int); + +fn main() { + struct Foo2; + struct Bar2(int, int, int); + let a = Bar(5, 5); + let b = Foo; +} From 95bc9ea26df56b29f74583317ab080fdc7b99757 Mon Sep 17 00:00:00 2001 From: Jihyun Yu Date: Sat, 2 Mar 2013 12:57:05 +0900 Subject: [PATCH 08/10] Remove REC, change related tests/docs --- doc/rust.md | 109 +++--------------- doc/tutorial-borrowed-ptr.md | 11 +- src/libcore/dvec.rs | 8 +- src/libcore/os.rs | 18 +-- src/libcore/ptr.rs | 6 +- src/libstd/ebml.rs | 4 +- src/libstd/sync.rs | 4 +- src/libsyntax/parse/parser.rs | 16 +-- src/libsyntax/print/pprust.rs | 2 +- src/test/compile-fail/autoderef-full-lval.rs | 17 ++- src/test/compile-fail/bad-record-pat-2.rs | 13 --- src/test/compile-fail/bad-record-pat.rs | 13 --- src/test/compile-fail/binop-add-tup-assign.rs | 13 --- src/test/compile-fail/binop-add-tup.rs | 13 --- src/test/compile-fail/break-outside-loop.rs | 7 +- src/test/compile-fail/fru-extra-field.rs | 21 ---- .../compile-fail/let-destruct-refutable.rs | 21 ---- src/test/compile-fail/nonscalar-cast.rs | 10 +- src/test/compile-fail/rec-expected.rs | 19 --- src/test/compile-fail/rec-extend.rs | 18 --- src/test/compile-fail/rec-missing-fields.rs | 19 --- .../writing-through-read-alias.rs | 19 --- .../compile-fail/writing-to-immutable-rec.rs | 12 -- src/test/run-pass/lint-structural-records.rs | 14 --- src/test/run-pass/uniq-cc-generic.rs | 4 +- 25 files changed, 75 insertions(+), 336 deletions(-) delete mode 100644 src/test/compile-fail/bad-record-pat-2.rs delete mode 100644 src/test/compile-fail/bad-record-pat.rs delete mode 100644 src/test/compile-fail/binop-add-tup-assign.rs delete mode 100644 src/test/compile-fail/binop-add-tup.rs delete mode 100644 src/test/compile-fail/fru-extra-field.rs delete mode 100644 src/test/compile-fail/let-destruct-refutable.rs delete mode 100644 src/test/compile-fail/rec-expected.rs delete mode 100644 src/test/compile-fail/rec-extend.rs delete mode 100644 src/test/compile-fail/rec-missing-fields.rs delete mode 100644 src/test/compile-fail/writing-through-read-alias.rs delete mode 100644 src/test/compile-fail/writing-to-immutable-rec.rs delete mode 100644 src/test/run-pass/lint-structural-records.rs diff --git a/doc/rust.md b/doc/rust.md index 13d897a00d2..e8018671fde 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1285,19 +1285,22 @@ An _implementation_ is an item that implements a [trait](#traits) for a specific Implementations are defined with the keyword `impl`. ~~~~ -# type Point = {x: float, y: float}; +# struct Point {x: float, y: float}; # type Surface = int; -# type BoundingBox = {x: float, y: float, width: float, height: float}; +# struct BoundingBox {x: float, y: float, width: float, height: float}; # trait Shape { fn draw(Surface); fn bounding_box() -> BoundingBox; } # fn do_draw_circle(s: Surface, c: Circle) { } -type Circle = {radius: float, center: Point}; +struct Circle { + radius: float, + center: Point, +} impl Shape for Circle { fn draw(s: Surface) { do_draw_circle(s, self); } fn bounding_box() -> BoundingBox { let r = self.radius; - {x: self.center.x - r, y: self.center.y - r, + BoundingBox{x: self.center.x - r, y: self.center.y - r, width: 2.0 * r, height: 2.0 * r} } } @@ -1637,38 +1640,6 @@ rec_expr : '{' ident ':' expr [ ".." expr ] '}' ~~~~~~~~ -> **Note:** In future versions of Rust, record expressions and [record types](#record-types) will be removed. - -A [_record_](#record-types) _expression_ is one or more comma-separated -name-value pairs enclosed by braces. A fieldname can be any identifier, -and is separated from its value expression by a -colon. To indicate that a field is mutable, the `mut` keyword is -written before its name. - -~~~~ -{x: 10f, y: 20f}; -{name: "Joe", age: 35u, score: 100_000}; -{ident: "X", mut count: 0u}; -~~~~ - -The order of the fields in a record expression is significant, and -determines the type of the resulting value. `{a: u8, b: u8}` and `{b: -u8, a: u8}` are two different fields. - -A record expression can terminate with the syntax `..` followed by an -expression to denote a functional update. The expression following -`..` (the base) must be of a record type that includes at least all the -fields mentioned in the record expression. A new record will be -created, of the same type as the base expression, with the given -values for the fields that were explicitly specified, and the values -in the base record for all other fields. The ordering of the fields in -such a record expression is not significant. - -~~~~ -let base = {x: 1, y: 2, z: 3}; -{y: 0, z: 10, .. base}; -~~~~ - ### Method-call expressions ~~~~~~~~{.ebnf .gram} @@ -1689,7 +1660,7 @@ field_expr : expr '.' ident A _field expression_ consists of an expression followed by a single dot and an identifier, when not immediately followed by a parenthesized expression-list (the latter is a [method call expression](#method-call-expressions)). -A field expression denotes a field of a [structure](#structure-types) or [record](#record-types). +A field expression denotes a field of a [structure](#structure-types). ~~~~~~~~ {.field} myrecord.myfield; @@ -1905,8 +1876,10 @@ An example of three different swap expressions: # let mut x = &mut [0]; # let mut a = &mut [0]; # let i = 0; -# let y = {mut z: 0}; -# let b = {mut c: 0}; +# struct S1 { z: int }; +# struct S2 { c: int }; +# let mut y = S1{z: 0}; +# let mut b = S2{c: 0}; x <-> a; x[i] <-> a[i]; @@ -2328,42 +2301,6 @@ match x { } ~~~~ -Records and structures can also be pattern-matched and their fields bound to variables. -When matching fields of a record, -the fields being matched are specified first, -then a placeholder (`_`) represents the remaining fields. - -~~~~ -# type options = {choose: bool, size: ~str}; -# type player = {player: ~str, stats: (), options: options}; -# fn load_stats() { } -# fn choose_player(r: &player) { } -# fn next_player() { } - -fn main() { - let r = { - player: ~"ralph", - stats: load_stats(), - options: { - choose: true, - size: ~"small" - } - }; - - match r { - {options: {choose: true, _}, _} => { - choose_player(&r) - } - {player: ref p, options: {size: ~"small", _}, _} => { - log(info, (copy *p) + ~" is small"); - } - _ => { - next_player(); - } - } -} -~~~~ - Patterns that bind variables default to binding to a copy of the matched value. This can be made explicit using the ```copy``` keyword, changed to bind to a borrowed pointer by using the ```ref``` keyword, or to a mutable borrowed pointer using ```ref mut```, or the value can be moved into @@ -2692,25 +2629,6 @@ let a: List = Cons(7, @Cons(13, @Nil)); ~~~~ -### Record types - -> **Note:** Records are not nominal types, thus do not directly support recursion, visibility control, -> out-of-order field initialization, or coherent trait implementation. -> Records are therefore deprecated and will be removed in future versions of Rust. -> [Structure types](#structure-types) should be used instead. - -The record type-constructor forms a new heterogeneous product of values. -Fields of a record type are accessed by name and are arranged in memory in the order specified by the record type. - -An example of a record type and its use: - -~~~~ -type Point = {x: int, y: int}; -let p: Point = {x: 10, y: 11}; -let px: int = p.x; -~~~~ - - ### Pointer types All pointers in Rust are explicit first-class values. @@ -3040,7 +2958,8 @@ Some operations (such as field selection) implicitly dereference boxes. An example of an _implicit dereference_ operation performed on box values: ~~~~~~~~ -let x = @{y: 10}; +struct Foo { y: int } +let x = @Foo{y: 10}; assert x.y == 10; ~~~~~~~~ diff --git a/doc/tutorial-borrowed-ptr.md b/doc/tutorial-borrowed-ptr.md index 0c1624706bf..e638579253f 100644 --- a/doc/tutorial-borrowed-ptr.md +++ b/doc/tutorial-borrowed-ptr.md @@ -166,9 +166,9 @@ operator. For example, I could write: # struct Point {x: float, y: float} // as before # struct Size {w: float, h: float} // as before # struct Rectangle {origin: Point, size: Size} -# let rect_stack = &{origin: Point {x: 1f, y: 2f}, size: Size {w: 3f, h: 4f}}; -# let rect_managed = @{origin: Point {x: 3f, y: 4f}, size: Size {w: 3f, h: 4f}}; -# let rect_unique = ~{origin: Point {x: 5f, y: 6f}, size: Size {w: 3f, h: 4f}}; +# let rect_stack = &Rectangle {origin: Point {x: 1f, y: 2f}, size: Size {w: 3f, h: 4f}}; +# let rect_managed = @Rectangle {origin: Point {x: 3f, y: 4f}, size: Size {w: 3f, h: 4f}}; +# let rect_unique = ~Rectangle {origin: Point {x: 5f, y: 6f}, size: Size {w: 3f, h: 4f}}; # fn compute_distance(p1: &Point, p2: &Point) -> float { 0f } compute_distance(&rect_stack.origin, &rect_managed.origin); ~~~ @@ -274,13 +274,14 @@ the following function is legal: ~~~ # fn some_condition() -> bool { true } +# struct Foo { f: int } fn example3() -> int { - let mut x = ~{f: 3}; + let mut x = ~Foo {f: 3}; if some_condition() { let y = &x.f; // -+ L return *y; // | } // -+ - x = ~{f: 4}; + x = ~Foo {f: 4}; ... # return 0; } diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs index 1fef4ad42f1..7197de36404 100644 --- a/src/libcore/dvec.rs +++ b/src/libcore/dvec.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -62,17 +62,17 @@ pub struct DVec { /// Creates a new, empty dvec pub pure fn DVec() -> DVec { - DVec {mut data: ~[]} + DVec {data: ~[]} } /// Creates a new dvec with a single element pub pure fn from_elem(e: A) -> DVec { - DVec {mut data: ~[e]} + DVec {data: ~[e]} } /// Creates a new dvec with the contents of a vector pub pure fn from_vec(v: ~[A]) -> DVec { - DVec {mut data: v} + DVec {data: v} } /// Consumes the vector and returns its contents diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 8b6d27496d9..09588f3280d 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -322,8 +322,8 @@ pub struct Pipe { mut in: c_int, mut out: c_int } #[cfg(unix)] pub fn pipe() -> Pipe { unsafe { - let mut fds = Pipe {mut in: 0 as c_int, - mut out: 0 as c_int }; + let mut fds = Pipe {in: 0 as c_int, + out: 0 as c_int }; assert (libc::pipe(&mut fds.in) == (0 as c_int)); return Pipe {in: fds.in, out: fds.out}; } @@ -339,8 +339,8 @@ pub fn pipe() -> Pipe { // fully understand. Here we explicitly make the pipe non-inheritable, // which means to pass it to a subprocess they need to be duplicated // first, as in rust_run_program. - let mut fds = Pipe { mut in: 0 as c_int, - mut out: 0 as c_int }; + let mut fds = Pipe {in: 0 as c_int, + out: 0 as c_int }; let res = libc::pipe(&mut fds.in, 1024 as c_uint, (libc::O_BINARY | libc::O_NOINHERIT) as c_int); assert (res == 0 as c_int); @@ -566,13 +566,17 @@ pub fn path_exists(p: &Path) -> bool { * * If the given path is relative, return it prepended with the current working * directory. If the given path is already an absolute path, return it - * as is. This is a shortcut for calling os::getcwd().unsafe_join(p) + * as is. */ // NB: this is here rather than in path because it is a form of environment // querying; what it does depends on the process working directory, not just // the input paths. pub fn make_absolute(p: &Path) -> Path { - getcwd().unsafe_join(p) + if p.is_absolute { + copy *p + } else { + getcwd().push_many(p.components) + } } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 2266c2511f8..ca5f6671130 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -300,7 +300,7 @@ impl Ord for &const T { pub fn test() { unsafe { struct Pair {mut fst: int, mut snd: int}; - let mut p = Pair {mut fst: 10, mut snd: 20}; + let mut p = Pair {fst: 10, snd: 20}; let pptr: *mut Pair = &mut p; let iptr: *mut int = cast::reinterpret_cast(&pptr); assert (*iptr == 10);; @@ -308,7 +308,7 @@ pub fn test() { assert (*iptr == 30); assert (p.fst == 30);; - *pptr = Pair {mut fst: 50, mut snd: 60}; + *pptr = Pair {fst: 50, snd: 60}; assert (*iptr == 50); assert (p.fst == 50); assert (p.snd == 60); diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index 7d04f676079..cbe0580a609 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -219,7 +219,7 @@ pub mod reader { } pub fn Decoder(d: Doc) -> Decoder { - Decoder { mut parent: d, mut pos: d.start } + Decoder { parent: d, pos: d.start } } priv impl Decoder { diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index 39d3fd569a6..51ff69da98d 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -87,7 +87,7 @@ enum Sem = Exclusive>; #[doc(hidden)] fn new_sem(count: int, q: Q) -> Sem { Sem(exclusive(SemInner { - mut count: count, waiters: new_waitqueue(), blocked: q })) + count: count, waiters: new_waitqueue(), blocked: q })) } #[doc(hidden)] fn new_sem_and_signal(count: int, num_condvars: uint) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6294243d486..444f1201fc3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -1093,15 +1093,10 @@ pub impl Parser { self.mk_expr(lo, hi, expr_tup(es)) } } else if *self.token == token::LBRACE { - if self.looking_at_record_literal() { - ex = self.parse_record_literal(); - hi = self.span.hi; - } else { - self.bump(); - let blk = self.parse_block_tail(lo, default_blk); - return self.mk_expr(blk.span.lo, blk.span.hi, - expr_block(blk)); - } + self.bump(); + let blk = self.parse_block_tail(lo, default_blk); + return self.mk_expr(blk.span.lo, blk.span.hi, + expr_block(blk)); } else if token::is_bar(*self.token) { return self.parse_lambda_expr(); } else if self.eat_keyword(~"if") { @@ -1223,6 +1218,7 @@ pub impl Parser { self.bump(); let mut fields = ~[]; let mut base = None; + fields.push(self.parse_field(token::COLON)); while *self.token != token::RBRACE { if self.try_parse_obsolete_with() { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 0f161a444bd..ac21e27bb8b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1213,7 +1213,7 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) { print_expr(s, expr); end(s); } - _ => word(s.s, ~",") + _ => (word(s.s, ~",")) } word(s.s, ~"}"); } diff --git a/src/test/compile-fail/autoderef-full-lval.rs b/src/test/compile-fail/autoderef-full-lval.rs index fec5c994de7..cbbf484ad55 100644 --- a/src/test/compile-fail/autoderef-full-lval.rs +++ b/src/test/compile-fail/autoderef-full-lval.rs @@ -9,18 +9,23 @@ // except according to those terms. // error-pattern: mismatched types -type clam = {x: @int, y: @int}; +struct clam { + x: @int, + y: @int, +} -type fish = {a: @int}; +struct fish { + a: @int, +} fn main() { - let a: clam = {x: @1, y: @2}; - let b: clam = {x: @10, y: @20}; + let a: clam = clam{x: @1, y: @2}; + let b: clam = clam{x: @10, y: @20}; let z: int = a.x + b.y; log(debug, z); assert (z == 21); - let forty: fish = {a: @40}; - let two: fish = {a: @2}; + let forty: fish = fish{a: @40}; + let two: fish = fish{a: @2}; let answer: int = forty.a + two.a; log(debug, answer); assert (answer == 42); diff --git a/src/test/compile-fail/bad-record-pat-2.rs b/src/test/compile-fail/bad-record-pat-2.rs deleted file mode 100644 index 3707dc923c8..00000000000 --- a/src/test/compile-fail/bad-record-pat-2.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern:did not expect a record with a field `q` - -fn main() { match {x: 1, y: 2} { {x: x, q: q} => { } } } diff --git a/src/test/compile-fail/bad-record-pat.rs b/src/test/compile-fail/bad-record-pat.rs deleted file mode 100644 index a7ce8e2ef5c..00000000000 --- a/src/test/compile-fail/bad-record-pat.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern:expected a record with 2 fields, found one with 1 - -fn main() { match {x: 1, y: 2} { {x: x} => { } } } diff --git a/src/test/compile-fail/binop-add-tup-assign.rs b/src/test/compile-fail/binop-add-tup-assign.rs deleted file mode 100644 index 3e560c8eaf6..00000000000 --- a/src/test/compile-fail/binop-add-tup-assign.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern:+ cannot be applied to type `{x: bool}` - -fn main() { let x = {x: true}; x += {x: false}; } diff --git a/src/test/compile-fail/binop-add-tup.rs b/src/test/compile-fail/binop-add-tup.rs deleted file mode 100644 index 660e951c847..00000000000 --- a/src/test/compile-fail/binop-add-tup.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern:+ cannot be applied to type `{x: bool}` - -fn main() { let x = {x: true} + {x: false}; } diff --git a/src/test/compile-fail/break-outside-loop.rs b/src/test/compile-fail/break-outside-loop.rs index c36d60fdac1..b3154c9742a 100644 --- a/src/test/compile-fail/break-outside-loop.rs +++ b/src/test/compile-fail/break-outside-loop.rs @@ -9,9 +9,14 @@ // except according to those terms. // error-pattern:`break` outside of loop + +struct Foo { + t: ~str +} + fn main() { let pth = break; - let rs: {t: ~str} = {t: pth}; + let rs: Foo = Foo{t: pth}; } diff --git a/src/test/compile-fail/fru-extra-field.rs b/src/test/compile-fail/fru-extra-field.rs deleted file mode 100644 index 64d76d6fb74..00000000000 --- a/src/test/compile-fail/fru-extra-field.rs +++ /dev/null @@ -1,21 +0,0 @@ -// -*- rust -*- -// 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. - - -// error-pattern: record - -type point = {x: int, y: int}; - -fn main() { - let origin: point = {x: 0, y: 0}; - - let origin3d: point = {z: 0,.. origin}; -} diff --git a/src/test/compile-fail/let-destruct-refutable.rs b/src/test/compile-fail/let-destruct-refutable.rs deleted file mode 100644 index 9bd9db20779..00000000000 --- a/src/test/compile-fail/let-destruct-refutable.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern:refutable pattern -// error-pattern:refutable pattern - -enum xx { xx(int), yy, } - -fn main() { - let @{x: xx(x), y: y} = @{x: xx(10), y: 20}; - assert (x + y == 30); - - let [a, b] = ~[1, 2]; -} diff --git a/src/test/compile-fail/nonscalar-cast.rs b/src/test/compile-fail/nonscalar-cast.rs index 54c0f6ca07f..d84775d02ac 100644 --- a/src/test/compile-fail/nonscalar-cast.rs +++ b/src/test/compile-fail/nonscalar-cast.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -10,6 +10,10 @@ // error-pattern:non-scalar cast -fn main() { - log(debug, { x: 1 } as int); +struct foo { + x:int +} + +fn main() { + log(debug, foo{ x: 1 } as int); } diff --git a/src/test/compile-fail/rec-expected.rs b/src/test/compile-fail/rec-expected.rs deleted file mode 100644 index 962201aa9b9..00000000000 --- a/src/test/compile-fail/rec-expected.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -type foo = {a: int}; -type bar = {b: int}; - -fn want_foo(f: foo) {} -fn have_bar(b: bar) { - want_foo(b); //~ ERROR expected a record with field `a` -} - -fn main() {} diff --git a/src/test/compile-fail/rec-extend.rs b/src/test/compile-fail/rec-extend.rs deleted file mode 100644 index aa4f9d0501a..00000000000 --- a/src/test/compile-fail/rec-extend.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern:expected `int` but found `bool` - -fn main() { - - let a = {foo: 0i}; - - let b = {foo: true,.. a}; -} diff --git a/src/test/compile-fail/rec-missing-fields.rs b/src/test/compile-fail/rec-missing-fields.rs deleted file mode 100644 index 2ad2f00ee26..00000000000 --- a/src/test/compile-fail/rec-missing-fields.rs +++ /dev/null @@ -1,19 +0,0 @@ -// -*- rust -*- -// 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. - - -// error-pattern: mismatched types - -// Issue #51. - -type point = {x: int, y: int}; - -fn main() { let p: point = {x: 10}; log(debug, p.y); } diff --git a/src/test/compile-fail/writing-through-read-alias.rs b/src/test/compile-fail/writing-through-read-alias.rs deleted file mode 100644 index 3b2591c3bfa..00000000000 --- a/src/test/compile-fail/writing-through-read-alias.rs +++ /dev/null @@ -1,19 +0,0 @@ -// -*- rust -*- -// 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. - - -// error-pattern:assigning to immutable field - -type point = {x: int, y: int, z: int}; - -fn f(p: point) { p.x = 13; } - -fn main() { let x: point = {x: 10, y: 11, z: 12}; f(x); } diff --git a/src/test/compile-fail/writing-to-immutable-rec.rs b/src/test/compile-fail/writing-to-immutable-rec.rs deleted file mode 100644 index 4cc9dae7deb..00000000000 --- a/src/test/compile-fail/writing-to-immutable-rec.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern: assigning to immutable field -fn main() { let r: {x: int} = {x: 1}; r.x = 6; } diff --git a/src/test/run-pass/lint-structural-records.rs b/src/test/run-pass/lint-structural-records.rs deleted file mode 100644 index e5107ba187c..00000000000 --- a/src/test/run-pass/lint-structural-records.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[warn(structural_records)]; -pub fn main() { - let _foo = {x:5}; -} diff --git a/src/test/run-pass/uniq-cc-generic.rs b/src/test/run-pass/uniq-cc-generic.rs index 1b602ab7d30..def49ef0f8c 100644 --- a/src/test/run-pass/uniq-cc-generic.rs +++ b/src/test/run-pass/uniq-cc-generic.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -24,7 +24,7 @@ fn make_uniq_closure(a: A) -> fn~() -> uint { fn empty_pointy() -> @mut Pointy { return @mut Pointy { - mut a : none, + a : none, d : make_uniq_closure(~"hi") } } From ca1ceb15b1f80d687525f166d99adb1c37b6081d Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 1 Mar 2013 22:07:12 -0500 Subject: [PATCH 09/10] add a TotalOrd trait --- src/libcore/cmp.rs | 76 ++++++++++++++++++++++++++++++++++++++++++ src/libcore/prelude.rs | 2 +- src/libcore/str.rs | 40 +++++++++++++++++++++- src/libcore/vec.rs | 59 +++++++++++++++++++++++++++----- 4 files changed, 166 insertions(+), 11 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index fd99235bd27..d588f0c53b1 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -37,6 +37,70 @@ pub trait Eq { pure fn ne(&self, other: &Self) -> bool; } +#[deriving_eq] +pub enum Ordering { Less, Equal, Greater } + +/// Trait for types that form a total order +pub trait TotalOrd { + pure fn cmp(&self, other: &Self) -> Ordering; +} + +pure fn icmp(a: &T, b: &T) -> Ordering { + if *a < *b { Less } + else if *a > *b { Greater } + else { Equal } +} + +impl TotalOrd for u8 { + #[inline(always)] + pure fn cmp(&self, other: &u8) -> Ordering { icmp(self, other) } +} + +impl TotalOrd for u16 { + #[inline(always)] + pure fn cmp(&self, other: &u16) -> Ordering { icmp(self, other) } +} + +impl TotalOrd for u32 { + #[inline(always)] + pure fn cmp(&self, other: &u32) -> Ordering { icmp(self, other) } +} + +impl TotalOrd for u64 { + #[inline(always)] + pure fn cmp(&self, other: &u64) -> Ordering { icmp(self, other) } +} + +impl TotalOrd for i8 { + #[inline(always)] + pure fn cmp(&self, other: &i8) -> Ordering { icmp(self, other) } +} + +impl TotalOrd for i16 { + #[inline(always)] + pure fn cmp(&self, other: &i16) -> Ordering { icmp(self, other) } +} + +impl TotalOrd for i32 { + #[inline(always)] + pure fn cmp(&self, other: &i32) -> Ordering { icmp(self, other) } +} + +impl TotalOrd for i64 { + #[inline(always)] + pure fn cmp(&self, other: &i64) -> Ordering { icmp(self, other) } +} + +impl TotalOrd for int { + #[inline(always)] + pure fn cmp(&self, other: &int) -> Ordering { icmp(self, other) } +} + +impl TotalOrd for uint { + #[inline(always)] + pure fn cmp(&self, other: &uint) -> Ordering { icmp(self, other) } +} + /** * Trait for values that can be compared for a sort-order. * @@ -94,3 +158,15 @@ pub pure fn min(v1: T, v2: T) -> T { pub pure fn max(v1: T, v2: T) -> T { if v1 > v2 { v1 } else { v2 } } + +#[cfg(test)] +mod test { + #[test] + fn test_int() { + assert 5.cmp(&10) == Less; + assert 10.cmp(&5) == Greater; + assert 5.cmp(&5) == Equal; + assert (-5).cmp(&12) == Less; + assert 12.cmp(-5) == Greater; + } +} diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index d0a16f7875b..a7b4500c3e3 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -24,7 +24,7 @@ pub use result::{Result, Ok, Err}; /* Reexported types and traits */ pub use clone::Clone; -pub use cmp::{Eq, Ord}; +pub use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater}; pub use container::{Container, Mutable, Map, Set}; pub use hash::Hash; pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 6ee6d282841..ef0fa9fc4e2 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -20,7 +20,7 @@ use at_vec; use cast; use char; -use cmp::{Eq, Ord}; +use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater}; use libc; use libc::size_t; use io::WriterUtil; @@ -773,6 +773,35 @@ pub pure fn eq(a: &~str, b: &~str) -> bool { eq_slice(*a, *b) } +pure fn cmp(a: &str, b: &str) -> Ordering { + let low = uint::min(a.len(), b.len()); + + for uint::range(0, low) |idx| { + match a[idx].cmp(&b[idx]) { + Greater => return Greater, + Less => return Less, + Equal => () + } + } + + a.len().cmp(&b.len()) +} + +#[cfg(notest)] +impl TotalOrd for &str { + pure fn cmp(&self, other: & &self/str) -> Ordering { cmp(*self, *other) } +} + +#[cfg(notest)] +impl TotalOrd for ~str { + pure fn cmp(&self, other: &~str) -> Ordering { cmp(*self, *other) } +} + +#[cfg(notest)] +impl TotalOrd for @str { + pure fn cmp(&self, other: &@str) -> Ordering { cmp(*self, *other) } +} + /// Bytewise slice less than pure fn lt(a: &str, b: &str) -> bool { let (a_len, b_len) = (a.len(), b.len()); @@ -2382,6 +2411,7 @@ mod tests { use ptr; use str::*; use vec; + use cmp::{TotalOrd, Less, Equal, Greater}; #[test] fn test_eq() { @@ -3388,4 +3418,12 @@ mod tests { assert view("abcdef", 1, 5).to_managed() == @"bcde"; } + #[test] + fn test_total_ord() { + "1234".cmp(& &"123") == Greater; + "123".cmp(& &"1234") == Less; + "1234".cmp(& &"1234") == Equal; + "12345555".cmp(& &"123456") == Less; + "22".cmp(& &"1234") == Greater; + } } diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 4d28c769b18..86365247044 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -15,7 +15,7 @@ use container::{Container, Mutable}; use cast::transmute; use cast; -use cmp::{Eq, Ord}; +use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater}; use iter::BaseIter; use iter; use kinds::Copy; @@ -1425,7 +1425,7 @@ pub pure fn rev_eachi(v: &r/[T], blk: fn(i: uint, v: &r/T) -> bool) { * Both vectors must have the same length */ #[inline] -pub fn each2(v1: &[U], v2: &[T], f: fn(u: &U, t: &T) -> bool) { +pub pure fn each2(v1: &[U], v2: &[T], f: fn(u: &U, t: &T) -> bool) { assert len(v1) == len(v2); for uint::range(0u, len(v1)) |i| { if !f(&v1[i], &v2[i]) { @@ -1575,6 +1575,38 @@ impl Eq for @[T] { // Lexicographical comparison +pure fn cmp(a: &[T], b: &[T]) -> Ordering { + let low = uint::min(a.len(), b.len()); + + for uint::range(0, low) |idx| { + match a[idx].cmp(&b[idx]) { + Greater => return Greater, + Less => return Less, + Equal => () + } + } + + a.len().cmp(&b.len()) +} + +#[cfg(notest)] +impl TotalOrd for &[T] { + #[inline(always)] + pure fn cmp(&self, other: & &self/[T]) -> Ordering { cmp(*self, *other) } +} + +#[cfg(notest)] +impl TotalOrd for ~[T] { + #[inline(always)] + pure fn cmp(&self, other: &~[T]) -> Ordering { cmp(*self, *other) } +} + +#[cfg(notest)] +impl TotalOrd for @[T] { + #[inline(always)] + pure fn cmp(&self, other: &@[T]) -> Ordering { cmp(*self, *other) } +} + pure fn lt(a: &[T], b: &[T]) -> bool { let (a_len, b_len) = (a.len(), b.len()); let mut end = uint::min(a_len, b_len); @@ -2151,7 +2183,7 @@ pub mod bytes { use vec; /// Bytewise string comparison - pub pure fn cmp(a: &~[u8], b: &~[u8]) -> int { + pub pure fn memcmp(a: &~[u8], b: &~[u8]) -> int { let a_len = len(*a); let b_len = len(*b); let n = uint::min(a_len, b_len) as libc::size_t; @@ -2172,22 +2204,22 @@ pub mod bytes { } /// Bytewise less than or equal - pub pure fn lt(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) < 0 } + pub pure fn lt(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) < 0 } /// Bytewise less than or equal - pub pure fn le(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) <= 0 } + pub pure fn le(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) <= 0 } /// Bytewise equality - pub pure fn eq(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) == 0 } + pub pure fn eq(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) == 0 } /// Bytewise inequality - pub pure fn ne(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) != 0 } + pub pure fn ne(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) != 0 } /// Bytewise greater than or equal - pub pure fn ge(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) >= 0 } + pub pure fn ge(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) >= 0 } /// Bytewise greater than - pub pure fn gt(a: &~[u8], b: &~[u8]) -> bool { cmp(a, b) > 0 } + pub pure fn gt(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) > 0 } /** * Copies data from one vector to another. @@ -2429,6 +2461,7 @@ mod tests { use option; use sys; use vec::*; + use cmp::*; fn square(n: uint) -> uint { return n * n; } @@ -3942,6 +3975,14 @@ mod tests { } } + #[test] + fn test_total_ord() { + [1, 2, 3, 4].cmp(& &[1, 2, 3]) == Greater; + [1, 2, 3].cmp(& &[1, 2, 3, 4]) == Less; + [1, 2, 3, 4].cmp(& &[1, 2, 3, 4]) == Equal; + [1, 2, 3, 4, 5, 5, 5, 5].cmp(& &[1, 2, 3, 4, 5, 6]) == Less; + [2, 2].cmp(& &[1, 2, 3, 4]) == Greater; + } } // Local Variables: From 035233a25907af8206d254878e7e04048fcac95e Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sat, 2 Mar 2013 13:27:29 -0500 Subject: [PATCH 10/10] treemap: reimplement using TotalOrd --- src/libcore/prelude.rs | 2 +- src/libstd/treemap.rs | 167 +++++++++++++++++++++-------------------- 2 files changed, 87 insertions(+), 82 deletions(-) diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index a7b4500c3e3..186253761fa 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -27,7 +27,7 @@ pub use clone::Clone; pub use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater}; pub use container::{Container, Mutable, Map, Set}; pub use hash::Hash; -pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter}; +pub use iter::{BaseIter, ReverseIter, ExtendedIter, EqIter, CopyableIter}; pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times}; pub use num::NumCast; pub use path::GenericPath; diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index 88e4ade4b82..a093351c4a7 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -10,12 +10,8 @@ //! An ordered map and set implemented as self-balancing binary search //! trees. The only requirement for the types is that the key implements -//! `Ord`, and that the `lt` method provides a total ordering. +//! `TotalOrd`. -use core::container::{Container, Mutable, Map, Set}; -use core::cmp::{Eq, Ord}; -use core::iter::{BaseIter, ReverseIter}; -use core::option::{Option, Some, None}; use core::prelude::*; // This is implemented as an AA tree, which is a simplified variation of @@ -39,7 +35,7 @@ pub struct TreeMap { priv length: uint } -impl Eq for TreeMap { +impl Eq for TreeMap { pure fn eq(&self, other: &TreeMap) -> bool { if self.len() != other.len() { false @@ -61,7 +57,8 @@ impl Eq for TreeMap { } // Lexicographical comparison -pure fn lt(a: &TreeMap, b: &TreeMap) -> bool { +pure fn lt(a: &TreeMap, + b: &TreeMap) -> bool { let mut x = a.iter(); let mut y = b.iter(); @@ -78,7 +75,7 @@ pure fn lt(a: &TreeMap, b: &TreeMap) -> bool { return a_len < b_len; } -impl Ord for TreeMap { +impl Ord for TreeMap { #[inline(always)] pure fn lt(&self, other: &TreeMap) -> bool { lt(self, other) @@ -97,7 +94,7 @@ impl Ord for TreeMap { } } -impl BaseIter<(&K, &V)> for TreeMap { +impl BaseIter<(&K, &V)> for TreeMap { /// Visit all key-value pairs in order pure fn each(&self, f: fn(&(&self/K, &self/V)) -> bool) { each(&self.root, f) @@ -105,14 +102,14 @@ impl BaseIter<(&K, &V)> for TreeMap { pure fn size_hint(&self) -> Option { Some(self.len()) } } -impl ReverseIter<(&K, &V)> for TreeMap { +impl ReverseIter<(&K, &V)> for TreeMap { /// Visit all key-value pairs in reverse order pure fn each_reverse(&self, f: fn(&(&self/K, &self/V)) -> bool) { each_reverse(&self.root, f); } } -impl Container for TreeMap { +impl Container for TreeMap { /// Return the number of elements in the map pure fn len(&self) -> uint { self.length } @@ -120,7 +117,7 @@ impl Container for TreeMap { pure fn is_empty(&self) -> bool { self.root.is_none() } } -impl Mutable for TreeMap { +impl Mutable for TreeMap { /// Clear the map, removing all key-value pairs. fn clear(&mut self) { self.root = None; @@ -128,7 +125,7 @@ impl Mutable for TreeMap { } } -impl Map for TreeMap { +impl Map for TreeMap { /// Return true if the map contains a value for the specified key pure fn contains_key(&self, key: &K) -> bool { self.find(key).is_some() @@ -146,12 +143,10 @@ impl Map for TreeMap { loop { match *current { Some(ref r) => { - if *key < r.key { - current = &r.left; - } else if r.key < *key { - current = &r.right; - } else { - return Some(&r.value); + match key.cmp(&r.key) { + Less => current = &r.left, + Greater => current = &r.right, + Equal => return Some(&r.value) } } None => return None @@ -177,7 +172,7 @@ impl Map for TreeMap { } } -pub impl TreeMap { +pub impl TreeMap { /// Create an empty TreeMap static pure fn new() -> TreeMap { TreeMap{root: None, length: 0} } @@ -207,7 +202,7 @@ pub struct TreeMapIterator { /// Advance the iterator to the next node (in order) and return a /// tuple with a reference to the key and value. If there are no /// more nodes, return `None`. -pub fn map_next(iter: &mut TreeMapIterator/&r) +pub fn map_next(iter: &mut TreeMapIterator/&r) -> Option<(&r/K, &r/V)> { while !iter.stack.is_empty() || iter.node.is_some() { match *iter.node { @@ -226,8 +221,8 @@ pub fn map_next(iter: &mut TreeMapIterator/&r) } /// Advance the iterator through the map -pub fn map_advance(iter: &mut TreeMapIterator/&r, - f: fn((&r/K, &r/V)) -> bool) { +pub fn map_advance(iter: &mut TreeMapIterator/&r, + f: fn((&r/K, &r/V)) -> bool) { loop { match map_next(iter) { Some(x) => { @@ -242,25 +237,25 @@ pub struct TreeSet { priv map: TreeMap } -impl BaseIter for TreeSet { +impl BaseIter for TreeSet { /// Visit all values in order pure fn each(&self, f: fn(&T) -> bool) { self.map.each_key(f) } pure fn size_hint(&self) -> Option { Some(self.len()) } } -impl ReverseIter for TreeSet { +impl ReverseIter for TreeSet { /// Visit all values in reverse order pure fn each_reverse(&self, f: fn(&T) -> bool) { self.map.each_key_reverse(f) } } -impl Eq for TreeSet { +impl Eq for TreeSet { pure fn eq(&self, other: &TreeSet) -> bool { self.map == other.map } pure fn ne(&self, other: &TreeSet) -> bool { self.map != other.map } } -impl Ord for TreeSet { +impl Ord for TreeSet { #[inline(always)] pure fn lt(&self, other: &TreeSet) -> bool { self.map < other.map } #[inline(always)] @@ -271,7 +266,7 @@ impl Ord for TreeSet { pure fn gt(&self, other: &TreeSet) -> bool { self.map > other.map } } -impl Container for TreeSet { +impl Container for TreeSet { /// Return the number of elements in the set pure fn len(&self) -> uint { self.map.len() } @@ -279,12 +274,12 @@ impl Container for TreeSet { pure fn is_empty(&self) -> bool { self.map.is_empty() } } -impl Mutable for TreeSet { +impl Mutable for TreeSet { /// Clear the set, removing all values. fn clear(&mut self) { self.map.clear() } } -impl Set for TreeSet { +impl Set for TreeSet { /// Return true if the set contains a value pure fn contains(&self, value: &T) -> bool { self.map.contains_key(value) @@ -309,12 +304,10 @@ impl Set for TreeSet { while a.is_some() && b.is_some() { let a1 = a.unwrap(); let b1 = b.unwrap(); - if a1 < b1 { - a = set_next(&mut x); - } else if b1 < a1 { - b = set_next(&mut y); - } else { - return false; + match a1.cmp(b1) { + Less => a = set_next(&mut x), + Greater => b = set_next(&mut y), + Equal => return false } } } @@ -341,13 +334,12 @@ impl Set for TreeSet { let a1 = a.unwrap(); let b1 = b.unwrap(); - if b1 < a1 { - return false + match a1.cmp(b1) { + Less => (), + Greater => return false, + Equal => b = set_next(&mut y), } - if !(a1 < b1) { - b = set_next(&mut y); - } a = set_next(&mut x); } } @@ -373,11 +365,13 @@ impl Set for TreeSet { let a1 = a.unwrap(); let b1 = b.unwrap(); - if a1 < b1 { + let cmp = a1.cmp(b1); + + if cmp == Less { if !f(a1) { return } a = set_next(&mut x); } else { - if !(b1 < a1) { a = set_next(&mut x) } + if cmp == Equal { a = set_next(&mut x) } b = set_next(&mut y); } } @@ -404,11 +398,13 @@ impl Set for TreeSet { let a1 = a.unwrap(); let b1 = b.unwrap(); - if a1 < b1 { + let cmp = a1.cmp(b1); + + if cmp == Less { if !f(a1) { return } a = set_next(&mut x); } else { - if b1 < a1 { + if cmp == Greater { if !f(b1) { return } } else { a = set_next(&mut x); @@ -434,10 +430,13 @@ impl Set for TreeSet { while a.is_some() && b.is_some() { let a1 = a.unwrap(); let b1 = b.unwrap(); - if a1 < b1 { + + let cmp = a1.cmp(b1); + + if cmp == Less { a = set_next(&mut x); } else { - if !(b1 < a1) { + if cmp == Equal { if !f(a1) { return } } b = set_next(&mut y); @@ -465,12 +464,14 @@ impl Set for TreeSet { let a1 = a.unwrap(); let b1 = b.unwrap(); - if b1 < a1 { + let cmp = a1.cmp(b1); + + if cmp == Greater { if !f(b1) { return } b = set_next(&mut y); } else { if !f(a1) { return } - if !(a1 < b1) { + if cmp == Equal { b = set_next(&mut y); } a = set_next(&mut x); @@ -480,7 +481,7 @@ impl Set for TreeSet { } } -pub impl TreeSet { +pub impl TreeSet { /// Create an empty TreeSet static pure fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } @@ -498,12 +499,12 @@ pub struct TreeSetIterator { /// Advance the iterator to the next node (in order). If this iterator is /// finished, does nothing. -pub fn set_next(iter: &mut TreeSetIterator/&r) -> Option<&r/T> { +pub fn set_next(iter: &mut TreeSetIterator/&r) -> Option<&r/T> { do map_next(&mut iter.iter).map |&(value, _)| { value } } /// Advance the iterator through the set -fn set_advance(iter: &mut TreeSetIterator/&r, +fn set_advance(iter: &mut TreeSetIterator/&r, f: fn(&r/T) -> bool) { do map_advance(&mut iter.iter) |(k, _)| { f(k) } } @@ -518,14 +519,14 @@ struct TreeNode { level: uint } -pub impl TreeNode { +pub impl TreeNode { #[inline(always)] static pure fn new(key: K, value: V) -> TreeNode { TreeNode{key: key, value: value, left: None, right: None, level: 1} } } -pure fn each(node: &r/Option<~TreeNode>, +pure fn each(node: &r/Option<~TreeNode>, f: fn(&(&r/K, &r/V)) -> bool) { do node.iter |x| { each(&x.left, f); @@ -533,7 +534,7 @@ pure fn each(node: &r/Option<~TreeNode>, } } -pure fn each_reverse(node: &r/Option<~TreeNode>, +pure fn each_reverse(node: &r/Option<~TreeNode>, f: fn(&(&r/K, &r/V)) -> bool) { do node.iter |x| { each_reverse(&x.right, f); @@ -542,7 +543,7 @@ pure fn each_reverse(node: &r/Option<~TreeNode>, } // Remove left horizontal link by rotating right -fn skew(node: &mut ~TreeNode) { +fn skew(node: &mut ~TreeNode) { if node.left.map_default(false, |x| x.level == node.level) { let mut save = node.left.swap_unwrap(); node.left <-> save.right; // save.right now None @@ -553,7 +554,7 @@ fn skew(node: &mut ~TreeNode) { // Remove dual horizontal link by rotating left and increasing level of // the parent -fn split(node: &mut ~TreeNode) { +fn split(node: &mut ~TreeNode) { if node.right.map_default(false, |x| x.right.map_default(false, |y| y.level == node.level)) { let mut save = node.right.swap_unwrap(); @@ -564,24 +565,28 @@ fn split(node: &mut ~TreeNode) { } } -fn insert(node: &mut Option<~TreeNode>, key: K, - value: V) -> bool { +fn insert(node: &mut Option<~TreeNode>, key: K, + value: V) -> bool { match *node { Some(ref mut save) => { - if key < save.key { + match key.cmp(&save.key) { + Less => { let inserted = insert(&mut save.left, key, value); skew(save); split(save); inserted - } else if save.key < key { + } + Greater => { let inserted = insert(&mut save.right, key, value); skew(save); split(save); inserted - } else { + } + Equal => { save.key = key; save.value = value; false + } } } None => { @@ -591,8 +596,9 @@ fn insert(node: &mut Option<~TreeNode>, key: K, } } -fn remove(node: &mut Option<~TreeNode>, key: &K) -> bool { - fn heir_swap(node: &mut ~TreeNode, +fn remove(node: &mut Option<~TreeNode>, + key: &K) -> bool { + fn heir_swap(node: &mut ~TreeNode, child: &mut Option<~TreeNode>) { // *could* be done without recursion, but it won't borrow check do child.mutate |mut child| { @@ -611,11 +617,10 @@ fn remove(node: &mut Option<~TreeNode>, key: &K) -> bool { return false // bottom of tree } Some(ref mut save) => { - let (removed, this) = if save.key < *key { - (remove(&mut save.right, key), false) - } else if *key < save.key { - (remove(&mut save.left, key), false) - } else { + let (removed, this) = match key.cmp(&save.key) { + Less => (remove(&mut save.left, key), false), + Greater => (remove(&mut save.right, key), false), + Equal => { if save.left.is_some() { if save.right.is_some() { let mut left = save.left.swap_unwrap(); @@ -637,6 +642,7 @@ fn remove(node: &mut Option<~TreeNode>, key: &K) -> bool { } else { (true, true) } + } }; if !this { @@ -682,12 +688,9 @@ fn remove(node: &mut Option<~TreeNode>, key: &K) -> bool { #[cfg(test)] mod test_treemap { + use core::prelude::*; use super::*; - use core::cmp::{Ord, Eq}; - use core::option::{Some, Option, None}; use core::rand; - use core::str; - use core::vec; #[test] fn find_empty() { @@ -742,7 +745,8 @@ mod test_treemap { assert m.find(&k1) == Some(&v1); } - fn check_equal(ctrl: &[(K, V)], map: &TreeMap) { + fn check_equal(ctrl: &[(K, V)], + map: &TreeMap) { assert ctrl.is_empty() == map.is_empty(); for ctrl.each |x| { let &(k, v) = x; @@ -762,11 +766,11 @@ mod test_treemap { } } - fn check_left(node: &Option<~TreeNode>, - parent: &~TreeNode) { + fn check_left(node: &Option<~TreeNode>, + parent: &~TreeNode) { match *node { Some(ref r) => { - assert r.key < parent.key; + assert r.key.cmp(&parent.key) == Less; assert r.level == parent.level - 1; // left is black check_left(&r.left, r); check_right(&r.right, r, false); @@ -775,11 +779,12 @@ mod test_treemap { } } - fn check_right(node: &Option<~TreeNode>, - parent: &~TreeNode, parent_red: bool) { + fn check_right(node: &Option<~TreeNode>, + parent: &~TreeNode, + parent_red: bool) { match *node { Some(ref r) => { - assert r.key > parent.key; + assert r.key.cmp(&parent.key) == Greater; let red = r.level == parent.level; if parent_red { assert !red } // no dual horizontal links assert red || r.level == parent.level - 1; // right red or black @@ -790,7 +795,7 @@ mod test_treemap { } } - fn check_structure(map: &TreeMap) { + fn check_structure(map: &TreeMap) { match map.root { Some(ref r) => { check_left(&r.left, r);