【问题标题】:Textfile-parsing function fails to compile owing to lifetime/borrow error由于生存期/借用错误,文本文件解析函数无法编译
【发布时间】:2015-07-25 00:21:10
【问题描述】:

注意。这篇文章最初是包含两个问题的较大帖子的一部分(我认为这是一个以不同方式表现出来的错误),但为了遵守网站指南,我将它分成两个单独的帖子,这是第二个。第一个帖子是here

我正在尝试解析一个简单的配置文本文件,该文件每行包含一个三个单词的条目,布局如下:

ITEM name value
ITEM name value
//etc.

我已经在此处(和on the Rust playground)复制了执行解析(以及随后的编译错误)的函数:

use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;
use std::collections::HashMap;

fn main() { }

pub fn parse(path: &Path) -> config_struct {

    let file = File::open(&path).unwrap();
    let reader = BufReader::new(&file);
    let line_iterator = reader.lines();
    let mut connection_map = HashMap::new();
    let mut target_map = HashMap::new();

    for line in line_iterator {

        let line_slice = line.unwrap();
        let word_vector: Vec<&str> = line_slice.split_whitespace().collect();

        if word_vector.len() != 3 { continue; }

        // no match statement   
        connection_map.insert(word_vector[1], word_vector[2]);
    }

    config_struct { connections: connection_map, targets: target_map }
}

pub struct config_struct<'a>  {
    // <name, value>
    connections: HashMap<&'a str, &'a str>,
    // <name, value>
    targets: HashMap<&'a str, &'a str>,
}
<anon>:20:38: 20:48 error: `line_slice` does not live long enough
<anon>:20         let word_vector: Vec<&str> = line_slice.split_whitespace().collect();
                                               ^~~~~~~~~~
note: in expansion of for loop expansion
<anon>:17:5: 26:6 note: expansion site
<anon>:9:44: 29:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 9:43...
<anon>:9 pub fn parse(path: &Path) -> config_struct {
<anon>:10 
<anon>:11     let file = File::open(&path).unwrap();
<anon>:12     let reader = BufReader::new(&file);
<anon>:13     let line_iterator = reader.lines();
<anon>:14     let mut connection_map = HashMap::new();
          ...
<anon>:19:40: 26:6 note: ...but borrowed value is only valid for the block suffix following statement 0 at 19:39
<anon>:19         let line_slice = line.unwrap();
<anon>:20         let word_vector: Vec<&str> = line_slice.split_whitespace().collect();
<anon>:21 
<anon>:22         if word_vector.len() != 3 { continue; }
<anon>:23 
<anon>:24         // no match statement   
          ...
error: aborting due to previous error

本质上,我在使用借用检查器时遇到了问题;在我的代码中,word_vector 不是填充了不指向line_slice 的拥有对象吗?我认为unwrap()collect() 可能返回了一个引用,并且该引用超出了范围,但unwrapcollect 的Rust Docs 建议不然。

【问题讨论】:

    标签: rust text-parsing lifetime borrow-checker


    【解决方案1】:

    &amp;str 不能在没有存储它所包含的值的情况下存在——它纯粹是一个引用(因此是 &amp;)。

    从文件中读取你得到Strings; 这些提供存储。但是你正在丢弃它们,试图只返回字符串。

    也可以这样想:

    pub fn parse(path: &Path) -> config_struct<'???>;
    

    返回值应该有多长的生命周期?

    它没有抱怨该部分的唯一原因是它推断 Path 引用生命周期和返回值生命周期是相同的,这意味着您正在返回对 Path 内的某些内容的引用,而你不是。

    在这种情况下,您通常需要存储Strings 而不是&amp;strs。使用.to_owned() 将每个&amp;str 转换为String

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多