I've seen a few instances of this sort of pattern in Rust code:
trait Task {
fn run(self: Box<Self>) -> i32;
}
struct SomeTask {}
impl Task for SomeTask {
fn run(self: Box<SomeTask>) -> i32 {
1
}
}
fn main() {
let task: Box<Task> = Box::new(SomeTask {});
task.run();
}
Now... I understand the intent of this code, it's a trait that implements the self consuming pattern:
fn foo(self);
Ok... but what?
You can qualify self as something other than Self
? Are there other things self can be, other than Self
, &Self
, &mut Self
and, apparently Box<Self>
?
Why does this feature exist, given you can already do this without it:
trait Runnable {
fn run(self) -> i32;
}
trait Task {
fn value(&self) -> i32;
}
struct SomeTask {}
impl Runnable for Box<Task> {
fn run(self: Box<Task>) -> i32 {
self.value()
}
}
impl Task for SomeTask {
fn value(&self) -> i32 {
1
}
}
fn main() {
let s: Box<Task> = Box::new(SomeTask {});
s.run();
}
It feels a little bit like this is left-over cruft from missing box foo
syntax, where they really wanted to allow fn foo(box self)
, but it was inconsistent without box syntax existing in the first place... but I still don't understand what the functional purpose of this receiver type is.
(Edit, since the related question is ancient and doesn't specifically answer the question. See https://github.com/rust-lang/rust/issues/44874 for the ongoing discussion around this issue; tldr: Apparently arbitrary receiver types are a thing, and they're on the way but not stable yet)