Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `MyVec: AsMut<MyVec>` is not satisfied
--> src/main.rs:24:29
|
24 | let mut r = use_or_make(Some(&mut v));
| ----------- ^^^^^^^^^^^^ the trait `AsMut<MyVec>` is not implemented for `MyVec`, which is required by `&mut MyVec: AsMut<MyVec>`
| |
| required by a bound introduced by this call
|
= note: required for `&mut MyVec` to implement `AsMut<MyVec>`
note: required by a bound in `use_or_make`
--> src/main.rs:13:19
|
13 | fn use_or_make<V: AsMut<MyVec>>(v: Option<V>) -> Option<MyVec> {
| ^^^^^^^^^^^^ required by this bound in `use_or_make`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (bin "playground") due to 1 previous error
Basically, my question is simple, for all T, why doesn't Rust automatically implement AsMut<&mut T>?
Ideally, AsMut would be reflexive, i.e. there would be an impl<T: ?Sized> AsMut<T> for T with as_mut simply returning its argument unchanged. Such a blanket implementation is currently not provided due to technical restrictions of Rust’s type system (it would be overlapping with another existing blanket implementation for &mut T where T: AsMut<U> which allows AsMut to auto-dereference, see “Generic Implementations” above).
In Rust, the two implementations you mentioned can’t coexist due to a conflict in how Rust’s trait system handles ambiguity when resolving method calls. Let’s break down why that happens.
The Implementations
Here are the two implementations in question:
Reflexive implementation:
impl<T> AsMut<T> for T
where
T: ?Sized,
This implementation would allow any type T to convert itself to a mutable reference to itself (e.g., &mut T to &mut T).
Transitive implementation:
impl<T, U> AsMut<U> for &mut T
where
T: AsMut<U> + ?Sized,
U: ?Sized,
This allows a mutable reference to T (&mut T) to be converted to U as long as T implements AsMut<U>. This is useful for types where T can convert itself to U through AsMut.
Why Both Can't Coexist
The conflict arises due to how Rust resolves trait implementations when a type could match multiple implementations. Here’s the core issue:
When using AsMut, Rust needs to determine which implementation to use. Suppose we have a type T, and we call as_mut on a mutable reference &mut T.
With both implementations, there are two possible matches:
The reflexive implementation (impl<T> AsMut<T> for T) allows T to convert itself to T.
The transitive implementation (impl<T, U> AsMut<U> for &mut T) allows &mut T to convert to U if T: AsMut<U>.
Rust’s trait system currently does not have a mechanism to disambiguate between these two implementations when both are available for the same type. Rust must be able to clearly decide which implementation to use, but in this case, it would face ambiguity for types where both could apply.
Trade-off Decision in the Standard Library
The Rust standard library has chosen to provide the transitive implementation because it’s more flexible and aligns with more use cases. The reflexive version, though intuitive, is less commonly required, and the transitive form adds a lot of power when working with complex types. Therefore, by design, only the transitive implementation is provided to avoid ambiguity and ensure predictable trait resolution.
This choice ultimately reflects a trade-off in favor of flexibility and versatility over consistency with the reflexive form.
========== END OF FROM CHATGPT ==========
Is its explanation accurate?
My follow up question would then be, why can't we specify which trait we want to use using the as keyword? e.g. <T as AsMut<U>>::as_mut(t);
And in this Playground, I can also implement AsMut<MyVec> for MyVec, it doesn't clash with anything else. Why is that so?
Also, for libraries that have types that are 'container-like', i.e. they hold certain states within themselves, e.g. Vec<T> holding some numbers of T, and these types have mutable methods that mutate its internal state, should the library authors of these types implement AsMut<LibraryType> for LibraryType?