ржавчина E0597: заимствованная стоимость не доживает - PullRequest
0 голосов
/ 11 апреля 2020

Я пытаюсь переписать алгоритм с javascript на ржавчину. В следующем коде я получаю заимствованное значение не живет достаточно долго ошибка в номер строки 17 .

[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

Я хочу подробное объяснение / решение, если возможно.

1 Ответ

0 голосов
/ 11 апреля 2020

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 для защиты значений в памяти, чтобы они не просачивались и не ссылались, не ссылаясь на неправильный адрес памяти.

Также, если вы хотите работать с отсоединяемыми объектами и играть со ссылкой (например, * 1024) *, javascript, golang) Предлагаю прочитать это https://doc.rust-lang.org/book/ch15-05-interior-mutability.html

...