Определение небезопасной функции
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
/// Преобразует указатель, который может быть нулевым, в ссылку.
///
/// Возвращает `None`, если `p` равен null, иначе оборачивает `val` в `Some`.
fn ptr_to_ref<'a, T>(ptr: *mut T) -> Option<&'a mut T> {
if ptr.is_null() {
None
} else {
// SAFETY: `ptr` не равен null
unsafe { Some(&mut *ptr) }
}
}
«Это выглядит как безопасный код, однако на самом деле требуется небезопасный блок».
Обратите внимание на операцию разыменования, то есть на *p внутри небезопасного блока.
«Вызывающий код должен обеспечить, что ptr равен null или что его можно преобразовать в ссылку».
«Это может показаться контринтуитивным, но многие указатели нельзя преобразовать в ссылки».
«Среди прочего можно создать указатель, который указывает на произвольные биты, а не на корректное значение. Rust этого не допускает, и от этого должна защищаться сама функция».
«Итак, как проектировщики API, у нас есть два пути. Мы можем либо взять на себя ответственность за защиту от некорректных входных данных, либо переложить эту ответственность на вызывающий код с помощью ключевого слова unsafe».
«Первый путь трудный. Мы принимаем обобщённый тип T, то есть все возможные типы, реализующие Sized. Это очень много типов!»
«Поэтому второй путь выглядит разумнее».
Дополнительный материал (если останется время)
«Кстати, если вас интересуют подробности указателей и правила их преобразования в ссылки, в стандартной библиотеке много полезной документации. Также стоит посмотреть исходный код многих методов std::pointer».
«Например, функция ptr_to_ref с этого слайда на самом деле существует в стандартной библиотеке как метод as_mut у указателей».
Откройте документацию std::pointer.as_mut и обратите внимание на раздел Safety.