For some reason convert_mut_direct() fails but convert_mut_indirect() works just fine. What am I missing and where can I read more about this? An admittedly cursory glance at the books Mutability chapter didn't make it clear where/when I need to care about mut for a non mutable call.
The .into() call relies on the generic trait Into<T> and thus takes the &mut OtherStruct exactly as is. &mut OtherStruct does not impl Into<Vec<MyStruct>> and so Rust fails to find any matching method to call.
When you call convert(convertee), you pass a unique reference to a function that expects a shared reference. In this case, Rust employs a coercion called "auto-reborrow". If effectively turns the call into convert(&*convertee). Inside convert(), the convertee has the right type so that Rust can find its Into<Vec<MyStruct>> impl and the code compiles.
It's unfortunately not particularly easy to find some official documentation on it. The best I could find is this page of the 'nomicon, where it is referred to as "pointer-weakening".
There is one kind of reborrow, however, that is not covered by this: The automatic reborrow of &'a mut T to &'b mut T, where 'b is shorter than 'a. This reborrow makes the following possible without an error claiming "use of moved value: mr":
Unique references cannot be copied (hence "unique"), so you would expect that the first call moves mr and marks the variable as no longer usable. However, the call actually desugars to takes_mut_ref(&mut *mr), and it is fresh, shorter reference that gets moved. Hence, mr is still usable at the second function call.