[][src]Struct multiref::Pair

#[repr(transparent)]pub struct Pair<A: ?Sized, B: ?Sized> { /* fields omitted */ }

A wrapper for a pair of references.

Available only through a (possibly mutable) reference.

Usage

Can be created from (a (possibly mutable) reference to) a pair of (possibly mutable) references by means of the From trait or with the help of new and new_mut functions.

Pairs can be combined to form longer tuples:

let (mut a, mut b, mut c) = (1, 2, 3);
let mut bc = (&mut b, &mut c);
let mut a_pbc = (&mut a, Pair::new_mut(&mut bc));
let pabc = Pair::new_mut(&mut a_pbc);

*pabc.snd_mut().snd_mut() = 4;

// an alternative (more clumsy) way to do the same (modulo indices) thing
*pabc.as_mut().1.as_mut().0 = 5;

// and in continuation-passing style:
pabc.modify(|a_pbc| { *a_pbc.0 = 6; });

assert!(a == 6);
assert!(b == 5);
assert!(c == 4);

A solution facilitating working with more than two values is due to appear in one of the next versions of the crate.

Drawbacks

There was an unsound behaviour in the 0.1.1 version of the crate: the following code successfully compiled (and panicked due to use after drop):

This example deliberately fails to compile
// struct for tracking usage after drop
// (not very reliable, but seems to work for stack-allocated variables)
#[derive(Debug, PartialEq, Eq)] 
struct SelfShredding(i32); 

impl Drop for SelfShredding {
    fn drop(&mut self) { self.0 = 0; }
}

let (mut a, mut b) = (SelfShredding(1), SelfShredding(2));
let mut ab = (&mut a, &mut b);
let pab = Pair::new_mut(&mut ab);
 
{
    let (mut c, mut d) = (SelfShredding(3), SelfShredding(4));
    let mut cd = (&mut c, &mut d);
    let pcd = Pair::new_mut(&mut cd); 

    std::mem::swap(pab, pcd);
}
 
assert_eq!(ab.0, &SelfShredding(3)); // use after drop

The solution is to make Pair<A, B> unmovable. Currently it's done via making Pair<A,B> a DST and encoding &Pair<A, B> as a fat pointer (to a slice of length 1) thus requiring twice the needed size.

Currently I do not know any solutions not involving outer Pin (which is incompatible with distributive law) or DST-wrapping (which requires storing an extra usize, always equal to 1).

Implementations

impl<'a, A: ?Sized, B: ?Sized> Pair<A, B>[src]

pub fn new<'x: 'a>(pair_ref: &'a (&'x A, &'x B)) -> &'a Self[src]

The same as pair_ref.into().

pub fn fst(&'a self) -> &'a A[src]

The first component.

pub fn snd(&'a self) -> &'a B[src]

The second component.

pub fn as_ref(&'a self) -> &'a (&'a A, &'a B)[src]

Both components.

A little more efficient than (pair.fst(), pair.snd()) because it returns the original place where the wrapped references are situated.

pub fn new_mut<'x: 'a>(pair_ref: &'a mut (&'x mut A, &'x mut B)) -> &'a mut Self[src]

The same as pair_ref.into().

pub fn fst_mut(&'a mut self) -> &'a mut A[src]

The first mutable component.

pub fn snd_mut(&'a mut self) -> &'a mut B[src]

The second mutable component.

pub fn as_mut(&'a mut self) -> &'a mut (&'a mut A, &'a mut B)[src]

Both components.

Obviously, you can't simply make (pair.fst_mut(), pair.snd_mut()). Thus this method is much more useful than as_ref.

pub fn modify<R, F>(&'a mut self, f: F) -> R where
    F: FnOnce(&'a mut (&'a mut A, &'a mut B)) -> R, 
[src]

Provides an access to the underlying pair of references via CPS.

Trait Implementations

impl<'a, 'x: 'a, A, B> From<&'a (&'x A, &'x B)> for &'a Pair<A, B> where
    A: ?Sized,
    B: ?Sized
[src]

impl<'a, 'x: 'a, A, B> From<&'a mut (&'x mut A, &'x mut B)> for &'a mut Pair<A, B> where
    A: ?Sized,
    B: ?Sized
[src]

Auto Trait Implementations

impl<A, B> !Send for Pair<A, B>

impl<A, B> !Sync for Pair<A, B>

impl<A: ?Sized, B: ?Sized> Unpin for Pair<A, B>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]