struct S<T> {
t: T,
}
// Why is Unpin not automatically implemented for S when I can always
// (regardless of T) implement it manually like this?
impl<T> Unpin for S<T> {}
// By commenting out the previous line we can see that S is not automatically
// Unpin because the following code stops compiling.
fn check_unpin<T>() {
fn use_unpin<T: Unpin>() {}
use_unpin::<S<T>>();
}
If I can trivially make S Unpin then why is not automatically Unpin?
The Unpin documentation says
This trait is automatically implemented for almost every type.
without specifying the "almost" more.
I think the Unpin-ness of T does not matter as long we never construct a Pin<T>. Maybe the compiler is trying to protect me from accidentally making S!Unpin with a slight code change (that uses T in such a way).
To first order, implementing Unpin for a type is a promise that the type is not self-referencing. By implementing Unpin for S<T> you're effectively promising that S does not have structural pinning. If S<T> were automatically Unpin, it would be unsound to add a function like this one:
impl<T> S<T> {
fn project(self: Pin<&mut Self>) -> Pin<&mut T> {
/* use some `unsafe` in here */
}
}
In order to add that function, you would have to un-implement Unpin first, which would be a backwards-incompatible change. It's more conservative to not implement Unpin for generic types unless you have consciously decided that S will not support structural pinning.
Language-feature-wise, Unpin is an auto trait, like Send and Sync (that explains the "almost every type").
Generally, a type being Unpin or not is completely irrelevant for types with no self: Pin<&mut Self> methods. It doesn't really enable you to do anything either way.
Of course, adding the unconditional impl makes some unsafe code incorrect, but still that situation only matters if you have a self: Pin<&mut Self> method, or may get one in the future.