Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cannot return reference to temporary value

Tags:

rust

I am trying to learn Rust, and while doing so I wanted to try converting a struct object to a byte array, but I am running into issues doing so.

So I have this:

struct Node<'a> {
    id: u8,
    name: &'a str,
    data: &'a str,
}
impl<'a> Node<'a> {
    fn new() -> Node<'a> {
        return Node {
            id: 1,
            name: "superName",
            data: "some random desc2",
        };
    }

    fn to_buffer(&mut self) -> &'a [u8] {
        let mut size = mem::size_of::<Node>();
        size = size + self.name.len() * mem::size_of::<char>();
        size = size + self.data.len() * mem::size_of::<char>();
        println!("size {}", size);
        return &[self.id];
    }
}

but I am just getting the error "cannot return reference to temporary value" And I am not 100% sure that I understand the error message to begin with... is it because self.id is only scoped to this function and would be removed from the stack when it is returned?

And is there any way around this?

like image 352
munHunger Avatar asked Sep 12 '20 14:09

munHunger


2 Answers

Anything starting with & in Rust is a reference to a value, rather than a value itself. A &[u8] is a reference to a value which needs to exist elsewhere.

Because you create the value it's a reference to within the function, when the function returns, the value the reference points to no longer exists. (id still exists, but the slice containing id does not).

Instead, you can return an owned value, rather than a reference to one:

   fn to_buffer(&mut self) -> Vec<u8> {
        let mut size = mem::size_of::<Node>();
        size = size + self.name.len() * mem::size_of::<char>();
        size = size + self.data.len() * mem::size_of::<char>();
        println!("size {}", size);
        return vec![self.id];
    }

which the caller can then take a reference of if that's what they need.

like image 145
Daniel Wagner-Hall Avatar answered Sep 19 '22 14:09

Daniel Wagner-Hall


Since you originally wanted a reference to self.id but considered as a slice of only one element, I would suggest that instead of creating a new owned value (a vector, with heap allocation...) you just use std::slice::from_ref().

    fn to_buffer(&mut self) -> &[u8] {
        let mut size = mem::size_of::<Node>();
        size = size + self.name.len() * mem::size_of::<char>();
        size = size + self.data.len() * mem::size_of::<char>();
        println!("size {}", size);
        // return &[self.id];
        std::slice::from_ref(&self.id)
    }
like image 38
prog-fh Avatar answered Sep 19 '22 14:09

prog-fh