-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Trait documentation clarifications #33815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
1e493fd
bbfb6e7
2f44053
fc467b3
e831c72
54d2ef0
c41227f
61bb9b2
9efa445
8b00a08
bd50eff
b4e123d
d2ee6e0
c22c524
497cbb6
9149992
daa9dca
d81a999
1b32298
1a7d3e1
1e809f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,14 +46,39 @@ | |
|
|
||
| use marker::Sized; | ||
|
|
||
| /// A common trait for cloning an object. | ||
| /// A common trait for cloning an object. Differs from `Copy` in that you can | ||
| /// define `Clone` to run arbitrary code, while you are not allowed to override | ||
| /// the implementation of `Copy` that only does a `memcpy`. | ||
| /// | ||
| /// This trait can be used with `#[derive]`. | ||
| /// 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 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) -> Self { *self } | ||
| /// } | ||
| /// ``` | ||
| #[stable(feature = "rust1", since = "1.0.0")] | ||
| pub trait Clone : Sized { | ||
| /// Returns a copy of the value. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,12 +53,42 @@ use option::Option::{self, Some}; | |
| /// symmetrically and transitively: if `T: PartialEq<U>` and `U: PartialEq<V>` | ||
| /// then `U: PartialEq<T>` and `T: PartialEq<V>`. | ||
| /// | ||
| /// ## Derivable | ||
| /// | ||
| /// This trait can be used with `#[derive]`. When `derive`d on structs, two | ||
| /// instances are equal if all fields are equal, and non 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, | ||
| /// } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: newline after this line, to give it some room |
||
| /// impl PartialEq for Book { | ||
| /// fn eq(&self, other: &Self) -> 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 +126,32 @@ pub trait PartialEq<Rhs: ?Sized = Self> { | |
| /// 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: &Self) -> bool { | ||
| /// self.isbn == other.isbn | ||
| /// } | ||
| /// } | ||
| /// impl Eq for Book {} | ||
| /// ``` | ||
| #[stable(feature = "rust1", since = "1.0.0")] | ||
| pub trait Eq: PartialEq<Self> { | ||
| // FIXME #13101: this method is used solely by #[deriving] to | ||
|
|
@@ -190,8 +245,48 @@ 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; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd add a newline after this |
||
| /// #[derive(Eq)] | ||
| /// struct Person { | ||
| /// id: u32, | ||
| /// name: String, | ||
| /// height: u32, | ||
| /// } | ||
| /// | ||
| /// impl Ord for Person { | ||
| /// fn cmp(&self, other: &Self) -> Ordering { | ||
|
||
| /// self.height.cmp(&other.height) | ||
| /// } | ||
| /// } | ||
| /// | ||
| /// impl PartialOrd for Person { | ||
| /// fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | ||
| /// Some(self.cmp(other)) | ||
| /// } | ||
| /// } | ||
| /// | ||
| /// impl PartialEq for Person { | ||
| /// fn eq(&self, other: &Self) -> bool { | ||
| /// self.height == other.height | ||
| /// } | ||
| /// } | ||
| /// ``` | ||
| #[stable(feature = "rust1", since = "1.0.0")] | ||
| pub trait Ord: Eq + PartialOrd<Self> { | ||
| /// This method returns an `Ordering` between `self` and `other`. | ||
|
|
@@ -242,15 +337,57 @@ impl PartialOrd for Ordering { | |
| /// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T: | ||
| /// PartialOrd<V>`. | ||
| /// | ||
| /// ## 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. | ||
| /// | ||
| /// However it remains possible to implement the others separately for types which do not have a | ||
| /// 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`: | ||
| /// | ||
| /// ``` | ||
| /// impl PartialOrd for Person { | ||
| /// fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | ||
| /// Some(self.cmp(other)) | ||
| /// } | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// 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: &Self) -> Option<Ordering> { | ||
| /// self.height.partial_cmp(&other.height) | ||
| /// } | ||
| /// } | ||
| /// | ||
| /// impl PartialEq for Person { | ||
| /// fn eq(&self, other: &Self) -> bool { | ||
| /// self.height == other.height | ||
| /// } | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// # Examples | ||
| /// | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,10 +84,33 @@ | |
|
|
||
| use marker::Sized; | ||
|
|
||
| /// A trait for giving a type a useful default value. | ||
| /// A trait for giving a type a useful default value. For more information, see | ||
| /// [the module-level documentation][module]. | ||
|
||
| /// | ||
| /// A struct can derive default implementations of `Default` for basic types using | ||
| /// `#[derive(Default)]`. | ||
| /// [module]: ../../std/default/index.html | ||
| /// | ||
| /// ## 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)] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is dead code because
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think so? I don't really understand why some existing examples have |
||
| /// enum Kind { | ||
| /// A, | ||
| /// B, | ||
| /// C, | ||
| /// } | ||
| /// | ||
| /// impl Default for Kind { | ||
| /// fn default() -> Kind { Kind::A } | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// # Examples | ||
| /// | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 `)`. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How stable do we consider the exact output of the format traits? /cc @aturon |
||
| /// | ||
| /// # Examples | ||
| /// | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 trait `Hash`: | ||
|
||
| /// | ||
| /// ``` | ||
| /// use std::hash::{Hash, Hasher}; | ||
| /// | ||
| /// struct Person { | ||
| /// id: u32, | ||
| /// name: String, | ||
| /// phone: u64, | ||
| /// } | ||
| /// | ||
| /// impl Hash for Person { | ||
| /// fn hash<H: Hasher>(&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. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, GitHub is being weird, and when I refreshed, my comments were gone, so trying again. Sorry if this is a duplicate.
First, this summary line is a bit long. We try to keep the very first line a sentence, and while what was here was a bit... sparse, the summary line should still be shorter than this.
Second, the
Copy/Clonedistinction isn't really about overriding, exactly. Or rather, to me, the not-overriding is the implementation rather than the important bit. The important bit is thatCopyis extremely inexpensive and is implicit.Clonemay or may not be expensive, and is always explicit. The mechanism to ensure this is to not let you implement the details of aCopy.I also have small concerns about putting stuff about
Copy's semantics right here in the summary; while they won't really be changing.... idk. Hm.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love your explanation of the distinction between
CloneandCopy, working that in.