In order to learn Rust I'm just writing trivial programs. Here I've written a LinkedList with an insert function that adds nodes to the end of the list. The function works as expected but I don't understand why my mut positioning in the struct is working as intended. Here's the code:
struct LinkedNode<'a, T> {
val: T,
next: Option<&'a mut LinkedNode<'a, T>>
}
impl<'a, T> LinkedNode<'a, T> {
fn new(val: T, next: Option<&'a mut LinkedNode<'a, T>>) -> LinkedNode<'a, T> {
LinkedNode { val, next }
}
fn insert(&mut self, node: &'a mut LinkedNode<'a, T>)
where T: Display {
let mut i = &mut self.next;
while let Some(n) = i {
i = &mut n.next;
}
*i = Some(node);
}
}
Everything makes sense except this part:
struct LinkedNode<'a, T> {
...
next: Option<&'a mut LinkedNode<'a, T>>
}
What I'm mutating here is next and not the &'a LinkedNode<'a, T> within it.
I would have expected to need the following code instead:
struct LinkedNode<'a, T> {
...
next: mut Option<&'a LinkedNode<'a, T>>
}
but this doesn't even compile. It gives me this error instead:
error: expected type, found keyword `mut`
--> src/lib.rs:5:11
|
3 | struct LinkedNode<'a, T> {
| ---------- while parsing this struct
4 | val: T,
5 | next: mut Option<&'a LinkedNode<'a, T>>
| ^^^ expected type
Can someone explain what's going on here to me please?
There's two meanings for
mut.In
&mut, it means a mutable, exclusive reference. An&mutvalue can change the contents it points to and give out&mutreferences to itself and its contents.In patterns, like
let mut x = y;,mutmeans that the binding is mutable. This value itself is mutable, and can give out&mutreferences to itself and its contents. There's alsoref mut, which creates an&mutbinding, but that doesn't apply here. You can also have&mutin a pattern, likelet &mut x = y, which destructures the reference, copying the value. This also doesn't apply here.Having a bare
mutin a type, like you tried above, doesn't make any sense. Immutable and mutable owned values (not references) are the same type. The only type-levelmutis&mut.It might make theoretical sense to have something like this.
However, this is not allowed either, because in rust, the mutability of each member is inherited from the owner of the whole struct.
If you struct was this.
Then you couldn't insert more than one node because you can't get a mutable reference to the node in
next, regardless of the mutability ofnextitself.Also, linked lists in rust are not a trivial program.