提交 5c28762c 编写于 作者: P Pavel Kirpichenkov

Fix check for local classes in approximating string table

Take local/anonymous classes and their inner classes into account.
Simplify approximation: use first available super classifier instead
of first super class. This approximation should only happen for
private declarations that were not previously approximated by frontend.
So basically the only requirement for the approximated types is to be
denotable. Note that this only works if the types are not used later.
JVM uses a different string table implementatin as it needs exact
types of private members for reflection.

^KT-20996 Fixed
上级 b66f5c81
...@@ -13,19 +13,11 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils ...@@ -13,19 +13,11 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
open class ApproximatingStringTable : StringTableImpl() { class ApproximatingStringTable : StringTableImpl() {
override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? { override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? {
return if (descriptor.containingDeclaration is CallableMemberDescriptor) { return if (DescriptorUtils.isLocal(descriptor)) {
val superClassifiers = descriptor.getAllSuperClassifiers() descriptor.getAllSuperClassifiers().firstOrNull()?.classId
.mapNotNull { it as ClassifierDescriptorWithTypeParameters } ?: ClassId.topLevel(StandardNames.FqNames.any.toSafe())
.filter { it != descriptor }
.toList()
if (superClassifiers.size == 1) {
superClassifiers[0].classId
} else {
val superClass = superClassifiers.find { !DescriptorUtils.isInterface(it) }
superClass?.classId ?: ClassId.topLevel(StandardNames.FqNames.any.toSafe())
}
} else { } else {
super.getLocalClassIdReplacement(descriptor) super.getLocalClassIdReplacement(descriptor)
} }
......
...@@ -29,6 +29,32 @@ private val o8 = object : G<Int>() {} ...@@ -29,6 +29,32 @@ private val o8 = object : G<Int>() {}
private val o9 = object : G<Int>(), I1, I2 {} private val o9 = object : G<Int>(), I1, I2 {}
private val o10 = object : G<Int>(), I3 {} private val o10 = object : G<Int>(), I3 {}
private val o11 = object {
inner class D {
fun df() {}
}
fun d(): D = D()
}.d()
private val o12 = {
class L {
fun l() {}
}
L()
}()
private val o13 = {
class L {
inner class L1 {
inner class L2 {
fun l2() {}
}
}
}
L().L1().L2()
}()
fun fn() { fun fn() {
o1.foo() o1.foo()
o2.i1() o2.i1()
...@@ -50,6 +76,9 @@ fun fn() { ...@@ -50,6 +76,9 @@ fun fn() {
o10.g() o10.g()
o10.i1() o10.i1()
o10.i2() o10.i2()
o11.df()
o12.l()
o13.l2()
} }
class W { class W {
......
...@@ -39,6 +39,32 @@ class C { ...@@ -39,6 +39,32 @@ class C {
fun x() = "OK" fun x() = "OK"
} }
private val propOI = object {
inner class D {
fun df() {}
}
fun d(): D = D()
}.d()
private val propL = run {
class L {
fun l() = "propL.l"
}
L()
}
private val propL2 = run {
class L {
inner class L1 {
inner class L2 {
fun l2() = "propL2.l2"
}
}
}
L().L1().L2()
}
} }
// MODULE: main(lib) // MODULE: main(lib)
...@@ -48,4 +74,7 @@ fun test() { ...@@ -48,4 +74,7 @@ fun test() {
println(C().<!INVISIBLE_MEMBER!>propI<!>.x()) println(C().<!INVISIBLE_MEMBER!>propI<!>.x())
println(C().<!INVISIBLE_MEMBER!>propAI<!>.x()) println(C().<!INVISIBLE_MEMBER!>propAI<!>.x())
println(C().<!INVISIBLE_MEMBER!>propG<!>.x()) println(C().<!INVISIBLE_MEMBER!>propG<!>.x())
} println(C().<!INVISIBLE_MEMBER!>propOI<!>.df())
\ No newline at end of file println(C().<!INVISIBLE_MEMBER!>propL<!>.l())
println(C().<!INVISIBLE_MEMBER!>propL2<!>.l2())
}
...@@ -15,6 +15,9 @@ public final class C { ...@@ -15,6 +15,9 @@ public final class C {
private final val propAI: C.propAI.<no name provided> private final val propAI: C.propAI.<no name provided>
private final val propG: C.propG.<no name provided> private final val propG: C.propG.<no name provided>
private final val propI: C.propI.<no name provided> private final val propI: C.propI.<no name provided>
private final val propL: C.propL.<anonymous>.L
private final val propL2: C.propL2.<anonymous>.L.L1.L2
private final val propOI: C.propOI.<no name provided>.D
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
......
...@@ -735,6 +735,18 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration ...@@ -735,6 +735,18 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
listOf(library), listOf(library),
K2MetadataCompiler(), K2MetadataCompiler(),
) )
val klibLibrary = compileCommonLibrary(
libraryName = "library",
listOf("-Xexpect-actual-linker"),
)
compileKotlin(
"anonymousObjectTypeMetadata.kt",
tmpdir,
listOf(klibLibrary),
K2MetadataCompiler(),
listOf("-Xexpect-actual-linker")
)
} }
private fun loadClassFile(className: String, dir: File, library: File) { private fun loadClassFile(className: String, dir: File, library: File) {
......
...@@ -34,14 +34,40 @@ class C { ...@@ -34,14 +34,40 @@ class C {
override fun baz() = "propG.baz" override fun baz() = "propG.baz"
} }
fun test() = "${propA.bar()};${propI.foo()};${propAI.foo()};${propAI.bar()};${propG.baz()}" private val propInner = object {
inner class D {
fun df() = "propInner.df"
}
fun d(): D = D()
}.d()
private val propL = run {
class L {
fun l() = "propL.l"
}
L()
}
private val propL2 = run {
class L {
inner class L1 {
inner class L2 {
fun l2() = "propL2.l2"
}
}
}
L().L1().L2()
}
fun test() = "${propA.bar()};${propI.foo()};${propAI.foo()};${propAI.bar()};${propG.baz()};${propInner.df()};${propL.l()};${propL2.l2()}"
} }
// MODULE: main(lib) // MODULE: main(lib)
// FILE: main.kt // FILE: main.kt
fun box(): String { fun box(): String {
val result = C().test() val result = C().test()
if (result != "propA.bar;propI.foo;propAI.foo;propAI.bar;propG.baz") return "fail: $result" if (result != "propA.bar;propI.foo;propAI.foo;propAI.bar;propG.baz;propInner.df;propL.l;propL2.l2") return "fail: $result"
return "OK" return "OK"
} }
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册