May be it was discussed somewhere, but I expect the case below (calling MyTrait::do_smth_and_make_11(self)) not to go into any recursion, but rather be a compiler error or to call the exact implementation from a trait (I prefer the latter variant, but you decide):
That doesn’t make sense because traits don’t have methods, they specify interfaces.
When you say:
trait Test {
fn test(&self) {
println!("it works!");
}
}
struct X;
impl Test for X { };
What you’re actually saying is “Implement Test on X filling in any default implementations that I don’t specify.” Basically, Test::test(x) (where x : X) means “lookup the method test in X’s implementation of the Test trait and call it on x.” This method could have either been manually defined by the programmer or “filled in” by the compiler.
To further illustrate this point, the following doesn’t work:
I think default implementation can be referred as an “abstract method”.
If this method needs self pointer to be passed inside, then user can’t call it without having a corresponding trait implementor—so I see no conflicts with “interface” or “abstract class” case. If it’s a “static” method of a trait, then I suppose it’s just a free function in some namespace, so it may freely be called.
Though, on the other hand if a trait is commonly a verb (“ability”), then probably it can not act as a true namespace (a subject), but then why it may have static methods?
Anyway, visually, when user like me reads a syntax like Trait::method, he expects some concrete method to be called, since it’s a quite precise path, similar to ones from use section. …But then user gets some unexpected SuggestedImplementor::method called instead.
So, if “call exact method” approach is not right, then I suppose this ability should be disabled completely, not to confuse end-users.
It can't. A trait can only describe static methods on implementations of the trait. Traits do not have methods; traits have method signatures and can optionally provide "suggested implementations". To quote myself:
To further illustrate this point, the following doesn't work:
Thank you, now I get it. I forgot about the existence of overlapping methods in Traits.
But then it’s a syntax question for me, still, since :: commonly used in current versions of rust to describe exact paths and reads like that to me, while this case you describe is… may be closer to… typecast?
Wouldn’t something like (d as TraitA).do_it() or (TraitA)(d).do_it() or TraitA(d).do_it() or whatever without :: and (&d) do better in this case? Or was it discussed somewhere already?
I wish the language could have an option to simplify this out: just disallow traits with the same method name+signature from being implemented on the same type;
Require library designers to collaborate on consistent method names, when their domains overlap. (I would hope traits would still allow methods of different signatures to work, e.g. the way multiparam type classes now give decent overloading, even if one trait can’t have overloads;)
This would allow closer translation to & from C++ methods. (you could always roll a C++ class that gathers trait implementations, or get further translating a C++ class into trait impls),and might be able to link identically mangled functions… and it would simplify navigation. (“where is this method”, not “what trait is this method in, where is the trait”… a double indirection in navigation)
I think I do agree with this, since the language spec tells it has no method overloading, and having the similarly-named methods in different traits is kinda creepy way of actually doing that, under cover.
An ability to reach some “default implementation” with a path and pass there an implementor instance, would be a nice feature for me, though.