diff options
| author | bors <bors@rust-lang.org> | 2014-05-20 13:21:18 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-05-20 13:21:18 -0700 |
| commit | 4dff9cbf58bb7a274a693eb7d19006402945fc7e (patch) | |
| tree | c8eefbda7bfb2a21f240a3ba4ab9e3ffc7e57898 /src | |
| parent | f9bd6b4e3900da77f06ebad04ae6bada1e26e042 (diff) | |
| parent | c9ab33a8fde708c8a4cf70b03f5d69370220665c (diff) | |
| download | rust-4dff9cbf58bb7a274a693eb7d19006402945fc7e.tar.gz rust-4dff9cbf58bb7a274a693eb7d19006402945fc7e.zip | |
auto merge of #14304 : brson/rust/moredocs, r=kballard
Includes module docs for `cell`.
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/cell.rs | 152 | ||||
| -rw-r--r-- | src/libcore/lib.rs | 33 | ||||
| -rw-r--r-- | src/libcore/ops.rs | 2 | ||||
| -rw-r--r-- | src/libstd/lib.rs | 15 |
4 files changed, 182 insertions, 20 deletions
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index d42ad49485f..093b3f57047 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -8,7 +8,157 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Types that provide interior mutability. +//! Sharable mutable containers. +//! +//! Values of the `Cell` and `RefCell` types may be mutated through +//! shared references (i.e. the common `&T` type), whereas most Rust +//! types can only be mutated through unique (`&mut T`) references. We +//! say that `Cell` and `RefCell` provide *interior mutability*, in +//! contrast with typical Rust types that exhibit *inherited +//! mutability*. +//! +//! Cell types come in two flavors: `Cell` and `RefCell`. `Cell` +//! provides `get` and `set` methods that change the +//! interior value with a single method call. `Cell` though is only +//! compatible with types that implement `Copy`. For other types, +//! one must use the `RefCell` type, acquiring a write lock before +//! mutating. +//! +//! `RefCell` uses Rust's lifetimes to implement *dynamic borrowing*, +//! a process whereby one can claim temporary, exclusive, mutable +//! access to the inner value. Borrows for `RefCell`s are tracked *at +//! runtime*, unlike Rust's native reference types which are entirely +//! tracked statically, at compile time. Because `RefCell` borrows are +//! dynamic it is possible to attempt to borrow a value that is +//! already mutably borrowed; when this happens it results in task +//! failure. +//! +//! # When to choose interior mutability +//! +//! The more common inherited mutability, where one must have unique +//! access to mutate a value, is one of the key language elements that +//! enables Rust to reason strongly about pointer aliasing, statically +//! preventing crash bugs. Because of that, inherited mutability is +//! preferred, and interior mutability is something of a last +//! resort. Since cell types enable mutation where it would otherwise +//! be disallowed though, there are occassions when interior +//! mutability might be appropriate, or even *must* be used, e.g. +//! +//! * Introducing inherited mutability roots to shared types. +//! * Implementation details of logically-immutable methods. +//! * Mutating implementations of `clone`. +//! +//! ## Introducing inherited mutability roots to shared types +//! +//! Shared smart pointer types, including `Rc` and `Arc`, provide +//! containers that can be cloned and shared between multiple parties. +//! Because the contained values may be multiply-aliased, they can +//! only be borrowed as shared references, not mutable references. +//! Without cells it would be impossible to mutate data inside of +//! shared boxes at all! +//! +//! It's very common then to put a `RefCell` inside shared pointer +//! types to reintroduce mutability: +//! +//! ``` +//! extern crate collections; +//! +//! use collections::HashMap; +//! use std::cell::RefCell; +//! use std::rc::Rc; +//! +//! fn main() { +//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new())); +//! shared_map.borrow_mut().insert("africa", 92388); +//! shared_map.borrow_mut().insert("kyoto", 11837); +//! shared_map.borrow_mut().insert("piccadilly", 11826); +//! shared_map.borrow_mut().insert("marbles", 38); +//! } +//! ``` +//! +//! ## Implementation details of logically-immutable methods +//! +//! Occasionally it may be desirable not to expose in an API that +//! there is mutation happening "under the hood". This may be because +//! logically the operation is immutable, but e.g. caching forces the +//! implementation to perform mutation; or because you must employ +//! mutation to implement a trait method that was originally defined +//! to take `&self`. +//! +//! ``` +//! extern crate collections; +//! +//! use collections::HashMap; +//! use std::cell::RefCell; +//! +//! struct Graph { +//! edges: HashMap<uint, uint>, +//! span_tree_cache: RefCell<Option<Vec<(uint, uint)>>> +//! } +//! +//! impl Graph { +//! fn minimum_spanning_tree(&self) -> Vec<(uint, uint)> { +//! // Create a new scope to contain the lifetime of the +//! // dynamic borrow +//! { +//! // Take a reference to the inside of cache cell +//! let mut cache = self.span_tree_cache.borrow_mut(); +//! if cache.is_some() { +//! return cache.get_ref().clone(); +//! } +//! +//! let span_tree = self.calc_span_tree(); +//! *cache = Some(span_tree); +//! } +//! +//! // Recursive call to return the just-cached value. +//! // Note that if we had not let the previous borrow +//! // of the cache fall out of scope then the subsequent +//! // recursive borrow would cause a dynamic task failure. +//! // This is the major hazard of using `RefCell`. +//! self.minimum_spanning_tree() +//! } +//! # fn calc_span_tree(&self) -> Vec<(uint, uint)> { vec![] } +//! } +//! # fn main() { } +//! ``` +//! +//! ## Mutating implementations of `clone` +//! +//! This is simply a special - but common - case of the previous: +//! hiding mutability for operations that appear to be immutable. +//! The `clone` method is expected to not change the source value, and +//! is declared to take `&self`, not `&mut self`. Therefore any +//! mutation that happens in the `clone` method must use cell +//! types. For example, `Rc` maintains its reference counts within a +//! `Cell`. +//! +//! ``` +//! use std::cell::Cell; +//! +//! struct Rc<T> { +//! ptr: *mut RcBox<T> +//! } +//! +//! struct RcBox<T> { +//! value: T, +//! refcount: Cell<uint> +//! } +//! +//! impl<T> Clone for Rc<T> { +//! fn clone(&self) -> Rc<T> { +//! unsafe { +//! (*self.ptr).refcount.set((*self.ptr).refcount.get() + 1); +//! Rc { ptr: self.ptr } +//! } +//! } +//! } +//! ``` +//! +// FIXME: Explain difference between Cell and RefCell +// FIXME: Downsides to interior mutability +// FIXME: Can't be shared between threads. Dynamic borrows +// FIXME: Relationship to Atomic types and RWLock use clone::Clone; use cmp::Eq; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 9f147fafdc2..ffb9b676e7d 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -8,12 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! The Rust core library +//! The Rust Core Library //! -//! This library is meant to represent the core functionality of rust that is -//! maximally portable to other platforms. To that extent, this library has no -//! knowledge of things like allocation, threads, I/O, etc. This library is -//! built on the assumption of a few existing symbols: +//! The Rust Core Library is the dependency-free foundation of [The +//! Rust Standard Library](../std/index.html). It is the portable glue +//! between the language and its libraries, defining the intrinsic and +//! primitive building blocks of all Rust code. It links to no +//! upstream libraries, no system libraries, and no libc. +//! +//! The core library is *minimal*: it isn't even aware of heap allocation, +//! nor does it provide concurrency or I/O. These things require +//! platform integration, and this library is platform-agnostic. +//! +//! *It is not recommended to use the core library*. The stable +//! functionality of libcore is reexported from the +//! [standard library](../std/index.html). The composition of this library is +//! subject to change over time; only the interface exposed through libstd is +//! intended to be stable. +//! +//! # How to use the core library +//! +// FIXME: Fill me in with more detail when the interface settles +//! This library is built on the assumption of a few existing symbols: //! //! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are //! often generated by LLVM. Additionally, this library can make explicit @@ -23,16 +39,11 @@ //! distribution. //! //! * `rust_begin_unwind` - This function takes three arguments, a -//! `&fmt::Arguments`, a `&str`, and a `uint. These three arguments dictate +//! `&fmt::Arguments`, a `&str`, and a `uint`. These three arguments dictate //! the failure message, the file at which failure was invoked, and the line. //! It is up to consumers of this core library to define this failure //! function; it is only required to never return. //! -//! Currently, it is *not* recommended to use the core library. The stable -//! functionality of libcore is exported directly into the -//! [standard library](../std/index.html). The composition of this library is -//! subject to change over time, only the interface exposed through libstd is -//! intended to be stable. #![crate_id = "core#0.11.0-pre"] #![license = "MIT/ASL2"] diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 4c31face2e3..1eab5c04469 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -10,7 +10,7 @@ /*! * - * Traits representing built-in operators, useful for overloading + * Overloadable operators * * Implementing these traits allows you to get an effect similar to * overloading operators. diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a45f8a83a24..a9ec9c1ddc5 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -16,9 +16,8 @@ //! //! ## Intrinsic types and operations //! -//! The [`ptr`](../core/ptr/index.html), [`mem`](../core/mem/index.html), -//! and [`cast`](../core/cast/index.html) modules deal with unsafe pointers, -//! memory manipulation, and coercion. +//! The [`ptr`](../core/ptr/index.html) and [`mem`](../core/mem/index.html) +//! modules deal with unsafe pointers and memory manipulation. //! [`kinds`](../core/kinds/index.html) defines the special built-in traits, //! and [`raw`](../core/raw/index.html) the runtime representation of Rust types. //! These are some of the lowest-level building blocks of Rust @@ -135,24 +134,26 @@ extern crate libc; #[cfg(test)] pub use realstd::cmp; #[cfg(test)] pub use realstd::ty; -#[cfg(not(test))] pub use core::cmp; -#[cfg(not(test))] pub use core::kinds; -#[cfg(not(test))] pub use core::ops; -#[cfg(not(test))] pub use core::ty; + +// NB: These reexports are in the order they should be listed in rustdoc pub use core::any; pub use core::bool; pub use core::cell; pub use core::char; pub use core::clone; +#[cfg(not(test))] pub use core::cmp; pub use core::container; pub use core::default; pub use core::intrinsics; pub use core::iter; +#[cfg(not(test))] pub use core::kinds; pub use core::mem; +#[cfg(not(test))] pub use core::ops; pub use core::ptr; pub use core::raw; pub use core::tuple; +#[cfg(not(test))] pub use core::ty; pub use core::result; pub use alloc::owned; |
