From ba6857d801b6217a190e92e43cacd8468ff2d72a Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Fri, 26 Jun 2020 14:28:11 +0200 Subject: [PATCH 1/2] Document the trait keyword --- src/libstd/keyword_docs.rs | 175 ++++++++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 3 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index f987eb67ea5f2..7bedb6fd6238b 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1353,11 +1353,180 @@ mod super_keyword {} #[doc(keyword = "trait")] // -/// A common interface for a class of types. +/// A common interface for a group of types. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// A `trait` is an interface that types can implement. It is said they +/// "implement" the trait or "conform" to the trait. /// -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// This interface is made up of three varieties of items: +/// +/// - functions +/// - types +/// - constants +/// +/// Traits may also contain additional type parameters. Those type parameters +/// or the trait itself can be constrained by other traits. +/// +/// See the [Reference][Ref-Traits] for a lot more information on traits. +/// +/// # Examples +/// +/// Traits are declared using the `trait` keyword. Types can implement them +/// using [`impl`] `Trait` [`for`] `Type`: +/// +/// ```rust +/// trait Zero { +/// const ZERO: Self; +/// fn is_zero(&self) -> bool; +/// } +/// +/// impl Zero for i32 { +/// const ZERO: Self = 0; +/// +/// fn is_zero(&self) -> bool { +/// *self == Self::ZERO +/// } +/// } +/// +/// assert_eq!(i32::ZERO, 0); +/// assert!(i32::ZERO.is_zero()); +/// assert!(!4.is_zero()); +/// ``` +/// +/// With an associated type: +/// +/// ```rust +/// trait Builder { +/// type Built; +/// +/// fn build(&self) -> Self::Built; +/// } +/// ``` +/// +/// Traits can be generic, with constraints or without: +/// +/// ```rust +/// trait MaybeFrom { +/// fn maybe_from(value: T) -> Option +/// where +/// Self: Sized; +/// } +/// ``` +/// +/// Traits can build upon the requirements of other traits. In the example +/// below `Iterator` is a **supertrait** and `ThreeIterator` is a **subtrait**: +/// +/// ```rust +/// trait ThreeIterator: std::iter::Iterator { +/// fn next_three(&mut self) -> Option<[Self::Item; 3]>; +/// } +/// ``` +/// +/// Traits can be used in functions, as parameters: +/// +/// ```rust +/// # #![allow(dead_code)] +/// fn debug_iter(it: I) where I::Item: std::fmt::Debug { +/// for elem in it { +/// println!("{:#?}", elem); +/// } +/// } +/// +/// // u8_len_1, u8_len_2 and u8_len_3 are equivalent +/// +/// fn u8_len_1(val: impl Into>) -> usize { +/// val.into().len() +/// } +/// +/// fn u8_len_2>>(val: T) -> usize { +/// val.into().len() +/// } +/// +/// fn u8_len_3(val: T) -> usize +/// where +/// T: Into>, +/// { +/// val.into().len() +/// } +/// ``` +/// +/// Or as return types: +/// +/// ```rust +/// # #![allow(dead_code)] +/// fn from_zero_to(v: u8) -> impl Iterator { +/// (0..v).into_iter() +/// } +/// ``` +/// +/// The use of the [`impl`] keyword in this position allows the function writer +/// to hide the concrete type as an implementation detail which can change +/// without breaking user's code. +/// +/// # Trait objects +/// +/// A *trait object* is an opaque value of another type that implements a set of +/// traits. A trait object implements all specified traits as well as their +/// supertraits (if any). +/// +/// The syntax is the following: `dyn BaseTrait + AutoTrait1 + ... AutoTraitN`. +/// Only one `BaseTrait` can be used so this will not compile: +/// +/// ```rust,compile_fail,E0225 +/// trait A {} +/// trait B {} +/// +/// let _: Box; +/// ``` +/// +/// Neither will this, which is a syntax error: +/// +/// ```rust,compile_fail +/// trait A {} +/// trait B {} +/// +/// let _: Box; +/// ``` +/// +/// On the other hand, this is correct: +/// +/// ```rust +/// trait A {} +/// +/// let _: Box; +/// ``` +/// +/// The [Reference][Ref-Trait-Objects] has more information about trait objects, +/// their limitations and the differences between editions. +/// +/// # Unsafe traits +/// +/// Some traits may be unsafe to implement. Using the [`unsafe`] keyword in +/// front of the trait's declaration is used to mark this: +/// +/// ```rust +/// unsafe trait UnsafeTrait {} +/// +/// unsafe impl UnsafeTrait for i32 {} +/// ``` +/// +/// # Differences between the 2015 and 2018 editions +/// +/// In the 2015 edition parameters pattern where not needed for traits: +/// +/// ```rust,edition2015 +/// trait Tr { +/// fn f(i32); +/// } +/// ``` +/// +/// This behavior is no longer valid in edition 2018. +/// +/// [`for`]: keyword.for.html +/// [`impl`]: keyword.impl.html +/// [`unsafe`]: keyword.unsafe.html +/// [Ref-Traits]: ../reference/items/traits.html +/// [Ref-Trait-Objects]: ../reference/types/trait-object.html mod trait_keyword {} #[doc(keyword = "true")] From 8a2f147b5b9756e67dc2299777b8b534bbd73d0b Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Thu, 16 Jul 2020 23:58:57 +0200 Subject: [PATCH 2/2] Fix small nits, clarfying some confusing vocabulary and using more consistent wording --- src/libstd/keyword_docs.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 7bedb6fd6238b..19f3503bb842f 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1355,18 +1355,24 @@ mod super_keyword {} // /// A common interface for a group of types. /// -/// A `trait` is an interface that types can implement. It is said they -/// "implement" the trait or "conform" to the trait. +/// A `trait` is like an interface that data types can implement. When a type +/// implements a trait it can be treated abstractly as that trait using generics +/// or trait objects. /// -/// This interface is made up of three varieties of items: +/// Traits can be made up of three varieties of associated items: /// -/// - functions +/// - functions and methods /// - types /// - constants /// /// Traits may also contain additional type parameters. Those type parameters /// or the trait itself can be constrained by other traits. /// +/// Traits can serve as markers or carry other logical semantics that +/// aren't expressed through their items. When a type implements that +/// trait it is promising to uphold its contract. [`Send`] and [`Sync`] are two +/// such marker traits present in the standard library. +/// /// See the [Reference][Ref-Traits] for a lot more information on traits. /// /// # Examples @@ -1525,6 +1531,8 @@ mod super_keyword {} /// [`for`]: keyword.for.html /// [`impl`]: keyword.impl.html /// [`unsafe`]: keyword.unsafe.html +/// [`Send`]: marker/trait.Send.html +/// [`Sync`]: marker/trait.Sync.html /// [Ref-Traits]: ../reference/items/traits.html /// [Ref-Trait-Objects]: ../reference/types/trait-object.html mod trait_keyword {}