From b298a58c782f1434b09d4aaea6bffd4f99d3e7f6 Mon Sep 17 00:00:00 2001 From: Natalie Boehm Date: Fri, 4 Aug 2017 12:25:05 -0400 Subject: [PATCH 1/4] Update String Deref to explain why using &String does not always work --- src/liballoc/string.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 622cc68964bf7..110699c1e03bd 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -144,7 +144,7 @@ use boxed::Box; /// # Deref /// /// `String`s implement [`Deref`]``, and so inherit all of [`str`]'s -/// methods. In addition, this means that you can pass a `String` to any +/// methods. In addition, this means that you can pass a `String` to a /// function which takes a [`&str`] by using an ampersand (`&`): /// /// ``` @@ -160,8 +160,31 @@ use boxed::Box; /// /// This will create a [`&str`] from the `String` and pass it in. This /// conversion is very inexpensive, and so generally, functions will accept -/// [`&str`]s as arguments unless they need a `String` for some specific reason. +/// [`&str`]s as arguments unless they need a `String` for some specific +/// reason. /// +/// In certain cases Rust doesn't have enough information to make this conversion, +/// known as deref coercion. For example, in this case a string slice implements +/// a trait and the function takes anything that implements the trait, Rust would +/// need to make two implicit conversions which Rust doesn't know how to do. The +/// following example will not compile for that reason. +/// +/// ```compile_fail,E0277 +/// trait TraitExample {} +/// +/// impl<'a> TraitExample for &'a str {} +/// +/// fn example_func(example_arg: A) {} +/// +/// fn main() { +/// let example_string = String::from("example_string"); +/// example_func(&example_string); +/// } +/// ``` +/// +/// What would work in this case is changing the line `example_func(&example_string);` +/// to `example_func(example_string.to_str());`. This works because we're doing the +/// conversion explicitly, rather than relying on the implicit conversion. /// /// # Representation /// From 2a62b91343b4de94b6cfe401e8ad9bc0414f245f Mon Sep 17 00:00:00 2001 From: Natalie Boehm Date: Mon, 7 Aug 2017 13:56:20 -0400 Subject: [PATCH 2/4] Update explanation of deref coercion --- src/liballoc/string.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 110699c1e03bd..89f3ddcd18a79 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -163,11 +163,12 @@ use boxed::Box; /// [`&str`]s as arguments unless they need a `String` for some specific /// reason. /// -/// In certain cases Rust doesn't have enough information to make this conversion, -/// known as deref coercion. For example, in this case a string slice implements -/// a trait and the function takes anything that implements the trait, Rust would -/// need to make two implicit conversions which Rust doesn't know how to do. The -/// following example will not compile for that reason. +/// In certain cases Rust doesn't have enough information to make this +/// conversion, known as deref coercion. In the following example a string +/// slice `&'a str` implements the trait `TraitExample`, and the function +/// `example_func` takes anything that implements the trait. In this case Rust +/// would need to make two implicit conversions, which Rust doesn't have the +/// means to do. For that reason, the following example will not compile. /// /// ```compile_fail,E0277 /// trait TraitExample {} @@ -182,9 +183,10 @@ use boxed::Box; /// } /// ``` /// -/// What would work in this case is changing the line `example_func(&example_string);` -/// to `example_func(example_string.to_str());`. This works because we're doing the -/// conversion explicitly, rather than relying on the implicit conversion. +/// What would work in this case is changing the line +/// `example_func(&example_string);` to +/// `example_func(example_string.to_str());`. This works because we're doing +/// the conversion explicitly, rather than relying on the implicit conversion. /// /// # Representation /// From 40f5b308bcf8024cd17b982d543695873bc9dd53 Mon Sep 17 00:00:00 2001 From: Natalie Boehm Date: Tue, 8 Aug 2017 14:57:34 -0400 Subject: [PATCH 3/4] Update solution to add using `&*` as well as `as_str()` --- src/liballoc/string.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 89f3ddcd18a79..a1f0b4f0de19d 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -183,10 +183,15 @@ use boxed::Box; /// } /// ``` /// -/// What would work in this case is changing the line -/// `example_func(&example_string);` to -/// `example_func(example_string.to_str());`. This works because we're doing -/// the conversion explicitly, rather than relying on the implicit conversion. +/// There are two options that would work instead. The first would be to +/// change the line `example_func(&example_string);` to +/// `example_func(example_string.as_str());`, using the method `as_str()` +/// to explicitly extract the string slice containing the string. The second +/// way changes `example_func(&example_string);` to +/// `example_func(&*example_string);`. In this case we are dereferencing a +/// `String` to a `str`, then referencing the `str` back to `&str`. The +/// second way is more idiomatic, however both work to do the conversion +/// explicitly rather than relying on the implicit conversion. /// /// # Representation /// From fac6ce79e54a2d5bdbdc5157c645970a479e2fb1 Mon Sep 17 00:00:00 2001 From: Natalie Boehm Date: Tue, 8 Aug 2017 16:57:11 -0400 Subject: [PATCH 4/4] Fix trait name `Deref` --- src/liballoc/string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index a1f0b4f0de19d..322b137e99f0e 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -164,7 +164,7 @@ use boxed::Box; /// reason. /// /// In certain cases Rust doesn't have enough information to make this -/// conversion, known as deref coercion. In the following example a string +/// conversion, known as `Deref` coercion. In the following example a string /// slice `&'a str` implements the trait `TraitExample`, and the function /// `example_func` takes anything that implements the trait. In this case Rust /// would need to make two implicit conversions, which Rust doesn't have the