[PL] ABI compatibility tests for reworked partial linkage

This commit is contained in:
Dmitriy Dolovov
2023-03-22 13:59:33 +01:00
committed by Space Team
parent 2a4d880037
commit 4f1155b06f
262 changed files with 4278 additions and 1359 deletions
@@ -0,0 +1,21 @@
open class RemovedClass {
val p1 = "p1"
fun f1() = "f1"
}
interface RemovedInterface {
val p1: String
val p2 get() = "p2"
fun f1(): String
fun f2() = "f2"
}
class ClassWithChangedMembers {
fun removedFun() = "removedFun"
fun changedFun(x: String) = x
}
interface InterfaceWithChangedMembers {
fun removedFun() = "removedFun"
fun changedFun(x: String) = x
}
@@ -0,0 +1,23 @@
//open class RemovedClass {
// val p1 = "p1"
// fun f1() = "f1"
//}
//interface RemovedInterface {
// val p1: String
// val p2 get() = "p2"
// fun f1(): String
// fun f2() = "f2"
//}
class ClassWithChangedMembers {
// fun removedFun() = "removedFun"
// fun changedFun(x: String) = x
fun changedFun(x: Int) = x.toString()
}
interface InterfaceWithChangedMembers {
// fun removedFun() = "removedFun"
// fun changedFun(x: String) = x
fun changedFun(x: Int) = x.toString()
}
@@ -0,0 +1,6 @@
STEP 0:
dependencies: stdlib
STEP 1:
dependencies: stdlib
modifications:
U : l1.kt.1 -> l1.kt
@@ -0,0 +1,74 @@
class RemovedClassImpl : RemovedClass() {
val p2 = "p2"
fun f2() = "f2"
}
class RemovedInterfaceImpl : RemovedInterface {
override val p1 = "p1"
val p3 = "p3"
override fun f1() = "f1"
fun f3() = "f3"
}
// This is required to check that function references for unchanged classes are evaluated correctly.
class StableClass {
fun foo(i: Int): String = i.toString()
inner class Inner {
fun bar(i: Int): String = i.toString()
}
}
fun functionWithUnlinkedParameter(p: RemovedClass?) = "functionWithUnlinkedParameter"
fun functionWithUnlinkedReturnValue(): RemovedClass = TODO("functionWithUnlinkedReturnValue")
fun <T : RemovedClass> functionWithRemovedTypeParameter(a: Any?): T = TODO("functionWithRemovedTypeParameter")
fun referenceRemovedClassReference(): String = RemovedClass::class.simpleName.orEmpty()
fun referenceRemovedClassConstructorReference(): String = ::RemovedClass.name
fun referenceRemovedClassProperty1Reference(): String = RemovedClass::p1.name
fun referenceRemovedClassFunction1Reference(): String = RemovedClass::f1.name
fun referenceRemovedClassImplReference(): String = RemovedClassImpl::class.simpleName.orEmpty()
fun referenceRemovedClassImplConstructorReference(): String = ::RemovedClassImpl.name
fun referenceRemovedClassImplProperty1Reference(): String = RemovedClassImpl::p1.name
fun referenceRemovedClassImplProperty2Reference(): String = RemovedClassImpl::p2.name
fun referenceRemovedClassImplFunction1Reference(): String = RemovedClassImpl::f1.name
fun referenceRemovedClassImplFunction2Reference(): String = RemovedClassImpl::f2.name
fun referenceRemovedInterfaceReference(): String = RemovedInterface::class.simpleName.orEmpty()
fun referenceRemovedInterfaceProperty1Reference(): String = RemovedInterface::p1.name
fun referenceRemovedInterfaceProperty2Reference(): String = RemovedInterface::p2.name
fun referenceRemovedInterfaceFunction1Reference(): String = RemovedInterface::f1.name
fun referenceRemovedInterfaceFunction2Reference(): String = RemovedInterface::f2.name
fun referenceRemovedInterfaceImplReference(): String = RemovedInterfaceImpl::class.simpleName.orEmpty()
fun referenceRemovedInterfaceImplProperty1Reference(): String = RemovedInterfaceImpl::p1.name
fun referenceRemovedInterfaceImplProperty2Reference(): String = RemovedInterfaceImpl::p2.name
fun referenceRemovedInterfaceImplProperty3Reference(): String = RemovedInterfaceImpl::p3.name
fun referenceRemovedInterfaceImplFunction1Reference(): String = RemovedInterfaceImpl::f1.name
fun referenceRemovedInterfaceImplFunction2Reference(): String = RemovedInterfaceImpl::f2.name
fun referenceRemovedInterfaceImplFunction3Reference(): String = RemovedInterfaceImpl::f3.name
fun referenceStableClassConstructor(): String = ::StableClass.name
fun referenceStableClassMemberFunctionWithoutDispatchReceiver(): String = StableClass::foo.name
fun referenceStableClassMemberFunctionWithDispatchReceiver(stableClass: StableClass): String = stableClass::foo.name
fun referenceStableClassInnerConstructorWithoutDispatchReceiver(): String = StableClass::Inner.name
fun referenceStableClassInnerConstructorWithDispatchReceiver(stableClass: StableClass): String = stableClass::Inner.name
fun referenceStableClassInnerMemberFunctionWithoutDispatchReceiver(): String = StableClass.Inner::bar.name
fun referenceStableClassInnerMemberFunctionWithDispatchReceiver(stableClassInner: StableClass.Inner): String = stableClassInner::bar.name
fun referenceRemovedFunFromClass(): String = ClassWithChangedMembers::removedFun.name
fun referenceChangedFunFromClass(): String = ClassWithChangedMembers::changedFun.name
fun referenceRemovedFunFromInterface(): String = InterfaceWithChangedMembers::removedFun.name
fun referenceChangedFunFromInterface(): String = InterfaceWithChangedMembers::changedFun.name
fun referenceFunctionWithUnlinkedParameter(): String = ::functionWithUnlinkedParameter.name
fun referenceFunctionWithUnlinkedReturnValue(): String = ::functionWithUnlinkedReturnValue.name
fun referenceFunctionWithRemovedTypeParameter(): String {
/*
* The syntax of function references does not allow explicitly specifying type arguments.
* The compiler will report "Not enough information to infer type variable T" error on
* `::functionWithRemovedTypeParameter` statement. So let's put the reference into
* the context with evident type arguments.
*/
return listOf<Any?>(null).map<Any?, RemovedClassImpl>(::functionWithRemovedTypeParameter).joinToString()
}
@@ -0,0 +1,2 @@
STEP 0:
dependencies: stdlib, lib1
@@ -0,0 +1,49 @@
import abitestutils.abiTest
fun box() = abiTest {
val stableClass = StableClass()
val stableClassInner = stableClass.Inner()
expectFailure(linkage("Reference to class 'RemovedClass' can not be evaluated: No class found for symbol '/RemovedClass'")) { referenceRemovedClassReference() }
expectFailure(linkage("Reference to constructor 'RemovedClass.<init>' can not be evaluated: No constructor found for symbol '/RemovedClass.<init>'")) { referenceRemovedClassConstructorReference() }
expectFailure(linkage("Reference to property 'p1' can not be evaluated: No property found for symbol '/RemovedClass.p1'")) { referenceRemovedClassProperty1Reference() }
expectFailure(linkage("Reference to function 'f1' can not be evaluated: No function found for symbol '/RemovedClass.f1'")) { referenceRemovedClassFunction1Reference() }
expectFailure(linkage("Reference to class 'RemovedClassImpl' can not be evaluated: Expression uses unlinked class symbol '/RemovedClass' (via class 'RemovedClassImpl')")) { referenceRemovedClassImplReference() }
expectFailure(linkage("Reference to constructor 'RemovedClassImpl.<init>' can not be evaluated: Class 'RemovedClassImpl' uses unlinked class symbol '/RemovedClass'")) { referenceRemovedClassImplConstructorReference() }
expectFailure(linkage("Reference to property 'p1' can not be evaluated: No property found for symbol '/RemovedClassImpl.p1'")) { referenceRemovedClassImplProperty1Reference() }
expectFailure(linkage("Reference to property 'p2' can not be evaluated: Dispatch receiver class 'RemovedClassImpl' uses unlinked class symbol '/RemovedClass'")) { referenceRemovedClassImplProperty2Reference() }
expectFailure(linkage("Reference to function 'f1' can not be evaluated: No function found for symbol '/RemovedClassImpl.f1'")) { referenceRemovedClassImplFunction1Reference() }
expectFailure(linkage("Reference to function 'f2' can not be evaluated: Dispatch receiver class 'RemovedClassImpl' uses unlinked class symbol '/RemovedClass'")) { referenceRemovedClassImplFunction2Reference() }
expectFailure(linkage("Reference to class 'RemovedInterface' can not be evaluated: No class found for symbol '/RemovedInterface'")) { referenceRemovedInterfaceReference() }
expectFailure(linkage("Reference to property 'p1' can not be evaluated: No property found for symbol '/RemovedInterface.p1'")) { referenceRemovedInterfaceProperty1Reference() }
expectFailure(linkage("Reference to property 'p2' can not be evaluated: No property found for symbol '/RemovedInterface.p2'")) { referenceRemovedInterfaceProperty2Reference() }
expectFailure(linkage("Reference to function 'f1' can not be evaluated: No function found for symbol '/RemovedInterface.f1'")) { referenceRemovedInterfaceFunction1Reference() }
expectFailure(linkage("Reference to function 'f2' can not be evaluated: No function found for symbol '/RemovedInterface.f2'")) { referenceRemovedInterfaceFunction2Reference() }
expectFailure(linkage("Reference to class 'RemovedInterfaceImpl' can not be evaluated: Expression uses unlinked class symbol '/RemovedInterface' (via class 'RemovedInterfaceImpl')")) { referenceRemovedInterfaceImplReference() }
expectFailure(linkage("Reference to property 'p1' can not be evaluated: Dispatch receiver class 'RemovedInterfaceImpl' uses unlinked class symbol '/RemovedInterface'")) { referenceRemovedInterfaceImplProperty1Reference() }
expectFailure(linkage("Reference to property 'p2' can not be evaluated: No property found for symbol '/RemovedInterfaceImpl.p2'")) { referenceRemovedInterfaceImplProperty2Reference() }
expectFailure(linkage("Reference to property 'p3' can not be evaluated: Dispatch receiver class 'RemovedInterfaceImpl' uses unlinked class symbol '/RemovedInterface'")) { referenceRemovedInterfaceImplProperty3Reference() }
expectFailure(linkage("Reference to function 'f1' can not be evaluated: Dispatch receiver class 'RemovedInterfaceImpl' uses unlinked class symbol '/RemovedInterface'")) { referenceRemovedInterfaceImplFunction1Reference() }
expectFailure(linkage("Reference to function 'f2' can not be evaluated: No function found for symbol '/RemovedInterfaceImpl.f2'")) { referenceRemovedInterfaceImplFunction2Reference() }
expectFailure(linkage("Reference to function 'f3' can not be evaluated: Dispatch receiver class 'RemovedInterfaceImpl' uses unlinked class symbol '/RemovedInterface'")) { referenceRemovedInterfaceImplFunction3Reference() }
expectSuccess("<init>") { referenceStableClassConstructor() }
expectSuccess("foo") { referenceStableClassMemberFunctionWithoutDispatchReceiver() }
expectSuccess("foo") { referenceStableClassMemberFunctionWithDispatchReceiver(stableClass) }
expectSuccess("<init>") { referenceStableClassInnerConstructorWithoutDispatchReceiver() }
expectSuccess("<init>") { referenceStableClassInnerConstructorWithDispatchReceiver(stableClass) }
expectSuccess("bar") { referenceStableClassInnerMemberFunctionWithoutDispatchReceiver() }
expectSuccess("bar") { referenceStableClassInnerMemberFunctionWithDispatchReceiver(stableClassInner) }
expectFailure(linkage("Reference to function 'removedFun' can not be evaluated: No function found for symbol '/ClassWithChangedMembers.removedFun'")) { referenceRemovedFunFromClass() }
expectFailure(linkage("Reference to function 'changedFun' can not be evaluated: No function found for symbol '/ClassWithChangedMembers.changedFun'")) { referenceChangedFunFromClass() }
expectFailure(linkage("Reference to function 'removedFun' can not be evaluated: No function found for symbol '/InterfaceWithChangedMembers.removedFun'")) { referenceRemovedFunFromInterface() }
expectFailure(linkage("Reference to function 'changedFun' can not be evaluated: No function found for symbol '/InterfaceWithChangedMembers.changedFun'")) { referenceChangedFunFromInterface() }
expectFailure(linkage("Reference to function 'functionWithUnlinkedParameter' can not be evaluated: Function uses unlinked class symbol '/RemovedClass'")) { referenceFunctionWithUnlinkedParameter() }
expectFailure(linkage("Reference to function 'functionWithUnlinkedReturnValue' can not be evaluated: Function uses unlinked class symbol '/RemovedClass'")) { referenceFunctionWithUnlinkedReturnValue() }
expectFailure(linkage("Reference to function 'functionWithRemovedTypeParameter' can not be evaluated: Function uses unlinked class symbol '/RemovedClass' (via type parameter 'T')")) { referenceFunctionWithRemovedTypeParameter() }
}
@@ -0,0 +1,2 @@
STEP 0:
dependencies: stdlib, lib1, lib2
@@ -0,0 +1,7 @@
MODULES: lib1, lib2, main
STEP 0:
libs: lib1, lib2, main
STEP 1:
libs: lib1