Токены для конкретных переменных (Branding 1/4)
Что если мы хотим привязать токен к конкретной переменной?
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
struct Bytes {
bytes: Vec<u8>,
}
struct ProvenIndex(usize);
impl Bytes {
fn get_index(&self, ix: usize) -> Option<ProvenIndex> {
if ix < self.bytes.len() { Some(ProvenIndex(ix)) } else { None }
}
fn get_proven(&self, token: &ProvenIndex) -> u8 {
unsafe { *self.bytes.get_unchecked(token.0) }
}
}
fn main() {
let data_1 = Bytes { bytes: vec![0, 1, 2] };
if let Some(token_1) = data_1.get_index(2) {
data_1.get_proven(&token_1); // Работает нормально!
// let data_2 = Bytes { bytes: vec![0, 1] };
// data_2.get_proven(&token_1); // Паника! Можно ли это предотвратить?
}
}
-
Что если мы хотим привязать токен к конкретной переменной в нашем коде? Можно ли сделать это в системе типов Rust?
-
Мотивация: мы хотим иметь тип-токен, который представляет известный корректный индекс в массиве байтов.
Имея такие подтверждённые индексы, мы могли бы полностью отказаться от проверок границ, поскольку токены служили бы доказательством существования индекса.
Поскольку корректность индекса известна,
get_proven()может пропустить проверку границ.В этом примере ничто не мешает использовать подтверждённый индекс одного массива для другого массива. Если в этом случае индекс выходит за границы, это неопределённое поведение.
-
Продемонстрируйте: раскомментируйте строку
data_2.get_proven(&token_1);.Здесь код паникует! Мы хотим предотвратить такое «перекрёстное» использование токенов для индексов на этапе компиляции.
-
Спросите: как можно попробовать это сделать?
Ожидайте, что слушатели не придут к хорошей реализации сами, но будьте готовы экспериментировать и отрабатывать их предложения.
-
Спросите: какие есть альтернативы и почему они не годятся?
Ожидаемый ответ: проверка границ индексов во время выполнения, тем более что и
Vec::get, иBytes::get_indexуже используют проверку во время выполнения.Проверка границ во время выполнения не предотвращает саму ошибочную подстановку, а лишь гарантирует панику.
-
Такая привязка токенов называется Branding. Это продвинутая техника, которая расширяет применимость типов-токенов на большее число API.
-
GhostCell— известный пример использования этой техники, к нему мы вернёмся на следующих слайдах.