【问题标题】:rust E0597: borrowed value does not live lnog enoughrust E0597:借来的价值不够长
【发布时间】:2020-07-23 19:59:45
【问题描述】:

我正在尝试将算法从 javascript 重写为 rust。在以下代码中,我在 第 17 行处收到 borrowed value does not live enough 错误。

[dependencies]
scraper = "0.11.0"
use std::fs;

fn get_html(fname: &str) -> String {
    fs::read_to_string(fname).expect("Something went wrong reading the file")
}

pub mod diff_html {
    use scraper::{element_ref::ElementRef, Html};

    pub struct DiffNode<'a> {
        node_ref: ElementRef<'a>,
    }

    impl<'a> DiffNode<'a> {
        fn from_html(html: &str) -> Self {
            let doc = Self::get_doc(&html);
            let root_element = doc.root_element().to_owned();
            let diffn = Self {
                node_ref: root_element,
            };
            diffn
        }

        fn get_doc(html: &str) -> Html {
            Html::parse_document(html).to_owned()
        }
    }

    pub fn diff<'a>(html1: &str, _html2: &str) -> DiffNode<'a> {
        let diff1 = DiffNode::from_html(&html1);
        diff1
    }
}

fn main() {
    //read strins
    let filename1: &str = "test/test1.html";
    let filename2: &str = "test/test2.html";

    let html1: &str = &get_html(filename1);
    let html2: &str = &get_html(filename2);

    let diff1 = diff_html::diff(html1, html2);

    //write html
    //fs::write("test_outs/testx.html", html1).expect("unable to write file");
    //written output file.
}
warning: unused variable: `diff1`
  --> src\main.rs:43:9
   |
43 |     let diff1 = diff_html::diff(html1, html2);
   |         ^^^^^ help: if this is intentional, prefix it with an underscore: `_diff1`
   |
   = note: `#[warn(unused_variables)]` on by default

error[E0597]: `doc` does not live long enough
  --> src\main.rs:17:32
   |
14 |     impl<'a> DiffNode<'a> {
   |          -- lifetime `'a` defined here
...
17 |             let root_element = doc.root_element().to_owned();
   |                                ^^^--------------------------
   |                                |
   |                                borrowed value does not live long enough
   |                                assignment requires that `doc` is borrowed for `'a`
...
22 |         }
   |         - `doc` dropped here while still borrowed

如果可能的话,我想要一个详细的解释/解决方案。

【问题讨论】:

标签: rust reference lifetime ownership


【解决方案1】:

root_element 实际上是一个ElementRef,它引用了doc 中的对象,而不是实际拥有的对象。这里的对象doc 是在from_html 函数中创建的,因此归函数所有。因为doc 没有返回,所以在from_html 功能块结束时从内存中删除/删除。

ElementRef 需要 doc,它所引用的东西,当它从内存中返回时是活着的。

pub mod diff_html {
    use scraper::{element_ref::ElementRef, Html};

    pub struct DiffNode<'a> {
        node_ref: ElementRef<'a>,
    }

    impl<'a> DiffNode<'a> {
        fn from_html(html: &'a scraper::html::Html) -> Self {
            Self {
                node_ref: html.root_element(),
            }
        }
    }

    pub fn diff<'a>(html1_string: &str, _html2_string: &str) {
        let html1 = Html::parse_document(&html1_string);
        let diff1 = DiffNode::from_html(&html1);

        // do things here

        // at the end of the function, diff1 and html1 is dropped together
        // this way the compiler doesn't yell at you 
    }
}

您或多或少需要使用 diff 函数执行类似的操作,以使 HTML 和 ElementRef 的生命周期相同。

这种行为实际上是 Rust 保护内存中值的特性,这样它就不会泄漏或引用不引用错误的内存地址。

另外,如果您想操作可分离对象并玩参考(如 java、javascript、golang),我建议阅读此https://doc.rust-lang.org/book/ch15-05-interior-mutability.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多