How to return ownership from a trait method

Hey there I am new to rust. I'm stuck on this thing.

fn main() {
  let mut terminal: Terminal = termin::root(CrosstermHandler::new(stdout()));
  
  // it says first mutable borrow occurs here
  let win1: &mut Window = terminal.root.new_child(Window::default());

  terminal.render(win1); // unable to do this (second mutable borrow occurs here)
}
impl Window{
    pub fn new_child(&mut self, win: Window) -> &mut Window {
        self.sub_windows.push(win);
        let idx = self.sub_windows.len() - 1;
        &mut self.sub_windows[idx]
    }
}
pub struct Terminal {
  pub root: Window
}

impl Terminal {
    pub fn render(&mut self, win: &Window) {
        ...
    }
}

It says cannot borrow 'terminal' as mutable more than once at a time

I think I'm borrowing the terminal.root while calling the new_child method. But how to return the ownership back?

Your problem is your method signature

fn new_child(&mut self, win: Window) -> &mut Window

This borrows self for as long as the returned reference to the window exists.

One common pattern is to return an index into the sub_windows array[1].

Another is to use shared ownership like Rc/Arc and possibly interior mutability via RefCell/Mutex so you don't have to return a reference to the Window.

I will also note that none of the code you shared appears to be a trait method.


  1. or use a newtype wrapper like struct WindowIndex(usize); ↩ī¸Ž

3 Likes

Yes shared mutability is what I need. I want to store the child windows in a Vec so whenever the parent window renders all the child windows will also render. But also keep the child Window as a mutable variable so that I can render them individually as need and also modify it's properties.

(And my bad I mean the impl method)

I'm very knew to rust-way-of-thinking so what do you suggest like how to store the child windows

currently I'm doing

struct Window {
  sub_windows: Vec<Window>
}

I want to be able to do

let mut win1 = Window::default();
let mut win2 = win1.child_window(Window::default());

or

let mut win1 = Window::default();
let mut win2 = Window::default();

win1.push_window(&win2);

whenever the win2 variable updates it should also update in win1.sub_windows.

If you aren't using multithreading you can just use Rc and RefCell for now

Playground

use std::{cell::RefCell, rc::Rc};

fn main() {
    let mut terminal = Terminal::new();

    // it says first mutable borrow occurs here
    let win1 = terminal
        .root
        .borrow_mut()
        .new_child(Window::new("First Child".into()));

    terminal.render(terminal.root.clone());
    terminal.render(win1); // unable to do this (second mutable borrow occurs here)
}

#[derive(Debug)]
struct Window {
    pub name: String,
    pub sub_windows: Vec<Rc<RefCell<Window>>>,
}

impl Window {
    pub fn new(name: String) -> Self {
        Self {
            name,
            sub_windows: Vec::new(),
        }
    }

    pub fn new_child(&mut self, win: Window) -> Rc<RefCell<Window>> {
        let win = Rc::new(RefCell::new(win));
        self.sub_windows.push(win.clone());

        win
    }
}

struct Terminal {
    pub root: Rc<RefCell<Window>>,
}

impl Terminal {
    pub fn new() -> Self {
        Self {
            root: Rc::new(RefCell::new(Window::new("Root Window".into()))),
        }
    }

    pub fn render(&mut self, window: Rc<RefCell<Window>>) {
        println!("{:?}", window)
    }
}

Note that RefCell enforces the borrow checker rules at runtime, so it's possible for your code to crash if you aren't careful about how you're structuring your code.

1 Like