В чем разница между этой функцией ржавчины о продолжительности жизни - PullRequest
1 голос
/ 01 апреля 2020

Концепция срока службы ржавчины для меня так запутана. У меня есть две функции ниже:

fn test1<'a, 'b: 'a>(x: &'a u32, y: &'b u32) -> &'a u32 {
    if x > y {
        x
    } else {
        y
    }
}

fn test2<'a, 'b: 'a>(x: &'b u32, y: &'a u32) -> &'a u32 {
    if x > y {
        x
    } else {
        y
    }
}

fn main() {
    let a = 5;

    {
        let b = 6;
        let c = test1(&a, &b);
        println!("{}", c);
    }

    {
        let b = 6;
        let c = test2(&a, &b);
        println!("{}", c);
    }
}

Эта программа может быть скомпилирована, и результат будет

6
6

Однако я не могу понять разницу между test1 и test2 Кто-нибудь может это объяснить?

1 Ответ

3 голосов
/ 01 апреля 2020

TLDR: Практической разницы нет.

Следует понимать, что показатели времени жизни Rust не являются строгим утверждением равенства, вместо этого они обозначают отношения «длиннее, чем». Поэтому, когда вы пишете:

fn foo<'a> (x: &'a i32)

Вы говорите компилятору, что: «Чтобы вызвать foo, должно существовать некоторое время жизни 'a, а x должен жить как минимум столько, сколько 'a (но x может жить дольше, чем это) ".

Возвращаясь к определениям вашей функции:

fn test1<'a, 'b: 'a>(x: &'a u32, y: &'b u32) -> &'a u32

Это означает:

  • Там должно существовать некоторое время жизни 'a, такое, что x живет по крайней мере столько же, сколько 'a (но может жить дольше).
  • Должно существовать некоторое время жизни 'b, которое по крайней мере столько, сколько 'a (но может быть таким же), так что y живет как минимум столько же, сколько 'b (но может жить дольше).
  • И возвращаемое значение не может жить дольше, чем 'a.

Поскольку на 'b нет других ограничений, компилятор всегда может выбрать 'b = 'a, и код будет компилировать, пока выполняются ограничения на 'a.

Когда вы вызываете функцию, компилятор ищет некоторые времена жизни 'a и 'b, которые соответствуют вышеуказанным ограничениям:

let a = 5;
{
    let b = 6;
    let c = test1(&a, &b);
    println!("{}", c);
}
  • Возвращаемое значение не может жить дольше, чем 'a, поэтому 'a должно начинаться с вызова функции (потому что возвращаемое значение не существует раньше ) и заканчиваются на закрывающей скобке в ближайшее время.
  • Здесь x равно a, а x должно жить как минимум столько же, сколько 'a. Поскольку a определено до вызова функции и все еще живо в закрывающей скобке, все в порядке.
  • Здесь y равно b, а y должно жить как минимум столько же, сколько и 'b. Если мы выберем 'b = 'a, то все в порядке, поскольку b определено до вызова функции и действует до закрывающей фигурной скобки.

Поэтому компилятор выбирает 'a == 'b, начиная с вызова функции и заканчивается на закрывающей скобке. Обе переменные a и b живут дольше, чем это, но это нормально, так как аннотации времени жизни для параметров являются нижними границами истинного времени жизни соответствующих переменных.

Примечание: то же самое рассуждение применимо к вашей второй функции и снова компилятор всегда может выбрать 'b = 'a всякий раз, когда соблюдаются все другие ограничения.

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