The E0384 error is one of the common errors programmers new to Rust will face. By default, variables are immutable in Rust. Having immutable variables helps up write concurrent codes and avoid common problems that come along with concurrency.
Sample Erring Codes
Consider the following codes. First, we declare and initialize a variable with 2. Then, we print the value. Finally, we attempt to change the variable’s value to 100. At this point, we get a compilation error.
1 2 3 4 5 | fn main() { let i:i32 = 2; println!("{}", i); i = 100; } |
The codes generate the following output. The error message tells us that we cannot modify the value of the variable i. Note that this is happening at compile-time, not at run-time. Therefore, it is the Rust compiler the threw the E0384 error and stopped the compilation. So, how do we fix this?
1 2 3 4 5 6 7 8 9 10 11 12 13 | error[E0384]: cannot assign twice to immutable variable `i` --> src\main.rs:5:5 | 4 | let i:i32 = 2; | - | | | first assignment to `i` | help: make this binding mutable: `mut i` 5 | println!("{}", i); 6 | i = 100; | ^^^^^^^ cannot assign twice to immutable variable error: aborting due to previous error |
Fixing Rust E0384 Error On Variables
To fix the Rust E0384 error, we need to use the mut keyword between the let keyword and the variable name. Consider the following codes.
1 | let mux i:i32 = 2; |
If we are to fix the previous codes, they would look as follows.
1 2 3 4 5 6 | fn main() { let mut i:i32 = 2; println!("{}", i); i = 100; println!("{}", i); } |
The new codes generate the following output.
1 2 | 2 100 |
So far we’ve tried primitive types. The Rust E0384 error can also happen when we change the properties of struct instances. Consider the following codes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | struct Person { last_name: String, first_name: String } fn main() { let person = Person { last_name: String::from("San Gabriel"), first_name: String::from("First") }; println!("{}, {}", person.last_name, person.first_name); person = Person { last_name: String::from("Doe"), first_name: String::from("John") } } |
In the first scenario, we are instantiating a struct and assigning to the same variable on line 15. When run the codes, we get the following error.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | C:/Users/karldev/.cargo/bin/cargo.exe run --color=always --package E0384 --bin E0384 Compiling E0384 v0.1.0 (C:\Users\karldev\Desktop\dev\blogs\rust\E0384) warning: value assigned to `person` is never read --> src\main.rs:15:5 | 15 | person = Person { | ^^^^^^ | = note: `#[warn(unused_assignments)]` on by default = help: maybe it is overwritten before being read? error[E0384]: cannot assign twice to immutable variable `person` --> src\main.rs:15:5 | 8 | let person = Person { | ------ | | | first assignment to `person` | help: make this binding mutable: `mut person` ... 15 | person = Person { | ^^^^^^ cannot assign twice to immutable variable error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0384`. error: could not compile `E0384`. To learn more, run the command again with --verbose. |
We now know how to fix the Rust E0384 error and the correct codes as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | struct Person { last_name: String, first_name: String } fn main() { let mut person = Person { last_name: String::from("San Gabriel"), first_name: String::from("First") }; println!("{}, {}", person.last_name, person.first_name); person = Person { last_name: String::from("Doe"), first_name: String::from("John") } } |
If we go back to the original codes and change one of the instance properties, we will get the same Rust E0384 error.
1 2 3 4 5 6 7 8 9 10 11 | fn main() { let person = Person { last_name: String::from("San Gabriel"), first_name: String::from("First") }; println!("{}, {}", person.last_name, person.first_name); person.first_name = String::from("KL"); } |
The codes generate the following error.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | C:/Users/karldev/.cargo/bin/cargo.exe run --color=always --package E0384 --bin E0384 Compiling E0384 v0.1.0 (C:\Users\karldev\Desktop\dev\blogs\rust\E0384) error[E0594]: cannot assign to `person.first_name`, as `person` is not declared as mutable --> src\main.rs:15:5 | 8 | let person = Person { | ------ help: consider changing this to be mutable: `mut person` ... 15 | person.first_name = String::from("KL"); | ^^^^^^^^^^^^^^^^^ cannot assign error: aborting due to previous error For more information about this error, try `rustc --explain E0594`. error: could not compile `E0384`. To learn more, run the command again with --verbose. Process finished with exit code 101 |
How to fix this? Simply use the mut keyword on the person variable.
Fixing Same Error On References
Variables that only hold references are also immutable, by default. Consider the following codes.
1 2 3 4 5 6 7 8 | fn main() { let myname: &String = &String::from("Karl"); println!("{}", myname); myname = &String::from("KL"); } |
When the Rust compiler checks the codes, we get the following error.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | C:/Users/karldev/.cargo/bin/cargo.exe run --color=always --package E0384 --bin E0384 Compiling E0384 v0.1.0 (C:\Users\karldev\Desktop\dev\blogs\rust\E0384) warning: value assigned to `myname` is never read --> src\main.rs:7:5 | 7 | myname = &String::from("KL"); | ^^^^^^ | = note: `#[warn(unused_assignments)]` on by default = help: maybe it is overwritten before being read? error[E0384]: cannot assign twice to immutable variable `myname` --> src\main.rs:7:5 | 3 | let myname: &String = &String::from("Karl"); | ------ | | | first assignment to `myname` | help: make this binding mutable: `mut myname` ... 7 | myname = &String::from("KL"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0384`. error: could not compile `E0384`. To learn more, run the command again with --verbose. Process finished with exit code 101 |
How do we fix this? The correct codes are as follows.
1 2 3 4 5 6 7 8 | fn main() { let mut myname: &String = &String::from("Karl"); println!("{}", myname); myname = &String::from("KL"); } |
In summary, variables in Rust are immutable, by default. To make variables mutable, we use the mut keyword.
This post is now part of Rust Programming Language For Beginners Tutorial.