Используя одно и то же время жизни для указателя и параметра времени жизни структуры, на которую он указывает - PullRequest
3 голосов
/ 28 апреля 2020

Рассмотрим следующее:

struct Str<'a> {
    s: &'a str,
}

fn f1<'a>(_: &'a mut Str<'a>) {}

fn f2<'a, 'b>(_: &'a mut Str<'b>) {}

fn main() {
    let s = "hello".to_string();
    let mut a = Str {
        s: &s,
    };

    f1(&mut a);
    // f2(&mut a);

    let t: &Str = &a;
}

f2 использует два разных времени жизни, как это было бы, когда я их исключил, что прекрасно работает.

В этот момент я подумал, что время жизни 'a относится к времени жизни &mut a, а 'b относится к времени жизни &s.

А потом я написал f1, который использует один параметр времени жизни, подозревая, что время жизни 'a будет означать меньшее время жизни &mut a и время жизни &s.

Однако этот f1 завершается ошибкой со следующей ошибкой:

error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
  --> src/main.rs:21:19 
   |
18 |     f1(&mut a);
   |        ------ mutable borrow occurs here
...
21 |     let t: &Str = &a;
   |                   ^^
   |                   |
   |                   immutable borrow occurs here
   |                   mutable borrow later used here

меня смущает ошибка: почему a по-прежнему заимствовано как изменяемое после вызова f1?

Почему это не получается и что означает сообщение об ошибке?

1 Ответ

2 голосов
/ 28 апреля 2020

Почему a по-прежнему заимствовано как изменяемое после вызова f1?

fn main() {
    //                  scope of s ---\
    let s = "hello".to_string(); //   |
    let mut a = Str {            //   |
        s: &s,                   //   |
    };                           //   |
                                 //   |
    //        f1 borrows a until ---\ |
    f1(&mut a);                  // | | 
    // but it's used here \         | |
    let t: &Str = &a; //  X      // | |
                                 // X X
}

Область действия s находится до конца main. Из-за аннотаций времени жизни аргументов f1 изменяемая ссылка &mut a имеет время жизни, привязанное к области действия s, что означает, что f1 занимает a для всей области действия s .

Это не проблема с неизменяемыми ссылками, потому что более длинные времена жизни могут быть приведены к более коротким; другими словами, времена жизни неизменяемых ссылок ковариантны . Но время жизни изменяемых ссылок инвариантно . Это означает, что их нельзя принуждать к сокращению (или увеличению) времени жизни.

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