Struct Pair

Source
pub struct Pair<A: ?Sized, B: ?Sized> { /* private fields */ }
Expand description

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):

// 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§

Source§

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

Source

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

The same as pair_ref.into().

Source

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

The first component.

Source

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

The second component.

Source

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

Both components.

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

Source

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

The same as pair_ref.into().

Source

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

The first mutable component.

Source

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

The second mutable component.

Source

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

Both components.

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

Source

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

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

Trait Implementations§

Source§

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

Source§

fn from(pair: &'a (&'x A, &'x B)) -> Self

Converts to this type from the input type.
Source§

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,

Source§

fn from(pair: &'a mut (&'x mut A, &'x mut B)) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<A, B> Freeze for Pair<A, B>
where A: ?Sized, B: ?Sized,

§

impl<A, B> RefUnwindSafe for Pair<A, B>

§

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

§

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

§

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

§

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

§

impl<A, B> UnwindSafe for Pair<A, B>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more