"借来的价值不够活跃"似乎责怪错误的事

时间:2016-05-16 22:42:02

标签: rust

我正在计算一个单词出现在Macbeth中的次数:

use std::io::{BufRead, BufReader};
use std::fs::File;
use std::collections::HashMap;

fn main() {
    let f = File::open("macbeth.txt").unwrap();
    let reader = BufReader::new(f);
    let mut counts = HashMap::new();

    for l in reader.lines() {
        for w in l.unwrap().split_whitespace() {
            let count = counts.entry(w).or_insert(0);
            *count += 1;
        }
    }

    println!("{:?}", counts);
}

生锈barfs,说:

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:14:9
   |
11 |         for w in l.unwrap().split_whitespace() {
   |                  ---------- temporary value created here
...
14 |         }
   |         ^ temporary value dropped here while still borrowed
...
18 | }
   | - temporary value needs to live until here
   |
   = note: consider using a `let` binding to increase its lifetime

实际问题是w是一个引用,因此将其更改为w.to_string()可以解决它。当问题为l时,我不明白为什么Rust编译器将责任归咎于w。我怎么能推断w这里的问题是什么?

2 个答案:

答案 0 :(得分:9)

  

指责l

不是,真的。再次查看错误消息:

     for w in l.unwrap().split_whitespace() {
              ---------- temporary value created here

错误标记指向unwrapl的来电。

  

问题是w

不是,真的。 l的类型为Result<String>。当您致电unwrap时,您会收到String,然后split_whitespace会返回对该字符串的引用。这些引用仅与字符串一样存在,但是您的代码会尝试将它们放入一个比字符串更长寿的散列映射。问题是 l.unwrap() 的寿命不够长,而w只是对不能活得足够长的东西的引用。< / p>

从概念上讲,它与此代码的问题相同:

use std::collections::HashMap;

fn main() {
    let mut counts = HashMap::new();

    {
        let s = String::from("hello world");
        counts.insert(&s, 0);
    }

    println!("{:?}", counts);
}

其中也指向s,并表示它的寿命不长(因为它没有)。

正确的解决方案是将每个单词转换为String所拥有的HashMap所拥有的{/ 1}}:

for l in reader.lines() {
    for w in l.unwrap().split_whitespace() {
        counts.entry(w.to_string()).or_insert(0) += 1;
    }
}

答案 1 :(得分:5)

错误在这里是对的。 l会受到指责,因为只有w {和l} l.unwrap()并且l的生命时间不足以将其置于endDateObj.setMonth(startDateObj.getMonth() + monthsToBeAdded); 之内,var startDate = $('.pickupDate').datepicker('getDate'); var endDate = new Date(); endDate.setDate(startDate.getMonth() + monthsToAdd); $('input').val(endDate); 才会生存更高范围的hashmap。

在实践中,您只需要查看其他变量取决于编译器抱怨的变量的生命周期。

但Rust最近也在改进错误报告,所以我raise this case as potential bug