Fix nullable let member inference

This commit is contained in:
sergeych committed 2026-04-07 09:33:40 +03:00
1 parent 15617f6998
commit 2f145a0ea7
3 files changed
+155 -20

No files matched your search

+97
View File
@@ -1102,4 +1102,101 @@ class OOTest {
""".trimIndent())
}
@Test
fun testExtendingObjectWithExternals2() = runTest {
val s = EvalSession()
s.eval("""
import lyng.serialization
object Storage {
extern val spaceUsed: Int
extern val spaceAvailable: Int
/*
Return packed binary data or null
*/
extern fun getPacked(key: String): Buffer?
/*
Upsert packed binary data
*/
extern fun putPacked(key: String,value: Buffer)
/*
Delete data.
@return true if data were actually deleted, false means
there were no data for the key.
*/
extern fun delete(key: String): Bool
override fun putAt(key: String,value: Object) {
putPacked(key, Lynon.encode(value).toBuffer())
}
override fun getAt(key: String): Object? =
getPacked(key)?.let { Lynon.decode(it.toBitInput()) }
}
""".trimIndent()
)
val scope = s.getScope() as ModuleScope
scope.bindObject("Storage") {
init { _ ->
data = mutableMapOf<String, ObjBuffer>()
}
addVal("spaceUsed") {
val storage = (thisObj as ObjInstance).data as MutableMap<String, ObjBuffer>
ObjInt(storage.values.sumOf { it.size }.toLong())
}
addVal("spaceAvailable") {
val storage = (thisObj as ObjInstance).data as MutableMap<String, ObjBuffer>
val capacity = 1_024
ObjInt((capacity - storage.values.sumOf { it.size }).toLong())
}
addFun("getPacked") {
val storage = (thisObj as ObjInstance).data as MutableMap<String, ObjBuffer>
val key = (args.list[0] as ObjString).value
storage[key] ?: ObjNull
}
addFun("putPacked") {
val storage = (thisObj as ObjInstance).data as MutableMap<String, ObjBuffer>
val key = (args.list[0] as ObjString).value
val value = args.list[1] as ObjBuffer
storage[key] = value
ObjVoid
}
addFun("delete") {
val storage = (thisObj as ObjInstance).data as MutableMap<String, ObjBuffer>
val key = (args.list[0] as ObjString).value
ObjBool(storage.remove(key) != null)
}
}
s.eval("""
assertEquals(0, Storage.spaceUsed)
assertEquals(1024, Storage.spaceAvailable)
val missing: String? = Storage["missing"]
assertEquals(null, missing)
Storage["name"] = "alice"
Storage["count"] = 42
val name: String? = Storage["name"]
val count: Int? = Storage["count"]
assertEquals("alice", name)
assertEquals(42, count)
assert(Storage.spaceUsed > 0)
assert(Storage.spaceAvailable < 1024)
val wrappedName: String? = Storage.getAt("name")
assertEquals("alice", wrappedName)
Storage.putAt("flag", true)
val flag: Bool? = Storage["flag"]
assertEquals(true, flag)
assert(Storage.delete("name"))
val deletedName: String? = Storage["name"]
assertEquals(null, deletedName)
assert(!Storage.delete("name"))
""".trimIndent())
}
}
@@ -109,6 +109,19 @@ class ScriptTest {
assertTrue(res is ObjString && res.value.isNotEmpty())
}
@Test
fun testNullableLetKeepsReceiverMemberType() = runTest {
Script.newScope().eval(
"""
import lyng.serialization
val packed: Buffer? = Lynon.encode("alice").toBuffer()
val decoded = packed?.let { Lynon.decode(it.toBitInput()) }
assertEquals("alice", decoded)
""".trimIndent()
)
}
@Test
fun testNoInfiniteRecursionOnUnknownInNestedClosure() = runTest {
val scope = Script.newScope()