diff --git a/src/doc/trpl/deref-coercions.md b/src/doc/trpl/deref-coercions.md index afacd304055..b7011100971 100644 --- a/src/doc/trpl/deref-coercions.md +++ b/src/doc/trpl/deref-coercions.md @@ -1,3 +1,119 @@ % `Deref` coercions -Coming soon! +The standard library provides a special trait, [`Deref`][deref]. It’s normally +used to overload `*`, the dereference operator: + +```rust +use std::ops::Deref; + +struct DerefExample { + value: T, +} + +impl Deref for DerefExample { + type Target = T; + + fn deref(&self) -> &T { + &self.value + } +} + +fn main() { + let x = DerefExample { value: 'a' }; + assert_eq!('a', *x); +} +``` + +[deref]: ../std/ops/trait.Deref.html + +This is useful for writing custom pointer types. However, there’s a language +feature related to `Deref`: ‘deref coercions’. Here’s the rule: If you have a +type `U`, and it implements `Deref`, values of `&U` will +automatically coerce to a `&T`. Here’s an example: + +```rust +fn foo(s: &str) { + // borrow a string for a second +} + +// String implements Deref +let owned = "Hello".to_string(); + +// therefore, this works: +foo(&owned); +``` + +Using an ampersand in front of a value takes a reference to it. So `owned` is a +`String`, `&owned` is an `&String`, and since `impl Deref for +String`, `&String` will deref to `&str`, which `foo()` takes. + +That’s it. This rule is one of the only places in which Rust does an automatic +conversion for you, but it adds a lot of flexibility. For example, the `Rc` +type implements `Deref`, so this works: + +```rust +use std::rc::Rc; + +fn foo(s: &str) { + // borrow a string for a second +} + +// String implements Deref +let owned = "Hello".to_string(); +let counted = Rc::new(owned); + +// therefore, this works: +foo(&counted); +``` + +All we’ve done is wrap our `String` in an `Rc`. But we can now pass the +`Rc` around anywhere we’d have a `String`. The signature of `foo` +didn’t change, but works just as well with either type. This example has two +conversions: `Rc` to `String` and then `String` to `&str`. Rust will do +this as many times as possible until the types match. + +Another very common implementation provided by the standard library is: + +```rust +fn foo(s: &[i32]) { + // borrow a slice for a second +} + +// Vec implements Deref +let owned = vec![1, 2, 3]; + +foo(&owned); +``` + +Vectors can `Deref` to a slice. + +## Deref and method calls + +`Deref` will also kick in when calling a method. In other words, these are +the same two things in Rust: + +```rust +struct Foo; + +impl Foo { + fn foo(&self) { println!("Foo"); } +} + +let f = Foo; + +f.foo(); +``` + +Even though `f` isn’t a reference, and `foo` takes `&self`, this works. +That’s because these things are the same: + +```rust,ignore +f.foo(); +(&f).foo(); +(&&f).foo(); +(&&&&&&&&f).foo(); +``` + +A value of type `&&&&&&&&&&&&&&&&Foo` can still have methods defined on `Foo` +called, because the compiler will insert as many * operations as necessary to +get it right. And since it’s inserting `*`s, that uses `Deref`. diff --git a/src/doc/trpl/method-syntax.md b/src/doc/trpl/method-syntax.md index 5853f3d679c..1445d39fe87 100644 --- a/src/doc/trpl/method-syntax.md +++ b/src/doc/trpl/method-syntax.md @@ -18,7 +18,7 @@ foo.bar().baz(); Luckily, as you may have guessed with the leading question, you can! Rust provides the ability to use this ‘method call syntax’ via the `impl` keyword. -## Method calls +# Method calls Here’s how it works: @@ -83,7 +83,7 @@ impl Circle { } ``` -## Chaining method calls +# Chaining method calls So, now we know how to call a method, such as `foo.bar()`. But what about our original example, `foo.bar().baz()`? This is called ‘method chaining’, and we @@ -127,7 +127,7 @@ fn grow(&self) -> Circle { We just say we’re returning a `Circle`. With this method, we can grow a new circle to any arbitrary size. -## Static methods +# Static methods You can also define methods that do not take a `self` parameter. Here’s a pattern that’s very common in Rust code: @@ -158,7 +158,7 @@ This ‘static method’ builds a new `Circle` for us. Note that static methods are called with the `Struct::method()` syntax, rather than the `ref.method()` syntax. -## Builder Pattern +# Builder Pattern Let’s say that we want our users to be able to create Circles, but we will allow them to only set the properties they care about. Otherwise, the `x`