fix another type inference problem with external structures

This commit is contained in:
Sergey Chernov 2026-06-27 04:35:51 +03:00
parent 7af6d3925e
commit 90e46a3fff
3 changed files with 69 additions and 7 deletions

View File

@ -21,7 +21,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
group = "net.sergeych"
version = "1.5.6"
version = "1.5.7-SNAPSHOT"
// Removed legacy buildscript classpath declarations; plugins are applied via the plugins DSL below

View File

@ -6702,7 +6702,19 @@ class Compiler(
private fun inferCallReturnTypeDecl(ref: CallRef): TypeDecl? {
callReturnTypeDeclByRef[ref]?.let { return it }
val targetDecl = (resolveReceiverTypeDecl(ref.target) ?: seedTypeDeclFromRef(ref.target)) as? TypeDecl.Function
?: run {
val targetName = when (val target = ref.target) {
is LocalVarRef -> target.name
is FastLocalVarRef -> target.name
is LocalSlotRef -> target.name
else -> null
} ?: return null
val declaredReturn = callableReturnTypeDeclByName[targetName]
?: (seedTypeDeclByName(targetName) as? TypeDecl.Function)?.returnType
?: return null
callReturnTypeDeclByRef[ref] = declaredReturn
return declaredReturn
}
val bindings = mutableMapOf<String, TypeDecl>()
val paramList = mutableListOf<TypeDecl>()
targetDecl.receiver?.let { paramList += it }

View File

@ -19,13 +19,10 @@ package net.sergeych.lyng
import kotlinx.coroutines.test.runTest
import net.sergeych.lyng.bridge.bind
import net.sergeych.lyng.obj.ObjRecord
import net.sergeych.lyng.bridge.data
import net.sergeych.lyng.bridge.bindGlobalVar
import net.sergeych.lyng.bridge.data
import net.sergeych.lyng.bridge.globalBinder
import net.sergeych.lyng.obj.ObjFalse
import net.sergeych.lyng.obj.ObjInstance
import net.sergeych.lyng.obj.ObjTrue
import net.sergeych.lyng.obj.*
import kotlin.test.Test
import kotlin.test.assertEquals
@ -138,12 +135,65 @@ class GlobalPropertyCaptureRegressionTest {
assertEquals(77.0, x, "bound extern var should stay live after extern class property branch in child scope")
}
@Test
fun externPropertyOnExternFunctionResultCanAssignExternGlobalVar() = runTest {
val base = Script.newScope() as ModuleScope
var x = 0L
base.eval(
"""
extern var X: Int
class InputResult {
extern val value: Int?
}
""".trimIndent()
)
base.bind("InputResult") {
addVal("value") {
ObjInt.of(thisObjData<InputPayload>().value)
}
}
base.globalBinder().bindGlobalVar(
name = "X",
get = { x },
set = { x = it }
)
base.globalBinder().bindGlobalFunRaw("input") { _, _ ->
val instance = base.requireClass("InputResult").callOn(base.createChildScope()) as ObjInstance
instance.data = InputPayload(101L)
instance
}
val child = base.createChildScope()
child.eval(
"""
extern fun input(): InputResult
fun main() {
X = input().value
}
""".trimIndent()
)
child.eval("main()")
assertEquals(101L, x, "extern property read directly from extern function result should assign live extern var")
}
}
private data class ChoicePayload(
val isSkip: Boolean,
)
private data class InputPayload(
val value: Long,
)
@Suppress("UNCHECKED_CAST")
private fun <T> ScopeFacade.thisObjData(): T {
val instance = thisObj as? ObjInstance ?: raiseClassCastError("Expected result object instance")