> Do you mean single-method traits?
No, the pointer to vtable can point to a struct value containing multiple function pointers.
> if that’s a really common need you could have a generic wrapper rather than a specific one (like Reverse).
The way I see generic wrappers, it's not the integer that's reversed, but the data structure defined over it, and requiring wrapping/unwrapping reversed integers/etc. is ceremony in the wrong location. With specific wrappers, you could argue it often has semantic significance representing how your specific type isn't just a regular integer, but a Uid or such.
> Your complaint about ad-hoc comparator seems odd as your method would essentially require always doing that, unless I’m misunderstanding what you mean.
My change to Rust would make all trait-bounded generic functions consistently allow supplying a trait implementation separate from the underlying type, effectively transforming this pattern from an ad-hoc change to a language construct more flexible than globally coherent traits. From there on, you could layer on optional ergonomic improvements, like implicit trait implementations or optional default traits (while keeping the first-class ability to supply any trait implementation desired).
Is the idea practical? Maybe. Currently structs can't supply default field values, even though traits can supply default methods. But the hard part is that default trait methods are effectively templates, not functions:
trait A {
fn f() -> i32;
fn g() -> i32 {
Self::f()
}
}
struct T1;
impl A for T1 {
fn f() -> i32 {
1
}
}
struct T2;
impl A for T2 {
fn f() -> i32 {
2
}
}
To preserve the current semantics (a debatable goal), instead of building method table structs out of free functions (the most minimal and elegant implementation, though less ergonomic) like `static T1_A = A<T1>{...}`, you'd still have to keep a compromise syntax of some sort, closer to current `impl` but allowing you to optionally specify a name for the impl.
Another issue to be addressed is that global coherence can serve as a lint against accidentally implementing the same trait twice for a type (as opposed to deliberately providing two different implementations with different names the user can select.)