Okay, I think I'm coming around and starting to see things from your collective point of view. At first I thought the "refinement" idea was a novelty but after @digama0's and @alice's most recent explanations I'm starting to see how it can be universally applied to all of these different traits and their bounds.
I still think it's a little confusing that DerefMut refines Deref while Fn refines FnMut but maybe the explanation for that lies in what @steffahn said earlier about how types which are normally covariant become contravariant when used as function parameters. Please correct me if I am wrong.
I do think the "refinement" idea might be a stretch in some situations. Like if I wanted to implement a generic is_even function I'd write:
fn is_even<T>(num: T) -> bool
where
T: Rem<Output = T> + PartialEq<T> + Sized,
u8: TryInto<T>,
<u8 as TryInto<T>>::Error: Debug
{
num % 2.try_into().unwrap() == 0.try_into().unwrap()
}
In the above implementation it's easy to say the generic type parameter T depends on having implementations for the % and == operators and the ability of being converted to from a u8.
But if I wanted to make it a trait with a default implementation I'd write:
trait Even
where
Self: Rem<Output = Self> + PartialEq<Self> + Sized,
u8: TryInto<Self>,
<u8 as TryInto<Self>>::Error: Debug
{
fn is_even(self) -> bool {
self % 2.try_into().unwrap() == 0.try_into().unwrap()
}
}
In the above scenario would we still say that the idea of evenness is a refined concept of the combined ideas of modulo arithmetic, partial equality, and conversion from the u8 data type? I guess we can say that, so it still works, hmmm.
I think my experience with OO languages might be what is confusing me. A Dog is an Animal conceptually, but in the case of most OO languages, a Dog is also an Animal literally. A Dog class would literally inherit the data and methods from an Animal class and would be very tightly-coupled to the Animal class in a literal sense and not just in a vague conceptual sense. If we were to drop the Animal class from the codebase it would probably require significant refactors to Dog.
However, if we dropped Clone from the standard library it'd require no refactors or changes to Copy! Not only would Copy's implementation stay the same for all types which impl it (even if it wasn't provided by the compiler) but also the semantics of the trait and how it's used within user code would not change. Copy and Clone are conceptually related, a copy is just a cheap fast efficient clone, but they're otherwise completely independent and decoupled implementation-wise... BUT if some type T does impl Copy then this is the only Clone impl that makes sense:
impl<T: Copy> Clone for T {
fn clone(&self) -> Self {
*self
}
}
This is where the "reverse" part comes in. However as @steffahn and @alice pointed out there's no way for the compiler to enforce this, and there's no way for the standard library to provide this impl (aside through documentation). There's nothing stopping a user from writing a totally nonsense impl for Clone which doesn't use Copy at all.
Okay, so in summary: a conceptual dependence does not require or imply an implementation dependence. Thanks everyone!