rustpattern-matchingborrow-checkerrustrover

Why does a | (pipe) in a rust pattern match cause a "value used after move"?


EDIT: this question is based on a faulty premise. Turns out that this was a false-positive from my IDE; the code is perfectly valid. See answer below.


In rust, I'm a little confused about the semantics of the pipe | operator in match arms. Specifically, I have some code where using the pipe seems to cause use-after-move borrow checker errors.

Here's a minimal example; the first function doesnt_work will fail the borrow checker, the second one - which looks equivalent to me - works just fine.

fn doesnt_work(token_stream: &mut impl Iterator<Item = Token>) {
    for token in token_stream {
        match token {
            Token::ImplicitNode(data) | Token::ExplicitNode(data) =>
                _buildnode(data),
            _ => (),
}   }   }

fn works(token_stream: &mut impl Iterator<Item = Token>) {
    for token in token_stream {
        match token {
            Token::ImplicitNode(data) => _buildnode(data),
            Token::ExplicitNode(data) => _buildnode(data),
            _ => (),
}   }   }

#[derive(Debug, Eq, PartialEq, Clone)]
struct NodeData {}

#[derive(Debug, Eq, PartialEq, Clone)]
enum Token {
    ImplicitNode(NodeData),
    ExplicitNode(NodeData),
    OtherVariantsThatWeArentInterestedIn,
}

fn _buildnode(data: NodeData) { unimplemented!() }

To be clear, I'm not asking how to fix this; I'm seeking to understand why the borrow checker is complaining about the doesnt_work implementation here.

I had assumed that the pipe operator was basically shorthand for writing out multiple identical match arms, but apparently that's not right. So, what is the right way to think about this?


Solution

  • Answering my own question: the code compiles just fine; this is a bug in RustRover's (2024.1, 2024.2, 2024.3 EAP) borrow checker implementation.

    Here is the false positive: rustrover false positive