Question
Rust mut Before a Variable Name vs After the Colon Explained
Question
In Rust, I saw these two function signatures:
fn modify_foo(mut foo: Box<i32>) {
*foo += 1;
*foo;
}
fn modify_foo(foo: &mut i32) {
*foo += 1;
*foo;
}
Why is mut placed differently in these examples?
I expected the first function might also be written like this:
fn modify_foo(foo: mut Box<i32>) {
/* ... */
}
What is the difference between putting mut before the parameter name and using &mut in the type?
Short Answer
By the end of this page, you will understand that Rust uses mut in two different roles:
mut foo: Tmakes the binding mutable, meaning the local variablefoocan be reassigned or used in ways that require a mutable binding.foo: &mut Tmeans the type is a mutable reference, so the function receives permission to mutate the value being borrowed.
These look similar, but they solve different problems. One changes how the local name behaves, and the other changes what kind of value is being passed in.
Concept
Rust separates two ideas that many beginners initially combine:
- Is the variable binding mutable?
- Is the value being accessed through a mutable reference?
These are not the same thing.
1. mut foo: T means a mutable binding
When mut appears before a parameter or variable name, it applies to the binding.
fn example(mut x: i32) {
x += 1;
}
Here, x is a local variable inside the function. Marking it mut means:
- you can reassign
x - you can call operations that require mutable access to the binding
This does not mean the caller's original value becomes mutable. Parameters are passed into the function, and mut only affects the local binding inside that function.
2. foo: &mut T means a mutable reference type
When mut appears as part of &mut T, it is part of the .
Mental Model
Think of Rust mutability as two separate labels:
Label 1: Can I move or change this handle?
This is the binding:
mut foo: T
Imagine foo is a labeled handle in your hand. If the handle is mutable, you can change how you use that handle, such as reassigning it.
Label 2: Does this handle let me edit the thing it points to?
This is the reference type:
foo: &mut T
Now imagine the handle points to a box in a storage room. A normal reference is like a viewing pass. A mutable reference is like an editing pass.
So:
mut foo: T= the local handle is changeablefoo: &mut T= the handle gives write access to the underlying value
You can even combine them:
fn example(mut x: &mut i32) {
*x += 1;
}
This means:
xis a mutable reference to ani32
Syntax and Examples
Core syntax
Mutable binding
fn add_one(mut x: i32) {
x += 1;
println!("{x}");
}
x is a local mutable variable inside the function.
Mutable reference type
fn add_one(x: &mut i32) {
*x += 1;
}
x is a mutable reference, so the function can modify the original value.
Owned value with mutable binding
fn update_box(mut b: Box<i32>) {
*b += 1;
println!("{}", *b);
}
b is owned by the function. Since the binding is mutable, the value inside the box can be changed through mutable dereferencing.
Borrowed value with mutable reference
Step by Step Execution
Consider this example:
fn add_to_box(mut b: Box<i32>) {
*b += 1;
println!("inside function: {}", *b);
}
fn add_to_ref(x: &mut i32) {
*x += 1;
println!("inside function: {}", *x);
}
fn main() {
let boxed = Box::new(5);
add_to_box(boxed);
let mut value = 5;
add_to_ref(&mut value);
println!("after function: {}", value);
}
What happens in add_to_box
1. boxed is created
let boxed = Box::();
Real World Use Cases
When mut variable: T is used
This is common when a function takes ownership of a value and modifies it before returning or consuming it.
Examples
- Updating an owned
Stringbefore returning it - Modifying a
Vec<T>passed by value - Working with
Box<T>or custom structs the function owns - Reassigning a parameter during processing
fn normalize(mut name: String) -> String {
name.make_ascii_lowercase();
name
}
When value: &mut T is used
This is common when a function should modify existing data without taking ownership.
Examples
- Updating a counter
- Appending to a shared buffer
- Mutating a struct passed from caller code
- In-place parsing, formatting, or transformation
fn increment(counter: &mut i32) {
*counter += 1;
}
Real Codebase Usage
In real Rust projects, developers choose between mutable bindings and mutable references based on ownership design.
Common pattern: mutate owned input, then return it
fn add_suffix(mut s: String) -> String {
s.push_str("_done");
s
}
This is useful in pipelines where ownership is being transferred anyway.
Common pattern: in-place mutation via &mut
fn reset_flag(flag: &mut bool) {
*flag = false;
}
This avoids moving ownership and makes the function's intent explicit.
Common pattern: mutating struct fields
struct Config {
debug: bool,
}
fn enable_debug(config: &mut Config) {
config.debug = true;
}
Guarding APIs with borrowing rules
A function that takes &mut T clearly says:
Common Mistakes
Mistake 1: Thinking mut always means the same thing
Many beginners assume all mut keywords do the same job.
fn a(mut x: i32) {}
fn b(x: &mut i32) {}
These are different:
mut xchanges the binding&mut i32changes the reference type
Mistake 2: Trying to write foo: mut T
This is invalid for normal parameter types.
fn broken(x: mut String) {}
Use this instead:
fn fixed(mut x: String) {}
Mistake 3: Forgetting that &mut changes the caller's value
Comparisons
| Syntax | What mut applies to | Owns the value? | Can modify caller's original value? | Common use |
|---|---|---|---|---|
mut x: T | The local binding | Yes, if T is passed by value | No, not directly | Mutating or reassigning an owned parameter |
x: &mut T | The reference type | No | Yes | In-place mutation through borrowing |
x: &T | Immutable reference type | No | No | Read-only borrowing |
let mut x = value; |
Cheat Sheet
Quick rules
mut name: T= mutable bindingname: &mut T= mutable reference typename: mut T= invalid syntax for ordinary types
Common patterns
fn a(mut x: i32) {
x += 1;
}
fn b(x: &mut i32) {
*x += 1;
}
fn c(mut s: String) -> String {
s.push('!');
s
}
fn d(s: &mut String) {
s.push('!');
}
What each means
mut xmeans the local variablexcan change&mut Tmeans the function can mutate the referencedT
FAQ
Why is mut foo: T different from foo: &mut T in Rust?
mut foo: T makes the local parameter binding mutable. foo: &mut T means the function receives a mutable reference and can modify the borrowed value.
Can I write foo: mut Box<i32> in Rust?
No. That is not valid Rust syntax. For a mutable binding, write mut foo: Box<i32>.
Does mut foo: T let a function change the caller's original value?
Not by itself. It only makes the local owned binding mutable inside the function.
Why can *foo += 1 work with mut foo: Box<i32>?
Because the function owns the Box<i32>, and the binding is mutable, so Rust allows mutable access to the boxed value.
Do I need mut before a parameter name if the type is &mut T?
Usually no. &mut T already allows mutation of the referenced value. Add mut before the name only if you need to reassign the local parameter variable itself.
Mini Project
Description
Build a small Rust program that demonstrates the difference between modifying an owned value and modifying a borrowed value. This project helps you see when mut affects only a local binding and when &mut affects the caller's data.
Goal
Create a program with one function that takes ownership of a String and another that mutably borrows a String, then observe how each function changes data.
Requirements
- Create one function that accepts
mut text: Stringand modifies it. - Create another function that accepts
text: &mut Stringand modifies it. - In
main, call both functions and print the results. - Show that the owned value is moved, while the borrowed value remains usable after the function call.
Keep learning
Related questions
Accessing Cargo Package Metadata in Rust
Learn how to read Cargo package metadata like version, name, and authors in Rust using compile-time environment macros.
Associated Types vs Generic Type Parameters in Rust: When to Use Each
Learn when to use associated types vs generic parameters in Rust traits, with clear rules, examples, and practical API design advice.
Can a Struct Extend Another Struct in Rust? Composition vs Inheritance
Learn how Rust handles struct reuse without inheritance, using composition, traits, and wrapper structs with practical examples.