0

I'm about a week into learning Rust, and I'm struggling to understand some of the nuances of ownership. I have this code that works:

if let Some(node) = current {
    node.next = Some(Box::new(ListNode::new(sum_digit)));
    current = node.next.as_mut();
}

I thought that if let Some(node) = current was equivalent to assigning node the value of current.unwrap(). However, the code below doesn't work:

current.unwrap().next = Some(Box::new(ListNode::new(sum_digit)));
current = current.unwrap().next.as_mut();

I receive the following error message:

46  |         let mut current = head.as_mut();
    |             ----------- move occurs because `current` has type `Option<&mut Box<ListNode>>`, which does not implement the `Copy` trait
...
73  |                 current.unwrap().next = Some(Box::new(ListNode::new(sum_digit)));
    |                         -------- `current` moved due to this method call
74  |                 current = current.unwrap().next.as_mut();
    |                           ^^^^^^^ value used here after move

Is there a way to accomplish the same thing without using if let? I know that current is not None, so that is safe.

mattmunee
  • 19
  • 2
  • Well what happens if you do assign `node` the value of `current.unwrap()`? – mkrieger1 Sep 09 '22 at 15:19
  • @mkrieger1 I can use `let node = current.unwrap();`, then `node.next = Some(Box::new(ListNode::new(sum_digit)));`, then `current = node.next.as_mut();`, and that works. I guess the question then is how can I modify `next` element within `current` directly without creating this new variable `node`? – mattmunee Sep 09 '22 at 15:51
  • @mkrieger1 This still doesn't make any sense to me, since `current.unwrap().next = Some(Box::new(ListNode::new(sum_digit)));` works, but following that with `current = current.unwrap().next.as_mut();' causes the error message. – mattmunee Sep 09 '22 at 15:58
  • Does this answer your question? [Cannot move out of value which is behind a shared reference when unwrapping](https://stackoverflow.com/questions/32338659/cannot-move-out-of-value-which-is-behind-a-shared-reference-when-unwrapping) – Chayim Friedman Sep 11 '22 at 01:00

1 Answers1

3

I thought that if let Some(node) = current was equivalent to assigning node the value of current.unwrap().

current.unwrap() will unconditionally consume current. Thanks to match ergonomics if let doesn't have to do that.

Is there a way to accomplish the same thing without using if let? I know that current is not None, so that is safe.

current.as_mut().unwrap()? You're already using as_mut.

Option::as_mut will borrow the option, and create a new option with a reference to the contents of the existing one. You can consume that (by unwrapping) without affecting the original option.

Masklinn
  • 34,759
  • 3
  • 38
  • 57