ошибка [E0597]: заимствованное значение не живет достаточно долго в цикле while - PullRequest
0 голосов
/ 06 марта 2020

Я действительно новичок в Rust, у меня возникают проблемы с исправлением этой ошибки, но это происходит только в том случае, если я закомментирую оператор while, в основном я запрашиваю значения из консоли и сохраняю их в HashMap:

use std::collections::HashMap;
use std::io;

fn main() {
    let mut customers = HashMap::new();
    let mut next_customer = true;
    while next_customer {
        let mut input_string = String::new();
        let mut temp_vec = Vec::with_capacity(3);
        let mut vec = Vec::with_capacity(2);
        println!("Insert new customer f.e = customer id,name,address:");
        io::stdin().read_line(&mut input_string);
        input_string = input_string.trim().to_string();
        for s in input_string.split(",") {
            temp_vec.push(s);
        }
        vec.push(temp_vec[1]);
        vec.push(temp_vec[2]);
        let mut key_value = temp_vec[0].parse::<i32>().unwrap();
        customers.insert(key_value, vec);
        next_customer = false;
    }
    println!("DONE");
}

Код приводит к ошибке

error[E0597]: `input_string` does not live long enough
  --> src/main.rs:14:18
   |
14 |         for s in input_string.split(",") {
   |                  ^^^^^^^^^^^^ borrowed value does not live long enough
...
20 |         customers.insert(key_value, vec);
   |         --------- borrow later used here
21 |         next_customer = false;
22 |     }
   |     - `input_string` dropped here while still borrowed

Ответы [ 2 ]

2 голосов
/ 06 марта 2020

Как уже говорили другие, проблема заключается в времени жизни и / или типе значений, помещаемых в карту клиентов.

customers.insert(key_value, vec);
   |         --------- borrow later used here

Часто это происходит, когда компилятор решил присвоить объекту тип что ты не ожидал. Чтобы выяснить, что он делает, вы можете вызвать тип и посмотреть, как он жалуется. Изменение кода на:

    let mut customers: HashMap<(),()> = HashMap::new();

Дает нам две соответствующие ошибки:

20 |         customers.insert(key_value, vec);
   |                          ^^^^^^^^^ expected `()`, found `i32`
...
20 |         customers.insert(key_value, vec);
   |                                     ^^^ expected `()`, found struct `std::vec::Vec`
   |
   = note: expected unit type `()`
                 found struct `std::vec::Vec<&str>`

Таким образом, тип, который компилятор хочет предоставить объекту наших клиентов, равен HashMap<i32, Vec<&str>>

Проблема в том, что время жизни &str должно быть внутри блока, так как мы нигде не храним String, и они не могут иметь время жизни 'static, поскольку они введены пользователем.

Это означает, что мы, вероятно, хотим HashMap<i32,Vec<String>>.

. Изменение кода для использования одного из них дает нам ошибку о том, что vec не имеет нужного типа: он выводится как Vec<&str>, но мы хотим Vec<String>.

У нас есть два варианта.

  1. Преобразуйте ve c в нужный тип непосредственно перед тем, как вставить его в карту, используя customers.insert(key_value, vec.iter().map(|s| s.to_string()).collect()). (Хотя вы можете захотеть извлечь его из переменной для ясности).

  2. Явно измените тип ve c на Vec<String>

Вариант 1 «просто работает». Хотя вариант 2 ведет нас по пути внесения аналогичных изменений все ближе и ближе к вызову read_line.

Как только вы определились с исправлением в варианте 1, вы можете удалить добавленные вручную аннотации типов. разработать исправление, если вы найдете их слишком шумными.

1 голос
/ 06 марта 2020

Проблема в том, что вы передаете ссылку на базовые значения & str, которые будут отброшены. Один из способов - взять входную строку, обрезать и разделить ее, а затем клонировать в другой вектор.

let temp_vec: Vec<String> = input_string.trim().split(",").map(|t| t.to_string()).collect();
vec.push(temp_vec[1].clone());
vec.push(temp_vec[2].clone());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...