diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index e8ea993c6940a..e8cd36f3cd70b 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -46,14 +46,42 @@ use marker::Sized; -/// A common trait for cloning an object. +/// A common trait for the ability to explicitly duplicate an object. /// -/// This trait can be used with `#[derive]`. +/// Differs from `Copy` in that `Copy` is implicit and extremely inexpensive, while +/// `Clone` is always explicit and may or may not be expensive. In order to enforce +/// these characteristics, Rust does not allow you to reimplement `Copy`, but you +/// may reimplement `Clone` and run arbitrary code. +/// +/// Since `Clone` is more general than `Copy`, you can automatically make anything +/// `Copy` be `Clone` as well. +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d +/// implementation of `clone()` calls `clone()` on each field. +/// +/// ## How can I implement `Clone`? /// /// Types that are `Copy` should have a trivial implementation of `Clone`. More formally: /// if `T: Copy`, `x: T`, and `y: &T`, then `let x = y.clone();` is equivalent to `let x = *y;`. /// Manual implementations should be careful to uphold this invariant; however, unsafe code /// must not rely on it to ensure memory safety. +/// +/// An example is an array holding more than 32 elements of a type that is `Clone`; the standard +/// library only implements `Clone` up until arrays of size 32. In this case, the implementation of +/// `Clone` cannot be `derive`d, but can be implemented as: +/// +/// ``` +/// #[derive(Copy)] +/// struct Stats { +/// frequencies: [i32; 100], +/// } +/// +/// impl Clone for Stats { +/// fn clone(&self) -> Stats { *self } +/// } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Clone : Sized { /// Returns a copy of the value. diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index d3481ba3f0523..8764766b2ef86 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -53,12 +53,43 @@ use option::Option::{self, Some}; /// symmetrically and transitively: if `T: PartialEq` and `U: PartialEq` /// then `U: PartialEq` and `T: PartialEq`. /// +/// ## Derivable +/// +/// This trait can be used with `#[derive]`. When `derive`d on structs, two +/// instances are equal if all fields are equal, and not equal if any fields +/// are not equal. When `derive`d on enums, each variant is equal to itself +/// and not equal to the other variants. +/// +/// ## How can I implement `PartialEq`? +/// /// PartialEq only requires the `eq` method to be implemented; `ne` is defined /// in terms of it by default. Any manual implementation of `ne` *must* respect /// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and /// only if `a != b`. /// -/// This trait can be used with `#[derive]`. +/// An example implementation for a domain in which two books are considered +/// the same book if their ISBN matches, even if the formats differ: +/// +/// ``` +/// enum BookFormat { Paperback, Hardback, Ebook } +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// +/// impl PartialEq for Book { +/// fn eq(&self, other: &Book) -> bool { +/// self.isbn == other.isbn +/// } +/// } +/// +/// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; +/// let b2 = Book { isbn: 3, format: BookFormat::Ebook }; +/// let b3 = Book { isbn: 10, format: BookFormat::Paperback }; +/// +/// assert!(b1 == b2); +/// assert!(b1 != b3); +/// ``` /// /// # Examples /// @@ -96,7 +127,32 @@ pub trait PartialEq { /// This property cannot be checked by the compiler, and therefore `Eq` implies /// `PartialEq`, and has no extra methods. /// -/// This trait can be used with `#[derive]`. +/// ## Derivable +/// +/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has +/// no extra methods, it is only informing the compiler that this is an +/// equivalence relation rather than a partial equivalence relation. Note that +/// the `derive` strategy requires all fields are `PartialEq`, which isn't +/// always desired. +/// +/// ## How can I implement `Eq`? +/// +/// If you cannot use the `derive` strategy, specify that your type implements +/// `Eq`, which has no methods: +/// +/// ``` +/// enum BookFormat { Paperback, Hardback, Ebook } +/// struct Book { +/// isbn: i32, +/// format: BookFormat, +/// } +/// impl PartialEq for Book { +/// fn eq(&self, other: &Book) -> bool { +/// self.isbn == other.isbn +/// } +/// } +/// impl Eq for Book {} +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Eq: PartialEq { // FIXME #13101: this method is used solely by #[deriving] to @@ -190,8 +246,49 @@ impl Ordering { /// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and /// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. /// +/// ## Derivable +/// /// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic /// ordering based on the top-to-bottom declaration order of the struct's members. +/// +/// ## How can I implement `Ord`? +/// +/// `Ord` requires that the type also be `PartialOrd` and `Eq` (which requires `PartialEq`). +/// +/// Then you must define an implementation for `cmp()`. You may find it useful to use +/// `cmp()` on your type's fields. +/// +/// Here's an example where you want to sort people by height only, disregarding `id` +/// and `name`: +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// #[derive(Eq)] +/// struct Person { +/// id: u32, +/// name: String, +/// height: u32, +/// } +/// +/// impl Ord for Person { +/// fn cmp(&self, other: &Person) -> Ordering { +/// self.height.cmp(&other.height) +/// } +/// } +/// +/// impl PartialOrd for Person { +/// fn partial_cmp(&self, other: &Person) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// impl PartialEq for Person { +/// fn eq(&self, other: &Person) -> bool { +/// self.height == other.height +/// } +/// } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Ord: Eq + PartialOrd { /// This method returns an `Ordering` between `self` and `other`. @@ -242,6 +339,13 @@ impl PartialOrd for Ordering { /// transitively: if `T: PartialOrd` and `U: PartialOrd` then `U: PartialOrd` and `T: /// PartialOrd`. /// +/// ## Derivable +/// +/// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic +/// ordering based on the top-to-bottom declaration order of the struct's members. +/// +/// ## How can I implement `Ord`? +/// /// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated /// from default implementations. /// @@ -249,8 +353,64 @@ impl PartialOrd for Ordering { /// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 == /// false` (cf. IEEE 754-2008 section 5.11). /// -/// This trait can be used with `#[derive]`. When `derive`d, it will produce an ordering -/// based on the top-to-bottom declaration order of the struct's members. +/// `PartialOrd` requires your type to be `PartialEq`. +/// +/// If your type is `Ord`, you can implement `partial_cmp()` by using `cmp()`: +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// #[derive(Eq)] +/// struct Person { +/// id: u32, +/// name: String, +/// height: u32, +/// } +/// +/// impl PartialOrd for Person { +/// fn partial_cmp(&self, other: &Person) -> Option { +/// Some(self.cmp(other)) +/// } +/// } +/// +/// impl Ord for Person { +/// fn cmp(&self, other: &Person) -> Ordering { +/// self.height.cmp(&other.height) +/// } +/// } +/// +/// impl PartialEq for Person { +/// fn eq(&self, other: &Person) -> bool { +/// self.height == other.height +/// } +/// } +/// ``` +/// +/// You may also find it useful to use `partial_cmp()` on your type`s fields. Here +/// is an example of `Person` types who have a floating-point `height` field that +/// is the only field to be used for sorting: +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// struct Person { +/// id: u32, +/// name: String, +/// height: f64, +/// } +/// +/// impl PartialOrd for Person { +/// fn partial_cmp(&self, other: &Person) -> Option { +/// self.height.partial_cmp(&other.height) +/// } +/// } +/// +/// impl PartialEq for Person { +/// fn eq(&self, other: &Person) -> bool { +/// self.height == other.height +/// } +/// } +/// ``` /// /// # Examples /// diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 12c4a5ca200ad..485ddae07fbff 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -9,76 +9,6 @@ // except according to those terms. //! The `Default` trait for types which may have meaningful default values. -//! -//! Sometimes, you want to fall back to some kind of default value, and -//! don't particularly care what it is. This comes up often with `struct`s -//! that define a set of options: -//! -//! ``` -//! # #[allow(dead_code)] -//! struct SomeOptions { -//! foo: i32, -//! bar: f32, -//! } -//! ``` -//! -//! How can we define some default values? You can use `Default`: -//! -//! ``` -//! # #[allow(dead_code)] -//! #[derive(Default)] -//! struct SomeOptions { -//! foo: i32, -//! bar: f32, -//! } -//! -//! -//! fn main() { -//! let options: SomeOptions = Default::default(); -//! } -//! ``` -//! -//! Now, you get all of the default values. Rust implements `Default` for various primitives types. -//! If you have your own type, you need to implement `Default` yourself: -//! -//! ``` -//! # #![allow(dead_code)] -//! enum Kind { -//! A, -//! B, -//! C, -//! } -//! -//! impl Default for Kind { -//! fn default() -> Kind { Kind::A } -//! } -//! -//! #[derive(Default)] -//! struct SomeOptions { -//! foo: i32, -//! bar: f32, -//! baz: Kind, -//! } -//! -//! -//! fn main() { -//! let options: SomeOptions = Default::default(); -//! } -//! ``` -//! -//! If you want to override a particular option, but still retain the other defaults: -//! -//! ``` -//! # #[allow(dead_code)] -//! # #[derive(Default)] -//! # struct SomeOptions { -//! # foo: i32, -//! # bar: f32, -//! # } -//! fn main() { -//! let options = SomeOptions { foo: 42, ..Default::default() }; -//! } -//! ``` #![stable(feature = "rust1", since = "1.0.0")] @@ -86,8 +16,72 @@ use marker::Sized; /// A trait for giving a type a useful default value. /// -/// A struct can derive default implementations of `Default` for basic types using -/// `#[derive(Default)]`. +/// Sometimes, you want to fall back to some kind of default value, and +/// don't particularly care what it is. This comes up often with `struct`s +/// that define a set of options: +/// +/// ``` +/// # #[allow(dead_code)] +/// struct SomeOptions { +/// foo: i32, +/// bar: f32, +/// } +/// ``` +/// +/// How can we define some default values? You can use `Default`: +/// +/// ``` +/// # #[allow(dead_code)] +/// #[derive(Default)] +/// struct SomeOptions { +/// foo: i32, +/// bar: f32, +/// } +/// +/// +/// fn main() { +/// let options: SomeOptions = Default::default(); +/// } +/// ``` +/// +/// Now, you get all of the default values. Rust implements `Default` for various primitives types. +/// +/// If you want to override a particular option, but still retain the other defaults: +/// +/// ``` +/// # #[allow(dead_code)] +/// # #[derive(Default)] +/// # struct SomeOptions { +/// # foo: i32, +/// # bar: f32, +/// # } +/// fn main() { +/// let options = SomeOptions { foo: 42, ..Default::default() }; +/// } +/// ``` +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]` if all of the type's fields implement +/// `Default`. When `derive`d, it will use the default value for each field's type. +/// +/// ## How can I implement `Default`? +/// +/// Provide an implementation for the `default()` method that returns the value of +/// your type that should be the default: +/// +/// ``` +/// # #![allow(dead_code)] +/// enum Kind { +/// A, +/// B, +/// C, +/// } +/// +/// impl Default for Kind { +/// fn default() -> Kind { Kind::A } +/// } +/// ``` /// /// # Examples /// diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index dde4d03dad8ac..6579e5dab5432 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -318,7 +318,11 @@ impl<'a> Display for Arguments<'a> { /// /// [module]: ../../std/fmt/index.html /// -/// This trait can be used with `#[derive]`. +/// This trait can be used with `#[derive]` if all fields implement `Debug`. When +/// `derive`d for structs, it will use the name of the `struct`, then `{`, then a +/// comma-separated list of each field's name and `Debug` value, then `}`. For +/// `enum`s, it will use the name of the variant and, if applicable, `(`, then the +/// `Debug` values of the fields, then `)`. /// /// # Examples /// diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 4d0fed9833436..051eb974895ce 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -38,7 +38,7 @@ //! ``` //! //! If you need more control over how a value is hashed, you need to implement -//! the trait `Hash`: +//! the `Hash` trait: //! //! ```rust //! use std::hash::{Hash, Hasher, SipHasher}; @@ -97,7 +97,33 @@ mod sip; /// In other words, if two keys are equal, their hashes should also be equal. /// `HashMap` and `HashSet` both rely on this behavior. /// -/// This trait can be used with `#[derive]`. +/// ## Derivable +/// +/// This trait can be used with `#[derive]` if all fields implement `Hash`. +/// When `derive`d, the resulting hash will be the combination of the values +/// from calling `.hash()` on each field. +/// +/// ## How can I implement `Hash`? +/// +/// If you need more control over how a value is hashed, you need to implement +/// the `Hash` trait: +/// +/// ``` +/// use std::hash::{Hash, Hasher}; +/// +/// struct Person { +/// id: u32, +/// name: String, +/// phone: u64, +/// } +/// +/// impl Hash for Person { +/// fn hash(&self, state: &mut H) { +/// self.id.hash(state); +/// self.phone.hash(state); +/// } +/// } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait Hash { /// Feeds this value into the state given, updating the hasher as necessary. diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 1ed2a219fac3a..c18d230be31af 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -136,6 +136,26 @@ pub trait Unsize { /// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy` /// ``` /// +/// ## When can my type _not_ be `Copy`? +/// +/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased +/// mutable reference, and copying `String` would result in two attempts to free the same buffer. +/// +/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's +/// managing some resource besides its own `size_of::()` bytes. +/// +/// ## When should my type be `Copy`? +/// +/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing +/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future, +/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking +/// change: that second example would fail to compile if we made `Foo` non-`Copy`. +/// +/// ## Derivable +/// +/// This trait can be used with `#[derive]` if all of its components implement `Copy` and the type +/// implements `Clone`. The implementation will copy the bytes of each field using `memcpy`. +/// /// ## How can I implement `Copy`? /// /// There are two ways to implement `Copy` on your type: @@ -155,25 +175,6 @@ pub trait Unsize { /// /// There is a small difference between the two: the `derive` strategy will also place a `Copy` /// bound on type parameters, which isn't always desired. -/// -/// ## When can my type _not_ be `Copy`? -/// -/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased -/// mutable reference, and copying `String` would result in two attempts to free the same buffer. -/// -/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's -/// managing some resource besides its own `size_of::()` bytes. -/// -/// ## When should my type be `Copy`? -/// -/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing -/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future, -/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking -/// change: that second example would fail to compile if we made `Foo` non-`Copy`. -/// -/// # Derivable -/// -/// This trait can be used with `#[derive]`. #[stable(feature = "rust1", since = "1.0.0")] #[lang = "copy"] pub trait Copy : Clone {