Подтвердить что ты не робот

Почему существует обязательный `T: 'a` для хранения ссылки` &' a T`?

С учетом этого кода:

struct RefWrapper<'a, T> {
    r: &'a T,
}

... компилятор жалуется:

ошибка: тип параметра T может быть недостаточно длинным

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

Я уже неоднократно видел эту ошибку, и до сих пор я просто слушал компилятор, и все получилось отлично. Однако, думая больше об этом, я не понимаю, зачем мне писать T: 'a.

Насколько я понимаю, уже невозможно получить такую ​​ссылку. Имея &'a T, следует, что существует объект типа T, который живет как минимум 'a. Но мы не можем хранить ссылки в указанном объекте, которые указывают на данные, имеющие более короткий срок службы, чем 'a. Это уже привело бы к ошибке компилятора.

В этом смысле уже невозможно получить a &'a T, где T не переживает 'a. Таким образом, дополнительная аннотация (T: 'a) не нужна.

Я прав? Я ошибаюсь, и если да: как я могу сломать код, если T: 'a не требуется?


Ссылки:

4b9b3361

Ответ 1

Это часть правил корректности. Тип &'a T является только корректным, если T: 'a ( "T переживает" a ", это необходимо, потому что у нас есть ссылка, с которой мы можем получить доступ в области 'a; указанное значение в T должен быть действительным, по крайней мере, для этой области).

struct RefWrapper<'a, T> - это общий тип, и он говорит, что вы можете ввести время жизни 'x и тип U и вернуть тип RefWrapper<'x, U>. Однако этот тип не обязательно хорошо сформирован или даже реализован, если не соблюдается требование T: 'a.

Это требование исходит из детали реализации; это не обязательно, так что T и 'a используются вместе, как &'a T в внутренних структурах. Требование стробирования скважины необходимо продвигать в открытый интерфейс структуры RefWrapper, так что требования к формированию типа RefWrapper<'_, _> являются общедоступными, даже если внутренняя реализация не является.

(Есть другие места, где возвращается одно и то же требование T: 'a, но подразумевается:

pub fn foo<'a, T>(x: &'a T) { }

мы заметим разницу: здесь тип &'a T тоже является частью публичного api.)