Fix super constructor calls of anonymous objects and local classes
If a class inherits from another class which captures something (outer class instance, receiver parameter, local variables, etc.), the constructor of the former class should contain all the parameters of the super constructor as its own parameters, so that it could make a proper super call. All such parameters are now replicated in the derived constructor with kind = SUPER_CALL_PARAM, except an instance of the outer class (kind = OUTER), which can be taken from the derived's own OUTER when it has one, to prevent multiple passing of the same argument. Previously it worked only when inheriting from inner classes via a special hack (ConstructorFrameMap). Also reuse recently introduced ArgumentGenerator to automatically take care of default and vararg arguments of super constructor #KT-3581 Fixed #KT-5342 Fixed #KT-5343 Fixed
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
open class A(val s: String) {
|
||||
open inner class B(s: String): A(s)
|
||||
|
||||
open inner class C(s: String, additional: Double): B(s)
|
||||
|
||||
open inner class D(other: Int, another: Long, s: String) : C(s, another.toDouble())
|
||||
|
||||
open inner class E : D(0, 42L, "OK")
|
||||
|
||||
inner class F : E()
|
||||
}
|
||||
|
||||
fun box(): String = A("Fail").F().s
|
||||
@@ -0,0 +1,17 @@
|
||||
fun box(): String {
|
||||
open trait L1 {
|
||||
fun foo(): String
|
||||
}
|
||||
|
||||
open class L2(val s: String) : L1 {
|
||||
override fun foo() = s
|
||||
}
|
||||
|
||||
open class L3(unused: Double, value: String = "OK") : L2(value)
|
||||
|
||||
open class L4(i: Int, j: Long, z: Boolean, l: L3) : L3(3.14)
|
||||
|
||||
class L5 : L4(0, 0L, false, L3(2.71, "Fail"))
|
||||
|
||||
return L5().foo()
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// When inner class extends its outer, there are two instances of the outer present in the inner:
|
||||
// the enclosing one and the one in the super call.
|
||||
// Here we test that symbols are resolved to the instance created via the super call.
|
||||
// This differs from Java, so this test may change when we revisit code generation of inner classes
|
||||
|
||||
open class Outer(vararg val chars: Char) {
|
||||
open inner class Inner(val s: String): Outer(s[0], s[1]) {
|
||||
fun concat() = java.lang.String.valueOf(chars)
|
||||
}
|
||||
|
||||
fun value() = Inner("OK").concat()
|
||||
}
|
||||
|
||||
fun box() = Outer('F', 'a', 'i', 'l').value()
|
||||
@@ -0,0 +1,11 @@
|
||||
fun box(): String {
|
||||
val result = "OK"
|
||||
|
||||
open class Local(val ok: Boolean) {
|
||||
fun result() = if (ok) result else "Fail"
|
||||
}
|
||||
|
||||
class Derived : Local(true)
|
||||
|
||||
return Derived().result()
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
fun box(): String {
|
||||
val three = 3
|
||||
|
||||
open class Local(val one: Int) {
|
||||
open fun value() = "$three$one"
|
||||
}
|
||||
|
||||
val four = 4
|
||||
|
||||
class Derived(val two: Int) : Local(1) {
|
||||
override fun value() = super.value() + "$four$two"
|
||||
}
|
||||
|
||||
val result = Derived(2).value()
|
||||
return if (result == "3142") "OK" else "Fail: $result"
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// KT-3581
|
||||
|
||||
open class A(val result: String = "OK") {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = object : A() {}
|
||||
return a.result
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
open class SomeClass(val some: Double, val other: Int, vararg val args: String) {
|
||||
fun result() = args[1]
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return object : SomeClass(3.14, 42, "No", "OK", "Yes") {
|
||||
}.result()
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class A {
|
||||
open inner class Inner(val result: String)
|
||||
|
||||
fun box(): String {
|
||||
val o = object : Inner("OK") {
|
||||
fun ok() = result
|
||||
}
|
||||
return o.ok()
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = A().box()
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
class A {
|
||||
open inner class Inner(val result: String = "OK", val int: Int)
|
||||
|
||||
fun box(): String {
|
||||
val o = object : Inner(int = 0) {
|
||||
fun ok() = result
|
||||
}
|
||||
return o.ok()
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = A().box()
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
fun box(): String {
|
||||
val capture = "oh"
|
||||
|
||||
class Local {
|
||||
val captured = capture
|
||||
|
||||
open inner class Inner(val d: Double = -1.0, val s: String, vararg val y: Int) {
|
||||
open fun result() = "Fail"
|
||||
}
|
||||
|
||||
val obj = object : Inner(s = "OK") {
|
||||
override fun result() = s
|
||||
}
|
||||
}
|
||||
|
||||
return Local().obj.result()
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
fun box(): String {
|
||||
class Local {
|
||||
open inner class Inner(val s: String) {
|
||||
open fun result() = "Fail"
|
||||
}
|
||||
|
||||
val realResult = "OK"
|
||||
|
||||
val obj = object : Inner(realResult) {
|
||||
override fun result() = s
|
||||
}
|
||||
}
|
||||
|
||||
return Local().obj.result()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
open class A(val s: String)
|
||||
|
||||
fun box(): String {
|
||||
class B {
|
||||
val result = "OK"
|
||||
|
||||
val f = object : A(result) {}.s
|
||||
}
|
||||
|
||||
return B().f
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fun box(): String {
|
||||
val d = 42.0
|
||||
val c = 'C'
|
||||
|
||||
open class Local(val l: Long) {
|
||||
fun foo(): Boolean = d == 42.0 && c == 'C' && l == 239L
|
||||
}
|
||||
|
||||
if (object : Local(239L) {
|
||||
fun bar(): Boolean = foo()
|
||||
}.bar()) return "OK"
|
||||
|
||||
return "Fail"
|
||||
}
|
||||
Reference in New Issue
Block a user