You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
So, let's first lay out some known properties of Rust and the Rust type system/memory model.
A reference is not just a transparent wrapper over an immutable view into some T; it also
encodes a "place", also called a "region" or lifetime.
Reconstructing an enum from a discriminant involves taking two pieces of data which have
different regions/come from different places and producing a piece of data which lives in one
place, which we can then encode a reference to.
There is no way to safely do the latter for any type without Copy bounds, because Rust
explicitly does not allow you to move out of an immutable or mutable reference, as per the
borrowing rules.
And a couple properties of the Dialectic backend.
In order for a backend to send something by reference, that thing must all live in the same place
(it must be behind a single immutable reference.)
A backend cannot be expected to send an enum case detached from its discriminant. If we are to
allow a blanket impl of TransmitCase for Transmit wherever T: Match, then Transmit must
be able to send a <T as Case<N>>::Case as a Twithout knowing the difference between T::Case and T. Which is impossible; there is data lost in the conversion to T::Case which
cannot be recovered, beginning with the type itself (in the case of the mpsc backend the TypeId
is lost) and ending with a possible enum discriminant (which cannot be inferred for an enum that
has more than one variant with the same case type.)
To sum up: the first issue we have is that it is absolutely not possible to send some T::Case as T. We must send the T. The second issue we have is that it is absolutely not possible to go
from some &T::Case to some &T; besides the type, there is the additional region information to
be lost, which is important to the Rust compiler even if it is unimportant to us. We cannot expect
it to be unimportant to types we are sending.
So, in conclusion: it is impossible to send an &T::Case without first constructing a T from the &T::Case. Therefore, it does not make sense to allow any sort of transparent sending of &T::Case. In any event that it will be cheap or expensive, that cost in the backend cannot be
less than any cloning cost in user code; it could even be more expensive, as the backend code will
have to make assumptions about how to construct a T from an &T::Case. Even in the case where we
risk unsafety, we have to construct a T, unsafely, in order to be sent.
As such, the best solution is to only allow TransmitCase by value.
The text was updated successfully, but these errors were encountered:
Just dumping out some thoughts from DMs.
So, let's first lay out some known properties of Rust and the Rust type system/memory model.
T
; it alsoencodes a "place", also called a "region" or lifetime.
different regions/come from different places and producing a piece of data which lives in one
place, which we can then encode a reference to.
Copy
bounds, because Rustexplicitly does not allow you to move out of an immutable or mutable reference, as per the
borrowing rules.
And a couple properties of the Dialectic backend.
(it must be behind a single immutable reference.)
allow a blanket impl of
TransmitCase
forTransmit
whereverT: Match
, thenTransmit
mustbe able to send a
<T as Case<N>>::Case
as aT
without knowing the difference betweenT::Case
andT
. Which is impossible; there is data lost in the conversion toT::Case
whichcannot be recovered, beginning with the type itself (in the case of the mpsc backend the
TypeId
is lost) and ending with a possible enum discriminant (which cannot be inferred for an enum that
has more than one variant with the same case type.)
To sum up: the first issue we have is that it is absolutely not possible to send some
T::Case
asT
. We must send theT
. The second issue we have is that it is absolutely not possible to gofrom some
&T::Case
to some&T
; besides the type, there is the additional region information tobe lost, which is important to the Rust compiler even if it is unimportant to us. We cannot expect
it to be unimportant to types we are sending.
So, in conclusion: it is impossible to send an
&T::Case
without first constructing aT
from the&T::Case
. Therefore, it does not make sense to allow any sort of transparent sending of&T::Case
. In any event that it will be cheap or expensive, that cost in the backend cannot beless than any cloning cost in user code; it could even be more expensive, as the backend code will
have to make assumptions about how to construct a
T
from an&T::Case
. Even in the case where werisk unsafety, we have to construct a
T
, unsafely, in order to be sent.As such, the best solution is to only allow
TransmitCase
by value.The text was updated successfully, but these errors were encountered: