1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
/// 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`](#method.new) and [`new_mut`](#method.new_mut) /// functions. /// /// Pairs can be combined to form longer tuples: /// /// ``` /// # use multiref::Pair; /// 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): /// /// ``` compile_fail /// # use multiref::Pair; /// // 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). #[repr(transparent)] pub struct Pair<A: ?Sized, B: ?Sized> { pair_box: [(*const A, *const B)], } impl<'a, 'x: 'a, A, B> From<&'a (&'x A, &'x B)> for &'a Pair<A, B> where A: ?Sized, B: ?Sized, { fn from(pair: &'a (&'x A, &'x B)) -> Self { unsafe { &*(core::slice::from_raw_parts(pair, 1) as *const _ as *const _) } } } 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, { fn from(pair: &'a mut (&'x mut A, &'x mut B)) -> Self { unsafe { &mut *(core::slice::from_raw_parts_mut(pair, 1) as *mut _ as *mut _) } } } impl<'a, A: ?Sized, B: ?Sized> Pair<A, B> { /// The same as `pair_ref.into()`. pub fn new<'x:'a>( pair_ref: &'a (&'x A, &'x B) ) -> &'a Self { pair_ref.into() } /// The first component. pub fn fst(&'a self) -> &'a A { unsafe { &*self.pair_box[0].0 } } /// The second component. pub fn snd(&'a self) -> &'a B { unsafe { &*self.pair_box[0].1 } } /// 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 as_ref(&'a self) -> &'a (&'a A, &'a B) { unsafe { &*(self as *const _ as *const _) } } /// The same as `pair_ref.into()`. pub fn new_mut<'x:'a>( pair_ref: &'a mut (&'x mut A, &'x mut B) ) -> &'a mut Self { pair_ref.into() } /// The first mutable component. pub fn fst_mut(&'a mut self) -> &'a mut A { unsafe { &mut *(self.pair_box[0].0 as *mut _) } } /// The second mutable component. pub fn snd_mut(&'a mut self) -> &'a mut B { unsafe { &mut *(self.pair_box[0].1 as *mut _) } } /// Both components. /// /// Obviously, you can't simply make `(pair.fst_mut(), pair.snd_mut())`. /// Thus this method is much more useful than [`as_ref`](#method.as_ref). pub fn as_mut(&'a mut self) -> &'a mut (&'a mut A, &'a mut B) { unsafe { &mut *(self as *mut _ as *mut _) } } /// Provides an access to the underlying pair of references via CPS. pub fn modify<R, F>(&'a mut self, f: F) -> R where F: FnOnce(&'a mut (&'a mut A, &'a mut B)) -> R { f(self.as_mut()) } }