Skip to content

RFC-011a: Реализация интерфейсов и динамическая диспетчеризация

Родительский RFC: RFC-011: Проектирование системы обобщённых типов

Данный RFC дополняет и заменяет части §2.1-2.4 RFC-011, касающиеся ограничений интерфейсов.

Краткое описание

RFC-011 определил систему обобщённых типов, но не детализировал механизм реализации интерфейсов. Этот документ дополняет:

  1. Объявление интерфейса: имя интерфейса записывается непосредственно в определении типа, без ключевого слова impl
  2. Реализация методов: поддерживаются как внутренние, так и внешние объявления
  3. Правила перегрузки: разные сигнатуры разрешены, одинаковые сигнатуры вызывают ошибку (перекрытие запрещено)
  4. Значения по умолчанию: = value записывается сразу после поля
  5. Динамическая диспетчеризация: сбор типов на этапе компиляции + сопоставление интерфейсов, без виртуальной таблицы

Основной дизайн:

yaoxiang
# Определение интерфейса
Animal: Type = {
    speak: (Self) -> String,
}

# Определение типа (внутреннее объявление)
Dog: Type = {
    x: Int = 10,
    Animal,  # Объявление интерфейса
    speak: (Self) -> String = "Woof",
}

# Внешнее объявление (перегрузка)
Dog.speak: (Self, volume: Int) -> String = "WOOF"

# Гетерогенный контейнер (динамическая диспетчеризация)
animals: List(Animal) = [Dog.new(), Cat.new()]
animals[0].speak()  # "Woof"

Устранённая сложность:

  • ❌ Нет ключевого слова impl
  • ❌ Нет аннотации dyn Trait + 'a
  • ❌ Нет виртуальной таблицы (сбор типов на этапе компиляции + enum-обёртка)
  • ❌ Нет перекрытия (единые правила перегрузки)

Мотивация

Недостатки RFC-011

RFC-011 определил систему обобщённых типов, но не детализировал:

ПроблемаОписание
Синтаксис объявления интерфейсаКак объявить, что тип реализует интерфейс?
Расположение реализации методовВнутреннее или внешнее объявление?
Правила перегрузкиКак обрабатывать одноимённые методы?
Синтаксис значений по умолчаниюКак задать значение по умолчанию для поля?
Динамическая диспетчеризацияКак реализовать гетерогенные контейнеры?

Цели проектирования

  1. Простота: не требуется ключевое слово impl
  2. Гибкость: реализация методов поддерживается внутри или снаружи
  3. Единство: правила перегрузки согласованы
  4. Удобство: лаконичный синтаксис значений по умолчанию
  5. Нулевые накладные расходы: без виртуальной таблицы, сбор типов на этапе компиляции

Сравнение с Rust

ХарактеристикаRustYaoXiang
Объявление интерфейсаimpl Animal for Dog { ... }Dog: Type = { Animal, ... }
Реализация методовВ блоке implВнутри или снаружи
ПерегрузкаНе поддерживаетсяПоддерживается (разные сигнатуры)
Значения по умолчаниюТребуется #[default]Записывается напрямую = value
Гетерогенный контейнерVec<Box<dyn Animal + 'a>>List(Animal)
Динамическая диспетчеризацияПоиск в виртуальной таблицеСбор типов на этапе компиляции

Предложение

1. Объявление интерфейса

Основное правило: имя интерфейса записывается непосредственно в определении типа, без ключевого слова impl.

yaoxiang
# Определение интерфейса
Animal: Type = {
    speak: (Self) -> String,
}

# Объявление типа реализует интерфейс
Dog: Type = {
    x: Int,
    Animal,  # Объявление интерфейса
}

Обработка компилятором:

  1. Распознать Animal как тип интерфейса
  2. Проверить, есть ли у Dog все методы, требуемые Animal
  3. Если проходит → сгенерировать доказательство реализации
  4. Если не проходит → ошибка компиляции

Эквивалентный синтаксический сахар:

yaoxiang
Dog: Type = {
    x: Int,
    Animal,  # Эквивалентно раскрытию методов Animal, но с сохранением метки источника
}

# Эквивалентно (но с сохранением информации об источнике)
Dog: Type = {
    x: Int,
    speak: (Self) -> String,  # Из Animal
}

Зачем нужна метка источника:

  • Прямое раскрытие теряет информацию об источнике
  • Метка источника используется для генерации доказательства реализации
  • Во время выполнения по доказательству находится правильный метод

2. Реализация методов

Основное правило: реализация методов поддерживается как во внутренних, так и во внешних объявлениях.

2.1 Внутреннее объявление

yaoxiang
Dog: Type = {
    x: Int = 10,
    Animal,
    speak: (Self) -> String = "Woof",  # Реализация метода внутри
}

2.2 Внешнее объявление

yaoxiang
Dog: Type = {
    x: Int,
    Animal,
}

# Реализация метода снаружи
Dog.speak: (Self) -> String = "Woof"

2.3 Смешанное объявление

yaoxiang
Dog: Type = {
    x: Int = 10,
    Animal,
    speak: (Self) -> String = "Woof",  # Часть методов внутри
}

# Часть методов снаружи
Dog.play: (Self) -> Void = { ... }

Обработка компилятором:

  1. Собрать все определения (внутренние и внешние)
  2. Сгруппировать по сигнатурам (перегрузка)
  3. Проверить наличие перекрытия (ошибка)
  4. Проверить полноту интерфейса
  5. Сгенерировать доказательство реализации

3. Перегрузка и перекрытие

Основные правила:

  • Разные сигнатуры → перегрузка → разрешено
  • Одинаковые сигнатуры → перекрытие → ошибка

3.1 Перегрузка (разрешено)

yaoxiang
# Разные типы параметров, перегрузка разрешена
Dog.speak: (Self) -> String = "Woof"
Dog.speak: (Self, volume: Int) -> String = "WOOF"

3.2 Перекрытие (запрещено)

yaoxiang
# Полностью одинаковые сигнатуры, перекрытие запрещено
Dog.speak: (Self) -> String = "Woof"
Dog.speak: (Self) -> String = "Bark"  # ❌ Ошибка: перекрытие не разрешено

Сообщение об ошибке:

Ошибка: Dog.speak(Self) -> String повторное определение
  --> файл2:5:1
  |
5 | Dog.speak: (Self) -> String = "Bark"
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ повторное определение
  |
  --> файл1:3:1
  |
3 | Dog.speak: (Self) -> String = "Woof"
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ первое определение

3.3 Единые правила

Внутренние и внешние объявления следуют одним и тем же правилам перегрузки/перекрытия:

yaoxiang
# Внутреннее объявление
Dog: Type = {
    x: Int,
    Animal,
    speak: (Self) -> String = "Woof",
}

# Внешнее объявление (перегрузка, разрешено)
Dog.speak: (Self, volume: Int) -> String = "WOOF"

# Внешнее объявление (перекрытие, запрещено)
Dog.speak: (Self) -> String = "Bark"  # ❌ Ошибка

4. Значения по умолчанию

Основное правило: = value записывается сразу после поля, без конструктора.

yaoxiang
Dog: Type = {
    x: Int = 10,  # Значение по умолчанию
    y: Int = 20,  # Значение по умолчанию
    Animal,
}

Конструктор, сгенерированный компилятором:

yaoxiang
# Все поля со значениями по умолчанию → генерируется конструктор без параметров
Dog.new: () -> Dog = { x: 10, y: 20 }

# Часть полей со значениями по умолчанию → генерируются конструкторы с частичными параметрами
Dog.new: (x: Int) -> Dog = { x: x, y: 20 }
Dog.new: (y: Int) -> Dog = { x: 10, y: y }

# Конструктор со всеми параметрами
Dog.new: (x: Int, y: Int) -> Dog = { x: x, y: y }

Внешнее объявление значений по умолчанию:

yaoxiang
Dog: Type = {
    x: Int,
    y: Int,
    Animal,
}

# Внешнее объявление значений по умолчанию
Dog.x: Int = 10
Dog.y: Int = 20

Эквивалентно внутреннему объявлению.

5. Реализация компилятора

5.1 Дескриптор интерфейса

rust
// Внутренняя структура компилятора: дескриптор интерфейса
struct InterfaceDescriptor {
    name: String,
    methods: Vec<MethodSignature>,
}

5.2 Определение типа

rust
// Внутренняя структура компилятора: определение типа
struct TypeDefinition {
    name: String,
    fields: Vec<Field>,
    interface_implementations: Vec<InterfaceImplementation>,
}

// Реализация интерфейса (с сохранением информации об источнике)
struct InterfaceImplementation {
    interface: InterfaceId,
    methods: HashMap<MethodId, FunctionBody>,
}

5.3 Доказательство реализации

rust
// Внутренняя структура компилятора: доказательство реализации
struct ImplementationProof {
    type_id: TypeId,
    interface_id: InterfaceId,
    methods: Vec<MethodPointer>,
}

5.4 Процесс компиляции

1. Парсинг определения типа, сбор объявлений интерфейсов
2. Сбор всех определений методов (внутренних и внешних)
3. Группировка по сигнатурам (перегрузка)
4. Проверка перекрытия (ошибка)
5. Проверка полноты интерфейса
6. Генерация доказательства реализации
7. Во время выполнения значение несёт доказательство реализации

6. Динамическая диспетчеризация

Основной дизайн: сбор типов на этапе компиляции + сопоставление интерфейсов, без виртуальной таблицы.

6.1 Гетерогенный контейнер

yaoxiang
# Определение интерфейса
Animal: Type = {
    speak: (Self) -> String,
}

# Определение типа
Dog: Type = {
    x: Int,
    Animal,
    speak: (Self) -> String = "Woof",
}

Cat: Type = {
    y: Int,
    Animal,
    speak: (Self) -> String = "Meow",
}

# Гетерогенный контейнер
animals: List(Animal) = [Dog.new(), Cat.new()]
animals[0].speak()  # "Woof"
animals[1].speak()  # "Meow"

6.2 Сбор типов на этапе компиляции

Основная стратегия: отслеживание принадлежности, инкрементное построение. Не производится сканирование всех типов, реализующих интерфейс, на этапе компиляции — вместо этого на каждой точке владения List(Animal) производится инкрементный сбор:

yaoxiang
// Точка конструирования
animals: List(Animal) = [Dog.new()]       // AnimalGroup = { Dog(Dog) }

// Точка append
animals.append(Cat.new())                  // Компилятор в точке append видит Cat → расширяет до { Dog, Cat }
animals.append(Bird.new())                 // Далее расширяет { Dog, Cat, Bird }

Обработка компилятором (инкрементная):

  1. Первый раз встречен List(I) при конструировании → генерируется начальный enum (все известные типы в текущей единице компиляции)
  2. При каждом append / push / присваивании по индексу → проверяется, есть ли тип значения уже в enum; если нет — расширяется enum вариант
  3. Для финального enum генерируется мономорфизированный код диспетчеризации match
  4. Кросс-единицы компиляции: на этапе линковки объединяются наборы вариантов enum из разных единиц

Автоматически сгенерированный enum:

yaoxiang
# Компилятор генерирует автоматически (пользователь не замечает)
AnimalGroup: Type = {
    Dog(Dog),
    Cat(Cat),
    Bird(Bird),    # ← append(Bird.new()) вызывает инкрементное расширение
}

# Внутри List(Animal) эквивалентен List(AnimalGroup)

6.3 Проверка сопоставления интерфейса

Ключевой инсайт: сопоставление интерфейса — это проверка на этапе компиляции, даже если типы загружаются из динамически подключаемых плагинов.

yaoxiang
# Система плагинов
plugin = load_plugin("bird.so")

# Компилятор проверяет: тип, возвращаемый plugin.create_bird(), должен реализовывать Animal
bird: Animal = plugin.create_bird()  # Проверка на этапе компиляции

# Помещение в гетерогенный контейнер —— точка append вызывает расширение enum
animals: List(Animal) = [Dog.new(), Cat.new()]
animals.append(bird)                 # Компилятор: (1) проверяет bird реализует Animal (2) расширяет enum

Обработка компилятором:

  1. Проверить тип возврата параметра append
  2. Убедиться, что этот тип реализует целевой интерфейс
  3. Если проходит → расширить enum, разрешить помещение
  4. Если не проходит → ошибка компиляции

6.4 Диспетчеризация во время выполнения

Последовательность вызова (match по enum на этапе компиляции, ImplementationProof уже стёрт):

animals[0].speak()

Сгенерированный компилятором match:
  match animals[0] {
    AnimalGroup.Dog(d) => d.speak(),
    AnimalGroup.Cat(c) => c.speak(),
    AnimalGroup.Bird(b) => b.speak(),
  }

Сравнение с виртуальной таблицей:

Виртуальная таблица (Rust)Enum на этапе компиляции (YaoXiang)
Способ поискаУказатель на виртуальную таблицу → указатель на методEnum match → прямой вызов
Накладные расходы во время выполненияОдно косвенное обращениеСравнение строк/branch (может быть оптимизировано CPU-предсказателем)
Генерация на этапе компиляцииВиртуальная таблицаEnum + match
Аннотации пользователяТребуются dyn Trait + 'aНе требуются
ImplementationProofНе применимоСтирается на этапе компиляции, не существует во время выполнения

Преимущества YaoXiang:

  • Не требуется аннотация бренда
  • Типовая безопасность на этапе компиляции
  • Прозрачность для пользователя (не нужно писать dyn Animal)
  • ImplementationProof — чистое понятие этапа компиляции, нулевые накладные расходы во время выполнения

6.5 Ограничения и область применения

Текущий период (одна единица компиляции): Полная поддержка. Отслеживание принадлежности охватывает все точки append/конструирования, enum строится инкрементно.

Кросс-единицы компиляции: На этапе линковки объединяются наборы вариантов enum из разных единиц. Дизайн использует тот же механизм, что и линковочный мономорфизм (единицы генерируют частичные enum, линковщик объединяет).

Не поддерживается: Динамические типы во время выполнения (полный утиный тип). Набор типов полностью известен на этапе компиляции.


Анализ вариантов использования

Базовая реализация интерфейса

yaoxiang
# Определение интерфейса
Animal: Type = {
    speak: (Self) -> String,
}

# Определение типа
Dog: Type = {
    x: Int = 10,
    Animal,
    speak: (Self) -> String = "Woof",
}

# Использование
dog = Dog.new()
dog.speak()  # "Woof"

Реализация множественных интерфейсов

yaoxiang
# Несколько интерфейсов
Animal: Type = {
    speak: (Self) -> String,
}

Pet: Type = {
    name: (Self) -> String,
}

# Тип реализует несколько интерфейсов
Dog: Type = {
    x: Int = 10,
    Animal,
    Pet,
    speak: (Self) -> String = "Woof",
    name: (Self) -> String = "Buddy",
}

# Использование
dog = Dog.new()
dog.speak()  # "Woof"
dog.name()   # "Buddy"

Обобщённые интерфейсы

yaoxiang
# Обобщённый интерфейс
Container: (T: Type) -> Type = {
    add: (self: &mut Self, item: T) -> Void,
    get: (self: &Self, index: Int) -> T,
}

# Реализация обобщённого интерфейса
IntList: Type = {
    data: Array(Int),
    Container(Int),
    add: (self: &mut Self, item: Int) -> Void = ...,
    get: (self: &Self, index: Int) -> Int = ...,
}

Гетерогенные контейнеры

yaoxiang
# Определение интерфейса
Animal: Type = {
    speak: (Self) -> String,
}

# Определение типа
Dog: Type = {
    x: Int,
    Animal,
    speak: (Self) -> String = "Woof",
}

Cat: Type = {
    y: Int,
    Animal,
    speak: (Self) -> String = "Meow",
}

# Гетерогенный контейнер
animals: List(Animal) = [Dog.new(), Cat.new()]

# Использование
for animal in animals {
    print(animal.speak())
}
# Вывод:
# Woof
# Meow

Система плагинов

yaoxiang
# Определение интерфейса
Plugin: Type = {
    name: (Self) -> String,
    execute: (Self) -> Void,
}

# Главная программа
main: () -> Void = {
    # Загрузка плагинов
    plugin1 = load_plugin("plugin1.so")
    plugin2 = load_plugin("plugin2.so")

    # Компилятор проверяет: plugin1 и plugin2 должны реализовывать интерфейс Plugin
    plugins: List(Plugin) = [plugin1, plugin2]

    # Выполнение всех плагинов
    for plugin in plugins {
        print(plugin.name())
        plugin.execute()
    }
}

Компромиссы

Преимущества

  1. Простота: не требуется ключевое слово impl
  2. Гибкость: реализация методов поддерживается внутри или снаружи
  3. Единство: правила перегрузки согласованы
  4. Удобство: лаконичный синтаксис значений по умолчанию
  5. Нулевые накладные расходы: без виртуальной таблицы, сбор типов на этапе компиляции
  6. Типовая безопасность: сопоставление интерфейса — проверка на этапе компиляции
  7. Прозрачность для пользователя: не нужно писать dyn Animal + 'a

Недостатки

  1. Ограничение: не поддерживаются динамические типы во время выполнения (полный утиный тип)
  2. Накладные расходы этапа компиляции: требуется генерация вариантов enum и кода диспетчеризации match для каждого интерфейса
  3. Набор типов: должен быть полностью известен на этапе компиляции (внутри одной единицы компиляции)

Меры смягчения

  1. Система плагинов: поддержка через проверку сопоставления интерфейса на этапе компиляции
  2. Набор типов: отслеживание принадлежности, инкрементное построение — сбор ведётся на каждой точке append/конструирования, а не глобальное сканирование
  3. Кросс-единицы компиляции: на этапе линковки объединяются наборы вариантов enum, используется тот же механизм, что и для линковочного мономорфизма

Альтернативные решения

РешениеПочему не выбрано
Ключевое слово implУвеличивает синтаксическую сложность
Виртуальная таблица (dyn Trait)Требует аннотации бренда ('a)
Полный утиный типНакладные расходы во время выполнения, отсутствие типовой безопасности
Ручная enum-обёрткаБольшая нагрузка на пользователя

Связь с RFC-009

Бренд и реализация интерфейса:

  • Реализация интерфейса находится на уровне типа, не затрагивает бренд
  • Бренд находится на уровне доказательства заимствования (RFC-009a)
  • Они ортогональны и не влияют друг на друга

Динамическая диспетчеризация и бренд:

  • Динамическая диспетчеризация использует доказательство реализации, не требует аннотации бренда
  • Доказательство реализации генерируется на этапе компиляции, во время выполнения отсутствует поиск
  • Это позволяет избежать сложности dyn Trait + 'a

Наследование интерфейсов

Интерфейс может включать другой интерфейс. Новый синтаксис не вводится — используется та же синтаксическая позиция, что и для объявления интерфейса типом:

yaoxiang
Animal: Type = {
    speak: (Self) -> String,
}

Pet: Type = {
    Animal,                       # Pet наследует Animal — без нового ключевого слова
    name: (Self) -> String,
}

# При реализации Dog интерфейса Pet должны выполняться все методы Animal и Pet
Dog: Type = {
    x: Int,
    Pet,
    speak: (Self) -> String = "Woof",  # Из Animal
    name: (Self) -> String = "Buddy",  # Из Pet
}

Принцип проектирования: Наследование существует, но его чрезмерное использование не поощряется. Основной способ комбинирования — через множественные объявления интерфейсов (Dog: Type = { Animal, Pet, ... }). Тип может напрямую объявить все интерфейсы, которые он удовлетворяет, без выражения через дерево наследования. Наследование интерфейсов используется только при наличии чёткой иерархии "is-a".

Обработка компилятором: Раскрытие цепочки наследования. Pet раскрывается в { все методы Animal, name: ... }. Когда Dog объявляет Pet, компилятор проверяет, что Dog удовлетворяет всем методам Animal и Pet.

Реализация методов по умолчанию

Интерфейс может предоставлять реализацию методов по умолчанию. Реализующий тип может выбрать перекрытие или наследование реализации по умолчанию:

yaoxiang
fmt: Type = {
    display: (Self) -> String,                      # Обязательно реализовать
    debug: (Self) -> String = Self.display(),       # ✅ Ссылка на метод того же интерфейса
    summary: (Self) -> String = f"<{Self.name}>",   # ❌ Ошибка компиляции: Self.name отсутствует в fmt
}

Основное ограничение: интерфейс не может предполагать реализацию вышестоящего. Методы по умолчанию могут ссылаться только на методы, объявленные в том же интерфейсе. Поля конкретного типа или методы других интерфейсов невидимы для методов по умолчанию — интерфейс является замкнутым контрактом и не может заглядывать в карманы реализующего типа. Нарушение этого ограничения вызывает ошибку непосредственно при определении интерфейса.

Наследование может предполагать реализацию нижестоящего: Когда интерфейс Pet наследует Animal, методы по умолчанию Pet могут использовать методы, объявленные в Animal — потому что они унаследованы, а значит гарантированно есть.

yaoxiang
Animal: Type = {
    speak: (Self) -> String,
}

Pet: Type = {
    Animal,                                              # Наследование
    name: (Self) -> String,
    introduce: (Self) -> String = Self.name() + " says " + Self.speak(),  # ✅ speak из унаследованного Animal
}

Поведение на этапе компиляции: При реализации типом интерфейса, для каждого метода:

  1. Тип предоставляет → используется метод типа
  2. Тип не предоставляет, в интерфейсе есть реализация по умолчанию → компилятор встраивает реализацию по умолчанию в тип (нулевые накладные расходы виртуальной таблицы)
  3. Тип не предоставляет, в интерфейсе нет реализации по умолчанию → ошибка компиляции

Принцип проектирования: Методы по умолчанию аналогичны автоматическому выводу Copy/Clone — компилятор генерирует автоматически при необходимости, пользователь может перекрыть. Не вводятся ключевые слова virtual/override/super.


Этапы реализации

ЭтапСодержаниеЗависимость
Phase 1Синтаксис объявления интерфейсаRFC-011
Phase 2Внутренние/внешние объявления методовPhase 1
Phase 3Правила перегрузки и перекрытияPhase 2
Phase 4Синтаксис значений по умолчаниюPhase 2
Phase 5Наследование интерфейсовPhase 3
Phase 6Реализация методов по умолчаниюPhase 5
Phase 7Генерация доказательства реализацииPhase 6
Phase 8Сбор типов на этапе компиляцииPhase 7
Phase 9Реализация динамической диспетчеризацииPhase 8

Запись решений по дизайну

РешениеРешениеПричинаДата
Синтаксис объявления интерфейсаИмя интерфейса записывается напрямую в теле типаУстранение ключевого слова impl, объявление интерфейса — естественная часть определения типа2026-06-14
Динамическая диспетчеризацияСбор типов на этапе компиляции + автоматическая генерация enumБез виртуальной таблицы, нулевой поиск во время выполнения, прозрачность для пользователя2026-06-14
Внешние объявления методовПоддерживаютсяЭквивалентная гибкость с внутренними объявлениями, компилятор отвечает за межфайловый сбор2026-06-14
ПерекрытиеЗапрещено (одинаковые сигнатуры вызывают ошибку)Перекрытие приводит к непредсказуемому поведению, перегрузка покрывает все случаи2026-06-14
Наследование интерфейсовПоддерживается, без нового синтаксисаТа же синтаксическая позиция, что для объявления интерфейса типом. Поощряется композиция (множественные объявления интерфейсов), не поощряются глубокие деревья наследования2026-07-03
Реализация методов по умолчаниюПоддерживается, аналогично автоматическому выводу Copy/CloneИнтерфейс предоставляет тело, компилятор встраивает в реализующий тип при необходимости; пользователь может перекрыть. Не вводятся virtual/override2026-07-03
Ограничение методов по умолчаниюПроверка при определении интерфейса: можно ссылаться только на методы того же интерфейса, нельзя предполагать реализацию вышестоящегоИнтерфейс — замкнутый контракт. Наследование может предполагать реализацию нижестоящего, но интерфейс не может предполагать поля/методы реализующего типа2026-07-03
Стратегия сбора типовОтслеживание принадлежности, инкрементное построение — сбор на каждой точке append/конструированияНе глобальное сканирование всех реализаторов, а инкрементное расширение enum в точках владения2026-07-03
ImplementationProofЧистое понятие этапа компиляции, стирается во время выполненияВо время выполнения используется enum match для диспетчеризации, доказательство используется только для проверки на этапе компиляции2026-07-03
Кросс-единицы компиляцииНа этапе линковки объединяются варианты enum из разных единицИспользуется тот же механизм, что и для линковочного мономорфизма, единицы генерируют частичные enum, линковщик объединяет2026-07-03

Открытые вопросы

  • [x] Наследование интерфейсов (интерфейс может наследовать другие интерфейсы) → Поддерживается, без нового синтаксиса. Pet: Type = { Animal, ... }
  • [x] Реализация методов по умолчанию (интерфейс может предоставлять реализацию по умолчанию) → Поддерживается, аналогично автоматическому выводу Copy. Интерфейс предоставляет тело, компилятор встраивает при необходимости
  • [ ] Продвинутое использование ограничений интерфейса (ассоциированные типы, GAT)
  • [ ] Взаимодействие с замыканиями (замыкания реализуют интерфейсы)

Список литературы


Жизненный цикл и судьба

СтатусРасположениеОписание
На рассмотренииdocs/design/rfc/review/Открыто для обсуждения сообщества