Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How I can mutate a struct's field from a method?

Tags:

mutable

rust

I want to do this:

struct Point {     x: i32,     y: i32, }  impl Point {     fn up(&self) {         self.y += 1;     } }  fn main() {     let p = Point { x: 0, y: 0 };     p.up(); } 

But this code throws a compiler error:

error[E0594]: cannot assign to field `self.y` of immutable binding  --> src/main.rs:8:9   | 7 |     fn up(&self) {   |           ----- use `&mut self` here to make mutable 8 |         self.y += 1;   |         ^^^^^^^^^^^ cannot mutably borrow field of immutable binding 
like image 281
alxkolm Avatar asked Nov 19 '14 17:11

alxkolm


People also ask

Are struct fields mutable Rust?

However, in Rust, mutability is an all-or-nothing attribute: either a variable is declared as mutable and all of its fields are also mutable (if it is a struct ), or it's declared immutable and so are all of its fields.

What is interior mutability?

Interior mutability is a design pattern in Rust that allows you to mutate data even when there are immutable references to that data: normally, this action is disallowed by the borrowing rules.

What is Mut in Rust?

mut stands for mutable. You are telling the Rust compiler that you will be changing this variable. What's nice is that Rust holds you to this contract. If you declare a variable using mut and never change it you'll see this warning.


2 Answers

You need to use &mut self instead of &self and make the p variable mutable:

struct Point {     x: i32,     y: i32, }  impl Point {     fn up(&mut self) {         // ^^^ Here         self.y += 1;     } }  fn main() {     let mut p = Point { x: 0, y: 0 };     //  ^^^ And here     p.up(); } 

In Rust, mutability is inherited: the owner of the data decides if the value is mutable or not. References, however, do not imply ownership and hence they can be immutable or mutable themselves. You should read the official book which explains all of these basic concepts.

like image 109
Vladimir Matveev Avatar answered Oct 14 '22 14:10

Vladimir Matveev


By using Cell<T> you can emulate field-level mutability:

use std::cell::Cell;  struct Point {     x: i32,     y: Cell<i32>, }  impl Point {     fn up(&self) {         self.y.set(self.y.get() + 1);     } }  fn main() {     let p = Point { x: 0, y: Cell::new(0) };     p.up();     println!("y: {:?}", p.y); } 

This will print y: Cell { value: 7 } and we've successfully updated y.

Additionally, if you are using nightly channel, you can declare #![feature(cell_update)] on top of your .rs file and use the following syntax inside your up() method:

impl Point {     fn up(&self) {         self.y.update(|x| x + 1);     } } 

Note: This feature above is a nightly-only experimental API.

From The Rust Programming Language at Rust 1.7.

like image 35
silvioprog Avatar answered Oct 14 '22 15:10

silvioprog