I have a confusion on auto dereferencing.
Here's some code that confuses me
use std::convert::TryInto;
fn main()
{
let x = 5u32;
let x_ref = &x;
let conversion: usize = x_ref.try_into().unwrap(); // bad
// let conversion: usize = (*x_ref).try_into().unwrap(); // good
println!("{}", conversion);
}
In a very abstract way, you can imagine &u32 to translate to something like SharedReference<u32>. The primary type of what you're trying to convert is a SharedReference and u32 is only the type parameter and not the other way around. The standard library doesn't implement TryInto for shared references, because it'd be ambiguous. If you try to convert a shared reference of a u32 into a usize, it could either dereference and convert the u32 into a usize or it could try to convert the reference itself into a usize, which would correspond to the address of where the u32 is stored.
I think there are too many levels of indirection here. As OptimisticPeach said, try_into is only implemented via the blanket impl:
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
So there is no direct impl for u32 here - it has to go through this generic thing first. Because of that generic impl, I believe it won't auto-deref, instead failing to recognize a method.
Here Rust has no choice but to auto-deref x to be able to find our .try_into() method. Whereas with ::core::convert::TryInto's .try_into(), it thinks it can use &'_ u32's .try_into() (so it does not auto-deref), but the only existing &'_ u32's .try_into() impl is one that delegates to TryFrom<&'_ u32>, for which there are no impls and thus fails.