Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[transmit-case] Issues with TransmitCase by ref #99

Open
sdleffler opened this issue Apr 12, 2021 · 0 comments · May be fixed by #98
Open

[transmit-case] Issues with TransmitCase by ref #99

sdleffler opened this issue Apr 12, 2021 · 0 comments · May be fixed by #98
Labels
enhancement New feature or request

Comments

@sdleffler
Copy link
Contributor

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.

  1. 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.
  2. 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.
  3. 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.

  1. 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.)
  2. 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 T without 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.

@sdleffler sdleffler added the enhancement New feature or request label Apr 12, 2021
sdleffler added a commit that referenced this issue Apr 12, 2021
sdleffler added a commit that referenced this issue Jun 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant