about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexis Bourget <alexis.bourget@gmail.com>2020-07-03 23:49:21 +0200
committerAlexis Bourget <alexis.bourget@gmail.com>2020-07-03 23:55:14 +0200
commit837a761b398a6ff6a97f7f61e390dae9efbeab79 (patch)
tree5615b6fdd1379469bb27f75a32dd938898fe7bc4
parentf844ea1e561475e6023282ef167e76bc973773ef (diff)
downloadrust-837a761b398a6ff6a97f7f61e390dae9efbeab79.tar.gz
rust-837a761b398a6ff6a97f7f61e390dae9efbeab79.zip
Document the where keyword
-rw-r--r--src/libstd/keyword_docs.rs137
1 files changed, 135 insertions, 2 deletions
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index 0b3386c05d5..058a89772d4 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -1651,9 +1651,142 @@ mod use_keyword {}
 //
 /// Add constraints that must be upheld to use an item.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// `where` allows specifying constraints on lifetime and generic parameters.
+/// The [RFC] introducing `where` contains detailed informations about the
+/// keyword.
 ///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// # Examples
+///
+/// `where` can be used for constraints with traits:
+///
+/// ```rust
+/// fn new<T: Default>() -> T {
+///     T::default()
+/// }
+///
+/// fn new_where<T>() -> T
+/// where
+///     T: Default,
+/// {
+///     T::default()
+/// }
+///
+/// assert_eq!(0.0, new());
+/// assert_eq!(0.0, new_where());
+///
+/// assert_eq!(0, new());
+/// assert_eq!(0, new_where());
+/// ```
+///
+/// `where` can also be used for lifetimes.
+///
+/// This compiles because the lifetime of `longer` is superior to the lifetime
+/// of `shorter`, thus the constraint is respected:
+///
+/// ```rust
+/// fn select<'a, 'b: 'a>(s1: &'a str, s2: &'b str, second: bool) -> &'a str {
+///     if second {
+///         s2
+///     } else {
+///         s1
+///     }
+/// }
+///
+/// fn select_where<'a, 'b>(s1: &'a str, s2: &'b str, second: bool) -> &'a str
+/// where
+///     'b: 'a,
+/// {
+///     if second {
+///         s2
+///     } else {
+///         s1
+///     }
+/// }
+///
+/// let outer = String::from("Long living ref");
+/// let longer = &outer;
+/// {
+///     let inner = String::from("Long living ref");
+///     let shorter = &inner;
+///
+///     assert_eq!(select(shorter, longer, false), shorter);
+///     assert_eq!(select(shorter, longer, true), longer);
+///
+///     assert_eq!(select_where(shorter, longer, false), shorter);
+///     assert_eq!(select_where(shorter, longer, true), longer);
+/// }
+/// ```
+///
+/// On the other hand, this will not compile: `shorter` does not have a lifetime
+/// that respects the constraint imposed by the `select` and `select_where`
+/// functions.
+///
+/// ```rust,compile_fail,E0597
+/// # fn select<'a, 'b: 'a>(s1: &'a str, s2: &'b str, second: bool) -> &'a str {
+/// #     if second {
+/// #         s2
+/// #     } else {
+/// #         s1
+/// #     }
+/// # }
+/// #
+/// # fn select_where<'a, 'b>(s1: &'a str, s2: &'b str, second: bool) -> &'a str
+/// # where
+/// #     'b: 'a,
+/// # {
+/// #     if second {
+/// #         s2
+/// #     } else {
+/// #         s1
+/// #     }
+/// # }
+/// let outer = String::from("Long living ref");
+/// let longer = &outer;
+/// let res1;
+/// let res2;
+/// {
+///     let inner = String::from("Long living ref");
+///     let shorter = &inner;
+///
+///     res1 = select(longer, shorter, false);
+///     res2 = select_where(longer, shorter, false);
+/// }
+/// assert_eq!(res1, &outer);
+/// assert_eq!(res2, &outer);
+/// ```
+///
+/// `where` can also be used to express more complicated constraints that cannot
+/// be written with the `<T: Trait>` syntax:
+///
+/// ```rust
+/// fn first_or_default<I>(mut i: I) -> I::Item
+/// where
+///     I: Iterator,
+///     I::Item: Default,
+/// {
+///     i.next().unwrap_or_else(I::Item::default)
+/// }
+///
+/// assert_eq!(first_or_default(vec![1, 2, 3].into_iter()), 1);
+/// assert_eq!(first_or_default(Vec::<i32>::new().into_iter()), 0);
+/// ```
+///
+/// `where` is available anywhere generic and lifetime parameters are available:
+///
+/// ```rust
+/// # #![allow(dead_code)]
+/// // The Cow type from the standard library uses where to impose constraints
+/// // on its parameters.
+/// pub enum Cow<'a, B>
+/// where
+///     B: 'a + ToOwned + ?Sized,
+///  {
+///     Borrowed(&'a B),
+///     Owned(<B as ToOwned>::Owned),
+/// }
+/// ```
+///
+/// [RFC]: https://github.com/rust-lang/rfcs/blob/master/text/0135-where.md
 mod where_keyword {}
 
 // 2018 Edition keywords