Which one is reason and which one is the result?
It seems to say, if &T is Send, then T is Sync; totally confused.
Why is not: if T is Sync, then &T is Send. if T is not Sync, then &T never be Send?
Which one is reason and which one is the result?
It seems to say, if &T is Send, then T is Sync; totally confused.
Why is not: if T is Sync, then &T is Send. if T is not Sync, then &T never be Send?
"If and only if" means that both of these are true:
&T is Send, then T is SyncT is Sync, then &T is SendTherefore both of these are also true:
T is not Sync, then &T is not Send&T is not Send, then T is not SyncYou can define Sync in terms of Send this way:
If
&TisSendthenTisSync; otherwise,Tis notSync.
The current implementation does have a causal direction:
unsafe impl<T: Sync + ?Sized> Send for &T {}
i.e the property of T influences the property of &T, and not vice-versa.
One could imagine it the other way though:
// core:
unsafe impl<T: ?Sized> Sync for T where &T: Send {}
// your crate:
unsafe impl Send for &YourType {}
There is difference between the two.
unsafe impl<T: Sync + ?Sized> Send for &T {}
will not make YourType Sync when I write
unsafe impl Send for &YourType {}
But the later one does
Yes, they are different, and we can't change that, so the alternative is just a thought experiment. With the blanket Send for &T we have now, you're responsible for impl Sync for YourType. If we had chosen the other way with blanket Sync for T, you would write impl Send for &YourType instead.
Most of the time though, you don't even write these unsafe impl anyway if you're dealing with safe types, as they are automatically inferred.
I think this doesn’t actually work though, even without the blanket impl in place.
I’m not 100% sure though why that error exists. (Well, I do know that it’s pretty important in order to prevent something like impl Unpin for dyn Foo {}, but that reasoning really only applies to trait objects.)
I’m also a bit confused as to why the error message says cross-crate traits with a default impl while the error code description I linked doesn’t mention anything about that with a default impl part.
Interesting -- I wonder if that's actually an important restriction of auto traits overall, or just a limitation in how the compiler is currently able to reason about them?
In the world where we would be writing manual Send for &YourType, this also implies that we'd want it automatic most of the time, so for every type the compiler would have to automatically consider Send for YourType and Send for &YourType, the latter looking at each Send for &Field within YourType. And Sync wouldn't be an auto trait at all, just using its blanket impl where &T: Send. But from this angle, it does seem much cleaner that Send and Sync are separate auto traits rather than doubling the work for Send.
I recommend this post about the relationships between Send and Sync.