не может заимствовать `rdr` как изменяемый более одного раза за раз [при использовании библиотеки из груза] - PullRequest
0 голосов
/ 09 мая 2018

Выполнение кода ниже:

extern crate csv;  // csv = "1.0.0-beta.5"

use std::fs::File;

fn main() {
    let file_path = "file.csv";
    let file = File::open(file_path).unwrap();

    let mut rdr = csv::ReaderBuilder::new()
        .has_headers(true)
        .from_reader(file);
    let headers = rdr.headers().unwrap();
    println!("{:?}", headers);

    //println!("{:?}", rdr.headers().unwrap());

    for result in rdr.records() {
        let record = result.unwrap();
        println!("{:?}", record);
    }
}

Результат:

error[E0499]: cannot borrow `rdr` as mutable more than once at a time
  --> src/main.rs:17:19
   |
12 |     let headers = rdr.headers().unwrap();
   |                   --- first mutable borrow occurs here
...
17 |     for result in rdr.records() {
   |                   ^^^ second mutable borrow occurs here
...
21 | }
   | - first borrow ends here

error: aborting due to previous error

Если я изменю эти строки:

let headers = rdr.headers().unwrap();
println!("{:?}", headers);

//println!("{:?}", rdr.headers().unwrap());

к приведенному ниже коду работает:

//let headers = rdr.headers().unwrap();
//println!("{:?}", headers);

println!("{:?}", rdr.headers().unwrap());

Точно так же, если я clone заголовки, это также работает:

let headers = rdr.headers().unwrap().clone();
println!("{:?}", headers);

Я прочитал связанный вопрос , однако этот вопрос касался функции, которую пользователь написал сам, тогда как в этом случае использования функция была предоставлена ​​библиотекой.

Как следует обращаться с такими ошибками и что именно вызывает эту ошибку?

1 Ответ

0 голосов
/ 09 мая 2018

Если вы посмотрите на headers подпись , это:

fn headers(&mut self) -> Result<&StringRecord>;

Так что headers() изменчиво заимствует экземпляр ReaderBuilder. То же самое для records():

fn records(&mut self) -> StringRecordsIter<R>;

Оба возвращаемых типа этих функций содержат изменяемые ссылки на базовый экземпляр ReaderBuilder.

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

Возможные меры смягчения : Используйте headers() в отдельной области. Таким образом, ссылки отбрасываются до вызова records().

let mut rdr = csv::ReaderBuilder::new()
    .has_headers(true)
    .from_reader(file);
{
   let headers = rdr.headers().unwrap();
   println!("{:?}", headers);
   // `headers` is dropped here.
}

for result in rdr.records() {
    let record = result.unwrap();
    println!("{:?}", record);
}

Ошибка не возникает при clone, поскольку при клонировании создается и размещается другой новый объект. У вас больше нет нескольких изменяемых ссылок.

То же самое, когда вы используете println!("{:?}", rdr.headers().unwrap());, значение, возвращаемое headers(), немедленно удаляется, поэтому средство проверки заимствования не жалуется на множественные изменяемые ссылки.

Независимо от того, предоставляются ли функции библиотекой или созданы пользователем, не имеет значения. Единственное, что имеет значение, это подписи функций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...