Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Токены для конкретных переменных (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 — известный пример использования этой техники, к нему мы вернёмся на следующих слайдах.