Improve support of 'lateinit' modifier

- Allow 'lateinit' for inline classes which underlying type
is suitable for 'lateinit'

- K2: report all problems related to 'lateinit' modifier

^KT-55052: Fixed
This commit is contained in:
Vladislav Grechko
2022-11-18 03:22:17 +01:00
committed by teamcity
parent e0c13e5276
commit cd6e865fb3
35 changed files with 406 additions and 84 deletions
@@ -7,6 +7,9 @@ lateinit var kest by Delegate
compiler/testData/cli/jvm/inapplicableLateinitModifier.kt:9:5: error: 'lateinit' modifier is allowed only on mutable properties
lateinit val fest = "10"
^
compiler/testData/cli/jvm/inapplicableLateinitModifier.kt:9:5: error: 'lateinit' modifier is not allowed on properties with initializer
lateinit val fest = "10"
^
compiler/testData/cli/jvm/inapplicableLateinitModifier.kt:11:5: error: 'lateinit' modifier is not allowed on properties of a type with nullable upper bound
lateinit var xest: String?
^
@@ -16,6 +19,9 @@ compiler/testData/cli/jvm/inapplicableLateinitModifier.kt:12:5: error: 'lateinit
compiler/testData/cli/jvm/inapplicableLateinitModifier.kt:13:5: error: 'lateinit' modifier is allowed only on mutable properties
lateinit val dest: String
^
compiler/testData/cli/jvm/inapplicableLateinitModifier.kt:13:5: error: 'lateinit' modifier is not allowed on properties with a custom getter or setter
lateinit val dest: String
^
compiler/testData/cli/jvm/inapplicableLateinitModifier.kt:18:5: error: 'lateinit' modifier is not allowed on properties of a type with nullable upper bound
lateinit var best: T
^
@@ -0,0 +1,69 @@
// WITH_STDLIB
// WORKS_WHEN_VALUE_CLASS
// LANGUAGE: +ValueClasses, +InlineLateinit
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC1(val x: String)
lateinit var a: IC1
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC2<T : Number>(val x: T)
class MyClass {
lateinit var b: IC2<Int>
fun isInit() = ::b.isInitialized
}
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC3<T>(val x: Comparable<T>)
OPTIONAL_JVM_INLINE_ANNOTATION
value class IC4(val x: IC1)
lateinit var c: IC4
inline fun <reified T> assertThrows(block: () -> Unit): Boolean {
try {
block.invoke()
} catch (t: Throwable) {
return t is T
}
return false
}
fun box(): String {
if (::a.isInitialized) return "Fail 1.1"
if (!assertThrows<UninitializedPropertyAccessException> { val t = a }) return "Fail 1.2"
a = IC1("a")
if (!::a.isInitialized) return "Fail 1.3"
if (a.x != "a") return "Fail 1.4"
val inst = MyClass()
if (inst.isInit()) return "Fail 2.1"
if (!assertThrows<UninitializedPropertyAccessException> { val t = inst.b }) return "Fail 2.2"
inst.b = IC2(42)
if (!inst.isInit()) return "Fail 2.3"
if (inst.b.x != 42) return "Fail 2.4"
lateinit var z: IC3<Double>
if (!assertThrows<UninitializedPropertyAccessException> { val t = z }) return "Fail 3.1"
z = IC3(5.0)
if (z.x != 5.0) return "Fail 3.2"
if (::c.isInitialized) return "Fail 4.1"
if (!assertThrows<UninitializedPropertyAccessException> { val t = c }) return "Fail 4.2"
c = IC4(IC1("c"))
if (!::c.isInitialized) return "Fail 4.3"
if (c.x.x != "c") return "Fail 4.4"
return "OK"
}
//CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 0 INVOKESTATIC IC1.box-impl
// 0 INVOKESTATIC IC2.box-impl
// 0 INVOKESTATIC IC3.box-impl
// 0 INVOKESTATIC IC4.box-impl
@@ -8,7 +8,7 @@ fun test() {
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T : <!UNRESOLVED_REFERENCE!>__UNRESOLVED__<!>><!> a1 = ""
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T : <!FINAL_UPPER_BOUND!>String<!>><!> a2 = 0
<!WRONG_MODIFIER_TARGET!>const<!> val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T><!> a3 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T><!> a4 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER, INAPPLICABLE_LATEINIT_MODIFIER, INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T><!> a4 = 0
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T><!> a5 by Delegate<Int>()
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING!><T><!> a6 by Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()
}
@@ -8,7 +8,7 @@ fun test() {
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T : <!UNRESOLVED_REFERENCE!>__UNRESOLVED__<!>><!> a1 = ""
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T : <!FINAL_UPPER_BOUND!>String<!>><!> a2 = 0
<!WRONG_MODIFIER_TARGET!>const<!> val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T><!> a3 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T><!> a4 = 0
<!INAPPLICABLE_LATEINIT_MODIFIER, INAPPLICABLE_LATEINIT_MODIFIER, INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T><!> a4 = 0
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T><!> a5 by Delegate<Int>()
val <!LOCAL_VARIABLE_WITH_TYPE_PARAMETERS!><T><!> a6 by Delegate<<!UNRESOLVED_REFERENCE!>T<!>>()
}
@@ -1,10 +0,0 @@
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses
// !DIAGNOSTICS: -UNUSED_VARIABLE
inline class Foo(val x: Int)
lateinit var a: Foo
fun foo() {
lateinit var b: Foo
}
@@ -1,5 +1,6 @@
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses
// !DIAGNOSTICS: -UNUSED_VARIABLE
// FIR_IDENTICAL
inline class Foo(val x: Int)
@@ -0,0 +1,86 @@
// WITH_STDLIB
// SKIP_TXT
// !LANGUAGE: +InlineLateinit
// FIR_IDENTICAL
@JvmInline
value class IC1(val x: Int)
@JvmInline
value class IC2(val x: IC1)
@JvmInline
value class IC3(val x: String)
@JvmInline
value class IC4(val x: String?)
@JvmInline
value class IC5(val x: IC4)
@JvmInline
value class IC6<T>(val x: T)
@JvmInline
value class IC7<T : Any>(val x: T)
@JvmInline
value class IC8(val x: <!VALUE_CLASS_CANNOT_BE_RECURSIVE!>IC9<!>)
@JvmInline
value class IC9(val x: <!VALUE_CLASS_CANNOT_BE_RECURSIVE!>IC8<!>)
@JvmInline
value class IC10(val x: IC6<String>)
@JvmInline
value class IC11(val x : IC4?)
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var a: IC1
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var b: IC2
lateinit var c: IC3
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var d: IC4
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e: IC6<String>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var f: IC6<*>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var g: IC5
lateinit var h: IC7<Double>
lateinit var i: IC7<*>
lateinit var j: IC8
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var k : IC10
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var o : IC3?
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var m : UInt
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var n : IC11
class B {
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var a: IC1
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var b: IC2
lateinit var c: IC3
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var d: IC4
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e: IC6<String>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var f: IC6<*>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var g: IC5
lateinit var h: IC7<Double>
lateinit var i: IC7<*>
lateinit var j: IC8
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var k : IC10
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var o : IC3?
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var m : UInt
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var n : IC11
}
fun foo() {
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var a: IC1
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var b: IC2
lateinit var c: IC3
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var d: IC4
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e: IC6<String>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var f: IC6<*>
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var g: IC5
lateinit var h: IC7<Double>
lateinit var i: IC7<*>
lateinit var j: IC8
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var k : IC10
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var o : IC3?
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var m : UInt
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var n : IC11
}
@@ -30,7 +30,7 @@ public abstract class A<T: Any, V: String?>(lateinit var p2: String) {
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e5 = "A"
// With initializer, primitive
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e6 = 3
<!INAPPLICABLE_LATEINIT_MODIFIER, INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e6 = 3
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var e7 by CustomDelegate()
@@ -1,9 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
lateinit var a: UInt
fun foo() {
lateinit var b: UByte
lateinit var c: UShort
lateinit var d: ULong
}
@@ -1,4 +1,5 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// FIR_IDENTICAL
<!INAPPLICABLE_LATEINIT_MODIFIER!>lateinit<!> var a: UInt
@@ -1,17 +0,0 @@
// !SKIP_JAVAC
// !LANGUAGE: +InlineClasses
// ALLOW_KOTLIN_PACKAGE
// !DIAGNOSTICS: -UNUSED_VARIABLE
package kotlin.jvm
annotation class JvmInline
@JvmInline
value class Foo(val x: Int)
lateinit var a: Foo
fun foo() {
lateinit var b: Foo
}
@@ -2,6 +2,7 @@
// !LANGUAGE: +InlineClasses
// ALLOW_KOTLIN_PACKAGE
// !DIAGNOSTICS: -UNUSED_VARIABLE
// FIR_IDENTICAL
package kotlin.jvm