You are mostly correct.
There is a neat trick to let the compiler tell you the type of variables rather than trying to infer them: let () = ...;.
Using the Playground I get for the 1st case:
9 | let () = self; | ^^ expected &Self, found ()
and for the 2nd case:
16 | let () = self; | ^^ expected &Circle, found ()
The first case is actually special, because HasArea is not a type, it's a trait.
So what is self? It's nothing yet.
Said another way, it poses for any possible concrete type that may implement HasArea. And thus the only guarantee we have about this trait is that it provides at least the interface of HasArea.
The key point is that you can place additional bounds. For example you could say:
trait HasArea: Debug { fn area(&self) -> f64; }
And in this case, Self: HasArea + Debug, meaning that self provides both the interfaces of HasArea and Debug.
The second and third cases are much easier: we know the exact concrete type for which the HasArea trait is implemented. It's Circle.
Therefore, the type of self in the fn area(&self) method is &Circle.
Note that if the type of the parameter is &Circle then it follows that in all its uses in the method it is &Circle. Rust has static typing (and no flow-dependent typing) so the type of a given binding does not change during its lifetime.
Things can get more complicated, however.
Imagine that you have two traits:
struct Segment(Point, Point); impl Segment { fn length(&self) -> f64; } trait Segmentify { fn segmentify(&self) -> Vec<Segment>; } trait HasPerimeter { fn has_perimeter(&self) -> f64; }
Then, you can implement HasPerimeter automatically for all shapes that can be broken down in a sequence of segments.
impl<T> HasPerimeter for T where T: Segmentify { // Note: there is a "functional" implementation if you prefer fn has_perimeter(&self) -> f64 { let mut total = 0.0; for s in self.segmentify() { total += s.length(); } total } }
What is the type of self here? It's &T.
What's T? Any type that implements Segmentify.
And therefore, all we know about T is that it implements Segmentify and HasPerimeter, and nothing else (we could not use println("{:?}", self); because T is not guaranteed to implement Debug).
selfandSelf.self.radiusis slightly different than the question about itself (it's about ownership andCopy). I suggest you edit it out to focus on whatselfis about here since that's the most difficult (and novel) part, whereas we already have plenty of questions about ownership.