Очистка lexical и упорядочена: defer регистрирует работу в одной области, а ограниченный File-using использует тот же unwind stack.
Политика
defer call или defer { block } принадлежит ближайшей lexical scope. Действия выполняются LIFO при обычном выходе и когда return, Result propagation, break или continue пересекает область. Успешный File-using регистрирует implicit close раньше поздних body-defers, поэтому cleanup body идёт первым, close — последним.
Определённое поведение
Break value полностью вычисляется до unwind пересечённых scopes. Success scope while let очищается до следующего scrutinee. Initializer using выполняется один раз до появления binding; ошибка распространяется до регистрации cleanup. File binding неизменяем и child-scoped, хвост body отбрасывается, а пересекающий control закрывает ресурс до продолжения. Замыкание может сохранить File value, но implicit close всё равно происходит при scope exit.
Ограничения и явный отказ
defer не является catch/finally и не заменяет возвращаемый Err ошибкой cleanup. using допускает один File, одно bare name и не даёт значение. Explicit close не отменяет зарегистрированный close. Обычный runtime fault abort не гарантирует языком выполнение всех lexical defers или using cleanup.
Отложенная граница
Пользовательские disposable protocols, несколько ресурсов, resource transfer, asynchronous cleanup, cancellation, module-lifetime finalization, host-exception guarantees и portable behavior повторного/post-close File находятся вне политики.
Пример
function writeLog(message: string) -> Result<(), string> {
let file = open("app.log")?
defer { file.close() }
file.write(message)?
return Ok(())
}