While trying to understand the Any
trait better, I saw that it has an impl
block for the trait itself. I don't understand the purpose of this construct, or even if it has a specific name.
I made a little experiment with both a "normal" trait method and a method defined in the impl
block:
trait Foo {
fn foo_in_trait(&self) {
println!("in foo")
}
}
impl dyn Foo {
fn foo_in_impl(&self) {
println!("in impl")
}
}
impl Foo for u8 {}
fn main() {
let x = Box::new(42u8) as Box<dyn Foo>;
x.foo_in_trait();
x.foo_in_impl();
let y = &42u8 as &dyn Foo;
y.foo_in_trait();
y.foo_in_impl(); // May cause an error, see below
}
Editor's note
In versions of Rust up to and including Rust 1.15.0, the line
y.foo_in_impl()
causes the error:error: borrowed value does not live long enough --> src/main.rs:20:14 | 20 | let y = &42u8 as &Foo; | ^^^^ does not live long enough ... 23 | } | - temporary value only lives until here | = note: borrowed value must be valid for the static lifetime...
This error is no longer present in subsequent versions, but the concepts explained in the answers are still valid.
From this limited experiment, it seems like methods defined in the impl
block are more restrictive than methods defined in the trait
block. It's likely that there's something extra that doing it this way unlocks, but I just don't know what it is yet! ^_^
The sections from The Rust Programming Language on traits and trait objects don't make any mention of this. Searching the Rust source itself, it seems like only Any
and Error
use this particular feature. I've not seen this used in the handful of crates where I have looked at the source code.
Self
in the trait block isFoo
andSelf
in theimpl
block isFoo + 'static
... – Lukas Kalbertodt