From d54d59b1824eaf006eb966a93596b980eac2c934 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Thu, 10 Jun 2021 22:17:03 -0500 Subject: [PATCH 01/10] method overviews for option and result --- library/core/src/option.rs | 199 +++++++++++++++++++++++++++++++++++++ library/core/src/result.rs | 41 ++++++++ 2 files changed, 240 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index aedfe88f688..5f3529caa9a 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -90,6 +90,205 @@ //! from `Some::(_)` to `T` (but transmuting `None::` to `T` //! is undefined behaviour). //! +//! # Method overview +//! +//! In addition to working with pattern matching, [`Option`] provides a wide +//! variety of different methods. +//! +//! ## Querying the variant +//! +//! The [`is_some`] and [`is_none`] methods return [`true`] if the [`Option`] +//! is [`Some`] or [`None`], respectively. +//! +//! [`is_some`]: Option::is_some +//! [`is_none`]: Option::is_none +//! +//! ## Adapters for working with references +//! +//! * [`as_ref`] converts from `&Option` to `Option<&T>` +//! * [`as_mut`] converts from `&mut Option` to `Option<&mut T>` +//! * [`as_deref`] converts from `&Option` to `Option<&T::Target>` +//! * [`as_deref_mut`] converts from `&mut Option` to `Option<&mut T::Target>` +//! * [`as_pin_ref`] converts from [`&Pin`]`>` to `Option<`[`Pin`]`<&T>>` +//! * [`as_pin_mut`] converts from [`&mut Pin`]`>` to `Option<`[`Pin`]`<&mut T>>` +//! +//! [`&mut Pin`]: crate::pin::Pin +//! [`&Pin`]: crate::pin::Pin +//! [`as_deref`]: Option::as_deref +//! [`as_deref_mut`]: Option::as_deref_mut +//! [`as_mut`]: Option::as_mut +//! [`as_pin_ref`]: Option::as_pin_ref +//! [`as_pin_mut`]: Option::as_pin_mut +//! [`as_ref`]: Option::as_ref +//! [`Pin`]: crate::pin::Pin +//! +//! ## Extracting the contained value +//! +//! These methods extract the contained value in an [`Option`] when it is +//! the [`Some`] variant. If the [`Option`] is [`None`]: +//! +//! * [`expect`] panics with a provided custom message +//! * [`unwrap`] panics with a generic message +//! * [`unwrap_or`] returns the provided default value +//! * [`unwrap_or_default`] returns the default value of the type `T` +//! (which must implement the [`Default`] trait) +//! * [`unwrap_or_else`] evaluates a provided function +//! +//! [`Default`]: crate::default::Default +//! [`expect`]: Option::expect +//! [`unwrap`]: Option::unwrap +//! [`unwrap_or`]: Option::unwrap_or +//! [`unwrap_or_default`]: Option::unwrap_or_default +//! [`unwrap_or_else`]: Option::unwrap_or_else +//! +//! ## Transforming contained values +//! +//! * [`map`] transforms [`Some`] to [`Some`] using the provided +//! function +//! * [`map_or`] transforms [`Some`] to a value of `U` using the +//! provided function, or transforms [`None`] to a provided default value +//! of `U` +//! * [`map_or_else`] transforms [`Some`] to [`Some`] using the +//! provided function, or transforms [`None`] to a value of `U` using +//! another provided function +//! * [`ok_or`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to +//! [`Err(err)`] using the provided default `err` value +//! * [`ok_or_else`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to +//! a value of [`Err`] using the provided function +//! +//! [`Err(err)`]: Err +//! [`map`]: Option::map +//! [`map_or`]: Option::map_or +//! [`map_or_else`]: Option::map_or_else +//! [`Ok(v)`]: Ok +//! [`ok_or`]: Option::ok_or +//! [`ok_or_else`]: Option::ok_or_else +//! [`Some(v)`]: Some +//! +//! ## Boolean operators +//! +//! These methods treat the [`Option`] as a boolean value, where [`Some`] +//! acts like [`true`] and [`None`] acts like [`false`]. There are two +//! categories of these methods: ones that take an [`Option`] as input, and +//! ones that take a function as input (to be lazily evaluated). +//! +//! The [`and`], [`or`], and [`xor`] methods take another [`Option`] as +//! input, and produce an [`Option`] as output. Only the [`and`] method can +//! produce an [`Option`] value having a different inner type `U` than +//! [`Option`]. +//! +//! | method | self | input | output | +//! |---------|-----------|-----------|-----------| +//! | [`and`] | N/A | `None` | `None` | +//! | [`and`] | `Some(x)` | `Some(y)` | `Some(y)` | +//! | [`or`] | `None` | `None` | `None` | +//! | [`or`] | `None` | `Some(y)` | `Some(y)` | +//! | [`or`] | `Some(x)` | N/A | `Some(x)` | +//! | [`xor`] | `None` | `None` | `None` | +//! | [`xor`] | `None` | `Some(y)` | `Some(y)` | +//! | [`xor`] | `Some(x)` | `None` | `Some(x)` | +//! | [`xor`] | `Some(x)` | `Some(y)` | `None` | +//! +//! The [`and_then`], [`filter`], and [`or_else`] methods take a function +//! as input, and only evaluate the function when they need to produce a +//! new value. [`and_then`] and [`or_else`] take a function that produces +//! another [`Option`] value, while [`filter`] takes a predicate that is +//! used to decide whether to pass the [`Some`] value through. Only the +//! [`and_then`] method can produce an [`Option`] value having a +//! different inner type `U` than [`Option`]. +//! +//! | method | self | function input | function result | output | +//! |--------------|-----------|----------------|-----------------|-----------| +//! | [`and_then`] | `None` | N/A | (not evaluated) | `None` | +//! | [`and_then`] | `Some(x)` | `x` | `None` | `None` | +//! | [`and_then`] | `Some(x)` | `x` | `Some(y)` | `Some(y)` | +//! | [`filter`] | `None` | N/A | (not evaluated) | `None` | +//! | [`filter`] | `Some(x)` | `x` | `false` | `None` | +//! | [`filter`] | `Some(x)` | `x` | `true` | `Some(x)` | +//! | [`or_else`] | `None` | N/A | `None` | `None` | +//! | [`or_else`] | `None` | N/A | `Some(y)` | `Some(y)` | +//! | [`or_else`] | `Some(x)` | N/A | (not evaluated) | `Some(x)` | +//! +//! [`and`]: Option::and +//! [`and_then`]: Option::and_then +//! [`filter`]: Option::filter +//! [`or`]: Option::or +//! [`or_else`]: Option::or_else +//! [`xor`]: Option::xor +//! +//! ## Iterators +//! +//! An [`Option`] can be iterated over. This can be helpful if you need an +//! iterator that is conditionally empty. The iterator will either produce +//! a single value (when the [`Option`] is [`Some`]), or produce no values +//! (when the [`Option`] is [`None`]). For example, [`into_iter`] acts like +//! [`once(v)`] if the [`Option`] is [`Some(v)`], and like [`empty()`] if +//! the [`Option`] is [`None`]. +//! +//! Iterators over [`Option`] come in three types: +//! +//! * [`into_iter`] consumes the [`Option`] and produces the contained +//! value +//! * [`iter`] produces an immutable reference of type `&T` to the +//! contained value +//! * [`iter_mut`] produces a mutable reference of type `&mut T` to the +//! contained value +//! +//! [`Option`] implements the [`FromIterator`] trait, which allows an +//! iterator over [`Option`] values to be collected into an [`Option`] of a +//! collection of each contained value of the original [`Option`] values, +//! or [`None`] if any of the elements was [`None`]. +//! +//! [`empty()`]: crate::iter::empty +//! [`FromIterator`]: Option#impl-FromIterator%3COption%3CA%3E%3E +//! [`into_iter`]: Option::into_iter +//! [`iter`]: Option::iter +//! [`iter_mut`]: Option::iter_mut +//! [`once(v)`]: crate::iter::once +//! [`Some(v)`]: Some +//! +//! An iterator over [`Option`] can be useful when chaining iterators: +//! +//! ``` +//! let yep = Some(42); +//! let nope = None; +//! let nums: Vec = (0..4).chain(yep.into_iter()).chain(4..8).collect(); +//! assert_eq!(nums, [0, 1, 2, 3, 42, 4, 5, 6, 7]); +//! let nums: Vec = (0..4).chain(nope.into_iter()).chain(4..8).collect(); +//! assert_eq!(nums, [0, 1, 2, 3, 4, 5, 6, 7]); +//! ``` +//! +//! One reason to chain iterators in this way is that a function returning +//! `impl Iterator` must have all possible return values be of the same +//! concrete type. Chaining an iterated [`Option`] can help with that. +//! +//! ``` +//! let yep = Some(42); +//! let nope = None; +//! +//! fn makeiter(opt: Option) -> impl Iterator { +//! (0..4).chain(opt.into_iter()).chain(4..8) +//! } +//! println!("{:?}", makeiter(yep).collect::>()); +//! println!("{:?}", makeiter(nope).collect::>()); +//! ``` +//! +//! If we try to do the same thing, but using pattern matching, we can't +//! return `impl Iterator` anymore because the concrete types of the return +//! values differ. +//! +//! ```compile_fail,E0308 +//! # use std::iter::{empty, once}; +//! // This won't compile because all possible returns from the function +//! // must have the same concrete type. +//! fn makeiter(opt: Option) -> impl Iterator { +//! match opt { +//! Some(x) => return (0..4).chain(once(x)).chain(4..8), +//! None => return (0..4).chain(empty()).chain(4..8) +//! } +//! } +//! ``` +//! //! # Examples //! //! Basic pattern matching on [`Option`]: diff --git a/library/core/src/result.rs b/library/core/src/result.rs index babd0a0b552..449a5b489c7 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -224,6 +224,47 @@ //! [`Ok(T)`]: Ok //! [`Err(E)`]: Err //! [`io::Error`]: ../../std/io/struct.Error.html +//! +//! # Method overview +//! +//! ## Boolean operators +//! +//! These methods treat the [`Result`] as a boolean value, where [`Ok`] +//! acts like [`true`] and [`Err`] acts like [`false`]. There are two +//! categories of these methods: ones that take a [`Result`] as input, and +//! ones that take a function as input (to be lazily evaluated). +//! +//! The [`and`] and [`or`] methods take another [`Result`] as input, and +//! produce an [`Result`] as output. Only the [`and`] method can produce a +//! [`Result`] value having a different inner type `U` than +//! [`Result`]. +//! +//! | method | self | input | output | +//! |---------|----------|----------|----------| +//! | [`and`] | N/A | `Err(e)` | `Err(e)` | +//! | [`and`] | `Ok(x)` | `Ok(y)` | `Ok(y)` | +//! | [`or`] | `Err(e)` | `Err(d)` | `Err(d)` | +//! | [`or`] | `Err(e)` | `Ok(y)` | `Ok(y)` | +//! | [`or`] | `Ok(x)` | N/A | `Ok(x)` | +//! +//! The [`and_then`] and [`or_else`] methods take a function as input, and +//! only evaluate the function when they need to produce a new value. Only +//! the [`and_then`] method can produce an [`Result`] value having a +//! different inner type `U` than [`Result`]. +//! +//! | method | self | function input | function result | output | +//! |--------------|----------|----------------|-----------------|----------| +//! | [`and_then`] | `Err(e)` | N/A | (not evaluated) | `Err(e)` | +//! | [`and_then`] | `Ok(x)` | `x` | `Err(d)` | `Err(d)` | +//! | [`and_then`] | `Ok(x)` | `x` | `Ok(y)` | `Ok(y)` | +//! | [`or_else`] | `Err(e)` | `e` | `Err(d)` | `Err(d)` | +//! | [`or_else`] | `Err(e)` | `e` | `Ok(y)` | `Ok(y)` | +//! | [`or_else`] | `Ok(x)` | N/A | (not evaluated) | `Ok(x)` | +//! +//! [`and`]: Result::and +//! [`and_then`]: Result::and_then +//! [`or`]: Result::or +//! [`or_else`]: Result::or_else #![stable(feature = "rust1", since = "1.0.0")] From 7edc66661f2d1f79b8295f03107b765ffdd0b860 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Fri, 11 Jun 2021 11:34:57 -0500 Subject: [PATCH 02/10] updates based on reviews Fix an error in `map_or_else`. Use more descriptive text for "don't care" in truth tables. Make minor corrections to truth tables. Rename `makeiter` to `make_iter` in examples. --- library/core/src/option.rs | 25 +++++++++++++------------ library/core/src/result.rs | 19 ++++++++++--------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 5f3529caa9a..a2abfe658bd 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -148,7 +148,7 @@ //! * [`map_or`] transforms [`Some`] to a value of `U` using the //! provided function, or transforms [`None`] to a provided default value //! of `U` -//! * [`map_or_else`] transforms [`Some`] to [`Some`] using the +//! * [`map_or_else`] transforms [`Some`] to a value of `U` using the //! provided function, or transforms [`None`] to a value of `U` using //! another provided function //! * [`ok_or`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to @@ -179,11 +179,12 @@ //! //! | method | self | input | output | //! |---------|-----------|-----------|-----------| -//! | [`and`] | N/A | `None` | `None` | +//! | [`and`] | `None` | (ignored) | `None` | +//! | [`and`] | `Some(x)` | `None` | `None` | //! | [`and`] | `Some(x)` | `Some(y)` | `Some(y)` | //! | [`or`] | `None` | `None` | `None` | //! | [`or`] | `None` | `Some(y)` | `Some(y)` | -//! | [`or`] | `Some(x)` | N/A | `Some(x)` | +//! | [`or`] | `Some(x)` | (ignored) | `Some(x)` | //! | [`xor`] | `None` | `None` | `None` | //! | [`xor`] | `None` | `Some(y)` | `Some(y)` | //! | [`xor`] | `Some(x)` | `None` | `Some(x)` | @@ -199,15 +200,15 @@ //! //! | method | self | function input | function result | output | //! |--------------|-----------|----------------|-----------------|-----------| -//! | [`and_then`] | `None` | N/A | (not evaluated) | `None` | +//! | [`and_then`] | `None` | (not provided) | (not evaluated) | `None` | //! | [`and_then`] | `Some(x)` | `x` | `None` | `None` | //! | [`and_then`] | `Some(x)` | `x` | `Some(y)` | `Some(y)` | -//! | [`filter`] | `None` | N/A | (not evaluated) | `None` | +//! | [`filter`] | `None` | (not provided) | (not evaluated) | `None` | //! | [`filter`] | `Some(x)` | `x` | `false` | `None` | //! | [`filter`] | `Some(x)` | `x` | `true` | `Some(x)` | -//! | [`or_else`] | `None` | N/A | `None` | `None` | -//! | [`or_else`] | `None` | N/A | `Some(y)` | `Some(y)` | -//! | [`or_else`] | `Some(x)` | N/A | (not evaluated) | `Some(x)` | +//! | [`or_else`] | `None` | (not provided) | `None` | `None` | +//! | [`or_else`] | `None` | (not provided) | `Some(y)` | `Some(y)` | +//! | [`or_else`] | `Some(x)` | (not provided) | (not evaluated) | `Some(x)` | //! //! [`and`]: Option::and //! [`and_then`]: Option::and_then @@ -266,11 +267,11 @@ //! let yep = Some(42); //! let nope = None; //! -//! fn makeiter(opt: Option) -> impl Iterator { +//! fn make_iter(opt: Option) -> impl Iterator { //! (0..4).chain(opt.into_iter()).chain(4..8) //! } -//! println!("{:?}", makeiter(yep).collect::>()); -//! println!("{:?}", makeiter(nope).collect::>()); +//! println!("{:?}", make_iter(yep).collect::>()); +//! println!("{:?}", make_iter(nope).collect::>()); //! ``` //! //! If we try to do the same thing, but using pattern matching, we can't @@ -281,7 +282,7 @@ //! # use std::iter::{empty, once}; //! // This won't compile because all possible returns from the function //! // must have the same concrete type. -//! fn makeiter(opt: Option) -> impl Iterator { +//! fn make_iter(opt: Option) -> impl Iterator { //! match opt { //! Some(x) => return (0..4).chain(once(x)).chain(4..8), //! None => return (0..4).chain(empty()).chain(4..8) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 449a5b489c7..bad75b722b1 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -239,13 +239,14 @@ //! [`Result`] value having a different inner type `U` than //! [`Result`]. //! -//! | method | self | input | output | -//! |---------|----------|----------|----------| -//! | [`and`] | N/A | `Err(e)` | `Err(e)` | -//! | [`and`] | `Ok(x)` | `Ok(y)` | `Ok(y)` | -//! | [`or`] | `Err(e)` | `Err(d)` | `Err(d)` | -//! | [`or`] | `Err(e)` | `Ok(y)` | `Ok(y)` | -//! | [`or`] | `Ok(x)` | N/A | `Ok(x)` | +//! | method | self | input | output | +//! |---------|----------|-----------|----------| +//! | [`and`] | `Err(e)` | (ignored) | `Err(e)` | +//! | [`and`] | `Ok(x)` | `Err(d)` | `Err(d)` | +//! | [`and`] | `Ok(x)` | `Ok(y)` | `Ok(y)` | +//! | [`or`] | `Err(e)` | `Err(d)` | `Err(d)` | +//! | [`or`] | `Err(e)` | `Ok(y)` | `Ok(y)` | +//! | [`or`] | `Ok(x)` | (ignored) | `Ok(x)` | //! //! The [`and_then`] and [`or_else`] methods take a function as input, and //! only evaluate the function when they need to produce a new value. Only @@ -254,12 +255,12 @@ //! //! | method | self | function input | function result | output | //! |--------------|----------|----------------|-----------------|----------| -//! | [`and_then`] | `Err(e)` | N/A | (not evaluated) | `Err(e)` | +//! | [`and_then`] | `Err(e)` | (not provided) | (not evaluated) | `Err(e)` | //! | [`and_then`] | `Ok(x)` | `x` | `Err(d)` | `Err(d)` | //! | [`and_then`] | `Ok(x)` | `x` | `Ok(y)` | `Ok(y)` | //! | [`or_else`] | `Err(e)` | `e` | `Err(d)` | `Err(d)` | //! | [`or_else`] | `Err(e)` | `e` | `Ok(y)` | `Ok(y)` | -//! | [`or_else`] | `Ok(x)` | N/A | (not evaluated) | `Ok(x)` | +//! | [`or_else`] | `Ok(x)` | (not provided) | (not evaluated) | `Ok(x)` | //! //! [`and`]: Result::and //! [`and_then`]: Result::and_then From 370f731dfb6e3fecadd210e3393e38de8503ab8e Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Fri, 11 Jun 2021 12:47:37 -0500 Subject: [PATCH 03/10] more transformation methods in option overview --- library/core/src/option.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index a2abfe658bd..c1b9517658a 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -143,6 +143,8 @@ //! //! ## Transforming contained values //! +//! * [`flatten`] removes one level of nesting from an +//! [`Option>`] //! * [`map`] transforms [`Some`] to [`Some`] using the provided //! function //! * [`map_or`] transforms [`Some`] to a value of `U` using the @@ -155,8 +157,11 @@ //! [`Err(err)`] using the provided default `err` value //! * [`ok_or_else`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to //! a value of [`Err`] using the provided function +//! * [`transpose`] transposes an [`Option`] of a [`Result`] into a +//! [`Result`] of an [`Option`] //! //! [`Err(err)`]: Err +//! [`flatten`]: Option::flatten //! [`map`]: Option::map //! [`map_or`]: Option::map_or //! [`map_or_else`]: Option::map_or_else @@ -164,6 +169,7 @@ //! [`ok_or`]: Option::ok_or //! [`ok_or_else`]: Option::ok_or_else //! [`Some(v)`]: Some +//! [`transpose`]: Option::transpose //! //! ## Boolean operators //! From 7265bef2e7d4320e809ca6694787925cd0d7b8cb Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Fri, 11 Jun 2021 13:10:29 -0500 Subject: [PATCH 04/10] add modify-in-place methods to option overview --- library/core/src/option.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c1b9517658a..dea32872243 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -296,6 +296,35 @@ //! } //! ``` //! +//! ## Modifying an [`Option`] in-place +//! +//! These methods return a mutable reference to the contained value of a +//! [`Some`]. +//! +//! * [`insert`] inserts a value, dropping any old contents +//! * [`get_or_insert`] gets the current value, inserting a provided +//! default value if it is [`None`] +//! * [`get_or_insert_default`] gets the current value, inserting the +//! default value of type `T` if it is [`None`] +//! * [`get_or_insert_with`] gets the current value, inserting a default +//! computed by the provided function if it is [`None`] +//! +//! [`insert`]: Option::insert +//! [`get_or_insert`]: Option::get_or_insert +//! [`get_or_insert_default`]: Option::get_or_insert_default +//! [`get_or_insert_with`]: Option::get_or_insert_with +//! +//! These methods transfer ownership of the [`Option`]. +//! +//! * [`take`] takes ownership of the [`Option`], including any contained +//! value, replacing it with [`None`] +//! * [`replace`] takes ownership of the [`Option`], including any +//! contained value, replacing it with a [`Some`] containing the provided +//! value +//! +//! [`take`]: Option::take +//! [`replace`]: Option::replace +//! //! # Examples //! //! Basic pattern matching on [`Option`]: From 834f4b770ea58ea39ed18bd50a880e9d61bdc69f Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Sat, 12 Jun 2021 15:10:58 -0500 Subject: [PATCH 05/10] updates based on feedback Make minor wording changes in a few places. Move `filter` to the "transformations" section. Add `zip` methods to the "transformations" section. Clarify the section about `Option` iterators, and add a section about collecting into `Option`. Clarify that for `Result`, `or` and `or_else` can also produce a `Result` having a different type. --- library/core/src/option.rs | 110 +++++++++++++++++++++++++------------ library/core/src/result.rs | 13 +++-- 2 files changed, 83 insertions(+), 40 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index dea32872243..28ea504ec0a 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -132,7 +132,8 @@ //! * [`unwrap_or`] returns the provided default value //! * [`unwrap_or_default`] returns the default value of the type `T` //! (which must implement the [`Default`] trait) -//! * [`unwrap_or_else`] evaluates a provided function +//! * [`unwrap_or_else`] returns the result of evaluating the provided +//! function //! //! [`Default`]: crate::default::Default //! [`expect`]: Option::expect @@ -143,6 +144,9 @@ //! //! ## Transforming contained values //! +//! * [`filter`] calls the provided predicate function on the contained +//! value `t` if the [`Option`] is [`Some(t)`], and returns [`Some(t)`] +//! if the function returns `true`; otherwise, returns [`None`] //! * [`flatten`] removes one level of nesting from an //! [`Option>`] //! * [`map`] transforms [`Some`] to [`Some`] using the provided @@ -159,8 +163,14 @@ //! a value of [`Err`] using the provided function //! * [`transpose`] transposes an [`Option`] of a [`Result`] into a //! [`Result`] of an [`Option`] +//! * [`zip`] returns [`Some((s, o))`] if `self` is [`Some(s)`] and the +//! provided [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] +//! * [`zip_with`] calls the provided function `f` and returns +//! [`Some(f(s, o))`] if `self` is [`Some(s)`] and the provided +//! [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] //! //! [`Err(err)`]: Err +//! [`filter`]: Option::filter //! [`flatten`]: Option::flatten //! [`map`]: Option::map //! [`map_or`]: Option::map_or @@ -168,8 +178,15 @@ //! [`Ok(v)`]: Ok //! [`ok_or`]: Option::ok_or //! [`ok_or_else`]: Option::ok_or_else +//! [`Some(f(s, o))`]: Some +//! [`Some(o)`]: Some +//! [`Some(s)`]: Some +//! [`Some((s, o))`]: Some +//! [`Some(t)`]: Some //! [`Some(v)`]: Some //! [`transpose`]: Option::transpose +//! [`zip`]: Option::zip +//! [`zip_with`]: Option::zip_with //! //! ## Boolean operators //! @@ -196,12 +213,9 @@ //! | [`xor`] | `Some(x)` | `None` | `Some(x)` | //! | [`xor`] | `Some(x)` | `Some(y)` | `None` | //! -//! The [`and_then`], [`filter`], and [`or_else`] methods take a function -//! as input, and only evaluate the function when they need to produce a -//! new value. [`and_then`] and [`or_else`] take a function that produces -//! another [`Option`] value, while [`filter`] takes a predicate that is -//! used to decide whether to pass the [`Some`] value through. Only the -//! [`and_then`] method can produce an [`Option`] value having a +//! The [`and_then`] and [`or_else`] methods take a function as input, and +//! only evaluate the function when they need to produce a new value. Only +//! the [`and_then`] method can produce an [`Option`] value having a //! different inner type `U` than [`Option`]. //! //! | method | self | function input | function result | output | @@ -209,21 +223,17 @@ //! | [`and_then`] | `None` | (not provided) | (not evaluated) | `None` | //! | [`and_then`] | `Some(x)` | `x` | `None` | `None` | //! | [`and_then`] | `Some(x)` | `x` | `Some(y)` | `Some(y)` | -//! | [`filter`] | `None` | (not provided) | (not evaluated) | `None` | -//! | [`filter`] | `Some(x)` | `x` | `false` | `None` | -//! | [`filter`] | `Some(x)` | `x` | `true` | `Some(x)` | //! | [`or_else`] | `None` | (not provided) | `None` | `None` | //! | [`or_else`] | `None` | (not provided) | `Some(y)` | `Some(y)` | //! | [`or_else`] | `Some(x)` | (not provided) | (not evaluated) | `Some(x)` | //! //! [`and`]: Option::and //! [`and_then`]: Option::and_then -//! [`filter`]: Option::filter //! [`or`]: Option::or //! [`or_else`]: Option::or_else //! [`xor`]: Option::xor //! -//! ## Iterators +//! ## Iterating over `Option` //! //! An [`Option`] can be iterated over. This can be helpful if you need an //! iterator that is conditionally empty. The iterator will either produce @@ -241,27 +251,26 @@ //! * [`iter_mut`] produces a mutable reference of type `&mut T` to the //! contained value //! -//! [`Option`] implements the [`FromIterator`] trait, which allows an -//! iterator over [`Option`] values to be collected into an [`Option`] of a -//! collection of each contained value of the original [`Option`] values, -//! or [`None`] if any of the elements was [`None`]. -//! //! [`empty()`]: crate::iter::empty -//! [`FromIterator`]: Option#impl-FromIterator%3COption%3CA%3E%3E //! [`into_iter`]: Option::into_iter //! [`iter`]: Option::iter //! [`iter_mut`]: Option::iter_mut //! [`once(v)`]: crate::iter::once //! [`Some(v)`]: Some //! -//! An iterator over [`Option`] can be useful when chaining iterators: +//! An iterator over [`Option`] can be useful when chaining iterators, for +//! example, to conditionally insert items. (It's not always necessary to +//! explicitly call an iterator constructor: many [`Iterator`] methods that +//! accept other iterators will also accept iterable types that implement +//! [`IntoIterator`], which includes [`Option`].) //! //! ``` //! let yep = Some(42); //! let nope = None; -//! let nums: Vec = (0..4).chain(yep.into_iter()).chain(4..8).collect(); +//! // chain() already calls into_iter(), so we don't have to do so +//! let nums: Vec = (0..4).chain(yep).chain(4..8).collect(); //! assert_eq!(nums, [0, 1, 2, 3, 42, 4, 5, 6, 7]); -//! let nums: Vec = (0..4).chain(nope.into_iter()).chain(4..8).collect(); +//! let nums: Vec = (0..4).chain(nope).chain(4..8).collect(); //! assert_eq!(nums, [0, 1, 2, 3, 4, 5, 6, 7]); //! ``` //! @@ -270,32 +279,63 @@ //! concrete type. Chaining an iterated [`Option`] can help with that. //! //! ``` -//! let yep = Some(42); -//! let nope = None; -//! -//! fn make_iter(opt: Option) -> impl Iterator { -//! (0..4).chain(opt.into_iter()).chain(4..8) +//! fn make_iter(do_insert: bool) -> impl Iterator { +//! // Explicit returns to illustrate return types matching +//! match do_insert { +//! true => return (0..4).chain(Some(42)).chain(4..8), +//! false => return (0..4).chain(None).chain(4..8), +//! } //! } -//! println!("{:?}", make_iter(yep).collect::>()); -//! println!("{:?}", make_iter(nope).collect::>()); +//! println!("{:?}", make_iter(true).collect::>()); +//! println!("{:?}", make_iter(false).collect::>()); //! ``` //! -//! If we try to do the same thing, but using pattern matching, we can't -//! return `impl Iterator` anymore because the concrete types of the return -//! values differ. +//! If we try to do the same thing, but using [`once()`] and [`empty()`], +//! we can't return `impl Iterator` anymore because the concrete types of +//! the return values differ. //! //! ```compile_fail,E0308 //! # use std::iter::{empty, once}; //! // This won't compile because all possible returns from the function //! // must have the same concrete type. -//! fn make_iter(opt: Option) -> impl Iterator { -//! match opt { -//! Some(x) => return (0..4).chain(once(x)).chain(4..8), -//! None => return (0..4).chain(empty()).chain(4..8) +//! fn make_iter(do_insert: bool) -> impl Iterator { +//! // Explicit returns to illustrate return types not matching +//! match x { +//! true => return (0..4).chain(once(42)).chain(4..8), +//! false => return (0..4).chain(empty()).chain(4..8), //! } //! } //! ``` //! +//! [`once()`]: crate::iter::once +//! +//! ## Collecting into `Option` +//! +//! [`Option`] implements the [`FromIterator`] trait, which allows an +//! iterator over [`Option`] values to be collected into an [`Option`] of a +//! collection of each contained value of the original [`Option`] values, +//! or [`None`] if any of the elements was [`None`]. +//! +//! [`FromIterator`]: Option#impl-FromIterator%3COption%3CA%3E%3E +//! +//! ``` +//! let v = vec![Some(2), Some(4), None, Some(8)]; +//! let res: Option> = v.into_iter().collect(); +//! assert_eq!(res, None); +//! let v = vec![Some(2), Some(4), Some(8)]; +//! let res: Option> = v.into_iter().collect(); +//! assert_eq!(res, Some(vec![2, 4, 8])); +//! ``` +//! +//! [`Option`] also implements the [`Product`] and [`Sum`] traits, allowing +//! an iterator over [`Option`] values to provide the +//! [`product`][m.product] and [`sum`][m.sum] methods. +//! +//! [`Product`]: Option#impl-Product%3COption%3CU%3E%3E +//! [`Sum`]: Option#impl-Sum%3COption%3CU%3E%3E +//! [m.product]: crate::iter::Iterator::product +//! [m.sum]: crate::iter::Iterator::sum +//! //! ## Modifying an [`Option`] in-place //! //! These methods return a mutable reference to the contained value of a diff --git a/library/core/src/result.rs b/library/core/src/result.rs index bad75b722b1..444de78a464 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -235,9 +235,10 @@ //! ones that take a function as input (to be lazily evaluated). //! //! The [`and`] and [`or`] methods take another [`Result`] as input, and -//! produce an [`Result`] as output. Only the [`and`] method can produce a +//! produce a [`Result`] as output. The [`and`] method can produce a //! [`Result`] value having a different inner type `U` than -//! [`Result`]. +//! [`Result`]. The [`or`] method can produce a [`Result`] +//! value having a different error type `F` than [`Result`]. //! //! | method | self | input | output | //! |---------|----------|-----------|----------| @@ -249,9 +250,11 @@ //! | [`or`] | `Ok(x)` | (ignored) | `Ok(x)` | //! //! The [`and_then`] and [`or_else`] methods take a function as input, and -//! only evaluate the function when they need to produce a new value. Only -//! the [`and_then`] method can produce an [`Result`] value having a -//! different inner type `U` than [`Result`]. +//! only evaluate the function when they need to produce a new value. The +//! [`and_then`] method can produce a [`Result`] value having a +//! different inner type `U` than [`Result`]. The [`or_else`] method +//! can produce a [`Result`] value having a different error type `F` +//! than [`Result`]. //! //! | method | self | function input | function result | output | //! |--------------|----------|----------------|-----------------|----------| From 1b58d93bb20fcf8529bfe994d0c85344db5da3b8 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Mon, 14 Jun 2021 19:30:05 -0500 Subject: [PATCH 06/10] add boolean operator example --- library/core/src/option.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 28ea504ec0a..e79b55193c6 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -233,6 +233,36 @@ //! [`or_else`]: Option::or_else //! [`xor`]: Option::xor //! +//! This is an example of using methods like [`and_then`] and [`or`] in a +//! pipeline of method calls. Early stages of the pipeline pass failure +//! values ([`None`]) through unchanged, and continue processing on +//! success values ([`Some`]). Toward the end, [`or`] substitutes an error +//! message if it receives [`None`]. +//! +//! ``` +//! # use std::collections::BTreeMap; +//! let mut bt = BTreeMap::new(); +//! bt.insert(20u8, "foo"); +//! bt.insert(42u8, "bar"); +//! let res = vec![0u8, 1, 11, 200, 22] +//! .into_iter() +//! .map(|x| { +//! // `checked_sub()` returns `None` on error +//! x.checked_sub(1) +//! // same with `checked_mul()` +//! .and_then(|x| x.checked_mul(2)) +//! // `BTreeMap::get` returns `None` on error +//! .and_then(|x| bt.get(&x)) +//! // Substitute an error message if we have `None` so far +//! .or(Some(&"error!")) +//! .copied() +//! // Won't panic because we unconditionally used `Some` above +//! .unwrap() +//! }) +//! .collect::>(); +//! assert_eq!(res, ["error!", "error!", "foo", "error!", "bar"]); +//! ``` +//! //! ## Iterating over `Option` //! //! An [`Option`] can be iterated over. This can be helpful if you need an From 9a00fd049bbc051ce1cbacb04c0db5a7bfc8d723 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Sat, 19 Jun 2021 15:09:27 -0500 Subject: [PATCH 07/10] add more to result overview --- library/core/src/result.rs | 181 +++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 444de78a464..75ba70dea1f 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -227,6 +227,103 @@ //! //! # Method overview //! +//! In addition to working with pattern matching, [`Result`] provides a +//! wide variety of different methods. +//! +//! ## Querying the variant +//! +//! The [`is_ok`] and [`is_err`] methods return [`true`] if the [`Result`] +//! is [`Ok`] or [`Err`], respectively. +//! +//! [`is_err`]: Result::is_err +//! [`is_ok`]: Result::is_ok +//! +//! ## Adapters for working with references +//! +//! * [`as_ref`] converts from `&Result` to `Result<&T, &E>` +//! * [`as_mut`] converts from `&mut Result` to `Result<&mut T, &mut E>` +//! * [`as_deref`] converts from `&Result` to `Result<&T::Target, &E>` +//! * [`as_deref_mut`] converts from `&mut Result` to `Result<&mut T::Target, &mut E>` +//! +//! [`as_deref`]: Result::as_deref +//! [`as_deref_mut`]: Result::as_deref_mut +//! [`as_mut`]: Result::as_mut +//! [`as_ref`]: Result::as_ref +//! +//! ## Extracting contained values +//! +//! These methods extract the contained value in a [`Result`] when it is +//! the [`Ok`] variant. If the [`Result`] is [`Err`]: +//! +//! * [`expect`] panics with a provided custom message +//! * [`unwrap`] panics with a generic message +//! * [`unwrap_or`] returns the provided default value +//! * [`unwrap_or_default`] returns the default value of the type `T` +//! (which must implement the [`Default`] trait) +//! * [`unwrap_or_else`] returns the result of evaluating the provided +//! function +//! +//! The panicking methods [`expect`] and [`unwrap`] require `E` to +//! implement the [`Debug`] trait. +//! +//! These methods extract the contained value in a [`Result`] when it is +//! the [`Err`] variant. They require `T` to implement the [`Debug`] trait. +//! If the [`Result`] is [`Ok`]: +//! +//! * [`expect_err`] panics with a provided custom message +//! * [`unwrap_err`] panics with a generic message +//! +//! [`Debug`]: crate::fmt::Debug +//! [`Default`]: crate::default::Default +//! [`expect`]: Result::expect +//! [`expect_err`]: Result::expect_err +//! [`unwrap`]: Result::unwrap +//! [`unwrap_err`]: Result::unwrap_err +//! [`unwrap_or`]: Result::unwrap_or +//! [`unwrap_or_default`]: Result::unwrap_or_default +//! [`unwrap_or_else`]: Result::unwrap_or_else +//! +//! ## Transforming contained values +//! +//! These transformations are from [`Result`] to [`Option`]: +//! +//! * [`err`][Result::err] transforms [`Result`] into [`Option`], +//! mapping [`Err(e)`] to [`Some(e)`] and [`Ok(v)`] to [`None`] +//! * [`ok`][Result::ok] transforms [`Result`] into [`Option`], +//! mapping [`Ok(v)`] to [`Some(v)`] and [`Err(e)`] to [`None`] +//! * [`transpose`] transposes a [`Result`] of an [`Option`] into an +//! [`Option`] of a [`Result`] +//! +//! These transformations are on [`Ok`] values: +//! +//! * [`map`] transforms [`Result`] into [`Result`] by applying +//! the provided function to the contained value of [`Ok`] and leaving +//! [`Err`] values unchanged +//! * [`map_or`] transforms [`Result`] into a value of `U` by +//! applying the provided function to the contained value of [`Ok`], or +//! returns the provided default value of `U` if the [`Result`] is +//! [`Err`] +//! * [`map_or_else`] transforms [`Result`] into a value of `U` by +//! applying the provided function to the contained value of [`Ok`], or +//! applies the provided fallback function to the contained value of +//! [`Err`] +//! +//! This transformation is on [`Err`] values: +//! +//! * [`map_err`] transforms [`Result`] into [`Result`] by +//! applying the provided function to the contained value of [`Err`] and +//! leaving [`Ok`] values unchanged +//! +//! [`Err(e)`]: Err +//! [`Ok(v)`]: Ok +//! [`Some(e)`]: Option::Some +//! [`Some(v)`]: Option::Some +//! [`map`]: Result::map +//! [`map_err`]: Result::map_err +//! [`map_or`]: Result::map_or +//! [`map_or_else`]: Result::map_or_else +//! [`transpose`]: Result::transpose +//! //! ## Boolean operators //! //! These methods treat the [`Result`] as a boolean value, where [`Ok`] @@ -269,6 +366,90 @@ //! [`and_then`]: Result::and_then //! [`or`]: Result::or //! [`or_else`]: Result::or_else +//! +//! ## Iterating over `Result` +//! +//! A [`Result`] can be iterated over. This can be helpful if you need an +//! iterator that is conditionally empty. The iterator will either produce +//! a single value (when the [`Result`] is [`Ok`]), or produce no values +//! (when the [`Result`] is [`Err`]). For example, [`into_iter`] acts like +//! [`once(v)`] if the [`Result`] is [`Ok(v)`], and like [`empty()`] if +//! the [`Result`] is [`Err(err)`]. +//! +//! Iterators over [`Result`] come in three types: +//! +//! * [`into_iter`] consumes the [`Result`] and produces the contained +//! value +//! * [`iter`] produces an immutable reference of type `&T` to the +//! contained value +//! * [`iter_mut`] produces a mutable reference of type `&mut T` to the +//! contained value +//! +//! See [Iterating over `Option`] for examples of how this can be useful. +//! +//! [`Err(err)`]: Err +//! [Iterating over `Option`]: crate::option#iterating-over-option +//! [`Ok(v)`]: Ok +//! [`empty()`]: crate::iter::empty +//! [`into_iter`]: Result::into_iter +//! [`iter`]: Result::iter +//! [`iter_mut`]: Result::iter_mut +//! [`once(v)`]: crate::iter::once +//! +//! You might want to use an iterator chain to do multiple instances of an +//! operation that can fail, but would like to ignore failures while +//! continuing to process the successful results. In this example, we take +//! advantage of the iterable nature of [`Result`] to select only the +//! [`Ok`] values using [`flatten`]. +//! +//! [`flatten`]: crate::iter::Iterator::flatten +//! +//! ``` +//! # use std::str::FromStr; +//! let mut results = vec![]; +//! let mut errs = vec![]; +//! let nums: Vec<_> = vec!["17", "not a number", "99", "-27", "768"] +//! .into_iter() +//! .map(u8::from_str) +//! // Save clones of the raw `Result` values to inspect +//! .inspect(|x| results.push(x.clone())) +//! // Challenge: explain how this captures only the `Err` values +//! .inspect(|x| errs.extend(x.clone().err())) +//! .flatten() +//! .collect(); +//! assert_eq!(errs.len(), 3); +//! assert_eq!(nums, [17, 99]); +//! println!("results {:?}", results); +//! println!("errs {:?}", errs); +//! println!("nums {:?}", nums); +//! ``` +//! +//! ## Collecting into `Result` +//! +//! [`Result`] implements the [`FromIterator`] trait, which allows an +//! iterator over [`Result`] values to be collected into a [`Result`] of a +//! collection of each contained value of the original [`Result`] values, +//! or [`Err`] if any of the elements was [`Err`]. +//! +//! [`FromIterator`]: Result#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E +//! +//! ``` +//! let v = vec![Ok(2), Ok(4), Err("err!"), Ok(8)]; +//! let res: Result, &str> = v.into_iter().collect(); +//! assert_eq!(res, Err("err!")); +//! let v = vec![Ok(2), Ok(4), Ok(8)]; +//! let res: Result, &str> = v.into_iter().collect(); +//! assert_eq!(res, Ok(vec![2, 4, 8])); +//! ``` +//! +//! [`Result`] also implements the [`Product`] and [`Sum`] traits, allowing +//! an iterator over [`Result`] values to provide the +//! [`product`][m.product] and [`sum`][m.sum] methods. +//! +//! [`Product`]: Result#impl-Product%3CResult%3CU%2C%20E%3E%3E +//! [`Sum`]: Result#impl-Sum%3CResult%3CU%2C%20E%3E%3E +//! [m.product]: crate::iter::Iterator::product +//! [m.sum]: crate::iter::Iterator::sum #![stable(feature = "rust1", since = "1.0.0")] From 771f35ce84477595e43bce2f262778c841d36963 Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Tue, 22 Jun 2021 15:35:14 -0500 Subject: [PATCH 08/10] Some is not a type, etc --- library/core/src/option.rs | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index e79b55193c6..8c12bcff5cc 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -144,25 +144,35 @@ //! //! ## Transforming contained values //! +//! These transformations are from [`Option`] to [`Result`]. +//! +//! * [`ok_or`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to +//! [`Err(err)`] using the provided default `err` value +//! * [`ok_or_else`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to +//! a value of [`Err`] using the provided function +//! * [`transpose`] transposes an [`Option`] of a [`Result`] into a +//! [`Result`] of an [`Option`] +//! +//! These transformations are on [`Some`] values. +//! //! * [`filter`] calls the provided predicate function on the contained //! value `t` if the [`Option`] is [`Some(t)`], and returns [`Some(t)`] //! if the function returns `true`; otherwise, returns [`None`] //! * [`flatten`] removes one level of nesting from an //! [`Option>`] -//! * [`map`] transforms [`Some`] to [`Some`] using the provided +//! * [`map`] transforms [`Option`] to [`Option`] by applying the +//! provided function to the contained value of [`Some`] and leaving +//! [`None`] values unchanged +//! * [`map_or`] transforms [`Option`] to a value of `U` by applying the +//! provided function to the contained value of [`Some`], or transforms +//! [`None`] to a provided default value of `U` +//! * [`map_or_else`] transforms [`Option`] to a value of `U` by +//! applying the provided function to the contained value of [`Some`], or +//! transforms [`None`] to a value of `U` using a provided fallback //! function -//! * [`map_or`] transforms [`Some`] to a value of `U` using the -//! provided function, or transforms [`None`] to a provided default value -//! of `U` -//! * [`map_or_else`] transforms [`Some`] to a value of `U` using the -//! provided function, or transforms [`None`] to a value of `U` using -//! another provided function -//! * [`ok_or`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to -//! [`Err(err)`] using the provided default `err` value -//! * [`ok_or_else`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to -//! a value of [`Err`] using the provided function -//! * [`transpose`] transposes an [`Option`] of a [`Result`] into a -//! [`Result`] of an [`Option`] +//! +//! These transformations combine two [`Some`] values. +//! //! * [`zip`] returns [`Some((s, o))`] if `self` is [`Some(s)`] and the //! provided [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] //! * [`zip_with`] calls the provided function `f` and returns From c196cc9f125b1a121cc2a636b21143a2bb0b7cdf Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Thu, 24 Jun 2021 12:33:51 -0500 Subject: [PATCH 09/10] option/result overviews: address feedback (Most of these are from a review by joshtriplett. Thanks!) Fix errors in `as_pin_ref` and `as_pin_mut` in the "Adapters for working with references" overview. Reword some headings about transformation methods. Reclassify `map`, `map_or`, `map_or_else`, `map_err`, etc. to more accurately reflect which variants they transform. Document `Debug` requirement for `get_or_insert_default`. Reword text about `take` and `replace` to be more accurate. Add examples for the `Product` and `Sum` traits. Also: Move link reference definitions closer to their uses. Warn about making link reference definintions for `err` and `ok`. Avoid making other link reference definitions that might conflict in the future (foreign methods that share a name with local ones, etc.) Write out the generics of `Option` and `Result` when the following text refers to the type parameters. --- library/core/src/option.rs | 158 +++++++++++++++++++++---------------- library/core/src/result.rs | 134 +++++++++++++++++-------------- 2 files changed, 164 insertions(+), 128 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 8c12bcff5cc..bd9ac7bb3d9 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -49,6 +49,8 @@ //! no "null" references. Instead, Rust has *optional* pointers, like //! the optional owned box, [`Option`]`<`[`Box`]`>`. //! +//! [`Box`]: ../../std/boxed/struct.Box.html +//! //! The following example uses [`Option`] to create an optional box of //! [`i32`]. Notice that in order to use the inner [`i32`] value, the //! `check_optional` function first needs to use pattern matching to @@ -83,6 +85,10 @@ //! * [`ptr::NonNull`] //! * `#[repr(transparent)]` struct around one of the types in this list. //! +//! [`Box`]: ../../std/boxed/struct.Box.html +//! [`num::NonZero*`]: crate::num +//! [`ptr::NonNull`]: crate::ptr::NonNull +//! //! This is called the "null pointer optimization" or NPO. //! //! It is further guaranteed that, for the cases above, one can @@ -100,32 +106,32 @@ //! The [`is_some`] and [`is_none`] methods return [`true`] if the [`Option`] //! is [`Some`] or [`None`], respectively. //! -//! [`is_some`]: Option::is_some //! [`is_none`]: Option::is_none +//! [`is_some`]: Option::is_some //! //! ## Adapters for working with references //! //! * [`as_ref`] converts from `&Option` to `Option<&T>` //! * [`as_mut`] converts from `&mut Option` to `Option<&mut T>` //! * [`as_deref`] converts from `&Option` to `Option<&T::Target>` -//! * [`as_deref_mut`] converts from `&mut Option` to `Option<&mut T::Target>` -//! * [`as_pin_ref`] converts from [`&Pin`]`>` to `Option<`[`Pin`]`<&T>>` -//! * [`as_pin_mut`] converts from [`&mut Pin`]`>` to `Option<`[`Pin`]`<&mut T>>` +//! * [`as_deref_mut`] converts from `&mut Option` to +//! `Option<&mut T::Target>` +//! * [`as_pin_ref`] converts from [`Pin`]`<&Option>` to +//! `Option<`[`Pin`]`<&T>>` +//! * [`as_pin_mut`] converts from [`Pin`]`<&mut Option>` to +//! `Option<`[`Pin`]`<&mut T>>` //! -//! [`&mut Pin`]: crate::pin::Pin -//! [`&Pin`]: crate::pin::Pin //! [`as_deref`]: Option::as_deref //! [`as_deref_mut`]: Option::as_deref_mut //! [`as_mut`]: Option::as_mut -//! [`as_pin_ref`]: Option::as_pin_ref //! [`as_pin_mut`]: Option::as_pin_mut +//! [`as_pin_ref`]: Option::as_pin_ref //! [`as_ref`]: Option::as_ref -//! [`Pin`]: crate::pin::Pin //! //! ## Extracting the contained value //! -//! These methods extract the contained value in an [`Option`] when it is -//! the [`Some`] variant. If the [`Option`] is [`None`]: +//! These methods extract the contained value in an [`Option`] when it +//! is the [`Some`] variant. If the [`Option`] is [`None`]: //! //! * [`expect`] panics with a provided custom message //! * [`unwrap`] panics with a generic message @@ -135,7 +141,6 @@ //! * [`unwrap_or_else`] returns the result of evaluating the provided //! function //! -//! [`Default`]: crate::default::Default //! [`expect`]: Option::expect //! [`unwrap`]: Option::unwrap //! [`unwrap_or`]: Option::unwrap_or @@ -144,7 +149,7 @@ //! //! ## Transforming contained values //! -//! These transformations are from [`Option`] to [`Result`]. +//! These methods transform [`Option`] to [`Result`]: //! //! * [`ok_or`] transforms [`Some(v)`] to [`Ok(v)`], and [`None`] to //! [`Err(err)`] using the provided default `err` value @@ -153,7 +158,14 @@ //! * [`transpose`] transposes an [`Option`] of a [`Result`] into a //! [`Result`] of an [`Option`] //! -//! These transformations are on [`Some`] values. +//! [`Err(err)`]: Err +//! [`Ok(v)`]: Ok +//! [`Some(v)`]: Some +//! [`ok_or`]: Option::ok_or +//! [`ok_or_else`]: Option::ok_or_else +//! [`transpose`]: Option::transpose +//! +//! These methods transform the [`Some`] variant: //! //! * [`filter`] calls the provided predicate function on the contained //! value `t` if the [`Option`] is [`Some(t)`], and returns [`Some(t)`] @@ -163,15 +175,26 @@ //! * [`map`] transforms [`Option`] to [`Option`] by applying the //! provided function to the contained value of [`Some`] and leaving //! [`None`] values unchanged -//! * [`map_or`] transforms [`Option`] to a value of `U` by applying the -//! provided function to the contained value of [`Some`], or transforms -//! [`None`] to a provided default value of `U` -//! * [`map_or_else`] transforms [`Option`] to a value of `U` by -//! applying the provided function to the contained value of [`Some`], or -//! transforms [`None`] to a value of `U` using a provided fallback -//! function //! -//! These transformations combine two [`Some`] values. +//! [`Some(t)`]: Some +//! [`filter`]: Option::filter +//! [`flatten`]: Option::flatten +//! [`map`]: Option::map +//! +//! These methods transform [`Option`] to a value of a possibly +//! different type `U`: +//! +//! * [`map_or`] applies the provided function to the contained value of +//! [`Some`], or returns the provided default value if the [`Option`] is +//! [`None`] +//! * [`map_or_else`] applies the provided function to the contained value +//! of [`Some`], or returns the result of evaluating the provided +//! fallback function if the [`Option`] is [`None`] +//! +//! [`map_or`]: Option::map_or +//! [`map_or_else`]: Option::map_or_else +//! +//! These methods combine the [`Some`] variants of two [`Option`] values: //! //! * [`zip`] returns [`Some((s, o))`] if `self` is [`Some(s)`] and the //! provided [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] @@ -179,22 +202,10 @@ //! [`Some(f(s, o))`] if `self` is [`Some(s)`] and the provided //! [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] //! -//! [`Err(err)`]: Err -//! [`filter`]: Option::filter -//! [`flatten`]: Option::flatten -//! [`map`]: Option::map -//! [`map_or`]: Option::map_or -//! [`map_or_else`]: Option::map_or_else -//! [`Ok(v)`]: Ok -//! [`ok_or`]: Option::ok_or -//! [`ok_or_else`]: Option::ok_or_else //! [`Some(f(s, o))`]: Some //! [`Some(o)`]: Some //! [`Some(s)`]: Some //! [`Some((s, o))`]: Some -//! [`Some(t)`]: Some -//! [`Some(v)`]: Some -//! [`transpose`]: Option::transpose //! [`zip`]: Option::zip //! [`zip_with`]: Option::zip_with //! @@ -223,6 +234,10 @@ //! | [`xor`] | `Some(x)` | `None` | `Some(x)` | //! | [`xor`] | `Some(x)` | `Some(y)` | `None` | //! +//! [`and`]: Option::and +//! [`or`]: Option::or +//! [`xor`]: Option::xor +//! //! The [`and_then`] and [`or_else`] methods take a function as input, and //! only evaluate the function when they need to produce a new value. Only //! the [`and_then`] method can produce an [`Option`] value having a @@ -237,11 +252,8 @@ //! | [`or_else`] | `None` | (not provided) | `Some(y)` | `Some(y)` | //! | [`or_else`] | `Some(x)` | (not provided) | (not evaluated) | `Some(x)` | //! -//! [`and`]: Option::and //! [`and_then`]: Option::and_then -//! [`or`]: Option::or //! [`or_else`]: Option::or_else -//! [`xor`]: Option::xor //! //! This is an example of using methods like [`and_then`] and [`or`] in a //! pipeline of method calls. Early stages of the pipeline pass failure @@ -282,7 +294,11 @@ //! [`once(v)`] if the [`Option`] is [`Some(v)`], and like [`empty()`] if //! the [`Option`] is [`None`]. //! -//! Iterators over [`Option`] come in three types: +//! [`Some(v)`]: Some +//! [`empty()`]: crate::iter::empty +//! [`once(v)`]: crate::iter::once +//! +//! Iterators over [`Option`] come in three types: //! //! * [`into_iter`] consumes the [`Option`] and produces the contained //! value @@ -291,12 +307,9 @@ //! * [`iter_mut`] produces a mutable reference of type `&mut T` to the //! contained value //! -//! [`empty()`]: crate::iter::empty //! [`into_iter`]: Option::into_iter //! [`iter`]: Option::iter //! [`iter_mut`]: Option::iter_mut -//! [`once(v)`]: crate::iter::once -//! [`Some(v)`]: Some //! //! An iterator over [`Option`] can be useful when chaining iterators, for //! example, to conditionally insert items. (It's not always necessary to @@ -334,6 +347,9 @@ //! we can't return `impl Iterator` anymore because the concrete types of //! the return values differ. //! +//! [`empty()`]: crate::iter::empty +//! [`once()`]: crate::iter::once +//! //! ```compile_fail,E0308 //! # use std::iter::{empty, once}; //! // This won't compile because all possible returns from the function @@ -347,16 +363,14 @@ //! } //! ``` //! -//! [`once()`]: crate::iter::once -//! //! ## Collecting into `Option` //! -//! [`Option`] implements the [`FromIterator`] trait, which allows an -//! iterator over [`Option`] values to be collected into an [`Option`] of a -//! collection of each contained value of the original [`Option`] values, -//! or [`None`] if any of the elements was [`None`]. +//! [`Option`] implements the [`FromIterator`][impl-FromIterator] trait, +//! which allows an iterator over [`Option`] values to be collected into an +//! [`Option`] of a collection of each contained value of the original +//! [`Option`] values, or [`None`] if any of the elements was [`None`]. //! -//! [`FromIterator`]: Option#impl-FromIterator%3COption%3CA%3E%3E +//! [impl-FromIterator]: Option#impl-FromIterator%3COption%3CA%3E%3E //! //! ``` //! let v = vec![Some(2), Some(4), None, Some(8)]; @@ -367,43 +381,52 @@ //! assert_eq!(res, Some(vec![2, 4, 8])); //! ``` //! -//! [`Option`] also implements the [`Product`] and [`Sum`] traits, allowing -//! an iterator over [`Option`] values to provide the -//! [`product`][m.product] and [`sum`][m.sum] methods. +//! [`Option`] also implements the [`Product`][impl-Product] and +//! [`Sum`][impl-Sum] traits, allowing an iterator over [`Option`] values +//! to provide the [`product`][Iterator::product] and +//! [`sum`][Iterator::sum] methods. //! -//! [`Product`]: Option#impl-Product%3COption%3CU%3E%3E -//! [`Sum`]: Option#impl-Sum%3COption%3CU%3E%3E -//! [m.product]: crate::iter::Iterator::product -//! [m.sum]: crate::iter::Iterator::sum +//! [impl-Product]: Option#impl-Product%3COption%3CU%3E%3E +//! [impl-Sum]: Option#impl-Sum%3COption%3CU%3E%3E +//! +//! ``` +//! let v = vec![None, Some(1), Some(2), Some(3)]; +//! let res: Option = v.into_iter().sum(); +//! assert_eq!(res, None); +//! let v = vec![Some(1), Some(2), Some(21)]; +//! let res: Option = v.into_iter().product(); +//! assert_eq!(res, Some(42)); +//! ``` //! //! ## Modifying an [`Option`] in-place //! -//! These methods return a mutable reference to the contained value of a -//! [`Some`]. +//! These methods return a mutable reference to the contained value of an +//! [`Option`]: //! //! * [`insert`] inserts a value, dropping any old contents //! * [`get_or_insert`] gets the current value, inserting a provided //! default value if it is [`None`] //! * [`get_or_insert_default`] gets the current value, inserting the -//! default value of type `T` if it is [`None`] +//! default value of type `T` (which must implement [`Default`]) if it is +//! [`None`] //! * [`get_or_insert_with`] gets the current value, inserting a default //! computed by the provided function if it is [`None`] //! -//! [`insert`]: Option::insert //! [`get_or_insert`]: Option::get_or_insert //! [`get_or_insert_default`]: Option::get_or_insert_default //! [`get_or_insert_with`]: Option::get_or_insert_with +//! [`insert`]: Option::insert //! -//! These methods transfer ownership of the [`Option`]. +//! These methods transfer ownership of the contained of an [`Option`]: //! -//! * [`take`] takes ownership of the [`Option`], including any contained -//! value, replacing it with [`None`] -//! * [`replace`] takes ownership of the [`Option`], including any -//! contained value, replacing it with a [`Some`] containing the provided -//! value +//! * [`take`] takes ownership of the contained value of an [`Option`], if +//! any, replacing the [`Option`] with [`None`] +//! * [`replace`] takes ownership of the contained value of an [`Option`], +//! if any, replacing the [`Option`] with a [`Some`] containing the +//! provided value //! -//! [`take`]: Option::take //! [`replace`]: Option::replace +//! [`take`]: Option::take //! //! # Examples //! @@ -456,11 +479,6 @@ //! None => println!("there are no animals :("), //! } //! ``` -//! -//! [`Box`]: ../../std/boxed/struct.Box.html -//! [`Box`]: ../../std/boxed/struct.Box.html -//! [`num::NonZero*`]: crate::num -//! [`ptr::NonNull`]: crate::ptr::NonNull #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 75ba70dea1f..b9bb8cc9406 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -242,8 +242,9 @@ //! //! * [`as_ref`] converts from `&Result` to `Result<&T, &E>` //! * [`as_mut`] converts from `&mut Result` to `Result<&mut T, &mut E>` -//! * [`as_deref`] converts from `&Result` to `Result<&T::Target, &E>` -//! * [`as_deref_mut`] converts from `&mut Result` to `Result<&mut T::Target, &mut E>` +//! * [`as_deref`] converts from `&Result` to `Result<&T::Target, &E>` +//! * [`as_deref_mut`] converts from `&mut Result` to +//! `Result<&mut T::Target, &mut E>` //! //! [`as_deref`]: Result::as_deref //! [`as_deref_mut`]: Result::as_deref_mut @@ -252,8 +253,8 @@ //! //! ## Extracting contained values //! -//! These methods extract the contained value in a [`Result`] when it is -//! the [`Ok`] variant. If the [`Result`] is [`Err`]: +//! These methods extract the contained value in a [`Result`] when it +//! is the [`Ok`] variant. If the [`Result`] is [`Err`]: //! //! * [`expect`] panics with a provided custom message //! * [`unwrap`] panics with a generic message @@ -266,26 +267,27 @@ //! The panicking methods [`expect`] and [`unwrap`] require `E` to //! implement the [`Debug`] trait. //! -//! These methods extract the contained value in a [`Result`] when it is -//! the [`Err`] variant. They require `T` to implement the [`Debug`] trait. -//! If the [`Result`] is [`Ok`]: +//! [`Debug`]: crate::fmt::Debug +//! [`expect`]: Result::expect +//! [`unwrap`]: Result::unwrap +//! [`unwrap_or`]: Result::unwrap_or +//! [`unwrap_or_default`]: Result::unwrap_or_default +//! [`unwrap_or_else`]: Result::unwrap_or_else +//! +//! These methods extract the contained value in a [`Result`] when it +//! is the [`Err`] variant. They require `T` to implement the [`Debug`] +//! trait. If the [`Result`] is [`Ok`]: //! //! * [`expect_err`] panics with a provided custom message //! * [`unwrap_err`] panics with a generic message //! //! [`Debug`]: crate::fmt::Debug -//! [`Default`]: crate::default::Default -//! [`expect`]: Result::expect //! [`expect_err`]: Result::expect_err -//! [`unwrap`]: Result::unwrap //! [`unwrap_err`]: Result::unwrap_err -//! [`unwrap_or`]: Result::unwrap_or -//! [`unwrap_or_default`]: Result::unwrap_or_default -//! [`unwrap_or_else`]: Result::unwrap_or_else //! //! ## Transforming contained values //! -//! These transformations are from [`Result`] to [`Option`]: +//! These methods transform [`Result`] to [`Option`]: //! //! * [`err`][Result::err] transforms [`Result`] into [`Option`], //! mapping [`Err(e)`] to [`Some(e)`] and [`Ok(v)`] to [`None`] @@ -294,35 +296,44 @@ //! * [`transpose`] transposes a [`Result`] of an [`Option`] into an //! [`Option`] of a [`Result`] //! -//! These transformations are on [`Ok`] values: -//! -//! * [`map`] transforms [`Result`] into [`Result`] by applying -//! the provided function to the contained value of [`Ok`] and leaving -//! [`Err`] values unchanged -//! * [`map_or`] transforms [`Result`] into a value of `U` by -//! applying the provided function to the contained value of [`Ok`], or -//! returns the provided default value of `U` if the [`Result`] is -//! [`Err`] -//! * [`map_or_else`] transforms [`Result`] into a value of `U` by -//! applying the provided function to the contained value of [`Ok`], or -//! applies the provided fallback function to the contained value of -//! [`Err`] -//! -//! This transformation is on [`Err`] values: -//! -//! * [`map_err`] transforms [`Result`] into [`Result`] by -//! applying the provided function to the contained value of [`Err`] and -//! leaving [`Ok`] values unchanged +// Do NOT add link reference definitions for `err` or `ok`, because they +// will generate numerous incorrect URLs for `Err` and `Ok` elsewhere, due +// to case folding. //! //! [`Err(e)`]: Err //! [`Ok(v)`]: Ok //! [`Some(e)`]: Option::Some //! [`Some(v)`]: Option::Some +//! [`transpose`]: Result::transpose +//! +//! This method transforms the contained value of the [`Ok`] variant: +//! +//! * [`map`] transforms [`Result`] into [`Result`] by applying +//! the provided function to the contained value of [`Ok`] and leaving +//! [`Err`] values unchanged +//! //! [`map`]: Result::map +//! +//! This method transforms the contained value of the [`Err`] variant: +//! +//! * [`map_err`] transforms [`Result`] into [`Result`] by +//! applying the provided function to the contained value of [`Err`] and +//! leaving [`Ok`] values unchanged +//! //! [`map_err`]: Result::map_err +//! +//! These methods transform a [`Result`] into a value of a possibly +//! different type `U`: +//! +//! * [`map_or`] applies the provided function to the contained value of +//! [`Ok`], or returns the provided default value if the [`Result`] is +//! [`Err`] +//! * [`map_or_else`] applies the provided function to the contained value +//! of [`Ok`], or applies the provided fallback function to the contained +//! value of [`Err`] +//! //! [`map_or`]: Result::map_or //! [`map_or_else`]: Result::map_or_else -//! [`transpose`]: Result::transpose //! //! ## Boolean operators //! @@ -346,6 +357,9 @@ //! | [`or`] | `Err(e)` | `Ok(y)` | `Ok(y)` | //! | [`or`] | `Ok(x)` | (ignored) | `Ok(x)` | //! +//! [`and`]: Result::and +//! [`or`]: Result::or +//! //! The [`and_then`] and [`or_else`] methods take a function as input, and //! only evaluate the function when they need to produce a new value. The //! [`and_then`] method can produce a [`Result`] value having a @@ -362,9 +376,7 @@ //! | [`or_else`] | `Err(e)` | `e` | `Ok(y)` | `Ok(y)` | //! | [`or_else`] | `Ok(x)` | (not provided) | (not evaluated) | `Ok(x)` | //! -//! [`and`]: Result::and //! [`and_then`]: Result::and_then -//! [`or`]: Result::or //! [`or_else`]: Result::or_else //! //! ## Iterating over `Result` @@ -373,10 +385,14 @@ //! iterator that is conditionally empty. The iterator will either produce //! a single value (when the [`Result`] is [`Ok`]), or produce no values //! (when the [`Result`] is [`Err`]). For example, [`into_iter`] acts like -//! [`once(v)`] if the [`Result`] is [`Ok(v)`], and like [`empty()`] if -//! the [`Result`] is [`Err(err)`]. +//! [`once(v)`] if the [`Result`] is [`Ok(v)`], and like [`empty()`] if the +//! [`Result`] is [`Err`]. //! -//! Iterators over [`Result`] come in three types: +//! [`Ok(v)`]: Ok +//! [`empty()`]: crate::iter::empty +//! [`once(v)`]: crate::iter::once +//! +//! Iterators over [`Result`] come in three types: //! //! * [`into_iter`] consumes the [`Result`] and produces the contained //! value @@ -387,22 +403,16 @@ //! //! See [Iterating over `Option`] for examples of how this can be useful. //! -//! [`Err(err)`]: Err //! [Iterating over `Option`]: crate::option#iterating-over-option -//! [`Ok(v)`]: Ok -//! [`empty()`]: crate::iter::empty //! [`into_iter`]: Result::into_iter //! [`iter`]: Result::iter //! [`iter_mut`]: Result::iter_mut -//! [`once(v)`]: crate::iter::once //! //! You might want to use an iterator chain to do multiple instances of an //! operation that can fail, but would like to ignore failures while //! continuing to process the successful results. In this example, we take //! advantage of the iterable nature of [`Result`] to select only the -//! [`Ok`] values using [`flatten`]. -//! -//! [`flatten`]: crate::iter::Iterator::flatten +//! [`Ok`] values using [`flatten`][Iterator::flatten]. //! //! ``` //! # use std::str::FromStr; @@ -426,12 +436,12 @@ //! //! ## Collecting into `Result` //! -//! [`Result`] implements the [`FromIterator`] trait, which allows an -//! iterator over [`Result`] values to be collected into a [`Result`] of a -//! collection of each contained value of the original [`Result`] values, -//! or [`Err`] if any of the elements was [`Err`]. +//! [`Result`] implements the [`FromIterator`][impl-FromIterator] trait, +//! which allows an iterator over [`Result`] values to be collected into a +//! [`Result`] of a collection of each contained value of the original +//! [`Result`] values, or [`Err`] if any of the elements was [`Err`]. //! -//! [`FromIterator`]: Result#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E +//! [impl-FromIterator]: Result#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E //! //! ``` //! let v = vec![Ok(2), Ok(4), Err("err!"), Ok(8)]; @@ -442,14 +452,22 @@ //! assert_eq!(res, Ok(vec![2, 4, 8])); //! ``` //! -//! [`Result`] also implements the [`Product`] and [`Sum`] traits, allowing -//! an iterator over [`Result`] values to provide the -//! [`product`][m.product] and [`sum`][m.sum] methods. +//! [`Result`] also implements the [`Product`][impl-Product] and +//! [`Sum`][impl-Sum] traits, allowing an iterator over [`Result`] values +//! to provide the [`product`][Iterator::product] and +//! [`sum`][Iterator::sum] methods. //! -//! [`Product`]: Result#impl-Product%3CResult%3CU%2C%20E%3E%3E -//! [`Sum`]: Result#impl-Sum%3CResult%3CU%2C%20E%3E%3E -//! [m.product]: crate::iter::Iterator::product -//! [m.sum]: crate::iter::Iterator::sum +//! [impl-Product]: Result#impl-Product%3CResult%3CU%2C%20E%3E%3E +//! [impl-Sum]: Result#impl-Sum%3CResult%3CU%2C%20E%3E%3E +//! +//! ``` +//! let v = vec![Err("error!"), Ok(1), Ok(2), Ok(3), Err("foo")]; +//! let res: Result = v.into_iter().sum(); +//! assert_eq!(res, Err("error!")); +//! let v: Vec> = vec![Ok(1), Ok(2), Ok(21)]; +//! let res: Result = v.into_iter().product(); +//! assert_eq!(res, Ok(42)); +//! ``` #![stable(feature = "rust1", since = "1.0.0")] From 2b4a6aa1494d80564662271900fa3c73d713411e Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Thu, 1 Jul 2021 19:14:27 -0500 Subject: [PATCH 10/10] fix missing word --- library/core/src/option.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index bd9ac7bb3d9..2d493c94571 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -417,7 +417,8 @@ //! [`get_or_insert_with`]: Option::get_or_insert_with //! [`insert`]: Option::insert //! -//! These methods transfer ownership of the contained of an [`Option`]: +//! These methods transfer ownership of the contained value of an +//! [`Option`]: //! //! * [`take`] takes ownership of the contained value of an [`Option`], if //! any, replacing the [`Option`] with [`None`]