From 496785f5ee4f2bac37e95abb0fecb110600c6b1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Raddum=20Berg?= Date: Sat, 2 May 2026 16:12:36 +0200 Subject: [PATCH 1/2] Kotlin wrapper updates + remove ambiguous OperationRead.run overload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Why: typr's RC6 migration depends on these — without them the generated Kotlin code can't call into the wrappers, and Scala 3 can't disambiguate the OperationRead.run overloads. - foundationskt.Bijection: add public companion `of(forward, backward)` so codegen can emit `Bijection.of(...)` returning the Kotlin wrapper (the chain of `DbType.to(Bijection.of(...))` then types correctly). - foundationskt.Connection: expose `javaConnection` (was internal) so typr-dsl-kotlin can unwrap when delegating to the Java DSL. - foundations.OperationRead: drop the `run(ConnectionRead)` overload inherited via Operation.run(Connection) was ambiguous in Scala 3. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/kotlin/dev/typr/foundationskt/Bijection.kt | 3 +++ .../src/kotlin/dev/typr/foundationskt/Connection.kt | 2 +- .../src/java/dev/typr/foundations/OperationRead.java | 5 ----- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/foundations-jdbc-kotlin/src/kotlin/dev/typr/foundationskt/Bijection.kt b/foundations-jdbc-kotlin/src/kotlin/dev/typr/foundationskt/Bijection.kt index 0a1b0f65..a6a81291 100644 --- a/foundations-jdbc-kotlin/src/kotlin/dev/typr/foundationskt/Bijection.kt +++ b/foundations-jdbc-kotlin/src/kotlin/dev/typr/foundationskt/Bijection.kt @@ -9,6 +9,9 @@ class Bijection(val underlying: dev.typr.foundations.Bijection) { fun inverse(): Bijection = Bijection(underlying.inverse()) companion object { + fun of(forward: (A) -> B, backward: (B) -> A): Bijection = + Bijection(dev.typr.foundations.Bijection.of(forward, backward)) + internal fun optionalToNullable(): dev.typr.foundations.Bijection, T?> = dev.typr.foundations.Bijection.optionalToNullable() diff --git a/foundations-jdbc-kotlin/src/kotlin/dev/typr/foundationskt/Connection.kt b/foundations-jdbc-kotlin/src/kotlin/dev/typr/foundationskt/Connection.kt index 0f724e68..6b3e4e39 100644 --- a/foundations-jdbc-kotlin/src/kotlin/dev/typr/foundationskt/Connection.kt +++ b/foundations-jdbc-kotlin/src/kotlin/dev/typr/foundationskt/Connection.kt @@ -15,7 +15,7 @@ open class ConnectionRead(val underlying: dev.typr.foundations.ConnectionRead) { class Connection(private val java: dev.typr.foundations.Connection) : ConnectionRead(java) { - internal val javaConnection: dev.typr.foundations.Connection get() = java + val javaConnection: dev.typr.foundations.Connection get() = java fun execute(op: Operation): T = java.execute(op.underlying) diff --git a/foundations-jdbc/src/java/dev/typr/foundations/OperationRead.java b/foundations-jdbc/src/java/dev/typr/foundations/OperationRead.java index abdc24a5..df7f2c36 100644 --- a/foundations-jdbc/src/java/dev/typr/foundations/OperationRead.java +++ b/foundations-jdbc/src/java/dev/typr/foundations/OperationRead.java @@ -17,11 +17,6 @@ public sealed interface OperationRead extends Operation OperationRead.Then, OperationRead.Configured { - /** Run this read operation on the given read connection. */ - default Out run(ConnectionRead conn) { - return conn.execute(this); - } - /** * Execute this operation using the given transactor. * From 237e7a490917ab15f504940841708bc568b7a660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Raddum=20Berg?= Date: Sat, 2 May 2026 22:10:25 +0200 Subject: [PATCH 2/2] fix: keep OperationRead.run(ConnectionRead), add override of run(Connection) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous commit's "remove the ambiguous overload" approach broke generated read repos in typr-3 — read methods take ConnectionRead but post-removal there was no run(ConnectionRead) sugar to invoke. The actual issue was Scala 3's overload resolver not applying specificity across inherited-vs-declared method boundaries: Java and Kotlin always picked run(Connection) over run(ConnectionRead) for c: Connection call sites, but Scala 3 reported ambiguous because one overload sat on Operation and the other on OperationRead. The fix: keep run(ConnectionRead) AND re-declare the inherited run(Connection) on OperationRead. Once both overloads are declared at the same level, Scala 3 applies specificity correctly and picks the right one. Pure delegation, no semantic change, both languages stay ergonomic with op.run(c) postfix sugar. Verified locally: typr-3 testers/pg/{scala/javatypes,java,kotlin} all compile clean against this foundations build. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../dev/typr/foundations/OperationRead.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/foundations-jdbc/src/java/dev/typr/foundations/OperationRead.java b/foundations-jdbc/src/java/dev/typr/foundations/OperationRead.java index df7f2c36..e27920f0 100644 --- a/foundations-jdbc/src/java/dev/typr/foundations/OperationRead.java +++ b/foundations-jdbc/src/java/dev/typr/foundations/OperationRead.java @@ -17,6 +17,24 @@ public sealed interface OperationRead extends Operation OperationRead.Then, OperationRead.Configured { + /** Run this read operation on a read-only connection. */ + default Out run(ConnectionRead conn) { + return conn.execute(this); + } + + /** + * Re-declares the inherited {@link Operation#run(Connection)} on this trait so Scala 3's + * overload resolver sees both {@code run(Connection)} and {@code run(ConnectionRead)} declared + * at the same level — then specificity ({@code Connection <: ConnectionRead}) picks the more + * specific overload for {@code c: Connection} call sites without ambiguity. Java and Kotlin + * always picked the most-specific overload regardless; this redeclaration is purely for the + * Scala 3 overload resolver. Pure delegation; same body as the inherited default. + */ + @Override + default Out run(Connection conn) { + return conn.execute(this); + } + /** * Execute this operation using the given transactor. *