Skip to content

A3: at most one constructed superclass - #9

Merged
milyin merged 1 commit into
docs/validation-umbrellafrom
step/a3-supertype-split
Aug 6, 2026
Merged

A3: at most one constructed superclass#9
milyin merged 1 commit into
docs/validation-umbrellafrom
step/a3-supertype-split

Conversation

@milyin

@milyin milyin commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Third step of #6. Stacked on #8.

Supertypes were one undifferentiated list where any number of entries could
carry constructor arguments:

pub supertypes: Vec<(KtType, Option<KtCode>)>,

so class A : B(x), C(y) rendered happily. Kotlin rejects it — a class may
construct at most one superclass.

pub struct KtSupertypes {
    superclass: Option<KtSuperclass>,   // at most one, may be constructed
    interfaces: Vec<KtType>,            // any number, never constructed
}

API change

.supertype(ty, args) splits into .extends(ty, args) and .implements(ty).
The old single method left the role of a supertype implied by whether the
caller happened to pass arguments — an interface and an argument-less
superclass were indistinguishable. Now the caller says which it is.

A second .extends panics rather than silently dropping the first, which is
what a plain overwrite would have done.

Render order is now structural

The superclass always leads, whatever order the builder calls came in — Kotlin
wants it first, and that is no longer the caller's job to remember:

KtClass::class_("ZThing")
    .implements(KtType::cls("AutoCloseable"))
    .extends(KtType::cls("Base"), Some("ptr"))
    .implements(KtType::cls("Comparable"))
// class ZThing : Base(ptr), AutoCloseable, Comparable

Verification

All 43 pre-existing tests pass untouched. Three added: ordering, an
argument-less superclass (: Base, for a subclass with no primary constructor
that delegates from secondary ones), and the double-extends panic.
cargo clippy --all-targets clean.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Kotlin declaration model to make “at most one constructed superclass” structurally enforceable, matching Kotlin’s constraint that only one superclass may be constructed while any number of interfaces may be implemented.

Changes:

  • Replaces the single supertypes: Vec<(KtType, Option<KtCode>)> list with KtSupertypes { superclass, interfaces } plus a KtSuperclass payload.
  • Splits the builder API from .supertype(ty, args) into .extends(ty, args) and .implements(ty), and makes rendering order structural (superclass first).
  • Updates rendering/import collection and adds tests for ordering, bare superclass rendering, and double-extends panic behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/model.rs Introduces KtSuperclass/KtSupertypes and updates class/companion supertype modeling and builder APIs.
src/render.rs Switches supertypes rendering/import collection to the new KtSupertypes iterator and enforces superclass-first render ordering.
src/tests.rs Migrates tests to new API and adds coverage for ordering, bare superclass, and double-extends panic.
src/lib.rs Exports the new KtSuperclass and KtSupertypes types as part of the public API.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/model.rs
Comment on lines +448 to 452
/// Implement an interface.
pub fn implements(mut self, ty: KtType) -> Self {
self.supertypes.interfaces.push(ty);
self
}
Supertypes were one undifferentiated `Vec<(KtType, Option<KtCode>)>`
where any number of entries could carry constructor arguments, so
`class A : B(x), C(y)` — which Kotlin rejects, a class may construct at
most one superclass — rendered happily.

Split the list by role:

    pub struct KtSupertypes {
        superclass: Option<KtSuperclass>,   // at most one, may be constructed
        interfaces: Vec<KtType>,            // any number, never constructed
    }

`.supertype(ty, args)` is replaced by `.extends(ty, args)` and
`.implements(ty)`, which forces the caller to say which role a supertype
plays instead of leaving it implied by whether arguments were passed. A
second `.extends` panics rather than silently dropping the first.

Render order becomes structural: the superclass always leads, whatever
order the builder calls came in.

All 43 pre-existing tests pass untouched; three added.
@milyin
milyin force-pushed the step/a3-supertype-split branch from 42802fc to 808547c Compare August 6, 2026 11:40
@milyin
milyin force-pushed the step/a2-companion-type branch from 191a2c1 to 2aee77c Compare August 6, 2026 11:40
@milyin
milyin changed the base branch from step/a2-companion-type to docs/validation-umbrella August 6, 2026 11:40
@milyin
milyin merged commit b04f256 into docs/validation-umbrella Aug 6, 2026
2 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants