I'm reading Rust Programming book. in Chapter 17 i can not understand this:
self: Box<Self>
You can easily explain?
First, let's give a bit of a context, as described in the book:
trait State {
fn request_review(self: Box<Self>) -> Box<dyn State>;
}
A bit further below in the book, it's explained:
We’ve added the request_review method to the State trait; all types that implement the trait will now need to implement the request_review method. Note that rather than having self, &self, or &mut self as the first parameter of the method, we have self: Box<Self>. This syntax means the method is only valid when called on a Box holding the type. This syntax takes ownership of Box<Self>, invalidating the old state so the state value of the Post can transform into a new state.
Let me give you an example. Say we have a struct A that implements State:
struct A {}
impl State for A {
fn request_review(self: Box<Self>) -> Box<dyn State> {
todo!();
}
}
If we tried this code:
let a = A {};
a.request_review();
, we would get a compiler error. However, if we tried the code below, there would be no problem:
let a = A {};
Box::new(a).request_review();
Related
I was writing some code and had a trait with a method that takes self by value. I want to call this method on a Box'd trait object (consuming the Box and its value). Is this possible? If so, how?
In terms of code, a minimal example looks like the following (incomplete) code:
trait Consumable {
fn consume(self) -> u64;
}
fn consume_box(ptr: Box<dyn Consumable>) -> u64 {
//what can I put here?
}
My question is how to fill in the function consume_box with the specified signature so that the value returned is whatever value would be gotten by calling consume on the Box'd value.
I had initially written
ptr.consume()
as the body of the function, though I realize this isn't quite the right idea, since it doesn't get across the fact that I want the Box to be consumed, not just its contents, but it's the only thing I could think of. This does not compile, giving an error:
cannot move a value of type dyn Consumable: the size of dyn Consumable cannot be statically determined
This was somewhat surprising to me, being new to Rust, I had thought that maybe the self argument was passed similarly to an rvalue reference in C++ (which is really what I want - in C++, I would probably implement this by a method with the signature virtual std::uint64_t consume() &&, letting a std::unique_ptr clean up the moved-from object via a virtual destructor), but I guess Rust is truly passing by value, moving the argument into place prior - so it's reasonable that it rejects the code.
Trouble is, I'm not sure how to get the behavior I want, where I can consume a Box'd trait object. I tried adding a method to the trait with a default implementation, thinking that might get me something useful in the vtable:
trait Consumable {
fn consume(self) -> u64;
fn consume_box(me: Box<Self>) -> u64 {
me.consume()
}
}
However, this then yields the error
the trait Consumable cannot be made into an object
when I mention the Box<dyn Consumable> type - which is not so surprising, since the compiler figuring out what to do with a function whose argument type varied with Self would have been miraculous.
Is it possible to implement the function consume_box with the provided signature - even modifying the trait if necessary?
If it's useful, more specifically, this is part of a sort of representation of some mathematical expressions - maybe a toy model would be that specific implementations that look roughly like:
impl Consumable for u64 {
fn consume(self) -> u64 {
self
}
}
struct Sum<A, B>(A, B);
impl<A: Consumable, B: Consumable> Consumable for Sum<A, B> {
fn consume(self) -> u64 {
self.0.consume() + self.1.consume()
}
}
struct Product<A, B>(A, B);
impl<A: Consumable, B: Consumable> Consumable for Product<A, B> {
fn consume(self) -> u64 {
self.0.consume() * self.1.consume()
}
}
fn parse(&str) -> Option<Box<dyn Consumable> > {
//do fancy stuff
}
where, for the most part, things are plain old data (but arbitrarily large blocks of it, potentially, due to the generics), but to also have this be compatible with passing around more opaque handles to these sorts of things - hence the desire to be able to work with Box<dyn Consumable>. At least at the language level, this is a good model of what sort of things I'm up to - the only resources owned by these objects are pieces of memory (nothing to do with multithreading and no self-referential shenanigans) - although this model doesn't capture that the use case I have is one where it's useful for the implementation to consume the object rather than to merely read it nor does it appropriately model that I want an "open" class of possible segments rather than a finite set of possiblities (making it hard to do something like an enum that represents a tree directly) - hence why I'm asking about passing by value rather than trying to rewrite it to pass by reference.
You can consume from a Box<dyn Trait> if the parameter is self: Box<Self>:
trait Consumable {
fn consume(self) -> u64;
fn consume_box(self: Box<Self>) -> u64;
}
struct Foo;
impl Consumable for Foo {
fn consume(self) -> u64 {
42
}
fn consume_box(self: Box<Self>) -> u64 {
self.consume()
}
}
fn main() {
let ptr: Box<dyn Consumable> = Box::new(Foo);
println!("result is {}", ptr.consume_box());
}
However, this does have the annoying boilerplate of having to implement consume_box() for each implementation; trying to define a default implementation will run into a "cannot move value of type Self - the size of Self cannot be statically determined" error.
In general though this is not supported. A dyn Consumable represents an unsized type which are very limited except through indirection (via references or Box-like structs). It works for the above case because Box is a bit special (is the only dispatchable type you can take ownership from) and the consume_box method does not put self on the stack as a dynamic trait object (only in each implementation where its concrete).
However there is RFC 1909: Unsized RValues which hopes to loosen some of these limits. One being able to pass unsized function parameters, like self in this case. The current implementation of this RFC accepts your initial code when compiled on nightly with unsized_fn_params:
#![feature(unsized_fn_params)]
trait Consumable {
fn consume(self) -> u64;
}
struct Foo;
impl Consumable for Foo {
fn consume(self) -> u64 {
42
}
}
fn main () {
let ptr: Box<dyn Consumable> = Box::new(Foo);
println!("result is {}", ptr.consume());
}
See on the playground.
I believe
trait Consumable {
fn consume(self) -> u64;
}
fn consume_box(val: impl Consumable) -> u64 {
val.consume()
}
might do what you want. I'm all but a Rust expert - or C++ expert for that matter -, but I think it should be working pretty much like the move-semantics in C++ you mentioned in terms of memory behavior. From what I understand it is a form of generic where Rust implements the Function for every type you call it with.
If you don't use nightly Rust, I wrote a macro here. It generates the second trait function automatically.
trait Consumable {
fn consume(self) -> u64;
fn consume_box(me: Box<Self>) -> u64 ;
}
I've got this code snippet (playground):
struct TeddyBear {
fluffiness: u8,
}
trait Scruffy {
fn scruff_up(self: &mut Box<Self>) -> Box<dyn Scruffy>;
}
impl Scruffy for TeddyBear {
fn scruff_up(self: &mut Box<Self>) -> Box<dyn Scruffy> {
// do something about the TeddyBear's fluffiness
}
}
It doesn't compile. The error is:
the trait Scruffy cannot be made into an object
, along with the hint:
because method scruff_up's self parameter cannot be dispatched on.
I checked the "E0038" error description, but I haven't been able to figure out which category my error falls into.
I also read the "object-safety" entry in "The Rust Reference", and I believe this matches the "All associated functions must either be dispatchable from a trait object", but I'm not sure, partly because I'm not sure what "receiver" means in that context.
Can you please clarify for me what's the problem with this code and why it doesn't work?
The problem is when you pass it in as a reference, because the inner type may not be well-sized (e.g. a trait object, like if you passed in a Box<Fluffy>) the compiler doesn't have enough information to figure out how to call methods on it. If you restrict it to sized objects (like your TeddyBear) it should compile
trait Scruffy {
fn scruff_up(self: &mut Box<Self>) -> Box<dyn Scruffy> where Self: Sized;
}
A receiver is the self (&self, &mut self, self: &mut Box<Self> and so on).
Note that the list you cited from the reference lists both Box<Self> and &mut Self, but does not list &mut Box<Self> nor it says that combinations of these types are allowed.
This is, indeed, forbidden. As for the why, it is a little more complex.
In order for a type to be a valid receiver, it needs to hold the following condition:
Given any type Self that implements Trait and the receiver type Receiver, the receiver type should implement DispatchFromDyn<dyn Trait> for itself with all Self occurrences of Self replaced with dyn Trait.
For instance:
&self (has the type &Self) has to implement DispatchFromDyn<&dyn Trait>, which it does.
Box<Self> has to implement DispatchFromDyn<Box<dyn Trait>>, which it does.
But in order for &mut Box<Self> to be an object-safe receiver, it would need to impl DispatchFromDyn<&mut Box<dyn Trait>>. What you want is kind of blanket implementation DispatchFromDyn<&mut T> for &mut U where U: DispatchFromDyn<T>.
This impl will never exist. Because it is unsound (even ignoring coherence problems).
As explained in the code in rustc that calculates this:
The only case where the receiver is not dispatchable, but is still a valid receiver type (just not object-safe), is when there is more than one level of pointer indirection. E.g., self: &&Self, self: &Rc<Self>, self: Box<Box<Self>>. In these cases, there is no way, or at least no inexpensive way, to coerce the receiver from the version where Self = dyn Trait to the version where Self = T, where T is the unknown erased type contained by the trait object, because the object that needs to be coerced is behind a pointer.
The problem is inherent to how Rust handles dyn Trait.
dyn Trait is a fat pointer: it is actually two words sized. One is a pointer to the data, and the other is a pointer to the vtable.
When you call a method on dyn Trait, the compiler looks up in the vtable, find the method for the concrete type (which is unknown at compilation time, but known at runtime), and calls it.
This all may be very abstract without an example:
trait Trait {
fn foo(&self);
}
impl Trait for () {
fn foo(&self) {}
}
fn call_foo(v: &dyn Trait) {
v.foo();
}
fn create_dyn_trait(v: &impl Trait) {
let v: &dyn Trait = v;
call_foo(v);
}
The compiler generates code like:
trait Trait {
fn foo(&self);
}
impl Trait for () {
fn foo(&self) {}
}
struct TraitVTable {
foo: fn(*const ()),
}
static TRAIT_FOR_UNIT_VTABLE: TraitVTable = TraitVTable {
foo: unsafe { std::mem::transmute(<() as Trait>::foo) },
};
type DynTraitRef = (*const (), &'static TraitVTable);
impl Trait for dyn Trait {
fn foo(self: DynTraitRef) {
(self.1.foo)(self.0)
}
}
fn call_foo(v: DynTraitRef) {
v.foo();
}
fn create_dyn_trait(v: &impl Trait) {
let v: DynTraitRef = (v as *const (), &TRAIT_FOR_UNIT_VTABLE);
call_foo(v);
}
Now suppose that the pointer to the value is behind an indirection. I'll use Box<&self> because it's simple but demonstrates the concept best, but the concept applies to &mut Box<Self> too: they have the same layout. How will we write foo() for impl Trait for dyn Trait?
trait Trait {
fn foo(self: Box<&Self>);
}
impl Trait for () {
fn foo(self: Box<&Self>) {}
}
struct TraitVTable {
foo: fn(Box<*const ()>),
}
static TRAIT_FOR_UNIT_VTABLE: TraitVTable = TraitVTable {
foo: unsafe { std::mem::transmute(<() as Trait>::foo) },
};
type DynTraitRef = (*const (), &'static TraitVTable);
impl Trait for dyn Trait {
fn foo(self: Box<DynTraitRef>) {
let concrete_foo: fn(Box<*const ()>) = self.1.foo;
let data: *const () = self.0;
concrete_foo(data) // We need to wrap `data` in `Box`! Error.
}
}
You may think "then the compiler should just insert a call to Box::new()!" But besides Box not being the only one here (what with Rc, for example?) and we will need some trait to abstract over this behavior, Rust never performs any hard work implicitly. This is a design choice, and an important one (as opposed to e.g. C++, where an innocent-looking statement like auto v1 = v; can allocate and copy 10GB by a copy constructor). Converting a type to dyn Trait and back is done implicitly: the first one by a coercion, the second one when you call a method of the trait. Thus, the only thing that Rust does for that is attaching a VTable pointer in the first case, or discarding it in the second case. Even allowing only references (&&&Self, no need to call a method, just take the address of a temporary) exceeds that. And it can have severe implications in unexpected places, e.g. register allocation.
So, what to do? You can take &mut self or self: Box<Self>. Which one to choose depends on whether you need ownership (use Box) or not (use a reference). And anyway, &mut Box<Self> is not so useful (its only advantage over &mut T is that you can replace the box and not just its contents, but when you do that that's usually a mistake).
I was writing some code and had a trait with a method that takes self by value. I want to call this method on a Box'd trait object (consuming the Box and its value). Is this possible? If so, how?
In terms of code, a minimal example looks like the following (incomplete) code:
trait Consumable {
fn consume(self) -> u64;
}
fn consume_box(ptr: Box<dyn Consumable>) -> u64 {
//what can I put here?
}
My question is how to fill in the function consume_box with the specified signature so that the value returned is whatever value would be gotten by calling consume on the Box'd value.
I had initially written
ptr.consume()
as the body of the function, though I realize this isn't quite the right idea, since it doesn't get across the fact that I want the Box to be consumed, not just its contents, but it's the only thing I could think of. This does not compile, giving an error:
cannot move a value of type dyn Consumable: the size of dyn Consumable cannot be statically determined
This was somewhat surprising to me, being new to Rust, I had thought that maybe the self argument was passed similarly to an rvalue reference in C++ (which is really what I want - in C++, I would probably implement this by a method with the signature virtual std::uint64_t consume() &&, letting a std::unique_ptr clean up the moved-from object via a virtual destructor), but I guess Rust is truly passing by value, moving the argument into place prior - so it's reasonable that it rejects the code.
Trouble is, I'm not sure how to get the behavior I want, where I can consume a Box'd trait object. I tried adding a method to the trait with a default implementation, thinking that might get me something useful in the vtable:
trait Consumable {
fn consume(self) -> u64;
fn consume_box(me: Box<Self>) -> u64 {
me.consume()
}
}
However, this then yields the error
the trait Consumable cannot be made into an object
when I mention the Box<dyn Consumable> type - which is not so surprising, since the compiler figuring out what to do with a function whose argument type varied with Self would have been miraculous.
Is it possible to implement the function consume_box with the provided signature - even modifying the trait if necessary?
If it's useful, more specifically, this is part of a sort of representation of some mathematical expressions - maybe a toy model would be that specific implementations that look roughly like:
impl Consumable for u64 {
fn consume(self) -> u64 {
self
}
}
struct Sum<A, B>(A, B);
impl<A: Consumable, B: Consumable> Consumable for Sum<A, B> {
fn consume(self) -> u64 {
self.0.consume() + self.1.consume()
}
}
struct Product<A, B>(A, B);
impl<A: Consumable, B: Consumable> Consumable for Product<A, B> {
fn consume(self) -> u64 {
self.0.consume() * self.1.consume()
}
}
fn parse(&str) -> Option<Box<dyn Consumable> > {
//do fancy stuff
}
where, for the most part, things are plain old data (but arbitrarily large blocks of it, potentially, due to the generics), but to also have this be compatible with passing around more opaque handles to these sorts of things - hence the desire to be able to work with Box<dyn Consumable>. At least at the language level, this is a good model of what sort of things I'm up to - the only resources owned by these objects are pieces of memory (nothing to do with multithreading and no self-referential shenanigans) - although this model doesn't capture that the use case I have is one where it's useful for the implementation to consume the object rather than to merely read it nor does it appropriately model that I want an "open" class of possible segments rather than a finite set of possiblities (making it hard to do something like an enum that represents a tree directly) - hence why I'm asking about passing by value rather than trying to rewrite it to pass by reference.
You can consume from a Box<dyn Trait> if the parameter is self: Box<Self>:
trait Consumable {
fn consume(self) -> u64;
fn consume_box(self: Box<Self>) -> u64;
}
struct Foo;
impl Consumable for Foo {
fn consume(self) -> u64 {
42
}
fn consume_box(self: Box<Self>) -> u64 {
self.consume()
}
}
fn main() {
let ptr: Box<dyn Consumable> = Box::new(Foo);
println!("result is {}", ptr.consume_box());
}
However, this does have the annoying boilerplate of having to implement consume_box() for each implementation; trying to define a default implementation will run into a "cannot move value of type Self - the size of Self cannot be statically determined" error.
In general though this is not supported. A dyn Consumable represents an unsized type which are very limited except through indirection (via references or Box-like structs). It works for the above case because Box is a bit special (is the only dispatchable type you can take ownership from) and the consume_box method does not put self on the stack as a dynamic trait object (only in each implementation where its concrete).
However there is RFC 1909: Unsized RValues which hopes to loosen some of these limits. One being able to pass unsized function parameters, like self in this case. The current implementation of this RFC accepts your initial code when compiled on nightly with unsized_fn_params:
#![feature(unsized_fn_params)]
trait Consumable {
fn consume(self) -> u64;
}
struct Foo;
impl Consumable for Foo {
fn consume(self) -> u64 {
42
}
}
fn main () {
let ptr: Box<dyn Consumable> = Box::new(Foo);
println!("result is {}", ptr.consume());
}
See on the playground.
I believe
trait Consumable {
fn consume(self) -> u64;
}
fn consume_box(val: impl Consumable) -> u64 {
val.consume()
}
might do what you want. I'm all but a Rust expert - or C++ expert for that matter -, but I think it should be working pretty much like the move-semantics in C++ you mentioned in terms of memory behavior. From what I understand it is a form of generic where Rust implements the Function for every type you call it with.
If you don't use nightly Rust, I wrote a macro here. It generates the second trait function automatically.
trait Consumable {
fn consume(self) -> u64;
fn consume_box(me: Box<Self>) -> u64 ;
}
This question already has answers here:
Why doesn't Rust support trait object upcasting?
(5 answers)
Can I cast between two traits?
(5 answers)
How do I convert a Vec<T> to a Vec<U> without copying the vector?
(2 answers)
Closed 2 years ago.
I've tried this post using the AsBase trait but couldn't quite get to a minimal example. And since that post is a bit old, the lack of dyn sometimes gets a bit confusing.
This is what I thought I could do:
trait Entity {}
trait Part: Entity {}
trait System {
fn parts(&self) -> &Vec<Box<dyn Entity>>; // This is the specification
}
struct System32 {
parts: Vec<Box<dyn Part>>, // But this is what I have
}
impl System for System32 {
fn parts(&self) -> &Vec<Box<dyn Entity>> {
&self.parts // error: expected trait Entity, found trait Part
// I've also tried:
// &self.parts as &Vec<Box<dyn Entity>>
// error: an `as` expression can only be used to convert between
// primitive types or to coerce to a specific trait object
}
}
Is this even possible? If yes, then how can I do the type conversion?
Is this even possible?
No.
There are two issues with it: first, Rust is not an inheritance-based language, trait B: A means "B requires A" more than "B extends A".
Now although this is probably not how Rust's trait should be thought of, there are ways to perform this "upcasting" regardless, and the language may eventually include this feature (in part for multi-trait objects).
However there is a bigger issue here: you're returning an &Vec.
This means that vector has to be owned by something as you're only returning a reference to it. But a Box<dyn Entity> and a Box<dyn Part> are completely different values.
Going back to Rust not being inheritance-based, the vtable for B does not embed the vtable for A, you can't just say "this is now a pointer to an A" because it absolutely is not[0].
This means going from Box<dyn Part> to Box<dyn Entity> is a full value conversion, not an in-place reinterpretation of the value as a different type.
Which means a new Box, and a new Vec, which means you can't just return a reference to an existing Vec claiming it's the type you want, the contents of the Vec itself need to change.
[0] unlike C++ I believe, at least for SI cases, with MI you'd have one of the parents be a simple reinterpretation but the others would have to offset the child pointer to get the correct vtable even if they're embedded, so I think you'd have the same issue
Masklinn above explained why you cannot do what you wanted to do.
I'm going here to try to provide an approach that would work for solving your problem using an approach similar to yours. Maybe there are better approaches though, could we see the bigger picture.
One way to achieve your pattern would be to have the type of entity your system manages be an associated type of your System trait. This enables you to write the following:
trait Entity {
fn do_something(&self) {}
}
trait Part: Entity {}
trait System {
type Entity: Entity + ?Sized;
// I renamed this function from "parts" to "entities" because it seems that's what you want it to return
fn entities(&self) -> &Vec<Box<Self::Entity>>; // This is the specification
fn do_something_with_entities(&self) {
for entity in self.entities() {
entity.do_something();
}
}
}
struct System32 {
parts: Vec<Box<dyn Part>>, // But this is what I have
}
impl System for System32 {
type Entity = dyn Part;
fn entities(&self) -> &Vec<Box<Self::Entity>> {
&self.parts
}
}
Now if you reaally need to be able to return some form of collection that outputs only actual dyn Entity because e.g. your system manages different types of what would be InnerEntity... well given the amount of dirty tricks I had to use I strongly beleive that is not idiomatic Rust, and you should probably express the whole problem so people can suggest more idiomatic solutions than trying to do inheritance in Rust, but in any case, this compilation of dirty stuff that eventually provides a reasonable interface with zero allocations was pretty fun to write.
// ------ TRAIT SYSTEM
// From https://users.rust-lang.org/t/casting-traitobject-to-super-trait/33524/16
// This intermediate trait allows to work around Sized/?Sized requirements
pub trait IntoSuper<Super: ?Sized> {
fn as_super(&self) -> &Super;
fn as_super_mut(&mut self) -> &mut Super;
fn into_super(self: Box<Self>) -> Box<Super>;
}
trait Entity {}
impl<'a, T: 'a + Entity> IntoSuper<dyn Entity + 'a> for T {
fn as_super(&self) -> &(dyn Entity + 'a) {
self
}
fn as_super_mut(&mut self) -> &mut (dyn Entity + 'a) {
self
}
fn into_super(self: Box<Self>) -> Box<dyn Entity + 'a> {
self
}
}
trait Part: Entity + IntoSuper<dyn Entity> {}
// The 'r lifetime needs to be at the trait level because GATs are not stable yet
// https://github.com/rust-lang/rust/issues/44265
// This workaround somewhat simulates GATs
trait System: for<'r> SystemInner<'r> {}
impl<T: for<'r> SystemInner<'r>> System for T {}
trait SystemInner<'r> {
/// Clone should be inexpensive
type EntitiesIter: Iterator<Item = &'r dyn Entity> + ExactSizeIterator + Clone + 'r;
fn entities(&'r self) -> Self::EntitiesIter; // This is the specification
}
type EntitiesIter<'r, Source> =
std::iter::Map<std::slice::Iter<'r, Box<Source>>, fn(&'r Box<Source>) -> &'r dyn Entity>;
// ------ END OF TRAIT SYSTEM
struct System32 {
parts: Vec<Box<dyn Part>>, // And this is what you have stored
}
impl<'r> SystemInner<'r> for System32 {
type EntitiesIter = EntitiesIter<'r, dyn Part>;
fn entities(&'r self) -> Self::EntitiesIter {
self.parts.iter().map(|p| p.as_super())
}
}
// System32 implements System because it implements SystemInner<'r> for every 'r
struct SomePart;
impl Entity for SomePart {}
impl Part for SomePart {}
fn main() {
let system = System32 {
parts: vec![Box::new(SomePart), Box::new(SomePart)],
};
let second_part: &dyn Entity = system.entities().nth(1).expect("We put two parts in our vec");
for part_as_dyn_entity in system.entities() {
// do stuff
}
}
I haven't come across Self in the documentation, only in the source code. The documentation only uses self.
Self is the type of the current object. It may appear either in a trait or an impl, but appears most often in trait where it is a stand-in for whatever type will end up implementing the trait (which is unknown when defining the trait):
trait Clone {
fn clone(&self) -> Self;
}
If I then implement Clone:
impl Clone for MyType {
// I can use either the concrete type (known here)
fn clone(&self) -> MyType;
// Or I can use Self again, it's shorter after all!
fn clone(&self) -> Self;
}
I could also use it in a regular impl if I am lazy (it's shorter!):
impl MySuperLongType {
fn new(a: u32) -> Self { ... }
}
self is the name used in a trait or an impl for the first argument of a method. Using another name is possible, however there is a notable difference:
if using self, the function introduced is a method
if using any other name, the function introduced is an associated function
In Rust, there is no implicit this argument passed to a type's methods: you have to explicitly pass the "current object" as a method parameter. This would result in:
impl MyType {
fn doit(this: &MyType, a: u32) { ... }
}
As we have seen, as a shorter form this could also be (still verbose):
impl MyType {
fn doit(this: &Self, a: u32) { ... }
}
Which is actually what &self boils down to under the covers.
impl MyType {
fn doit(&self, a: u32) { ... }
}
Thus the correspondence table:
self => self: Self
&self => self: &Self
&mut self => self: &mut Self
The way to invoke those functions change, however:
impl MyType {
fn doit(&self, a: u32) {
// ...
}
fn another(this: &Self, a: u32) {
// ...
}
}
fn main() {
let m = MyType;
// Both can be used as an associated function
MyType::doit(&m, 1);
MyType::another(&m, 2);
// But only `doit` can be used in method position
m.doit(3); // OK: `m` is automatically borrowed
m.another(4); // ERROR: no method named `another`
}
self when used as first method argument, is a shorthand for self: Self. There are also &self, which is equivalent to self: &Self, and &mut self, which is equivalent to self: &mut Self.
Self in method arguments is syntactic sugar for the receiving type of the method (i.e. the type whose impl this method is in). This also allows for generic types without too much repetition.
Self refers to the current type that implements a trait, self on the other hand refers to the instance.
Having self as the first parameter is how rust defines methods. It is just a convention that converts a function into a method, much like in python. Functionally, self is analogous to this in JavaScript.
For those who don't know the difference between a function and a method, methods are functions that are attached to an instance and invoked via that instance.
Self is a generic type and that is why it is not allowed in any position that requires a concrete type. This is commonly referred to as being object safe in rust docs.
Self is also used in method definitions inside an impl block so that when you rename the type during a refactoring, you don't have to go through every method and fixed them.
In Rust, self is also used in module resolution which refers to the current module. Here, it imports the io module:
use std::io::{self, Read};