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 Sync
T
is Sync
, then &T
is Send
Therefore both of these are also true:
T
is not Sync
, then &T
is not Send
&T
is not Send
, then T
is not Sync
You can define Sync
in terms of Send
this way:
If
&T
isSend
thenT
isSync
; otherwise,T
is 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
.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.