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

StackBox abstraction: feature unsized_rvalues-like functionality #3

Open
danielhenrymantilla opened this issue Oct 3, 2020 · 0 comments
Assignees
Labels
enhancement New feature or request question Further information is requested

Comments

@danielhenrymantilla
Copy link
Owner

This stems from the observation that returning a -> [u8] or a -> dyn Trait is almost like returning a -> &'ref mut [u8] or a -> &'ref mut dyn Trait except for the ownership semantics.

By ownership, the idea is that, compared to a classic -> &'ref mut... return value (which can currently already be implemented, with _no unsafe whatsoever), ownership has move semantics (e.g., no reborrowing possible, although a DerefMut could grant the usability of the latter), and more importantly, RAII / drop: the caller gets to decide when to drop the value, and thus, transitively, where to drop its fields, and all being statically guaranteed to happen exactly once.

This is best seen with an example: although -> &'local mut dyn FnMut() is already quite useful, what about dyn FnOnce()? The very point of the FnOnce() abstraction is that calling it requires ownership, to be able to have the body drop its environment when called.

The solution is then to create a StackBox<'frame, T : ?Sized> abstraction, that would be similar to &'frame mut T, but for those drop semantics (thus implemented as a &'frame mut ManuallyDrop<T>).

  • Creating such a value would generally be unsafe, since it would imply calling ManuallyDrop::drop on the pointee, but could be guaranteed to feature a non-unsafe API by using a macro:

    macro_rules! stackbox {( $value:expr ) => ({
        if false {
            drop($value); // check for `unsafe` hygiene
            unreachable!();
        }
        unsafe { StackBox::new(&mut $crate::core::mem::ManuallyDrop::new($value)) }
    })}

This leads to two issues:

  • Such a crate would break our #![forbid(unsafe_code)] guarantee. It would thus be bundled as an optional dependency.

  • Quid of unsized types? ManuallyDrop::new requires a sized value, so although the [...] case could be handled, especially with const_generics, the case with macros would also require yet another macro with unsafe inside, or using the super-unstable Unsize trait.

    • Follow-up from this, is that even if we were able to create a StackBox<'_, dyn FnOnce()>, then such a function would be technically uncallable, since it wouldn't benefit from the self: Box<Self> magically auto-generated-and-object-safe method that FnOnce::call_once features.

      This implies that StackBox<'_, dyn FnOnce()> would be impossible to return, although a StackBox<'_ dyn StackBoxCompatibleFnOnce()> would be possible 🙂. But then again, the issue will be be to handle as many arities as possible, especially when higher-order lifetimes are involved (e.g., impl<A> ... FnOnce(A) will not cover FnOnce(&'_ str)).

@danielhenrymantilla danielhenrymantilla added the question Further information is requested label Oct 3, 2020
@danielhenrymantilla danielhenrymantilla self-assigned this Oct 3, 2020
@danielhenrymantilla danielhenrymantilla added the enhancement New feature or request label Oct 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant