Cannot return mut reference to field

why can't I return mutable reference?
Even implementing a consuming self would suffice for my use case.
Can anybody help?

It will be easier to help if you quote the compiler's full error message, the function the error is within, and any relevant types.


In fact the relevant code snippet will be required too to find out what's wrong. The trouble with a link is that that project can be arbitrarily large, and that's where the needle gets lost in the haystack.


I unpacked it to a "snippet"

The reason rustc complains is 2-fold:

  1. Your MainViewState type doesn't implement your State trait
  2. Even if it did, your MainViewView type has a &MainViewState - which is not convertible to any kind of &mut borrow.

It seems like all this stems from the root fact that you put an immutable borrow in a struct.
Basically, if you don't know what you're doing when putting lifetimes on a type, it's best to avoid doing it. Adding lifetimes on a struct combined with not understanding lifetimes properly is a potent recipe for a bad time reminiscent of your original fights with borrowck except upgraded to Super Saiyan 29.


^ all this is a rant, hardly useful.

It seems like all this stems from the root fact that you put an immutable borrow in a struct.

YES. I do that quite often, for instance when I make an iterator, I return a struct containing a ref to larger object and position. That's normal pattern.
All I am struggling here is why I can't "unpack" that reference (even consuming the view, I don't care). Why having a mut struct that has a reference, I cannot use the reference it has.

You have a mutable struct (via a reference) with an immutable reference. If you need to mutate the value that reference points to, you need a mutable reference to that value.

The mutable reference you have would let you change which state struct your view was referencing, but it cannot allow you make changes to the state struct through the reference in your view because it isn't itself a mutable reference.

An awkward analogy: your view is a room, and the mutable reference to the view is a key to that room. The immutable reference your view contains is a window inside your view's room to another room (your state type). You can use the key to look through the window into the state's room but you can't change anything in that room because you don't have the key to it.

If Rust allowed you to randomly promote immutable references to mutable references there would not actually be a difference between immutable and mutable references.

If you can't have your view hold a mutable reference because other references to the state need to exist you may need wrap your state in a RefCell or an Arc<Mutex<...>>, or revisit your design for the system to avoid needing both multiple references and mutability at the same time.


It's not a rant. It's the default advice to people who are new(ish) to Rust. It even names the reason why.
It's advice that you are free to ignore.

Like I said above, that's the same question as asking why you can't transform an immutable borrow to a mutable one. It can't be done because it's unsound.

The borrow in your struct is immutable which means it can only be used in an immutable fashion, regardless of whether the binding to the strict itself is mutable or not.
If you want to use it mutably, turn the field type into a mutable borrow.

Knowing one trick involving lifetimes is not the same as understanding them btw. Lifetimes are likely the least intuitive part of Rust, right next to stuff like type variance.

1 Like

Here's the playground after

  • Changing MainViewView::state to be a &mut MainViewState
  • Changing TreeViewView::state to be a &mut TreeViewState
  • Changing both implementations of View::state to return &mut *self.state
  • Changing State::view to take a &mut self
  • Dropping tree_view to influence destructor order in impl State for MainViewState

I don't know if that will meet your needs at not, and I ignored various warnings signs like

  • trait View<'a> that doesn't use 'a
  • Some Box<dyn Foo + '_> that could probably be &'_ mut dyn Foo

Thank you!