Valen: заимствование, которое помнит, куда указывает ссылка

· Программы
Эван Овадиа представил новый проверщик заимствований для языка Valen — он отслеживает «путь» каждой ссылки и ловит use-after-free на этапе компиляции, оставаясь гибче, чем у Rust.

cover.svg

Эван Овадиа, автор экспериментального языка Valen (наследника Vale), опубликовал разбор нового механизма контроля памяти — так называемого «группового заимствования» (group borrowing). Идея принадлежит его коллеге Нику Смиту и изначально задумывалась для языка Mojo, но там не прижилась. После публикации прошлогодней статьи концепция, по словам автора, разошлась широко: её переняли Carbon от Google (со ссылкой на оригинал), а также языки Ante, Zeta и Fang.

В чём суть

Классические проверщики заимствований, как в Rust, держатся на правиле «общее исключает изменяемое»: пока вы держите ссылку на объект, никто другой изменить его не вправе. Это конфликтует с тем, как мы привыкли писать на C++, где один владелец и множество обычных указателей на него — норма. Групповое заимствование смягчает правило до простого «никакого использования после освобождения».

Механизм строится на понятии «пути». При единоличном владении у каждого объекта ровно один владелец, а значит — один путь, например world.entities[].hp. Каждая ссылка запоминает путь объекта, на который указывает. Когда объект изменяют или уничтожают, компилятор помечает все ссылки, указывающие внутрь него, как недействительные; попытка их использовать даёт ошибку компиляции.

Что это даёт

Подход допускает образцы, трудные для обычных проверщиков: несколько локальных переменных или параметров, указывающих на один объект, с записью через любой из них; паттерн ScopeGuard; множество структур со ссылками на общую подсистему. Ошибки use-after-free при этом по-прежнему ловятся на этапе компиляции и без накладных расходов во время выполнения.

Важная тонкость: функция в сигнатуре объявляет, какие пути она изменяет. Параметр вида entity in world.entities[] mut означает, что менять можно только элементы внутри world.entities, но не весь мир. Это укрепляет границы API и, как надеется автор, даёт оптимизатору больше точной информации (для чего, возможно, придётся патчить LLVM). В Valen всего один вид ссылки на заимствование, а изменяемость определяется функцией, а не типом.

Совместимость с Rust

Отдельное внимание уделено вызову кода на Rust. Ссылку Valen можно временно превратить в &mut, если на эти данные нет других путей, иначе — только в &. А чтобы понимать, куда указывает ссылка, возвращённая из Rust, введены «путевые шаблоны» вроде in self.gem... — «куда-то внутрь self.gem».

Это первая из серии статей. Автор обещает отдельно рассказать, как к заимствованию подмешать подсчёт ссылок и generational references. Примечательно, что сам текст написан без участия ИИ — как подчёркивает Овадиа, если вы хотите, чтобы текст читали, напишите его сами.


Источник: Lobsters

Комментарии

Войдите, чтобы комментировать.

  • Пока нет комментариев.