RFC-033: Оператор отражения ^^
Справочные материалы:
Краткое описание
В данном документе предлагается ввести оператор ^^ в качестве точки входа для рефлексии, позволяющей получать метаданные типов и значений. ^^T возвращает статический объект метаданных типа T, а ^^obj возвращает динамические метаданные типа значения obj. Объект метаданных представляет собой обычный тип записи, содержащий информацию о имени, параметрах, полях и т.д., и может использоваться как во время компиляции, так и во время выполнения.
Мотивация
Зачем нужна эта функциональность?
- Сериализация/десериализация: требуется доступ к информации о полях типа для автоматической генерации кода сериализации
- Метапрограммирование во время компиляции: требуется доступ к структуре типов во время компиляции для генерации кода или проверки ограничений
- Отладка/инструменты во время выполнения: требуется вывод информации о типах во время выполнения для помощи в отладке
- Проверка типов во время выполнения: требуется определение отношений типов во время выполнения, например, «какого типа obj?»
Текущие проблемы
В настоящее время YaoXiang не имеет механизма рефлексии и не позволяет получать метаданные типов ни во время компиляции, ни во время выполнения. Если напрямую использовать .name, .fields для доступа к метаданным типа, это приведёт к конфликту с пользовательскими полями:
Person: Type = { name: String, age: Int }
# Если Person.name — это имя метаданных типа или поле name?
# Это приведёт к сложностям разбора и семантической неоднозначностиНеобходим синтаксис, не затрагивающий обычное пространство имён полей, для доступа к метаданным типа.
Предложение
Основной дизайн
Вводится оператор ^^ в качестве точки входа для рефлексии, чётко разделяющий обычный код и запросы метаданных.
Два варианта использования:
- Статическая рефлексия (применяется к типам):
^^Tвозвращает статический объект метаданных типаT - Динамическая рефлексия (применяется к значениям):
^^objвозвращает динамические метаданные типа значенияobj
Структура метаданных:
TypeMeta: Type = {
name: String,
params: Array(ParamMeta),
fields: Array(FieldMeta),
return_type: Type,
refinement: Option(Expr) # Some(Expr) во время компиляции, None во время выполнения
}
ParamMeta: Type = {
name: String,
type: Type
}
FieldMeta: Type = {
name: String,
type: Type
}Уровень вселенной: если T: Type_n, то ^^T: Type_{n+1}, что соответствует стандартным правилам повышения уровня вселенной в теории типов.
Приоритет: ^^ является унарным префиксным оператором с наивысшим приоритетом. ^^T.name эквивалентно ^^T).name.
Примеры
Базовое использование
Point: Type = { x: Float, y: Float }
# Статическая рефлексия
meta = ^^Point
print(meta.name) # "Point"
print(meta.fields.len) # 2
print(meta.fields[0].name) # "x"
print(fields[0].type) # Float
# Динамическая рефлексия (требуется включить рефлексию времени выполнения)
obj = Point(1.0, 2.0)
meta = ^^obj
print(meta.name) # "Point"Обобщённые типы
List: (T: Type) -> Type = { data: Array(T), length: Int }
# Рефлексия самого обобщённого типа
meta = ^^List
print(meta.name) # "List"
print(meta.params) # [{ name: "T", type: Type }]
# Рефлексия конкретного инстанциированного типа
meta = ^^List(Int)
print(meta.name) # "List(Int)"
print(meta.params) # []Функции
add: (a: Int, b: Int) -> Int = a + b
meta = ^^add
print(meta.name) # "add"
print(meta.params) # [{ name: "a", type: Int }, { name: "b", type: Int }]
print(meta.return_type) # IntУточнённые типы
Positive: (x: Int) -> Type = { x > 0 }
# Во время компиляции: refinement имеет значение Some(Expr)
meta = ^^Positive
print(meta.name) # "Positive"
print(meta.refinement) # Some(AST(x > 0))
# Во время выполнения: refinement имеет значение None (стирание)Использование в предикатах времени компиляции
# Проверка наличия полей у типа
HasFields: (T: Type) -> Type = { ^^T.fields.len > 0 }
# Проверка типа поля
HasFloatField: (T: Type) -> Type = {
exists field in ^^T.fields: field.type == Float
}
# Использование
obj: HasFields(Point) = Point(1.0, 2.0) # ✅ Проверка пройдена
# obj: HasFields(Int) = 42 # ❌ Проверка не пройденаПример сериализации
# Чистая функция времени компиляции: генерация JSON-строки
to_json: (T: Type) -> ((obj: T) -> String) = {
meta = ^^T
parts: Array(String) = []
for field in meta.fields {
# Генерация кода доступа к полю во время компиляции
parts.push("\"${field.name}\": ${obj.${field.name}}")
}
return "{" + parts.join(", ") + "}"
}
# Использование
point_to_json = to_json(Point)
print(point_to_json(Point(1.0, 2.0))) # '{"x": 1.0, 'y': 2.0}'Синтаксические изменения
| До | После |
|---|---|
| Нет рефлексии | ^^T получение метаданных типа |
| Нет рефлексии | ^^obj получение динамических метаданных типа значения |
Детальный дизайн
Влияние на систему типов
- Новые типы:
TypeMeta,ParamMeta,FieldMeta - Уровень вселенной: тип, возвращаемый
^^T, на один уровень выше, чемT - Взаимодействие с обобщениями: поддерживаются как
^^List, так и^^List(Int) - Взаимодействие с функциями:
^^addвозвращает метаданные функции (включая параметры и тип возврата) - Взаимодействие с уточнёнными типами:
^^Positiveвозвращает метаданные уточнённого типа (включая выражение уточнения)
Поведение во время выполнения
Рефлексия во время компиляции:
^^Tполностью вычисляется во время компиляции, результат встраивается как константа- Выражения уточнения доступны во время компиляции
Рефлексия во время выполнения:
- По умолчанию отключена, нулевые накладные расходы
- Включается через опцию компиляции
--enable-runtime-reflection - После включения
^^objвозвращает динамические метаданные типа - Выражения уточнения стираются в
Noneво время выполнения
Генерация по требованию + treeshake:
- Метаданные генерируются только для типов, фактически использующих
^^ - Для неиспользуемых типов метаданные не генерируются (treeshake)
Изменения в компиляторе
- Лексический анализатор: распознавание
^^как единого токена - Синтаксический анализатор: добавление правила для выражения с префиксом
^^ - Система типов: добавление определений типов
TypeMeta,ParamMeta,FieldMeta - Проверка типов: генерация экземпляра метаданных для каждого типа
- Вычислитель времени компиляции: поддержка вычисления
^^Tво время компиляции - Время выполнения (опционально): генерация RTTI для отражаемых типов
Обратная совместимость
- ✅ Существующий синтаксис не затрагивается:
^^— новый оператор, не конфликтующий с существующим синтаксисом - ✅ Существующие типы не затрагиваются: все типы автоматически поддерживают
^^ - ✅ Существующие функции не затрагиваются: функции могут использовать
^^, но не обязаны - ✅ Предикаты времени компиляции не затрагиваются:
^^Tв предикатах ведёт себя так же, как обычное содержимое - ✅ Время выполнения не затрагивается: рефлексия времени выполнения отключена по умолчанию, нулевые накладные расходы
Компромиссы
Преимущества
- Единообразие: функции, обобщения, уточнённые типы обрабатываются унифицированно
- Нулевые накладные расходы: рефлексия времени компиляции полностью стирается, рефлексия времени выполнения опциональна
- Интеграция с существующими системами: бесшовная интеграция с предикатами времени компиляции (RFC-027)
- Простота:
^^— чистый символ, не конфликтующий с пользовательскими идентификаторами - Генерация по требованию: оптимизация treeshake, нулевые накладные расходы для неиспользуемых типов
Недостатки
- Кривая обучения: необходимо понимать семантику
^^и структуру метаданных - Накладные расходы во время выполнения: при включении рефлексии времени выполнения увеличиваются затраты памяти (один указатель на каждый экземпляр)
- Сложность реализации: требуется модификация нескольких компонентов компилятора
Альтернативные решения
| Решение | Почему не выбрано |
|---|---|
Функция reflect(T) | Добавляет лишний идентификатор в область видимости, может быть перекрыт пользователем |
Функция type_info(T) | То же |
Один оператор ^ | Может конфликтовать с побитовыми операциями, в C++26 именно из-за конфликта и выбрали ^^ |
Символы @@, ## и др. | Не имеют прецедентов, менее понятны, чем ^^ |
Этапы реализации
| Этап | Содержание | Зависимости |
|---|---|---|
| Phase 1 | Разбор оператора ^^ времени компиляции | Нет |
| Phase 2 | Определение структуры данных TypeMeta | Phase 1 |
| Phase 3 | Генерация метаданных времени компиляции | Phase 2 |
| Phase 4 | Поддержка рефлексии времени выполнения (опционально) | Phase 3 |
| Phase 5 | Интеграция с предикатами времени компиляции | Phase 3 |
Зависимости
Phase 1 (Разбор)
↓
Phase 2 (Структура данных)
↓
Phase 3 (Метаданные времени компиляции)
↓
├────────────┐
↓ ↓
Phase 4 Phase 5
(Рефлексия (Предикаты
времени времени
выполнения) компиляции)Риски
- Конфликты разбора:
^^может конфликтовать с существующим синтаксисом (после анализа — конфликтов нет) - Влияние на производительность: генерация метаданных времени компиляции может увеличить время компиляции (оптимизация treeshake смягчает это)
- Накладные расходы во время выполнения: при включении рефлексии времени выполнения увеличиваются затраты памяти (генерация по требованию смягчает это)
Открытые вопросы
- [x] Область действия
^^: действует только на типы и значения, не на выражения - [x] Цепной доступ: поддерживается, возвращаемый объект метаданных из
^^Tпозволяет нормально обращаться к свойствам - [x] Сопоставление с образцом: поддерживается,
TypeMetaявляется обычным типом записи, можно использовать нормальное сопоставление с образцом - [x] Сравнение: поддерживается, объекты метаданных одного типа равны
- [x] Затраты памяти: генерация по требованию + оптимизация treeshake
Приложения
Приложение A: Журнал архитектурных решений
| Решение | Вердикт | Дата | Записал |
|---|---|---|---|
Область действия ^^ | Действует только на типы и значения, не на выражения | 2026-06-16 | 晨煦 |
| Цепной доступ | Поддерживается | 2026-06-16 | 晨煦 |
| Сопоставление с образцом | Поддерживается | 2026-06-16 | 晨煦 |
| Сравнение | Поддерживается, метаданные одного типа равны | 2026-06-16 | 晨煦 |
| Затраты памяти | Генерация по требованию + treeshake | 2026-06-16 | 晨煦 |
| Взаимодействие с обобщениями | Поддерживаются как ^^List, так и ^^List(Int) | 2026-06-16 | 晨煦 |
| Хранение выражений уточнения | Доступны во время компиляции, стираются в None во время выполнения | 2026-06-16 | 晨煦 |
Приложение B: Глоссарий
| Термин | Определение |
|---|---|
| Рефлексия | Способность доступа к метаданным типа во время выполнения или компиляции |
| Метаданные | Информация, описывающая структуру типа (имя, поля, параметры и т.д.) |
| RTTI | Run-Time Type Information — информация о типах времени выполнения |
| treeshake | Оптимизация компилятора, удаление неиспользуемого кода |
| Уточнённый тип | Тип с ограничивающими условиями, например Positive: (x: Int) -> Type = { x > 0 } |
Список литературы
- RFC-010: Унифицированный синтаксис типов
- RFC-011: Проектирование системы обобщённых типов
- RFC-027: Предикаты времени компиляции и унифицированная статическая верификация
- RFC-011a: Реализация интерфейсов и динамическая диспетчеризация
- Предложение по рефлексии C++26
Жизненный цикл и судьба
┌─────────────┐
│ Черновик │ ← Текущее состояние
└──────┬──────┘
│
▼
┌─────────────┐
│ На рассмотрении │ ← Открыто для обсуждения сообщества и обратной связи
└──────┬──────┘
│
├──────────────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Принят │ │ Отклонён │
└──────┬──────┘ └──────┬──────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ accepted/ │ │ rfc/ │
│(официальный │ │ (оставлен │
│ дизайн) │ │ на месте) │
└─────────────┘ └─────────────┘