ejovo13
ejovo13

Reputation: 49

Apparent unused variable in match statement

I am implementing a simple library system to keep track of my pdfs.

I have a Subject enum and a Entry struct defined as follows:

pub enum Subject {

    Math,
    Programming,
    CompSci,
    Language,
    Misc,
    None
}

pub struct Entry {

    pub subject: Subject

}

I am trying to implement a function that will operate on a vector of Entry's and return a Vec<&Entry> whose entries match a given Subject.

I have a simple Library struct that is a wrapper around a Vec<Entry>:

pub struct Library {

    pub entries: Vec<Entry>

}

In order to do so, I need to iterate through entries and filter only the elements whose .subject field correspond to the desired subject. To accomplish this I have created a function that will return a predicate function.

Here is the get_subject function:

impl Library {
    
    pub fn get_subject(&self, subject: Subject) -> Vec<&Entry> {

        let pred = subject_pred(subject);
        self.entries.iter().filter(pred).collect::<Vec<&Entry>>()
    }
}

which calls the function subject_pred to create the correct predicate function:

// Return a PREDICATE that returns true when
// the passed ENTRY matches the desired SUBJECT
fn subject_pred(subject_UNUSED: Subject) -> impl FnMut(&&Entry) -> bool {
    |e: &&Entry| if matches!(&e.subject, subject_UNUSED) {
        true
    } else {
        false
    }
}

Here's the problem. This syntax compiles just fine but apparently the subject_UNUSED local variable in subject_pred is "unused". I am flabbergasted as my syntax clearly shows intent to match with the passed subject_UNUSED. When I test out this function on a vector of entries, the predicate always returns true (hence why I am receiving the "unused" warning) but I have literally no idea why.

If anyone could explain why the match statement is always matched, that would be greatly appreciated. I tried using a regular match statement but the same warning is popping up, and this is not the behavior that I am trying to code. If I don't include the subject_UNUSED in a traditional match statement, the compiler tells me that I have to cover the Math, Programming, CompSci, Language, Misc and None variants of my enum, which indicates to me that everything up until that point is good.

Upvotes: 3

Views: 1180

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 70860

You cannot match against a variable. What you've done is equivalent to

matches!(&e.subject, some_subject)

That matches any Subject, just like a wildcard (_), except it also captures it in the some_subject variable (can be used in a guard like matches!(&e.subject, subject_UNUSED if subject_UNUSED == ...)). Neither the captured variable nor the parameter (which is shadowed by it) are used.

What you need to do is to #[derive(PartialEq)] then use ==:

if e.subject == subject_UNUSED { ... }

By the way, your code also has other problems: you don't move into the closure and you're taking owned entries but produce borrowed.

Upvotes: 8

Related Questions