<buttonid="sidebar-toggle"class="icon-button"type="button"title="Toggle Table of Contents"aria-label="Toggle Table of Contents"aria-controls="sidebar">
<inputtype="search"id="searchbar"name="searchbar"placeholder="Search this book ..."aria-controls="searchresults-outer"aria-describedby="searchresults-header">
<p><strong>Interior mutability</strong> means having a little bit of mutability on the inside. Remember how in Rust you need to use <code>mut</code> to change a variable? There are also some ways to change them without the word <code>mut</code>. This is because Rust has some ways to let you safely change values inside of a struct that is immutable. Each one of them follows some rules that make sure that changing the values is still safe.</p>
<p>First, let's look at a simple example where we would want this. Imagine a <code>struct</code> called <code>PhoneModel</code> with many fields:</p>
<p>It is better for the fields in <code>PhoneModel</code> to be immutable, because we don't want the data to change. The <code>date_issued</code> and <code>screen_size</code> never change, for example.</p>
<p>But inside is one field called <code>on_sale</code>. A phone model will first be on sale (<code>true</code>), but later the company will stop selling it. Can we make just this one field mutable? Because we don't want to write <code>let mut super_phone_3000</code>. If we do, then every field will become mutable.</p>
<p>Rust has many ways to allow some safe mutability inside of something that is immutable. The most simple way is called <code>Cell</code>. First we use <code>use std::cell::Cell</code> so that we can just write <code>Cell</code> instead of <code>std::cell::Cell</code> every time.</p>
<p>Then we change <code>on_sale: bool</code> to <code>on_sale: Cell<bool></code>. Now it isn't a bool: it's a <code>Cell</code> that holds a <code>bool</code>.</p>
<p><code>Cell</code> has a method called <code>.set()</code> where you can change the value. We use <code>.set()</code> to change <code>on_sale: true</code> to <code>on_sale: Cell::new(true)</code>.</p>
// 10 years later, super_phone_3000 is not on sale anymore
super_phone_3000.on_sale.set(false);
}
</code></pre></pre>
<p><code>Cell</code> works for all types, but works best for simple Copy types because it gives values, not references. <code>Cell</code> has a method called <code>get()</code> for example that only works on Copy types.</p>
<p>Another type you can use is <code>RefCell</code>.</p>
<p>A <code>RefCell</code> is another way to change values without needing to declare <code>mut</code>. It means "reference cell", and is like a <code>Cell</code> but uses references instead of copies.</p>
<p>We will create a <code>User</code> struct. So far you can see that it is similar to <code>Cell</code>:</p>
<p>This prints <code>RefCell { value: true }</code>.</p>
<p>There are many methods for <code>RefCell</code>. Two of them are <code>.borrow()</code> and <code>.borrow_mut()</code>. With these methods, you can do the same thing you do with <code>&</code> and <code>&mut</code>. The rules are the same:</p>
<ul>
<li>Many borrows is fine,</li>
<li>one mutable borrow is fine,</li>
<li>but mutable and immutable together is not fine.</li>
</ul>
<p>So changing the value in a <code>RefCell</code> is very easy:</p>
.replace_with(|_| if date < 2000 { true } else { false });
println!("{:?}", user_1.active);
<spanclass="boring">}
</span></code></pre></pre>
<p>But you have to be careful with a <code>RefCell</code>, because it checks borrows at runtime, not compilation time. Runtime means when the program is actually running (after compilation). So this will compile, even though it is wrong:</p>
let borrow_one = user_1.active.borrow_mut(); // first mutable borrow - okay
let borrow_two = user_1.active.borrow_mut(); // second mutable borrow - not okay
}
</code></pre></pre>
<p>But if you run it, it will immediately panic.</p>
<pre><codeclass="language-text">thread 'main' panicked at 'already borrowed: BorrowMutError', C:\Users\mithr\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\src\libcore\cell.rs:877:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\rust_book.exe` (exit code: 101)
</code></pre>
<p><code>already borrowed: BorrowMutError</code> is the important part. So when you use a <code>RefCell</code>, it is good to compile <strong>and</strong> run to check.</p>
<p><code>Mutex</code> is another way to change values without declaring <code>mut</code>. Mutex means <code>mutual exclusion</code>, which means "only one at a time". This is why a <code>Mutex</code> is safe, because it only lets one process change it at a time. To do this, it uses <code>.lock()</code>. <code>Lock</code> is like locking a door from the inside. You go into a room, lock the door, and now you can change things inside the room. Nobody else can come in and stop you, because you locked the door.</p>
<p>A <code>Mutex</code> is easier to understand through examples.</p>
let my_mutex = Mutex::new(5); // A new Mutex<i32>. We don't need to say mut
let mut mutex_changer = my_mutex.lock().unwrap(); // mutex_changer is a MutexGuard
// It has to be mut because we will change it
// Now it has access to the Mutex
// Let's print my_mutex to see:
println!("{:?}", my_mutex); // This prints "Mutex { data: <locked> }"
// So we can't access the data with my_mutex now,
// only with mutex_changer
println!("{:?}", mutex_changer); // This prints 5. Let's change it to 6.
*mutex_changer = 6; // mutex_changer is a MutexGuard<i32> so we use * to change the i32
println!("{:?}", mutex_changer); // Now it says 6
}
</code></pre></pre>
<p>But <code>mutex_changer</code> still has a lock after it is done. How do we stop it? A <code>Mutex</code> is unlocked when the <code>MutexGuard</code> goes out of scope. "Go out of scope" means the code block is finished. For example:</p>
} // mutex_changer goes out of scope - now it is gone. It is not locked anymore
println!("{:?}", my_mutex); // Now it says: Mutex { data: 6 }
}
</code></pre></pre>
<p>If you don't want to use a different <code>{}</code> code block, you can use <code>std::mem::drop(mutex_changer)</code>. <code>std::mem::drop</code> means "make this go out of scope".</p>
let mut mutex_changer = my_mutex.lock().unwrap(); // mutex_changer has the lock
let mut other_mutex_changer = my_mutex.lock().unwrap(); // other_mutex_changer wants the lock
// the program is waiting
// and waiting
// and will wait forever.
println!("This will never print...");
}
</code></pre></pre>
<p>One other method is <code>try_lock()</code>. Then it will try once, and if it doesn't get the lock it will give up. Don't do <code>try_lock().unwrap()</code>, because it will panic if it doesn't work. <code>if let</code> or <code>match</code> is better:</p>
<p><code>*my_mutex.lock().unwrap() = 6;</code> means "unlock my_mutex and make it 6". There is no variable that holds it so you don't need to call <code>std::mem::drop</code>. You can do it 100 times if you want - it doesn't matter:</p>
<p><code>RwLock</code> means "read write lock". It is like a <code>Mutex</code> but also like a <code>RefCell</code>. You use <code>.write().unwrap()</code> instead of <code>.lock().unwrap()</code> to change it. But you can also use <code>.read().unwrap()</code> to get read access. It is like <code>RefCell</code> because it follows the rules:</p>
<ul>
<li>many <code>.read()</code> variables is okay,</li>
<li>one <code>.write()</code> variable is okay,</li>
<li>but more than one <code>.write()</code> or <code>.read()</code> together with <code>.write()</code> is not okay.</li>
</ul>
<p>The program will run forever if you try to <code>.write()</code> when you can't get access:</p>