There probably isn’t much about it explicitly, because it’s a direct consequence of a different design choice: the desire to not have monomorphization-time errors in generics.
Take a function like this:
fn foo<T>(x: T) { bar(x) }
Today, that’s easy:
- the call to
baris to thebarthat’s in-scope at the definition offoo -
barmust be a function that accepts anything, sinceTis unbounded
Imagine overloading existed. Both would be way harder:
- Which
barare we calling? Is it thebarin-scope right now? If there are two in-scope right now, which of them? An overload ofbarthat doesn’t exist yet? Abarin the same module where the concrete generic argument is defined? - When is
fooeven valid? Is it “whenever there’s abarsomewhere that happens to match what we need”? Do we need to like all the types for whichbarexists in the bound somewhere?
Explicitly indirecting through the trait, rather than having everything be a potential indirection point, makes everything was easier, both to understand what’s happening and to implement.