1. 1. Introduction
  2. 2. Введение
  3. 3. C чего начать
  4. 4. Изучение Rust
    1. 4.1. Угадайка
    2. 4.2. Обедающие философы
    3. 4.3. Вызов кода на Rust из других языков
  5. 5. Синтаксис и семантика
    1. 5.1. Связывание имён
    2. 5.2. Функции
    3. 5.3. Простые типы
    4. 5.4. Комментарии
    5. 5.5. Конструкция `if`
    6. 5.6. Циклы
    7. 5.7. Владение
    8. 5.8. Ссылки и заимствование
    9. 5.9. Время жизни
    10. 5.10. Изменяемость
    11. 5.11. Структуры
    12. 5.12. Перечисления
    13. 5.13. Конструкция `match`
    14. 5.14. Шаблоны сопоставления `match`
    15. 5.15. Синтаксис методов
    16. 5.16. Вектора
    17. 5.17. Строки
    18. 5.18. Обобщённое программирование
    19. 5.19. Типажи
    20. 5.20. Типаж `Drop`
    21. 5.21. Конструкция `if let`
    22. 5.22. Типажи-объекты
    23. 5.23. Замыкания
    24. 5.24. Универсальный синтаксис вызова функций
    25. 5.25. Контейнеры и модули
    26. 5.26. `const` и `static`
    27. 5.27. Атрибуты
    28. 5.28. Псевдонимы типов
    29. 5.29. Приведение типов
    30. 5.30. Ассоциированные типы
    31. 5.31. Безразмерные типы
    32. 5.32. Перегрузка операций
    33. 5.33. Преобразования при разыменовании
    34. 5.34. Макросы
    35. 5.35. Сырые указатели
    36. 5.36. Небезопасный код
  6. 6. Эффективное использование Rust
    1. 6.1. Стек и куча
    2. 6.2. Тестирование
    3. 6.3. Условная компиляция
    4. 6.4. Документация
    5. 6.5. Итераторы
    6. 6.6. Многозадачность
    7. 6.7. Обработка ошибок
    8. 6.8. Выбор гарантий
    9. 6.9. Интерфейс внешних функций
    10. 6.10. Типажи `Borrow` и `AsRef`
    11. 6.11. Каналы сборок
    12. 6.12. Using Rust without the standard library
  7. 7. Нестабильные возможности Rust
    1. 7.1. Плагины к компилятору
    2. 7.2. Встроенный ассемблерный код
    3. 7.3. Без stdlib
    4. 7.4. Внутренние средства
    5. 7.5. Элементы языка
    6. 7.6. Продвинутое руководство по компоновке
    7. 7.7. Тесты производительности
    8. 7.8. Синтаксис упаковки и шаблоны `match`
    9. 7.9. Шаблоны `match` для срезов
    10. 7.10. Ассоциированные константы
    11. 7.11. Пользовательские менеджеры памяти
  8. 8. Глоссарий
  9. 9. Syntax Index
  10. 10. Библиография

Безразмерные типы

Большинство типов имеют определённый размер в байтах. Этот размер обычно известен во время компиляции. Например, i32 — это 32 бита, или 4 байта. Однако, существуют некоторые полезные типы, которые не имеют определённого размера. Они называются «безразмерными» или «типами динамического размера». Один из примеров таких типов — это [T]. Этот тип представляет собой последовательность из определённого числа элементов T. Но мы не знаем, как много этих элементов, поэтому размер неизвестен.

Rust понимает несколько таких типов, но их использование несколько ограничено. Есть три ограничения:

  1. Мы можем работать с экземпляром безразмерного типа только с помощью указателя. &[T] будет работать, а [T] — нет.
  2. Переменные и аргументы не могут иметь тип динамического размера.
  3. Только последнее поле структуры может быть безразмерного типа; другие — нет. Варианты перечислений не могут содержать типы динамического размера в качестве данных.

А зачем это всё? Поскольку мы можем использовать [T] только через указатель, если бы язык не поддерживал безразмерные типы, мы бы не смогли написать такой код:

impl Foo for str {Run

или

impl<T> Foo for [T] {Run

Вместо этого, вам бы пришлось написать:

impl Foo for &str {Run

Таким образом, данная реализация работала бы только для ссылок, и не поддерживала бы другие типы указателей. А реализацию для безразмерного типа смогут использовать любые указатели, включая определённые пользователем умные указатели (позже, когда будут исправлены некоторые ошибки).

?Sized

Если вы пишете функцию, принимающую тип динамического размера, вы можете использовать специальное ограничение ?Sized:

struct Foo<T: ?Sized> {
    f: T,
}Run

Этот ? читается как «Т может быть размерным (Sized)». Он означает, что это ограничение особенное: оно разрешает использование некоторых типов, которые не могли бы быть использованы в его отсутствие. Таким образом, оно расширяет множество подходящих типов, а не сужает его. Это можно представить себе как если бы все типы T неявно были размерными (T: Sized), а ? отменял это ограничение по умолчанию.