Ease field initialization check

Since there is already VAL_REASSIGNMENT diagnostics, we can safely only
for direct assignments.
 #KT-40893 Fixed
This commit is contained in:
Ilmir Usmanov
2020-08-06 17:38:54 +02:00
parent 6c0abe7e48
commit b403b63f48
10 changed files with 73 additions and 5 deletions
@@ -5156,6 +5156,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/contracts/lambdaParameter.kt");
}
@TestMetadata("listAppend.kt")
public void testListAppend() throws Exception {
runTest("compiler/testData/codegen/box/contracts/listAppend.kt");
}
@TestMetadata("valInWhen.kt")
public void testValInWhen() throws Exception {
runTest("compiler/testData/codegen/box/contracts/valInWhen.kt");
@@ -14,8 +14,8 @@ import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.diagnostics.Errors.CAPTURED_VAL_INITIALIZATION
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.CAPTURED_IN_CLOSURE
import org.jetbrains.kotlin.resolve.BindingTrace
@@ -58,7 +58,7 @@ class CapturingInClosureChecker : CallChecker {
nameElement: PsiElement
) {
if (variable !is PropertyDescriptor || scopeContainer !is AnonymousFunctionDescriptor || variable.isVar) return
if ((nameElement as KtExpression).getAssignmentByLHS() == null) return
if (!isLhsOfAssignment(nameElement as KtExpression)) return
val scopeDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(scopeContainer) as? KtFunction ?: return
if (scopeContainer.containingDeclaration !is ConstructorDescriptor) return
if (!isExactlyOnceContract(trace.bindingContext, scopeDeclaration)) return
@@ -70,6 +70,11 @@ class CapturingInClosureChecker : CallChecker {
}
}
private fun isLhsOfAssignment(nameElement: KtExpression): Boolean {
val parent = nameElement.parent as? KtBinaryExpression ?: return false
return parent.operationToken == KtTokens.EQ && parent.left == nameElement
}
private fun isCapturedVariable(variableParent: DeclarationDescriptor, scopeContainer: DeclarationDescriptor): Boolean {
if (variableParent !is FunctionDescriptor || scopeContainer == variableParent) return false
+28
View File
@@ -0,0 +1,28 @@
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
// IGNORE_BACKEND: NATIVE
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
import kotlin.contracts.*
class A {
val value = arrayListOf("O")
init {
foo {
value += "K"
}
}
}
fun foo(block: () -> Unit) {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
}
fun box(): String {
val a = A()
return if (a.value == listOf("O", "K")) "OK" else "FAIL"
}
@@ -71,13 +71,13 @@ class Test1 {
<!VAL_REASSIGNMENT!>a<!> += "allowed"
}
crossinlineMe {
<!CAPTURED_VAL_INITIALIZATION, VAL_REASSIGNMENT!>b<!> += "not allowed"
<!VAL_REASSIGNMENT!>b<!> += "not allowed"
}
noinlineMe {
<!CAPTURED_VAL_INITIALIZATION, VAL_REASSIGNMENT!>c<!> += "not allowed"
<!VAL_REASSIGNMENT!>c<!> += "not allowed"
}
notinline {
<!CAPTURED_VAL_INITIALIZATION, VAL_REASSIGNMENT!>d<!> += "not allowed"
<!VAL_REASSIGNMENT!>d<!> += "not allowed"
}
}
}
@@ -5191,6 +5191,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/contracts/lambdaParameter.kt");
}
@TestMetadata("listAppend.kt")
public void testListAppend() throws Exception {
runTest("compiler/testData/codegen/box/contracts/listAppend.kt");
}
@TestMetadata("valInWhen.kt")
public void testValInWhen() throws Exception {
runTest("compiler/testData/codegen/box/contracts/valInWhen.kt");
@@ -5191,6 +5191,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/contracts/lambdaParameter.kt");
}
@TestMetadata("listAppend.kt")
public void testListAppend() throws Exception {
runTest("compiler/testData/codegen/box/contracts/listAppend.kt");
}
@TestMetadata("valInWhen.kt")
public void testValInWhen() throws Exception {
runTest("compiler/testData/codegen/box/contracts/valInWhen.kt");
@@ -5156,6 +5156,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/contracts/lambdaParameter.kt");
}
@TestMetadata("listAppend.kt")
public void testListAppend() throws Exception {
runTest("compiler/testData/codegen/box/contracts/listAppend.kt");
}
@TestMetadata("valInWhen.kt")
public void testValInWhen() throws Exception {
runTest("compiler/testData/codegen/box/contracts/valInWhen.kt");
@@ -4191,6 +4191,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/contracts/lambdaParameter.kt");
}
@TestMetadata("listAppend.kt")
public void testListAppend() throws Exception {
runTest("compiler/testData/codegen/box/contracts/listAppend.kt");
}
@TestMetadata("valInWhen.kt")
public void testValInWhen() throws Exception {
runTest("compiler/testData/codegen/box/contracts/valInWhen.kt");
@@ -4191,6 +4191,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/contracts/lambdaParameter.kt");
}
@TestMetadata("listAppend.kt")
public void testListAppend() throws Exception {
runTest("compiler/testData/codegen/box/contracts/listAppend.kt");
}
@TestMetadata("valInWhen.kt")
public void testValInWhen() throws Exception {
runTest("compiler/testData/codegen/box/contracts/valInWhen.kt");
@@ -4191,6 +4191,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/contracts/lambdaParameter.kt");
}
@TestMetadata("listAppend.kt")
public void testListAppend() throws Exception {
runTest("compiler/testData/codegen/box/contracts/listAppend.kt");
}
@TestMetadata("valInWhen.kt")
public void testValInWhen() throws Exception {
runTest("compiler/testData/codegen/box/contracts/valInWhen.kt");