How to return a newly created struct as a reference?
<p>As an exercise to learn Rust I decided to implement a Bit Vector library, with inspiration from <code>std::vec::Vec</code> for which methods to provide.</p>

<p>I have the following code:</p>

<pre><code>extern crate num;

use std::cmp::Eq;
use std::ops::{BitAnd,BitOrAssign,Index,Shl};
use num::{One,Zero,Unsigned,NumCast};

pub trait BitStorage: Sized + 
    BitAnd&lt;Self, Output = Self&gt; + 
    BitOrAssign&lt;Self&gt; + 
    Shl&lt;Self, Output = Self&gt; + 
    Eq + Zero + One + Unsigned + NumCast + Copy {}

impl&lt;S&gt; BitStorage for S where S: Sized + 
    BitAnd&lt;S, Output = S&gt; + 
    BitOrAssign&lt;S&gt; + 
    Shl&lt;S, Output = S&gt; + 
    Eq + Zero + One + Unsigned + NumCast + Copy {}

pub struct BitVector&lt;S: BitStorage&gt; {
    data: Vec&lt;S&gt;,
    capacity: usize,
    storage_size: usize
}

impl&lt;S: BitStorage&gt; BitVector&lt;S&gt; {
    pub fn with_capacity(capacity: usize) -&gt; BitVector&lt;S&gt; {
        let storage_size = std::mem::size_of::&lt;S&gt;() * 8;
        let len = (capacity / storage_size) + 1;
        BitVector { 
            data: vec![S::zero(); len],
            capacity: capacity,
            storage_size: storage_size
        }
    }

    pub fn get(&amp;self, index: usize) -&gt; Option&lt;bool&gt; {
        match self.index_in_bounds(index) {
            true =&gt; Some(self.get_unchecked(index)),
            false =&gt; None
        }
    }

    pub fn set(&amp;mut self, index: usize, value: bool) {
        self.panic_index_bounds(index);
        let (data_index, remainder) = self.compute_data_index_and_remainder(index);
        let value = if value { S::one() } else { S::zero() };
        self.data[data_index] |= value &lt;&lt; remainder;
    }

    pub fn capacity(&amp;self) -&gt; usize {
        self.capacity
    }

    pub fn split_at(&amp;self, index: usize) -&gt; (&amp;BitVector&lt;S&gt;, &amp;BitVector&lt;S&gt;) {
        self.panic_index_not_on_storage_bound(index);
        let data_index = self.compute_data_index(index);
        let (capacity_left, capacity_right) = self.compute_capacities(index);
        let (data_left, data_right) = self.data.split_at(data_index);

        let left = BitVector {
            data: data_left.to_vec(),
            capacity: capacity_left,
            storage_size: self.storage_size
        };
        let right = BitVector {
            data: data_right.to_vec(),
            capacity: capacity_right,
            storage_size: self.storage_size
        };
        (&amp;left, &amp;right)
    }

    pub fn split_at_mut(&amp;mut self, index: usize) -&gt; (&amp;mut BitVector&lt;S&gt;, &amp;mut BitVector&lt;S&gt;) {
        self.panic_index_not_on_storage_bound(index);
        let data_index = self.compute_data_index(index);
        let (capacity_left, capacity_right) = self.compute_capacities(index);
        let (data_left, data_right) = self.data.split_at_mut(data_index);

        let mut left = BitVector {
            data: data_left.to_vec(),
            capacity: capacity_left,
            storage_size: self.storage_size
        };
        let mut right = BitVector {
            data: data_right.to_vec(),
            capacity: capacity_right,
            storage_size: self.storage_size
        };
        (&amp;mut left, &amp;mut right)
    }

    #[inline]
    fn get_unchecked(&amp;self, index: usize) -&gt; bool {
        let (data_index, remainder) = self.compute_data_index_and_remainder(index);
        (self.data[data_index] &amp; (S::one() &lt;&lt; remainder)) != S::zero()
    }

    #[inline]
    fn compute_data_index_and_remainder(&amp;self, index: usize) -&gt; (usize, S) {
        let data_index = self.compute_data_index(index);
        let remainder = self.compute_data_remainder(index);
        (data_index, remainder)
    }

    #[inline]
    fn compute_data_index(&amp;self, index: usize) -&gt; usize {
        index / self.storage_size
    }

    #[inline]
    fn compute_data_remainder(&amp;self, index: usize) -&gt; S {
        let remainder = index % self.storage_size;
        // we know that remainder is always smaller or equal to the size that S can hold
        // for example if S = u8 then remainder &lt;= 2^8 - 1
        let remainder: S = num::cast(remainder).unwrap();
        remainder
    }

    #[inline]
    fn compute_capacities(&amp;self, index_to_split: usize) -&gt; (usize, usize) {
        (index_to_split, self.capacity - index_to_split)
    }

    #[inline]
    fn index_in_bounds(&amp;self, index: usize) -&gt; bool {
        index &lt; self.capacity
    }

    #[inline]
    fn panic_index_bounds(&amp;self, index: usize) {
        if !self.index_in_bounds(index) {
            panic!("Index out of bounds. Length = {}, Index = {}", self.capacity, index);
        }
    }

    #[inline]
    fn panic_index_not_on_storage_bound(&amp;self, index: usize) {
        if index % self.storage_size != 0 {
            panic!("Index not on storage bound. Storage size = {}, Index = {}", self.storage_size, index);
        }
    }
}

static TRUE: bool = true;
static FALSE: bool = false;

macro_rules! bool_ref {
    ($cond:expr) =&gt; (if $cond { &amp;TRUE } else { &amp;FALSE })
}

impl&lt;S: BitStorage&gt; Index&lt;usize&gt; for BitVector&lt;S&gt; {
    type Output = bool;

    fn index(&amp;self, index: usize) -&gt; &amp;bool {
        self.panic_index_bounds(index);
        bool_ref!(self.get_unchecked(index))
    }
}
</code></pre>

<p>The compiler errors occur at the <code>split_at</code> and <code>split_at_mut</code> methods: They basically tell me that <code>left</code> and <code>right</code> in both cases do not live long enough to be returned as a reference. I understand this, because they are created on the stack and then I want to return them as a reference.</p>

<p>However with my design being inspired by <code>std::vec::Vec</code> you can see that <a href="https://github.com/rust-lang/rust/blob/master/src/libcore/slice.rs">in the SliceExt trait</a> their definitions are as follows:</p>

<pre><code>#[stable(feature = "core", since = "1.6.0")]
fn split_at(&amp;self, mid: usize) -&gt; (&amp;[Self::Item], &amp;[Self::Item]);

#[stable(feature = "core", since = "1.6.0")]
fn split_at_mut(&amp;mut self, mid: usize) -&gt; (&amp;mut [Self::Item], &amp;mut [Self::Item]);
</code></pre>

<p>I suppose this is done for end user convenience as they rather deal with references than with boxes.</p>

<p>I think I could fix my errors by putting the returned bit vectors into a <code>Box&lt;_&gt;</code>, but is there a way to return the created structs as a reference?</p>

<p>As a bonus question: It does work if I return <code>(BitVector&lt;S&gt;, BitVector&lt;S&gt;)</code>, what are the downsides to doing this? Why does the <code>SliceExt</code> trait not do this?</p>