Extending borrowed lifetime for String slice

前端 未结 2 407
后悔当初
后悔当初 2020-12-12 00:39

I have a function that reads in a file, and for each line adds it to a HashSet of type &str, but I can\'t work out how to tell the borrow check

相关标签:
2条回答
  • 2020-12-12 00:50

    but I can't work out how to tell the borrow checker to increase the lifetime.

    It's impossible.


    The lifetime of a value, in C, C++ or Rust, is defined either:

    • by its lexical scope, if it is bound to an automatic variable
    • by its dynamic scope, if it is allocated on the heap

    You can create variables which reference this value, and if your reference lives longer than the value, then you have a dangling reference:

    • in C and C++, you better do nothing with it
    • in Rust, the compiler will refuse to compile your code

    In order to validate your program, the Rust compiler will require that you annotate the lifetime of your references; you will use lifetime annotations such as 'a in &'a T which allow naming a lifetime in order to document the relationship between the lifetime of multiple values.

    The operative word is document here: a lifetime is intangible and cannot be influenced, the lifetime annotation 'a is just a name to allow referring to it.


    So?

    Whenever you find yourself wanting to extend the lifetime of a reference, what you should be looking at instead is extending the lifetime of the referred... or simply not use a reference but a value instead.

    In this case, a simple solution is to return String instead of &str:

    fn build_collection_set(reader: &mut BufReader<File>) -> HashSet<String> {
        let mut collection_set = HashSet::new();
    
        for line in reader.lines() {
            let line = line.unwrap();
            if line.len() > 0 {
                collection_set.insert(line);
            }
        }
    
        collection_set
    }
    
    0 讨论(0)
  • 2020-12-12 01:01

    reader.lines() returns an iterator over owned Strings. But then in your for loop you cast these to borrowed references to &str. So when the iterator goes out of scope all your borrowed references become invalid. Consider using a HashSet<String> instead, which also is zero cost, because the Strings get moved into the HashSet and therefore aren't copied.

    Working example

    fn build_collection_set(reader: &mut BufReader<File>) -> HashSet<String> {
        let mut collection_set: HashSet<String> = HashSet::new();
    
        for line in reader.lines() {
            let line = line.unwrap();
            if line.len() > 0 {
                collection_set.insert(line);
            }
        }
        collection_set
    }
    
    0 讨论(0)
提交回复
热议问题