0

In The Rust Programming Language, there is a chapter which implements a minigrep. Instead of implementing a second search_case_insensitive() method, I wanted to implement a single API which would duplicate code. That attempt went something like this:

pub fn search<'a>(query: &str, lines: &'a str, case_insensitive: bool) -> Vec<&'a str> {
    let mut results = Vec::new();

    let mut query_to_search = query.clone();
    if case_insensitive {
        query_to_search = &query_to_search.to_lowercase();
    }   

    for line in lines.lines() {
        let mut line_to_search = line.clone();
        if case_insensitive {
            line_to_search = &line_to_search.to_lowercase();
        }   
        if line_to_search.contains(&query_to_search) {
            results.push(line);
        }   
    }   

    return results;
}

This results in a compiler error:

error[E0597]: borrowed value does not live long enough
--> src/lib.rs:49:28
  |
49|         query_to_search = &query_to_search.to_lowercase();
  |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value dropped here while still borrowed
  |                            |
  |                            temporary value does not live long enough
...
63| }
  | - temporary value needs to live until here
  |
  = note: consider using a `let` binding to increase its lifetime

And there is a similar error for this line:

line_to_search = &line_to_search.to_lowercase();

I understand that to_lowercase() is creating a new String object which is going out of scope after the if-condition, which is causing the borrow checker to throw an error.

How can I extend the lifetime of the String object returned by the to_lowercase() method so that it's not freed without creating a duplicate objects to hold the lowercase versions of the query/lines objects?

EXAMPLE:

pub fn search<'a>(query: &str, lines: &'a str, case_insensitive: bool) -> Vec<&'a str> {
    let mut results = Vec::new();

    let query_lower_case = query.to_lowercase(); // We are retaining this lower case object unnecessarily for case sensitive search
    let mut query_to_search: &str = &query.clone();
    if case_insensitive {
        query_to_search = &query_lower_case;
    }   

    for line in lines.lines() {
        let line_lower_case = line.to_lowercase(); // We are retaining this lower case object unnecessarily for case sensitive search
        let mut line_to_search: &str = &line.clone();
        if case_insensitive {
            line_to_search = &line_lower_case;
        }   
        if line_to_search.contains(&query_to_search) {
            results.push(line);
        }   
    }   

    return results;
}
skittish
  • 121
  • 10
  • One potential solution that I could think of: operate on actual objects instead of references. `let mut query_to_search: String = query.clone().to_string(); if case_insensitive { query_to_search = query.to_lowercase(); } for line in lines.lines() { let mut line_to_search: String = line.clone().to_string(); if case_insensitive { line_to_search = line.to_lowercase(); } if line_to_search.contains(&query_to_search) { results.push(line); } }` – skittish Jul 13 '18 at 21:32
  • The [duplicate applied to your question](https://play.rust-lang.org/?gist=692e19a21c818b825ecc95adab8ab9bb&version=stable&mode=debug&edition=2015) – Shepmaster Jul 13 '18 at 21:39
  • I agree that the duplicate applies. Just wanted to share what I ended up using. – skittish Jul 19 '18 at 19:37

0 Answers0