Implement 'trait' that update 'self' with a borrowed value

Hi all,

I'm new to rust, and I have some problems understanding lifetimes.
I know that I can create a struct that holds a reference to a field by specifying a lifetime.

struct Rectangle<'a> {
    width: &'a u8
}

impl<'a> Rectangle<'a> {
    fn set_width(&mut self, width: &'a u8) {
        self.width = width;
    }
}

Here comes my first question? When do you choose to store a reference inside a struct instead of an owned value?

The issue that I have is how I should implement a trait that tries to do the same:

trait FS {
    fn set_size(&mut self, size: &u8);
}

struct FSMock<'a> {
    size: &'a u8,
}

impl<'a> FS for FSMock<'a> {
    fn set_size(&mut self, size: &u8) {
        self.size = size;
    }
}

The code above does not work.
The error yielded is: Lifetime of reference outlives lifetime of borrowed content.
This does make sense, however, I can't find a solution to make it working.

Forgive the 'dumb' questions, but I'm new to Rust and I try to grasp my head around it.

In two cases: either an external library requires it, or we've benchmarked the already working code and found that making copies of some value is a bottleneck. In all other cases, this is mostly the wrong way.

It's also the wrong thing to do when learning Rust. You will learn the language far faster if you avoid storing references in structs until you are comfortable with other aspects of the language.

The best advice I got was not to feel bad about using clone() to make the borrow checker happy. I got a rather substantial application built with a gazillion clone() operations, most of which I was able to eliminate once I grokked the language.

3 Likes

This is still not a reason to use a Rust reference (a temporary borrow)!

You can store things "by reference" using Box (unique reference) which makes internal copies fast when such value is passed around, or Arc (shared reference) which allows multiple copies of the struct without copying the data behind Arc pointer.

1 Like

Structs with references inside are a rare case of a temporary struct, bound to a single scope, that is used to view data that is stored elsewhere.

&'a u8 guarantees that this byte can't change — nothing can change it in any way for as long as this struct uses it. It requires that this byte already existed in a variable/array/another struct that has been created before this struct has been created.

<'a> on this struct makes it temporary and bound to the same scope its data is from. If the data is in a variable, the struct will never be able to escape scope of that variable.

Rust references are mainly about borrowing, which means adding restrictions to things (making things immutable, unmovable, tied to a scope). They can't be used to store anything.

If your goal is to store data in a struct, you can't use references. Box/Rc/Arc can be used to store and pass things "by reference".

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.