Will this lifetime issue be solved?

Getter and setters have many use cases, but unfortunately in Rust getters also have this problem where you lose more fine-grained lifetime tracking and get lifetime errors:

pub struct Test {
    x: String,
    y: String,
}

impl Test {
    pub fn get_x_mut(&mut self) -> &mut String {
        &mut self.x
    }

    pub fn get_y_mut(&mut self) -> &mut String {
        &mut self.y
    }
}

// Works
pub fn test_1(a: &mut Test) {
    let x = &mut a.x;
    let y = &mut a.y;

    x.push('a');
    y.push('a');
}

// Doesn't work, lifetime errors
pub fn test_2(a: &mut Test) {
    let x = a.get_x_mut();
    let y = a.get_y_mut(); // `a` borrowed mut twice

    x.push('a');
    y.push('a');
}

I'm curious if (1) in principle it's possible to improve this so that test_2 above will work (2) if there are any work planned in rustc that will one day improve this so that test_2 above will work.

Thanks.

This has been discussed before, but in general, if you need mutable access to a field, just make it public. There's no advantage in making a private field just in order to immediately expose it mutably using a getter, you can't even enforce internal consistency of your data like this.

There's no advantage in making a private field just in order to immediately expose it mutably using a getter, you can't even enforce internal consistency of your data like this.

My example is not a real-world use case, it's just a minimal repro for the problem I'm describing. In practice, I may want to hide a field but expose a field of it (e.g. by returning &mut self.x.y). Or I may want to expose some of the fields, but want to keep others immutable:

pub struct Test {
    // Mutable field
    pub x: String,
    // Immutable field
    y: String,
}

impl Test {
    pub fn get_y(&self) -> &str {
        &self.y
    }
}

pub fn test(a: &mut Test) {
    let x = &mut a.x;
    let y = a.get_y();

    x.push('a');
}

Or I may want to add logging/tracing to getters and setters for debugging or actual logging etc.

I know the workarounds, but improving this would still be a QoL improvement for Rust programmers.

OK, I just wanted to clarify that. You might be interested in searching for "partial self borrows" for previous discussion on this topic.

Thanks. I found a few relevant questions but I'm more interested in a compiler developer's point of view on this than potential workarounds, and none of the existing topics has that kind of answer as far as I can see.

This question will probably be more suitable for internals.rust-lang.org, then.

1 Like

You may also be interested in this article on the topic by a key rustc developer (Niko Matsakis). It's mostly about working with the current situation, but the end of the article talks about considerations for the future, and links to prior conversations as well.

3 Likes

Thanks. That blog post and the linked discussions there are the answer I was looking for.

Just wanted to mention that the "shadow struct" (or "view struct") method in the blog post is very interesting. I'd recommend everyone who had this problem before to take a look at at least that section of the blog post.

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.