Реализация AnyMap и накладные расходы во время выполнения struct Port(u32);

Я читал "24 дня Rust" и пример AnyMap использования просто взорвал мой разум. Рассмотрим следующий код:

#[deriving(Show)]
struct Port(u32);

#[deriving(Show)]
struct ConnectionLimit(u32);

В нем говорится:

Здесь типы Port и ConnectionLimit являются абстракциями базового целого числа (без накладных расходов во время выполнения!).

Очень хорошо, я могу понять, как это может быть достигнуто. Все типы проверяются во время компиляции, а во время выполнения у нас есть только u32. Но как в таком случае создать карту из какого-то TypeId в Box<Any>? И как Any можно привести к любому подтипу, например u32?

исходный код на AnyMap довольно сложен и требует много метапрограммирования. Как это работает? Может быть, это просто ошибка в «24 днях Rust», а Port и ConnectionLimit на самом деле имеют накладные расходы во время выполнения?


person Aleksander Alekseev    schedule 14.04.2015    source источник


Ответы (1)


На самом деле, в C, C++ и других системных языках довольно часто используются разные типы с одним и тем же представлением в памяти.

В памяти:

  • u32 - это 4 последовательных байта памяти
  • Port - это 4 последовательных байта памяти
  • ConnectionLimit - это 4 последовательных байта памяти

Примечательно, что по сравнению со многими другими языками здесь нет «виртуальной таблицы» или другой посторонней информации, хранящейся в памяти для каждого экземпляра этих типов.

Что касается AnyMap, в точке, где вы сохраняете свой объект на карте, компилятор знает тип объекта и, следовательно, может предоставить правильный TypeId. Затем это необходимо сохранить вместе с данными объекта, потому что, если они когда-либо будут потеряны, их нельзя будет восстановить.

person Matthieu M.    schedule 14.04.2015
comment
Таким образом, TypeId — это просто константа, сгенерированная во время компиляции и используемая внутри универсальных функций получения/установки. И, согласно исходному коду, типы приводятся к/от Any в небезопасном блоке, что на самом деле довольно безопасно, потому что мы точно знаем, какой тип используется в каждой универсальной функции. Верно? - person Aleksander Alekseev; 14.04.2015
comment
@afiskon: Вы можете использовать Any без unsafe, насколько я знаю, однако он сам реализуется с unsafe за кулисами, потому что он манипулирует необработанной памятью. - person Matthieu M.; 14.04.2015
comment
Просто для ясности: функциональность anymap может быть реализована в совершенно безопасном коде; его можно просто сделать несколько более эффективным за счет использования там небезопасного кода, который действительно безошибочен, поскольку TypeId также хранится как ключ, а общие ограничения и т. д. известны статически. - person Chris Morgan; 14.04.2015