В нестабильном Rust уже несколько лет есть функция `arbitrary_self_types`. Давайте стабилизируем это!
Во-первых, что это за функция?
В обычном Rust мы можем вызывать методы для типа, даже если у нас не совсем есть тип, но вместо этого (скажем) `Rc` тип
Это также работает, если получатель метода (тип `self`) является интеллектуальным указателем, таким как `Rc` :
(Обратите внимание, что мы добавляем методы в блок `impl` для `MyThingy`, а не для `Rc`, даже если тип принимающей стороны `Rc`). Это работает для различных видов “умных указателей”, включая:
- Ссылки (очевидно)
- Rc и Arc
- Box
- Pin
Но они жестко запрограммированы. Ты не можешь этого сделать:
За исключением того, что вы можете скомпилировать, если используете `arbitrary_self_types` . Подобный этому:
Так что, в общем-то, все. `arbitrary_self_types` - это способ расширить разрешение методов Rust, чтобы справиться с косвенностью с помощью пользовательских интеллектуальных указателей. Это работает для всего, что реализует признак `Deref`. (Были бы возможны и другие реализации, но, похоже, на данный момент нет никаких существенных причин предпочесть другую реализацию.)
Почему это полезно?
Во-первых, кажется плохим, что этот поиск по методу жестко запрограммирован для `Box`, `Rc` и т.д. Когда Rust даже позволяет вам заменить асинхронный исполнитель, кажется, что жестко кодировать такие вещи противоречит нормам Rust. (Технически они не совсем жестко закодированы, они идентифицируются с помощью признака `lang_item Receiver`, который не предназначен для использования вне стандартной библиотеки Rust, так что это почти то же самое, что и жесткое кодирование.)
Но как насчет конкретных вариантов использования? Вот некоторые из них.
- Интеллектуальные ссылочные оболочки C++. Ссылки на C++ не имеют той же семантики, что и ссылки в Rust. Мы рискуем присвоить псевдоним `UB`, если выставляем ссылки на C++ как ссылки в Rust, и мы рискуем взрывом небезопасного кода, если выставляем ссылки на C++ как указатели в Rust. Нам нужна золотая середина, использующая интеллектуальный ссылочный тип, и мы не можем этого сделать без возможности обрабатывать вызовы методов для него.
- Аналогично, интерфейсы с несколькими языками сценариев нуждаются в пользовательском типе дескриптора, для которого были бы полезны вызовы методов. (То же самое относится и к Objective-C).
- Ядро Linux имеет пользовательский тип `Arc` и хочет иметь возможность вызывать методы для него.
- Приятно иметь возможность вызывать методы в оболочках новых типов, обертывающих что-то сложное.
- Это может заменить уродливый синтаксис (такой как `UnsafeCell::raw_get`) на более чистый синтаксис вызова метода
- Даже когда мы не хотим вызывать методы для произвольных типов self, это ограничивает качество диагностики, которую мы можем произвести, чтобы сказать, что это неправильно.
Итак, давайте стабилизируем ситуацию! Проблема с отслеживанием находится здесь. Изначально планировался RFC, но он был отложен: пришло время создать новый. На данный момент, похоже, нет никаких нерешенных вопросов по стабилизации работы, которая ведется каждую ночь. После этого существуют потенциальные расширения для поддержки вызовов методов без необходимости использования трейта `Deref`, но, похоже, нет никаких ограничений, которые мешают нам стабилизировать существующую поддержку.
Статья на list-site.