danielhenrymantilla / stackbox.rs

`&own` pointers in Stable Rust / `RefOwn` / `&mut` with move semantics (and thus drop)
Apache License 2.0
18 stars 2 forks source link

move semantics on the stackbox #4

Open petar-dambovaliev opened 3 years ago

petar-dambovaliev commented 3 years ago

Hey, i am trying to use this crate for indirection on a recursive definition. However, when i try to return the stackbox, it fails to compile with this error.

error[E0515]: cannot return value referencing temporary value
    --> gonzales/src/lib.rs:1517:5
     |
1517 |     stackbox!(states)
     |     ^^^^^^^^^^^^^^^^^
     |     |
     |     returns a value referencing data owned by the current function
     |     temporary value created here
danielhenrymantilla commented 3 years ago

Hey 👋 the point of a stackbox! is to be pointing somewhere in the stack; when using the macro with no $place provided (first rule of the macro_rules! definition in the docs), i.e., when not using StackBox::new_in, then the macro shall create stack storage (that the StackBox will point to) within the very stack frame where it is called, meaning you won't be able to return it or move it beyond that scope.

In order to return a StackBox<'frame, …>, you will need to take a &'frame mut Slot<…> parameter from the caller:

use ::stackbox::{prelude::*, Slot};

fn returns_stackbox (
    storage: &'_ mut Slot<i32>,
) -> StackBox<'_, i32>
{
    return stackbox!(storage, 42);
    // or
    return StackBox::new_in(storage, 42);
    // or
    return storage.stackbox(42);
}

fn middle_func (
    storage: &'_ mut Slot<i32>
) -> StackBox<'_, i32>
{
    let stackbox = returns_stackbox(storage);
    assert_eq!(*stackbox, 42);
    return stackbox;
}

fn caller ()
{
    mk_slots!(storage1, …); /* pinned to this stack frame, we cannot return from here */
    // or
    let ref mut storage1 = mk_slot();
    …
    let stackbox = middle_func(storage1);
    assert_eq!(*stackbox, 42);
}