I'm trying to understand why mixup() doesn't borrow it's params like the previous examples. I'm assuming that the returned Point is a completely new instance, and that self is not mutable here. Would appreciate any clarification.
Usually you'll consume self (e.g. fn mixup(self, ...)) when:
the type is either trivial and implements Copy (e.g. u32 or Point), because making a copy of the object and invoking the method can be as fast as/faster than passing around a reference, or
You want to make sure the caller can't keep using the object after calling that method (imagine some sort of DatabaseConnection::graceful_close() method).
Thanks for your time. What's throwing me here is that self was borrowed when Point was known to contain f32 values (Listing 10-10). So that seems like case #1 in your response. But then self was consumed when Point used generics (Listing 10-11). And in that case it's not clear to me whether the types in Point implement Copy.
I believe one of the fundamental differences is that in the former example, we know the fields are f32, and we know f32isCopy.
I don't think either Point is Copy, but primitive numbers always are. So in distance_from_origin, we can move self.x without owning self.
However, in the generic version, all we've declared is that T and U are some types - they may or may not be Copy. So if we want to make a new point and use self.x in it, then we have to move out of and invalidate self.x. In order to be allowed to invalidate self.x, we must own self (similar logic for other.y and owning other).
I think the book will go into more detail in this later, but this isn't exactly right. Specifically, we need to either own self or have Copy fields if we want to move our fields. In mixup, we do move our fields, so we need one of those two things.
But in another function, you might only need to borrow your field values. In this case, &self is sufficient, even if the fields are non-Copy.
For instance, we can define the following struct and method:
Since distance_from_origin is declared as &self, it only borrows self (in essence, it takes in &Point<f32>). So since PairOfPoints only need to borrow its fields, it can take &self as well.