Check whether the field is indeed being initialized
in checkFieldInExactlyOnceLambdaInitialization #KT-40691 Fixed
This commit is contained in:
Generated
+5
@@ -5131,6 +5131,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/contracts/exception.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("fieldReadInConstructor.kt")
|
||||
public void testFieldReadInConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forLoop.kt")
|
||||
public void testForLoop() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/forLoop.kt");
|
||||
|
||||
+4
-2
@@ -15,6 +15,7 @@ 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.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
|
||||
@@ -54,9 +55,10 @@ class CapturingInClosureChecker : CallChecker {
|
||||
variable: VariableDescriptor,
|
||||
trace: BindingTrace,
|
||||
scopeContainer: DeclarationDescriptor,
|
||||
reportOn: PsiElement
|
||||
nameElement: PsiElement
|
||||
) {
|
||||
if (variable !is PropertyDescriptor || scopeContainer !is AnonymousFunctionDescriptor || variable.isVar) return
|
||||
if ((nameElement as KtExpression).getAssignmentByLHS() == null) return
|
||||
val scopeDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(scopeContainer) as? KtFunction ?: return
|
||||
if (scopeContainer.containingDeclaration !is ConstructorDescriptor) return
|
||||
if (!isExactlyOnceContract(trace.bindingContext, scopeDeclaration)) return
|
||||
@@ -64,7 +66,7 @@ class CapturingInClosureChecker : CallChecker {
|
||||
val (callee, param) = getCalleeDescriptorAndParameter(trace.bindingContext, scopeDeclaration) ?: return
|
||||
if (callee !is FunctionDescriptor) return
|
||||
if (!callee.isInline || (param.isCrossinline || !InlineUtil.isInlineParameter(param))) {
|
||||
trace.report(CAPTURED_VAL_INITIALIZATION.on(reportOn as KtExpression, variable))
|
||||
trace.report(CAPTURED_VAL_INITIALIZATION.on(nameElement, variable))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = "Some value"
|
||||
|
||||
init {
|
||||
foo {
|
||||
println(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(block: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
A()
|
||||
return "OK"
|
||||
}
|
||||
+71
@@ -58,3 +58,74 @@ class Test {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
class Test1 {
|
||||
val a: String = ""
|
||||
val b: String = ""
|
||||
val c: String = ""
|
||||
val d: String = ""
|
||||
|
||||
init {
|
||||
inlineMe {
|
||||
a += "allowed"
|
||||
}
|
||||
crossinlineMe {
|
||||
b += "not allowed"
|
||||
}
|
||||
noinlineMe {
|
||||
c += "not allowed"
|
||||
}
|
||||
notinline {
|
||||
d += "not allowed"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
class Test2 {
|
||||
val a: String = ""
|
||||
val b: String = ""
|
||||
val c: String = ""
|
||||
val d: String = ""
|
||||
|
||||
init {
|
||||
var blackhole = ""
|
||||
inlineMe {
|
||||
blackhole += a
|
||||
}
|
||||
crossinlineMe {
|
||||
blackhole += b
|
||||
}
|
||||
noinlineMe {
|
||||
blackhole += c
|
||||
}
|
||||
notinline {
|
||||
blackhole += d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
class Test4 {
|
||||
val a: String = ""
|
||||
val b: String = ""
|
||||
val c: String = ""
|
||||
val d: String = ""
|
||||
|
||||
init {
|
||||
var blackhole: String
|
||||
inlineMe {
|
||||
blackhole = a
|
||||
}
|
||||
crossinlineMe {
|
||||
blackhole = b
|
||||
}
|
||||
noinlineMe {
|
||||
blackhole = c
|
||||
}
|
||||
notinline {
|
||||
blackhole = d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+71
@@ -58,3 +58,74 @@ class Test {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
class Test1 {
|
||||
val a: String = ""
|
||||
val b: String = ""
|
||||
val c: String = ""
|
||||
val d: String = ""
|
||||
|
||||
init {
|
||||
inlineMe {
|
||||
<!VAL_REASSIGNMENT!>a<!> += "allowed"
|
||||
}
|
||||
crossinlineMe {
|
||||
<!CAPTURED_VAL_INITIALIZATION, VAL_REASSIGNMENT!>b<!> += "not allowed"
|
||||
}
|
||||
noinlineMe {
|
||||
<!CAPTURED_VAL_INITIALIZATION, VAL_REASSIGNMENT!>c<!> += "not allowed"
|
||||
}
|
||||
notinline {
|
||||
<!CAPTURED_VAL_INITIALIZATION, VAL_REASSIGNMENT!>d<!> += "not allowed"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
class Test2 {
|
||||
val a: String = ""
|
||||
val b: String = ""
|
||||
val c: String = ""
|
||||
val d: String = ""
|
||||
|
||||
init {
|
||||
var blackhole = ""
|
||||
inlineMe {
|
||||
blackhole += a
|
||||
}
|
||||
crossinlineMe {
|
||||
blackhole += b
|
||||
}
|
||||
noinlineMe {
|
||||
blackhole += c
|
||||
}
|
||||
notinline {
|
||||
blackhole += d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts
|
||||
class Test4 {
|
||||
val a: String = ""
|
||||
val b: String = ""
|
||||
val c: String = ""
|
||||
val d: String = ""
|
||||
|
||||
init {
|
||||
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>blackhole<!>: String
|
||||
inlineMe {
|
||||
blackhole = a
|
||||
}
|
||||
crossinlineMe {
|
||||
blackhole = b
|
||||
}
|
||||
noinlineMe {
|
||||
blackhole = c
|
||||
}
|
||||
notinline {
|
||||
blackhole = d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+33
@@ -22,3 +22,36 @@ package
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts public final class Test1 {
|
||||
public constructor Test1()
|
||||
public final val a: kotlin.String = ""
|
||||
public final val b: kotlin.String = ""
|
||||
public final val c: kotlin.String = ""
|
||||
public final val d: kotlin.String = ""
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts public final class Test2 {
|
||||
public constructor Test2()
|
||||
public final val a: kotlin.String = ""
|
||||
public final val b: kotlin.String = ""
|
||||
public final val c: kotlin.String = ""
|
||||
public final val d: kotlin.String = ""
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@kotlin.contracts.ExperimentalContracts public final class Test4 {
|
||||
public constructor Test4()
|
||||
public final val a: kotlin.String = ""
|
||||
public final val b: kotlin.String = ""
|
||||
public final val c: kotlin.String = ""
|
||||
public final val d: kotlin.String = ""
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
+5
@@ -5161,6 +5161,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/contracts/exception.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("fieldReadInConstructor.kt")
|
||||
public void testFieldReadInConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forLoop.kt")
|
||||
public void testForLoop() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/forLoop.kt");
|
||||
|
||||
+5
@@ -5161,6 +5161,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/contracts/exception.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("fieldReadInConstructor.kt")
|
||||
public void testFieldReadInConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forLoop.kt")
|
||||
public void testForLoop() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/forLoop.kt");
|
||||
|
||||
+5
@@ -5131,6 +5131,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/contracts/exception.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("fieldReadInConstructor.kt")
|
||||
public void testFieldReadInConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forLoop.kt")
|
||||
public void testForLoop() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/forLoop.kt");
|
||||
|
||||
Generated
+5
@@ -4166,6 +4166,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/contracts/exception.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("fieldReadInConstructor.kt")
|
||||
public void testFieldReadInConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forLoop.kt")
|
||||
public void testForLoop() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/forLoop.kt");
|
||||
|
||||
Generated
+5
@@ -4166,6 +4166,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/contracts/exception.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("fieldReadInConstructor.kt")
|
||||
public void testFieldReadInConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forLoop.kt")
|
||||
public void testForLoop() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/forLoop.kt");
|
||||
|
||||
+5
@@ -4166,6 +4166,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/contracts/exception.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("fieldReadInConstructor.kt")
|
||||
public void testFieldReadInConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/fieldReadInConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forLoop.kt")
|
||||
public void testForLoop() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/forLoop.kt");
|
||||
|
||||
Reference in New Issue
Block a user