From 837a761b398a6ff6a97f7f61e390dae9efbeab79 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Fri, 3 Jul 2020 23:49:21 +0200 Subject: [PATCH 1/3] Document the where keyword --- src/libstd/keyword_docs.rs | 137 ++++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 2 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 0b3386c05d54b..058a89772d410 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 { +/// T::default() +/// } +/// +/// fn new_where() -> 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 `` syntax: +/// +/// ```rust +/// fn first_or_default(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::::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(::Owned), +/// } +/// ``` +/// +/// [RFC]: https://github.com/rust-lang/rfcs/blob/master/text/0135-where.md mod where_keyword {} // 2018 Edition keywords From f8335fb1e4e17ae035c4553fbf15fec74d92aeb3 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Thu, 23 Jul 2020 23:19:26 +0200 Subject: [PATCH 2/3] Fix nit and add link for Cow --- src/libstd/keyword_docs.rs | 40 ++++++++------------------------------ 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 058a89772d410..55a5a290a7438 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1684,14 +1684,6 @@ mod use_keyword {} /// 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, @@ -1706,30 +1698,18 @@ mod use_keyword {} /// let outer = String::from("Long living ref"); /// let longer = &outer; /// { -/// let inner = String::from("Long living ref"); +/// let inner = String::from("Short 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. +/// that respects the constraint imposed by the `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, @@ -1742,17 +1722,14 @@ mod use_keyword {} /// # } /// let outer = String::from("Long living ref"); /// let longer = &outer; -/// let res1; -/// let res2; +/// let res; /// { -/// let inner = String::from("Long living ref"); +/// let inner = String::from("Short living ref"); /// let shorter = &inner; /// -/// res1 = select(longer, shorter, false); -/// res2 = select_where(longer, shorter, false); +/// res = select_where(longer, shorter, false); /// } -/// assert_eq!(res1, &outer); -/// assert_eq!(res2, &outer); +/// assert_eq!(res, &outer); /// ``` /// /// `where` can also be used to express more complicated constraints that cannot @@ -1771,12 +1748,11 @@ mod use_keyword {} /// assert_eq!(first_or_default(Vec::::new().into_iter()), 0); /// ``` /// -/// `where` is available anywhere generic and lifetime parameters are available: +/// `where` is available anywhere generic and lifetime parameters are available, +/// as can be seen in the [`Cow`](crate::borrow::Cow) from the standard library: /// /// ```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, From 6af60d3e2434490ed0e4a4fee40435c989753a0b Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Fri, 24 Jul 2020 19:33:52 +0200 Subject: [PATCH 3/3] Fix nits, rework the second example of select (the one deliberately failing to compile) --- src/libstd/keyword_docs.rs | 48 ++++++++++++-------------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 55a5a290a7438..2047659c73505 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -1680,19 +1680,15 @@ mod use_keyword {} /// /// `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: +/// This compiles because `longer` outlives `shorter`, thus the constraint is +/// respected: /// /// ```rust -/// fn select_where<'a, 'b>(s1: &'a str, s2: &'b str, second: bool) -> &'a str +/// fn select<'short, 'long>(s1: &'short str, s2: &'long str, second: bool) -> &'short str /// where -/// 'b: 'a, +/// 'long: 'short, /// { -/// if second { -/// s2 -/// } else { -/// s1 -/// } +/// if second { s2 } else { s1 } /// } /// /// let outer = String::from("Long living ref"); @@ -1701,35 +1697,20 @@ mod use_keyword {} /// let inner = String::from("Short living ref"); /// let shorter = &inner; /// -/// assert_eq!(select_where(shorter, longer, false), shorter); -/// assert_eq!(select_where(shorter, longer, true), longer); +/// assert_eq!(select(shorter, longer, false), shorter); +/// assert_eq!(select(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_where` functions. +/// On the other hand, this will not compile because the `where 'b: 'a` clause +/// is missing: the `'b` lifetime is not known to live at least as long as `'a` +/// which means this function cannot ensure it always returns a valid reference: /// -/// ```rust,compile_fail,E0597 -/// # 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 res; +/// ```rust,compile_fail,E0623 +/// fn select<'a, 'b>(s1: &'a str, s2: &'b str, second: bool) -> &'a str /// { -/// let inner = String::from("Short living ref"); -/// let shorter = &inner; -/// -/// res = select_where(longer, shorter, false); +/// if second { s2 } else { s1 } /// } -/// assert_eq!(res, &outer); /// ``` /// /// `where` can also be used to express more complicated constraints that cannot @@ -1749,7 +1730,8 @@ mod use_keyword {} /// ``` /// /// `where` is available anywhere generic and lifetime parameters are available, -/// as can be seen in the [`Cow`](crate::borrow::Cow) from the standard library: +/// as can be seen with the [`Cow`](crate::borrow::Cow) type from the standard +/// library: /// /// ```rust /// # #![allow(dead_code)]