Struct recursive_reference::RecRef[][src]

pub struct RecRef<'a, T: ?Sized> { /* fields omitted */ }
Expand description

A Recursive reference. This struct is used to allow recursively reborrowing mutable references in a dynamic but safe way.

RecRef<'a, T> represents a reference to a value of type T, with lifetime 'a, which can move recursively into and out of its subfields of the same type T.

With a RecRef you can

  • Use the current reference (i.e, the top reference). the RecRef is a smart pointer to it.
  • Freeze the current reference and extend the RecRef with a new reference derived from it, using extend and similar functions. for example, push to the stack a reference to the child of the current node.
  • Pop the stack to get back to the previous reference, unfreezing it.

The methods’ types guarantee that the references will always have a legal lifetime and will respect rust’s borrow rules, even if that lifetime is not known in advance.

Internally, the RecRef stores a Vec of pointers, that it extends and pops from.

Implementations

Creates a new RecRef containing only a single reference.

Returns the size of rec_ref, i.e, the amount of references in it. It increases every time you extend rec_ref, and decreases every time you pop rec_ref. The size of a new RecRef is always 1.

This function extends rec_ref one time. If the current reference is current_ref: &mut T, then this call extends rec_ref with the new reference ref2: &mut T = func(current_ref). After this call, rec_ref will expose the new ref2, and current_ref will be frozen (As it is borrowed by ref2), until ref2 is popped off, unfreezing current_ref.

Safety:

Pay close attention to the type of func: we require that F: for<'b> FnOnce(&'b mut T) -> &'b mut T. That is, for every lifetime 'b, we require that F: FnOnce(&'b mut T) -> &'b mut T.

Let’s define 'freeze_time to be the time ref2 will be in the RecRef. That is, 'freeze_time is the time for which ref2 will live, and the lifetime in which current_ref will be frozen by ref2. Then, the type of func should have been FnOnce(&'freeze_time mut T) -> &'freeze_time mut T. If that woudld have been the type of func, the code would’ve followed rust’s borrowing rules correctly.

However, we can’t know yet what that lifetime is: it will be whatever amount of time passes until the programmer decides to pop ref2 out of the RecRef. And that hasn’t even been decided at this point. Whatever lifetime 'freeze_time that turns out to be, we will know after-the-fact that the type of func should have been FnOnce(&'freeze_time mut T) -> &'freeze_time mut T.

Therefore, the solution is to require that func will be able to work with any value of 'freeze_time. Then we can be sure that the code would’ve worked correctly if we put the correct lifetime there. Therefore, we can always pick correct lifetimes after-the-fact, so the code must be safe.

Also note: The type ensures that the current reference can’t be leaked outside of func. func can’t guarantee that current_ref will live for any length of time, so it can’t store it outside anywhere or give it to anything. It can only use current_ref while still inside func, and use it in order to return ref2, which is the intended usage.

Same as Self::extend, but allows the function to return an error value.

Same as Self::extend, but allows the function to return an error value, and also tells the inner function that 'a : 'b using a phantom argument.

This function maps the top of the RecRef. It’s similar to Self::extend, but it replaces the current reference instead of keeping it. See Self::extend for more details.

Same as Self::map, but allows the function to return an error value.

Same as Self::map, but allows the function to return an error value, and also tells the inner function that 'a : 'b using a phantom argument.

Push another reference to the RecRef, unrelated to the current one. rec_ref.push(new_ref) is morally equivalent to rec_ref.extend_result_precise(move |_, _| { Ok(new_ref) }). However, you might have some trouble making the anonymous function conform to the right type.

Lets the user use the last reference for some time, and discards it completely. After the user uses it, the next time they inspect the RecRef, it won’t be there. If the RecRef has only one reference left, this returns None, because the RecRef can’t be empty.

Discards the RecRef and returns the last reference. The difference between this and using Self::pop are:

Trait Implementations

Performs the conversion.

Performs the conversion.

RecRef<T> represents a reference to a value of type T, which can move recursively into and out of its subfields of the same type T. Therefore, it implements Deref and DerefMut with Item=T.

The resulting type after dereferencing.

Dereferences the value.

RecRef<T> represents a reference to a value of type T, which can move recursively into and out of its subfields of the same type T. Therefore, it implements Deref and DerefMut with Item=T.

Mutably dereferences the value.

Performs the conversion.

Safety:

Behaviorally, A RecRef is the same as &'a mut T, and should be Send for the same reason. Additionally, it contains a Vec. The Send instance for Vec contains the bound A: Send for the allocator type A, so we should require that as well. However, we don’t have direct access to the default allocator type. So instead we require Vec<&'a mut T>: Send.

Safety:

Behaviorally, A RecRef is the same as &'a mut T, and should be Sync for the same reason. Additionally, it contains a Vec. The Sync instance for Vec contains the bound A: Sync for the allocator type A, so we should require that as well. However, we don’t have direct access to the default allocator type. So instead we require Vec<&'a mut T>: Sync.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.