FIR: check assignments and references to members in constructors

I.e. emit VAL_REASSIGNMENT on repeated assignments to `this.something`,
UNINITIALIZED_VARIABLE on reads of it before any assignment if there is
no initializer, and CAPTURED_MEMBER_VAL_INITIALIZATION on assignments
inside non-called-in-place functions and named classes.

^KT-55528 Fixed
This commit is contained in:
pyos
2023-01-19 12:21:53 +01:00
committed by teamcity
parent 8f45acd71d
commit 99e51f6940
24 changed files with 199 additions and 211 deletions
@@ -134,7 +134,7 @@ class AnonymousInitializers(var a: String, val b: String) {
get() = 20
init {
i = 13
<!VAL_REASSIGNMENT!>i<!> = 13
<!VAL_REASSIGNMENT!>j<!> = 34
}
@@ -174,7 +174,7 @@ class AnonymousInitializers(var a: String, val b: String) {
val n: Int
init {
while (n == 0) {
while (<!UNINITIALIZED_VARIABLE!>n<!> == 0) {
}
n = 10
while (n == 0) {
@@ -7,7 +7,7 @@ class Test {
val t = object {
fun some() {
// See KT-13597
a = "12"
<!VAL_REASSIGNMENT!>a<!> = "12"
}
}
@@ -20,7 +20,7 @@ class Test2 {
init {
val t = object {
fun some() {
a = "12"
<!VAL_REASSIGNMENT!>a<!> = "12"
}
}
@@ -41,7 +41,7 @@ class Test4 {
init {
exec {
// See KT-14381
a = "12"
<!CAPTURED_MEMBER_VAL_INITIALIZATION!>a<!> = "12"
}
a = "34"
}
@@ -27,7 +27,7 @@ fun gav() {
class B {
init {
// Error! See KT-10445
x = ""
<!CAPTURED_VAL_INITIALIZATION!>x<!> = ""
}
}
// Error! See KT-10042
@@ -36,7 +36,7 @@ fun gav() {
class C(val s: String) {
constructor(): this("") {
// Error!
y = s
<!CAPTURED_VAL_INITIALIZATION!>y<!> = s
}
}
<!UNINITIALIZED_VARIABLE!>y<!>.length
@@ -77,7 +77,7 @@ class My {
class Your {
init {
// Error! See KT-10445
x = ""
<!CAPTURED_VAL_INITIALIZATION!>x<!> = ""
}
}
}
@@ -10,9 +10,9 @@ class Test {
run {
// Not sure do we need diagnostic also here
this@Test.str = "B"
this@Test.<!VAL_REASSIGNMENT!>str<!> = "B"
}
str = "C"
<!VAL_REASSIGNMENT!>str<!> = "C"
}
}
}
@@ -10,9 +10,9 @@ class Test {
run {
// Not sure do we need diagnostic also here
this@Test.str = "B"
this@Test.<!VAL_REASSIGNMENT!>str<!> = "B"
}
str = "C"
<!VAL_REASSIGNMENT!>str<!> = "C"
}
}
}
@@ -3,9 +3,9 @@ class A(val next: A? = null) {
init {
next?.<!VAL_REASSIGNMENT!>x<!> = "a"
x = "b"
this.x = "c"
x = "d" // don't repeat the same diagnostic again with this receiver
this.x = "e"
this.<!VAL_REASSIGNMENT!>x<!> = "c"
<!VAL_REASSIGNMENT!>x<!> = "d" // don't repeat the same diagnostic again with this receiver
this.<!VAL_REASSIGNMENT!>x<!> = "e"
next?.<!VAL_REASSIGNMENT!>x<!> = "f"
}
@@ -11,9 +11,9 @@ class Outer {
outer.<!VAL_REASSIGNMENT!>outerProp<!> = "3"
innerProp = "4" + inner.innerProp
this@Inner.innerProp = "5"
innerProp = "6" // do not repeat the same diagnostic with this receiver
this@Inner.innerProp = "7"
this@Inner.<!VAL_REASSIGNMENT!>innerProp<!> = "5"
<!VAL_REASSIGNMENT!>innerProp<!> = "6" // do not repeat the same diagnostic with this receiver
this@Inner.<!VAL_REASSIGNMENT!>innerProp<!> = "7"
inner.<!VAL_REASSIGNMENT!>innerProp<!> = "8"
}
@@ -3,9 +3,9 @@ class A(val next: A? = null) {
init {
next?.<!VAL_REASSIGNMENT!>x<!> = "a"
this@A.x = "b"
this.x = "c"
x = "d" // don't repeat the same diagnostic again with this receiver
this@A.x = "e"
this.<!VAL_REASSIGNMENT!>x<!> = "c"
<!VAL_REASSIGNMENT!>x<!> = "d" // don't repeat the same diagnostic again with this receiver
this@A.<!VAL_REASSIGNMENT!>x<!> = "e"
next?.<!VAL_REASSIGNMENT!>x<!> = "f"
}
@@ -11,7 +11,7 @@ class A(val w: Char) {
constructor(): this('a') {
y = 1
overinitialized = 2
<!VAL_REASSIGNMENT!>overinitialized<!> = 2
uninitialized = 3
}
@@ -1,39 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A {
val x: Int
var y: Int
val z: Int
val v = -1
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val uninitialized: Int<!>
val overinitialized: Int
constructor() {
x = 1
y = 2
overinitialized = 3
uninitialized = 4
}
constructor(a: Int): super() {
x = 5
y = 6
}
constructor(x: String): this() {
y = 7
uninitialized = 8
}
//anonymous
init {
z = 9
overinitialized = 10
}
// anonymous
init {
y = 12
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A {
val x: Int
@@ -1,8 +1,8 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A(val w: Int) {
val x: Int
val useUnitialized = x +
y +
val useUnitialized = <!UNINITIALIZED_VARIABLE!>x<!> +
<!UNINITIALIZED_VARIABLE!>y<!> +
v
var y: Int
val v = -1
@@ -11,20 +11,20 @@ class A(val w: Int) {
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val uninitialized: Int<!>
constructor(): this(1) {
x + y + v + uninitialized + w
x + y + v + <!UNINITIALIZED_VARIABLE!>uninitialized<!> + w
}
// anonymous
init {
x + y + v + uninitialized + w
<!UNINITIALIZED_VARIABLE!>x<!> + <!UNINITIALIZED_VARIABLE!>y<!> + v + <!UNINITIALIZED_VARIABLE!>uninitialized<!> + w
x = 1
x + y + v + uninitialized + w
x + <!UNINITIALIZED_VARIABLE!>y<!> + v + <!UNINITIALIZED_VARIABLE!>uninitialized<!> + w
}
// anonymous
init {
x + y + v + uninitialized + w
x + <!UNINITIALIZED_VARIABLE!>y<!> + v + <!UNINITIALIZED_VARIABLE!>uninitialized<!> + w
y = 7
x + y + v + uninitialized + w
x + y + v + <!UNINITIALIZED_VARIABLE!>uninitialized<!> + w
}
}
@@ -1,8 +1,8 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A {
val x: Int
val useUnitialized = x + // reported on each secondary constructor
y +
val useUnitialized = <!UNINITIALIZED_VARIABLE!>x<!> + // reported on each secondary constructor
<!UNINITIALIZED_VARIABLE!>y<!> +
v
var y: Int
val v = -1
@@ -19,7 +19,7 @@ class A {
x = 1
y = 2
x + y + v + uninitialized
x + y + v + <!UNINITIALIZED_VARIABLE!>uninitialized<!>
uninitialized = 3
@@ -27,16 +27,16 @@ class A {
}
constructor(a: Int): super() {
x + y + v + uninitialized
<!UNINITIALIZED_VARIABLE!>x<!> + y + v + <!UNINITIALIZED_VARIABLE!>uninitialized<!>
x = 4
y = 5
x + y + v + uninitialized
x + y + v + <!UNINITIALIZED_VARIABLE!>uninitialized<!>
}
//anonymous
init {
y
<!UNINITIALIZED_VARIABLE!>y<!>
}
// anonymous