В отчёте на Hacker News описана ошибка корректности (soundness) в Rust, при которой требования к времени жизни структуры можно обойти с помощью ковариантного присваивания полей. Автор делится небольшой программой, в которой используется тип-обёртка Q<T>, содержащий Option<T> и реализацию Drop. Реализация Drop перемещает содержимое в статический Mutex<Vec<Box<dyn Any + Send>>>, что должно быть невозможно для заимствованного значения, не живущего в течение 'static.
В примере локальная String присваивается обёртке по ссылке внутри внутренней области видимости, поэтому заимствование должно закончиться при выходе из этой области. Поскольку поле обёртки ковариантно, компилятор принимает присваивание, и ссылка затем может храниться дольше времени жизни локальной переменной. Программа компилируется и выводит непричастное содержимое памяти вместо того, чтобы быть отклонённой.
При запуске под AddressSanitizer программа аварийно завершается с ошибкой stack-use-after-scope, что подтверждает фактическое разыменование висячей ссылки. По сообщению, проблема воспроизводится в текущих nightly-сборках и в стабильных выпусках начиная как минимум с 1.85.0. К публикации приложены ссылки на примеры в Compiler Explorer с санитайзерами и без них.
Находка указывает на брешь в корректности в том, как вариантность взаимодействует с хранением на основе Drop. Такие проблемы сопровождающие Rust считают приоритетными, поскольку безопасный код никогда не должен приводить к неопределённому поведению.
Часто задаваемый вопрос: почему эта программа на Rust компилируется, несмотря на висячую ссылку?
Ковариантность поля позволяет компилятору принять присваивание ссылки с более коротким временем жизни, а затем реализация Drop сохраняет эту ссылку в контейнере 'static, продлевая её использование за пределы времени жизни локальной переменной. Это ошибка корректности: компилятор должен был отклонить код.
Источник: Hacker News · Сводку подготовил HeadlinesBriefing