`Transfer` is to move what `Clone` is to copy

Hello everyone,

This post announces two experimental crates:

  • stackpin attempts to provide traits, structs and macro to work with "unmovable" types in Rust (types that are tied to one point of the stack and shouldn't be moved after their declaration). To do so, it takes inspiration from the pin_utils crate, but stackpin promotes a model where all unmovable types are only accessible once pinned.

    {
        stack_let!(unmovable = Unmovable::from("Intel the Beagle!"); 
        // ''unmovable' is set to a Pin<StackPin<Unmovable>>
        // the underlying Unmovable cannot be moved from this scope
    }
    
  • transfer attempts to provide the equivalent of a C++ constructor to "unmovable" types, allowing types to execute user-controlled code when "moved", instead of just memcpy.

    {
        let outer_unmovable = Unmovable::empty();
        // outer_unmovable is a  Tr<Unmovable>. It has the size and alignment of an Unmovable, but cannot be used
        {
            stack_let!(inner_unmovable = Unmovable::from_unpin("Foobar");
            // work with inner_unmovable in this scope
            if inner_unmovable.feels_like_being_transferred() {
                transfer::transfer(inner_unmovable, outer_unmovable);
                // The contents of "inner_unmovable" has been transferred to "outer_unmovable"
                // and will be available until the end of the outer scope. 
            }
        }
    }
    

A first "application" of these crates is to make safe a reference type I proposed a long time ago, that can be stored in a struct without being parameterized by a lifetime. With stackpin I can make the reference type safe (or so I hope), with transfer I can improve its usability by allowing a limited form of "move".

Please note again that the crates are in a very experimental shape (regarding documentation, examples, tests, ...). Also, these are my first crates, so maybe I missed something obvious.

I decided to publish these crates because the idea has been sitting on my shelf for a long time, and I think that it could be useful as it could solve problems with "self referential structs", "scoped thread" in a new way, and these problems are often encountered in rust. So I thought that it was good to share the ideas, in the hope that it doesn't have unfixable soundness holes :sweat:

Among things that remain to do:

  • Document safety pre-requisites for stackpin better, so that it becomes possible for external crates to use the FromUnpinned trait with unsafe, without using the stack_let! macro
  • Document the transfer crate
  • Find better expression for the Transfer trait. The Transfer trait is likely not final. I have searched for a long time a better expression of the "Empty T value" problem, and I'm not satisfied with my current answer.
  • Improve the various ..._let! macros. The Transfer one are particularly lacking.
  • Create more examples using stackpin (scope_thread for instance) and transfer (e.g. frozen_tree could benefit from transfer capabilities)
  • Create an external crate for dynref.
6 Likes