Skip to content

Commit bbceeed

Browse files
authored
Rollup merge of rust-lang#43721 - natboehm:patch-1, r=steveklabnik
Provide more explanation for Deref in String docs While working on a different project I encountered a point of confusion where using `&String` to dereference a `String` into `&str` did not compile. I found the explanation of [String Deref](https://doc.rust-lang.org/std/string/struct.String.html#deref), thought that it matched what I was trying to do, and was confused as to why my program did not compile when the docs stated that it would work with 'any function which takes a `&str`'. At the bottom it is mentioned that this will 'generally' work, unless `String` is needed, but I found this statement confusing based on the previous claim of 'any'. Looking further into the docs I was able to find the function `as_str()` that works instead. I thought it might be helpful to mention here deref coercion, an instance in which using `&String` does not work, to explain why it does not work, then direct users to a different option that should work in this instance. A user casually skimming the page will likely come to this explanation first, then find `as_str()` later, but be no the wiser as to what potentially went wrong. r? @steveklabnik
2 parents 6da6697 + fac6ce7 commit bbceeed

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

Diff for: src/liballoc/string.rs

+32-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ use boxed::Box;
144144
/// # Deref
145145
///
146146
/// `String`s implement [`Deref`]`<Target=str>`, and so inherit all of [`str`]'s
147-
/// methods. In addition, this means that you can pass a `String` to any
147+
/// methods. In addition, this means that you can pass a `String` to a
148148
/// function which takes a [`&str`] by using an ampersand (`&`):
149149
///
150150
/// ```
@@ -160,8 +160,38 @@ use boxed::Box;
160160
///
161161
/// This will create a [`&str`] from the `String` and pass it in. This
162162
/// conversion is very inexpensive, and so generally, functions will accept
163-
/// [`&str`]s as arguments unless they need a `String` for some specific reason.
163+
/// [`&str`]s as arguments unless they need a `String` for some specific
164+
/// reason.
164165
///
166+
/// In certain cases Rust doesn't have enough information to make this
167+
/// conversion, known as `Deref` coercion. In the following example a string
168+
/// slice `&'a str` implements the trait `TraitExample`, and the function
169+
/// `example_func` takes anything that implements the trait. In this case Rust
170+
/// would need to make two implicit conversions, which Rust doesn't have the
171+
/// means to do. For that reason, the following example will not compile.
172+
///
173+
/// ```compile_fail,E0277
174+
/// trait TraitExample {}
175+
///
176+
/// impl<'a> TraitExample for &'a str {}
177+
///
178+
/// fn example_func<A: TraitExample>(example_arg: A) {}
179+
///
180+
/// fn main() {
181+
/// let example_string = String::from("example_string");
182+
/// example_func(&example_string);
183+
/// }
184+
/// ```
185+
///
186+
/// There are two options that would work instead. The first would be to
187+
/// change the line `example_func(&example_string);` to
188+
/// `example_func(example_string.as_str());`, using the method `as_str()`
189+
/// to explicitly extract the string slice containing the string. The second
190+
/// way changes `example_func(&example_string);` to
191+
/// `example_func(&*example_string);`. In this case we are dereferencing a
192+
/// `String` to a `str`, then referencing the `str` back to `&str`. The
193+
/// second way is more idiomatic, however both work to do the conversion
194+
/// explicitly rather than relying on the implicit conversion.
165195
///
166196
/// # Representation
167197
///

0 commit comments

Comments
 (0)