0

Consider a function that searches for a pattern in a huge string of lines and returns the lines on which matches are found:

fn search_insensitive<'a>(query: &str, content: &'a str) -> Vec<&'a str> {
    let lowercase_query = query.to_lowercase();
    let mut matches: Vec<&str> = Vec::new();
    for line in content.lines() {
        let lowercase_line = line.to_lowercase();
        if lowercase_line.contains(&lowercase_query) {
            matches.push(line)
        }
    }
    matches
}

The question I have is around the line if lowercase_line.contains(&lowercase_query). Why is lowercase_query passed as a reference here? If I pass it as a value instead I get the error:

error[E0277]: expected a `std::ops::FnMut<(char,)>` closure, found `std::string::String`
 --> src/lib.rs:6:27
  |
6 |         if lowercase_line.contains(lowercase_query) {
  |                           ^^^^^^^^ expected an `FnMut<(char,)>` closure, found `std::string::String`
  |
  = help: the trait `std::ops::FnMut<(char,)>` is not implemented for `std::string::String`
  = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `std::string::String`

I checked the definition of the contains function:

pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
    pat.is_contained_in(self)
}

I don't see anywhere the need for contains to take a reference. Can someone explain this?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
leoOrion
  • 1,833
  • 2
  • 26
  • 52
  • *"pass it as a value"* you have to think more of *moving it* and it does not make sense to move a value just for checking if it contains something. That's why it is passed as reference. – hellow Feb 28 '19 at 07:06
  • Please **search** for your error message before asking about it. – Shepmaster Feb 28 '19 at 13:16

1 Answers1

2

Because Pattern is implemented for &'a String but not for String

impl<'a, 'b> Pattern<'a> for &'b String

But I still don't get the relation between the error message when I do pass it by value

Answered by Jmb

If you look at the docs for Pattern you will see that the last documented impl is for FnMut (char) -> bool, which might explain why the compiler chose to show that specific type. It would probably have been better if the compiler had said impl Pattern<'_>

Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • Thanks. I did not notice this. But I still don't get the relation between the error message when I do pass it by value. – leoOrion Feb 28 '19 at 07:13
  • 2
    If you look at the [docs for Pattern](https://doc.rust-lang.org/std/str/pattern/trait.Pattern.html#impl-Pattern%3C%27a%3E-5) you will see that the last documented impl is for `FnMut (char) -> bool`, which might explain why the compiler chose to show that specific type. It would probably have been better if the compiler had said `impl Pattern<'_>` – Jmb Feb 28 '19 at 08:18