FIR: report VAL_REASSIGNMENT on synthetic immutable properties

#KT-50972 Fixed
This commit is contained in:
Mikhail Glukhikh
2022-01-26 16:21:41 +03:00
committed by teamcity
parent b8c36b7998
commit 029e946fb2
5 changed files with 16 additions and 9 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
@OptIn(SymbolInternals::class)
@@ -84,7 +85,7 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
return true
}
val kind = info[symbol] ?: EventOccurrencesRange.ZERO
if (symbol.fir.isVal && kind.canBeRevisited()) {
if (symbol.fir.isVal && (symbol is FirSyntheticPropertySymbol || kind.canBeRevisited())) {
reporter.reportOn(node.fir.lValue.source, FirErrors.VAL_REASSIGNMENT, symbol, context)
return true
}
@@ -110,7 +111,7 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
node: QualifiedAccessNode
): Boolean {
val kind = info[symbol] ?: EventOccurrencesRange.ZERO
if (!kind.isDefinitelyVisited()) {
if (symbol !is FirSyntheticPropertySymbol && !kind.isDefinitelyVisited()) {
reporter.reportOn(node.fir.source, FirErrors.UNINITIALIZED_VARIABLE, symbol, context)
return true
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.referredPropertySymbol
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol
class LocalPropertyAndCapturedWriteCollector private constructor() : ControlFlowGraphVisitorVoid() {
companion object {
@@ -53,11 +54,16 @@ class LocalPropertyAndCapturedWriteCollector private constructor() : ControlFlow
}
override fun visitVariableAssignmentNode(node: VariableAssignmentNode) {
val symbol = node.fir.referredPropertySymbol ?: return
if (symbol is FirSyntheticPropertySymbol) {
symbols[symbol] = true
return
}
// Check if this variable assignment is inside a lambda or a local function.
if (lambdaOrLocalFunctionStack.isEmpty()) return
// Check if the assigned variable doesn't belong to any lambda or local function.
val symbol = node.fir.referredPropertySymbol ?: return
if (symbol !in symbols || symbols[symbol] == false) return
// If all nested declarations are lambdas that are invoked in-place (according to the contract),
@@ -1,9 +1,9 @@
// FILE: KotlinFile.kt
fun foo(javaClass: JavaClass) {
javaClass.something1++
javaClass.something2++
javaClass.something3++
javaClass.something4++
javaClass.<!VAL_REASSIGNMENT!>something1<!>++
javaClass.<!VAL_REASSIGNMENT!>something2<!>++
javaClass.<!VAL_REASSIGNMENT!>something3<!>++
javaClass.<!VAL_REASSIGNMENT!>something4<!>++
javaClass.something5 = null
}
@@ -6,7 +6,7 @@ class KotlinClass {
fun foo(javaClass: JavaClass, kotlinClass: KotlinClass) {
useInt(javaClass.getSomething())
useInt(javaClass.something)
javaClass.something = 1
javaClass.<!VAL_REASSIGNMENT!>something<!> = 1
javaClass.<!UNRESOLVED_REFERENCE!>Something<!>
useInt(kotlinClass.getSomething())
kotlinClass.<!UNRESOLVED_REFERENCE!>something<!>
@@ -9,7 +9,7 @@ fun foo(k: KotlinClass) {
if (<!SENSELESS_COMPARISON!>k.something == null<!>) return
k.setSomething(1)
k.something = <!ASSIGNMENT_TYPE_MISMATCH!>1<!>
k.<!VAL_REASSIGNMENT!>something<!> = <!ASSIGNMENT_TYPE_MISMATCH!>1<!>
}
fun useString(i: String) {}