The discuttion if the Pre-RFC: Named arguments started to drift around the topic of overloading, so I’m forking it. Even if this post would probably be a better fit in URLO, I’m posting it here since I have a question directly related with this discussion (and I didn’t wanted to break the hyperlink to the original quote).
Some context:
I think there is something that I don’t understand. Why is ADL required for overloading?
Rust doesn’t have inheritance, this means that you don’t have the Int::toString
versus Object::toString
dilemma. And Rust evaluate the methods before monomorphisation. This means that if we wanted to expose overloads in a generic types, they would have to be explicitly listed in the trait(s) of the generic types. Something like:
trait HasOverload {
fn with_overload(self: i32);
fn with_overload(self: &'static str);
}
fn do_not_compile<T: HasOverload, Value>(t: T, v: Value) {
t.with_overload(v);
}
This should not compile since Value
could be something that isn’t i32
or &'static str
and this would lead to a post-monomorphisation error. So we must restrain the set of accepted value:
enum IntOrString {
i(i32),
s(&'static str),
}
fn valid_use<T: HasOverload>(t: T, v: IntOrString) {
match v {
i(value) => with_overload(value), // call the first overload
s(value) => with_overload(value), // call the second overload
}
}
It’s obviously not very ergonomic, but some sort of delegation mechanism could make it better
fn valid_use<T: HasOverload>(t: T, v: IntOrString) {
delegate!(with_overload, value);
}
Note: I tried to make
value.with_overload()
working (with an imaginary syntax), but it’s not possible right now since the arguments could be taken by value by one overload, immutable reference by a second, and by mutable reference by a third and we currently don’t have a way to abstract over this.
There is another possible interaction with specialization. As far as I understand specialization ensure that there is a set of function that is valid pre-monomorphisation (which ensure that you can’t have post-monomorphisation errors), but select the right one only post-monomorphisation.
trait HasOverload2 {
fn with_overload<T>(self: T); // default version
fn with_overload(self: i32); // specialized version
}
fn use<T: HasOverload, Value>(t: T, v: Value) {
with_overload(42); // call the specialized version
with_overload("str"); // call the default version
with_overload(v); // if `v` is an `i32` call the specialized version of the overload, and the default version otherwise
Am I missing something, I don’t see how ADL is required in Rust, even with more allowed syntax for overloading.