{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreih53lp24zrzosd5fpzlqvsdtcyewslv2gsy4cnsjv2n5uwjkfi24e",
"uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mp73p6srxnf2"
},
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreifiui2l7jzcazeoujqgtyurofvemfk757punphd7gwsezlnmrtbli"
},
"mimeType": "image/webp",
"size": 59712
},
"path": "/jazz_thumyat/understanding-mut-self-calls-on-temporaries-in-rust-5bm2",
"publishedAt": "2026-06-26T13:25:04.000Z",
"site": "https://dev.to",
"tags": [
"rust",
"learningrust"
],
"textContent": "`[T]` has the following `split_off` method. Notice that its receiver type is `&mut &'a Self`:\n\n\n\n pub fn split_off<'a, R: OneSidedRange<usize>>(\n self: &mut &'a Self,\n range: R,\n ) -> Option<&'a Self> {\n // ...\n }\n\n\nNow look at this code:\n\n\n\n let v = vec![1, 2, 3, 4, 5];\n let head = v.as_slice().split_off(..2);\n\n assert_eq!(head, Some([1, 2].as_slice()));\n\n\nThis may look confusing at first.\n\n`v.as_slice()` returns `&[i32]`, but `split_off()` expects `&mut &[i32]`. So where does the mutable reference come from?\n\nThe answer is that `v.as_slice()` creates a **temporary** value. In Rust, a temporary is a mutable place, so the compiler can automatically borrow it as `&mut`.\n\nYou can think of the code as if the compiler had written this:\n\n\n\n let mut temp = v.as_slice();\n temp.split_off(..2);\n\n\nThe mutable reference is taken to the temporary variable (`temp`), not to the original vector or slice. The vector `v` and the slice it produces are never mutated. Only the temporary variable is.\n\n## Proof that temporaries are mutable places\n\nA normal `let` binding is **immutable** unless you write `mut`. Because of that, the following code does **not** compile:\n\n\n\n let s: &[i32] = v.as_slice(); // no `mut`\n let _ = s.split_off(..2); // compiler error here\n\n\nThe compiler reports:\n\n\n\n error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable\n 13 | let _ = s.split_off(..2);\n | ^ cannot borrow as mutable\n help: consider changing this to be mutable\n 12 | let mut s: &[i32] = v.as_slice();\n\n\nThis shows the difference:\n\n * `let s: &[i32] = v.as_slice()` creates an immutable place, so Rust cannot take `&mut s`.\n * `v.as_slice()` creates a temporary, and a temporary is a mutable place, so Rust can automatically take `&mut` to call `split_off()`.\n\n\n\nThat is why `v.as_slice().split_off(..2)` compiles, while `s.split_off(..2)` does not unless `s` is declared with `mut`.",
"title": "Understanding `&mut &'a self` Calls on Temporaries in Rust"
}