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

Explicit "unsafe" in session type language #80

Open
plaidfinch opened this issue Mar 25, 2021 · 2 comments
Open

Explicit "unsafe" in session type language #80

plaidfinch opened this issue Mar 25, 2021 · 2 comments
Labels
enhancement New feature or request

Comments

@plaidfinch
Copy link
Contributor

plaidfinch commented Mar 25, 2021

Currently, if one needs to escape the session typing regimen temporarily, there is no way to do so while retaining the drop guards which are necessary to continue in over/split/call. Additionally, there is no marker in the type system to point at locations in a protocol where extra scrutiny is required due to departure from the listed session type.

Both of these issues can be allayed by the introduction of:

  • a new session type constructor, Unsafe<P> (only parameter is continuation, since its innards are opaque),
  • its corresponding Session! macro keyword unsafe; (no block, since its innards are opaque), and
  • a new method on Chan<S, Tx, Rx>:
async fn unsafe_with<F, Fut>(
    self, F
) -> (
    Fut::Output,
    Result<Chan<P, Tx, Rx>, IncompleteSession<Tx, Rx>>
)
where
    S: Session<Action = Unsafe<P>>
    F: FnOnce(DropGuard<Tx>, DropGuard<Rx>) -> Fut,
    Fut: Future
{
    // Call function on the drop guards for the transport ends, recover the transport ends or return an error.
}

In the above, DropGuard<T> is similar to the existing pattern in Dialectic of pairing a T with an Arc<Mutex<Result<T, IncompleteHalf<T>>>> and a Drop implementation that places T in the mutex. In the case of DropGuard, we don't need to worry about the case of an unfinished session, since Unsafe doesn't specify what session completion means. Thus, DropGuard should contain merely an Arc<Mutex<Option<T>>>. We can then implement Deref and DerefMut for DropGuard, allowing it to be used however the underlying Tx/Rx can be—including as the transmitter/receiver for a new Chan. This last ability means that Unsafe can crucially be used to nest protocols with different ways of using the underlying transport: for instance, to use different encodings/framings for messages in different parts of a protocol, or to embed a multiplexed subprotocol in a larger protocol, per the multiplexing backend described in #79.

@plaidfinch
Copy link
Contributor Author

Related to this issue, the function into_inner is almost never correct to call, since it unconditionally discards the drop guards on the Chan and therefore will result in a runtime error if called within over, split, or call. It should be replaced with:

fn try_into_inner(self) -> Option<(Tx, Rx)> {
    // only return `Some` if drop guard is a unique `Arc`
}

Documentation should discourage the use of this function and refer to unsafe_with for situations where only temporary access to the raw transport is needed.

@plaidfinch
Copy link
Contributor Author

Some may object to calling any of this "unsafe" since it cannot result in memory unsafety. Alternate nomenclature: Extern<P> type (alternatively: ExternCall?), extern; keyword (alternatively: extern call;? or extern _;?), extern_call function. This gets at the "this bit is not internally specified" notion, but without punning on the Rust meaning of "unsafe".

Presently, my favorite set of naming is Extern<P>/extern _;/extern_call.

@plaidfinch plaidfinch added enhancement New feature or request performance and removed performance labels Mar 25, 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

No branches or pull requests

1 participant