The documentation for Add
gives the following example:
use std::ops::Add;
#[derive(Debug, PartialEq)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
Why did the author of the docs use Self
here, instead of mentioning Point
by name? Is there a technical difference, or is it purely for style points?
There are two main reasons:
Self
is shorter than MyType
or SomeOtherType
and especially ThisTypeWithGenerics<'a, 'b, A, String>
.Is there a technical difference
Yes and no, depending on how you look at it. Self
is the type that has been "completely filled in" with regards to generics. This is relevant in cases like this:
struct Container<T>(T);
impl<T> Container<T> {
fn replace<U>(self, new: U) -> Self {
Container(new)
}
}
error[E0308]: mismatched types
--> src/lib.rs:5:19
|
3 | impl<T> Container<T> {
| - expected type parameter
4 | fn replace<U>(self, new: U) -> Self {
| - found type parameter
5 | Container(new)
| ^^^ expected type parameter `T`, found type parameter `U`
|
= note: expected type parameter `T`
found type parameter `U`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
Self
is the complete type Container<T>
, not the type constructor Container
. This can cause hard-to-understand errors.
See also: