Зачем нам нужно сообщать компилятору время жизни, если он может обнаружить проблемное время жизни самостоятельно?

Я изучаю концепцию продолжительности жизни из Книги по коричневой ржавчине.

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

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

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

Пример и вывод компилятора:

fn shortest<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
  if x.len() < y.len() {
    x
  } else {
    y
  }
}
fn main() {
  println!("{}", shortest("hello", "rust"));
}

  |
1 | fn shortest<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
  |             --  -- lifetime `'b` defined here
  |             |
  |             lifetime `'a` defined here
...
5 |     y
  |     ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
  |
  = help: consider adding the following bound: `'b: 'a`

Потому что компилятор не знает, какое время жизни x и y должно иметь. Если вы присвоите им разные параметры времени жизни 'a и 'b и вернете ссылку со временем жизни 'a из функции, компилятор может в этом случае сделать вывод, что 'b: 'a, поэтому он скажет вам добавить это необходимое ограничение. Однако вы также можете сообщить компилятору, что ожидаете, что x и y будут иметь одинаковое время жизни: Детская площадка

Richard Neumann 20.08.2024 14:51

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

eggyal 20.08.2024 14:54

Связано: stackoverflow.com/a/67816688/5397009

Jmb 20.08.2024 14:57
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
3
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, мой вопрос: в этом случае компилятор определенно может обнаружить неправильное время жизни [...] Не означает ли это, что компилятор определенно знает время жизни ссылок, которые участвуют в этой функции. В этом смысле, почему программисты удосуживаются добавлять время жизни в сигнатуру функции?

Определить правильность данного решения уравнения гораздо проще, чем решить его. Другими словами, возможность компилятора проверить ваши пожизненные аннотации не означает, что он может создать их за вас.

...и даже скажи мне, как это исправить

Вот это правильный вопрос. И у него есть три ответа.

  1. Производительность. Если компилятору придется анализировать весь ваш код, чтобы определить его время жизни, это будет намного медленнее (это своего рода противоядие от следующей причины: оно объясняет, почему компилятор не может делать это локально (т. е. анализируя одну функцию каждый раз) , это объясняет, почему он не может сделать это глобально (т.е. путем совместного анализа всех функций).

  2. Точность. Предложения компилятора так же хороши, как и предложения, и даже там их еще можно улучшить, но они уже нигде не смогут заменить программу проверки заимствований. В этом простом примере они правы, но в более сложных фрагментах быстро запутываются. Баги заполняются почти каждый день. Когда дело доходит до диагностики, это проблемы, которые приятно улучшить качество жизни, но они нанесут вред, если компилятор будет использовать только их.

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

    В качестве подпричины нам нравится, чтобы языковые правила были простыми, потому что так их можно легко понять. Выводы о времени жизни кросс-функций совсем не просты для понимания.

  3. Читабельность. Rust принял явное решение провести четкую границу: внутри функции многое выводится (например, не только время жизни, но и типы). Но за пределами функций при определении границ API все должно быть явно (из этого есть несколько исключений, но большинство частей языка подчиняются этому правилу). Это помогает компилятору, но не меньше помогает и программисту. Когда вы видите функцию в Rust, вы сразу же знаете ее тип и требования к сроку службы, и это служит документацией и помогает прояснить цель.

Определить правильность данного решения уравнения гораздо проще, чем решить его. Итак, вы доказали, что P != NP? :-D

Richard Neumann 20.08.2024 20:18

@RichardNeumann Нет, я доказал, что мы не знаем, = P = NP.

Chayim Friedman 20.08.2024 22:22

Другие вопросы по теме