What is the ownership of *self in matching expression for impl of struct in rust

Viewed 499

I am using example from here

#[derive(Debug)]
enum List {
    Cons(i32, RefCell<Rc<List>>),
    Nil,
}

impl List {
    fn tail(&self) -> Option<&RefCell<Rc<List>>> {
        match *self {
            Cons(_, ref item) => Some(item),
            Nil => None,
        }
    }
}

Given the function signature is &self , self is of reference type pointing at List and *self is the List instance itself.

But I remember match also take ownership of the object it is matching, so doesn't that cause problem to the struct because the List instance is move to match and not give back?

Also isn't &self immutable, why are we able to move self to match?

1 Answers

match by itself does not move anything. Moves, copies or borrows happen in the branches of the match. Example:

let s = "test".to_string();
let a = s; // this is a move
// println!("{}", s); // ... so this is a "use after move" compilation error

but if we do:

match a { // this is allowed, a does not move anywhere
    // but in the branch...
    // this is an error: it would move a to res
    // res if res == "test".to_string() => "ok",
    // ^^^ moves value into pattern guard
    ref res if res == "test" => "ok", // with ref it's fine (we're
    // taking a by reference)
    _ => "ko",
}

playground

Note that you might indeed run into ownership issues in the match, but they are typically due to something you're doing after the match keyword.

For instance this fails:

// let's break the string in two pieces
match a.split_off(2)
//    ^ cannot borrow mutably

but it's because of the split_off that takes &mut self, not the match on the result.

Related