Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to unborrow a mutable reference in rust?

Tags:

rust

Here is an example

#[derive(Debug)]
struct Point {
    x: Vec<i32>,
    y: i32,
}

let mut p = Point { x: vec![1], y: 7 };

// borrow out mutable reference p to a and b
let Point { x: a, y: b } = &mut p;

// mutate a
a.push(2); 
// how do I get p back?
println!("{:?}", p);

Is there a way to unborrow the reference without creating a new block or abstract into function?

like image 649
user10714010 Avatar asked Nov 28 '18 03:11

user10714010


People also ask

How do you borrow as mutable in Rust?

First, we change s to be mut . Then we create a mutable reference with &mut s where we call the change function, and update the function signature to accept a mutable reference with some_string: &mut String . This makes it very clear that the change function will mutate the value it borrows.

What is a mutable reference in Rust?

Back to Rust. A mutable reference is a borrow to any type mut T , allowing mutation of T through that reference. The below code illustrates the example of a mutable variable and then mutating its value through a mutable reference ref_i .

What is mutability in Rust?

Mutability is a property of either a borrow ( &mut ) or a binding ( let mut ). This means that, for example, you cannot have a struct with some fields mutable and some immutable: struct Point { x: i32, mut y: i32, // Nope. }

Can Rust be borrowed?

To accomplish this, Rust uses a borrowing mechanism. Instead of passing objects by value ( T ), objects can be passed by reference ( &T ). The compiler statically guarantees (via its borrow checker) that references always point to valid objects.


2 Answers

Use Rust 2018.

In Rust 2018, which has NLL, your example is valid.

like image 133
Yusuke NOJIMA Avatar answered Oct 19 '22 05:10

Yusuke NOJIMA


You can't. The fields x and y are (mutably) borrowed, which means Point is (mutably) borrowed. All this happens in the same scope, as a result Point will remain mutably borrowed until the end of the scope and you can't have a (immutable or mutable) borrow to the data after it is mutably borrowed. Interior Mutability is what you need to have a look at.

Using RefCell<T> :

use std::cell::RefCell;

#[derive(Debug)]
struct Point {
    x: RefCell<Vec<i32>>,
    y: i32,
}

fn main() {
    let p = Point {
        x: RefCell::new(vec![1]),
        y: 7,
    };

    (*p.x.borrow_mut()).push(2);

    println!("{:?}", p);
}

Edit 1: Yes, It is possible as per Yusuke NOJIMA's answer. You will need to add the attribute #![feature(nll)] to your code , using rust nightly.

#![feature(nll)]

#[derive(Debug)]
struct Point {
    x: Vec<i32>,
    y: i32,
}

...
...

For more, please refer the NLL RFC

like image 41
vikram2784 Avatar answered Oct 19 '22 07:10

vikram2784