Skip to content

Provide more explanation for Deref in String docs #43721

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 11, 2017
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions src/liballoc/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ use boxed::Box;
/// # Deref
///
/// `String`s implement [`Deref`]`<Target=str>`, 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 (`&`):
///
/// ```
Expand All @@ -160,8 +160,33 @@ 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. In the following example a string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be

`Deref`

since it's the name of a trait

/// 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 {}
///
/// impl<'a> TraitExample for &'a str {}
///
/// fn example_func<A: TraitExample>(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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line has a trailing whitespace making CI to reject the commit.

[00:03:44] tidy error: /checkout/src/liballoc/string.rs:187: trailing whitespace
[00:03:45] some tidy checks failed

/// `example_func(example_string.to_str());`. This works because we're doing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idiomatic solution is call it like this:

    example_func(&*example_string);

You dereference a String into a str, and then reference the str back to a &str.

Copy link
Member

@steveklabnik steveklabnik Aug 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think that &* is slightly more idiomatic, but it's also harder to understand. I think showing both is probably a good idea, because people will see &* in the wild.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I'll make the change. I like the idea of having both options in there, thanks!

/// the conversion explicitly, rather than relying on the implicit conversion.
///
/// # Representation
///
Expand Down