From 4434db4d692c8e8fc4ba4f7a77564c063ce0a5a6 Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Tue, 3 Oct 2017 15:02:51 +0300 Subject: [PATCH] Effects: add diagnostic tests on contracts - Make AbstractDiagnosticsTest dump function contracts - Add diagnostics tests on parsing contracts - Add diagnostics tests on smartcats in presence of functions with contracts - Add diagnostics tests on initialization and flow in presence of in-place called lambdas ========== Introduction of EffectSystem: 16/18 --- .../breakContinuesInInlinedLambda.kt | 50 ++ .../breakContinuesInInlinedLambda.txt | 7 + .../flowInlining/expressionBody.instructions | 97 ++++ .../flowInlining/expressionBody.kt | 17 + .../flowInlining/expressionBody.txt | 5 + .../implicitCastToAnyInReturnType.kt | 19 + .../implicitCastToAnyInReturnType.txt | 7 + .../flowInlining/inlinedLambdaAlwaysThrows.kt | 16 + .../inlinedLambdaAlwaysThrows.txt | 6 + .../flowInlining/irrelevantUnknownClosure.kt | 22 + .../flowInlining/irrelevantUnknownClosure.txt | 7 + .../flowInlining/labeledReturns.kt | 85 ++++ .../flowInlining/labeledReturns.txt | 13 + .../flowInlining/nestedTryCatchFinally.kt | 97 ++++ .../flowInlining/nestedTryCatchFinally.txt | 11 + .../flowInlining/nestedTryCatchs.kt | 46 ++ .../flowInlining/nestedTryCatchs.txt | 8 + .../flowInlining/nonLocalReturn.kt | 17 + .../flowInlining/nonLocalReturn.txt | 5 + .../flowInlining/nonReturningInlinedLambda.kt | 33 ++ .../nonReturningInlinedLambda.txt | 8 + .../severalJumpOutsFromInlinedLambda.kt | 78 +++ .../severalJumpOutsFromInlinedLambda.txt | 8 + .../flowInlining/throwIfNotCalled.kt | 47 ++ .../flowInlining/throwIfNotCalled.txt | 8 + .../controlflow/flowInlining/tryCatch.kt | 57 +++ .../controlflow/flowInlining/tryCatch.txt | 9 + .../flowInlining/tryCatchFinally.kt | 33 ++ .../flowInlining/tryCatchFinally.txt | 8 + .../controlflow/flowInlining/typeMismatch.kt | 18 + .../controlflow/flowInlining/typeMismatch.txt | 7 + .../flowInlining/unreachableCode.kt | 16 + .../flowInlining/unreachableCode.txt | 6 + .../atLeastOnce/valDefiniteReassignment.kt | 74 +++ .../atLeastOnce/valDefiniteReassignment.txt | 14 + .../atLeastOnce/varDefiniteInitialization.kt | 30 ++ .../atLeastOnce/varDefiniteInitialization.txt | 7 + .../atLeastOnce/varIndefiniteIntialization.kt | 28 ++ .../varIndefiniteIntialization.txt | 8 + .../exactlyOnce/valDefiniteInitialization.kt | 91 ++++ .../exactlyOnce/valDefiniteInitialization.txt | 21 + .../exactlyOnce/valDefiniteReassignment.kt | 27 + .../exactlyOnce/valDefiniteReassignment.txt | 7 + .../valIndefiniteInitialization.kt | 67 +++ .../valIndefiniteInitialization.txt | 22 + .../exactlyOnce/varDefiniteInitalization.kt | 41 ++ .../exactlyOnce/varDefiniteInitalization.txt | 9 + .../varIndefiniteInitialization.kt | 50 ++ .../varIndefiniteInitialization.txt | 10 + .../exactlyOnce/withReceiver.kt | 27 + .../exactlyOnce/withReceiver.txt | 8 + .../unknown/unknownInvocations.kt | 17 + .../unknown/unknownInvocations.txt | 6 + .../dsl/errors/booleanComparisons.kt | 22 + .../dsl/errors/booleanComparisons.txt | 4 + .../dsl/errors/callInContractDescription.kt | 13 + .../dsl/errors/callInContractDescription.txt | 4 + .../dsl/errors/nestedConditionalEffects.kt | 10 + .../dsl/errors/nestedConditionalEffects.txt | 3 + .../contracts/dsl/errors/notFirstStatement.kt | 11 + .../dsl/errors/notFirstStatement.txt | 3 + .../dsl/errors/referenceToProperty.kt | 13 + .../dsl/errors/referenceToProperty.txt | 10 + .../contracts/dsl/errors/unlabeledReceiver.kt | 11 + .../dsl/errors/unlabeledReceiver.txt | 4 + .../contracts/dsl/useBeforeDeclaration.kt | 19 + .../contracts/dsl/useBeforeDeclaration.txt | 6 + .../smartcasts/catchExceptionSpilling.kt | 20 + .../smartcasts/catchExceptionSpilling.txt | 6 + .../contracts/smartcasts/compositions.kt | 69 +++ .../contracts/smartcasts/compositions.txt | 12 + .../contracts/smartcasts/deeplyNested.kt | 102 ++++ .../contracts/smartcasts/deeplyNested.txt | 25 + .../contracts/smartcasts/intersectingInfo.kt | 59 +++ .../contracts/smartcasts/intersectingInfo.txt | 12 + .../contracts/smartcasts/intersectionTypes.kt | 43 ++ .../smartcasts/intersectionTypes.txt | 10 + .../smartcasts/multieffect/implicitIff.kt | 86 ++++ .../smartcasts/multieffect/implicitIff.txt | 18 + .../smartcasts/multieffect/returnsAndCalls.kt | 67 +++ .../multieffect/returnsAndCalls.txt | 11 + .../nullabilitySmartcastWhenNullability.kt | 55 +++ .../nullabilitySmartcastWhenNullability.txt | 10 + .../smartcasts/operatorsTests/andOperator.kt | 79 +++ .../smartcasts/operatorsTests/andOperator.txt | 18 + .../operatorsTests/andOperatorWithConstant.kt | 59 +++ .../andOperatorWithConstant.txt | 11 + .../operatorsTests/andOperatorWithUnknown.kt | 59 +++ .../operatorsTests/andOperatorWithUnknown.txt | 13 + .../operatorsTests/equalsOperator.kt | 45 ++ .../operatorsTests/equalsOperator.txt | 10 + .../equalsWithNullableBoolean.kt | 68 +++ .../equalsWithNullableBoolean.txt | 10 + .../operatorsTests/isInstanceOperator.kt | 59 +++ .../operatorsTests/isInstanceOperator.txt | 12 + .../smartcasts/operatorsTests/orOperator.kt | 76 +++ .../smartcasts/operatorsTests/orOperator.txt | 18 + .../operatorsTests/orOperatorWithConstant.kt | 56 +++ .../operatorsTests/orOperatorWithConstant.txt | 11 + .../operatorsTests/orOperatorWithUnknown.kt | 59 +++ .../operatorsTests/orOperatorWithUnknown.txt | 13 + .../smartcasts/partiallyIncorrect.kt | 20 + .../smartcasts/partiallyIncorrect.txt | 5 + .../contracts/smartcasts/receiver.kt | 34 ++ .../contracts/smartcasts/receiver.txt | 14 + .../contracts/smartcasts/throwsEffect.kt | 65 +++ .../contracts/smartcasts/throwsEffect.txt | 12 + .../typeSmartcastWhenNullability.kt | 58 +++ .../typeSmartcastWhenNullability.txt | 11 + .../smartcasts/unreachableBranches.kt | 31 ++ .../smartcasts/unreachableBranches.txt | 7 + .../contracts/smartcasts/when/withSubject.kt | 35 ++ .../contracts/smartcasts/when/withSubject.txt | 7 + .../when/withSubjectNullableBoolean.kt | 55 +++ .../when/withSubjectNullableBoolean.txt | 6 + .../smartcasts/when/withoutSubject.kt | 30 ++ .../smartcasts/when/withoutSubject.txt | 7 + .../checkers/AbstractDiagnosticsTest.kt | 4 +- .../DiagnosticsTestWithStdLibGenerated.java | 465 ++++++++++++++++++ ...ticsTestWithStdLibUsingJavacGenerated.java | 465 ++++++++++++++++++ 120 files changed, 4179 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/breakContinuesInInlinedLambda.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/breakContinuesInInlinedLambda.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.instructions create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/implicitCastToAnyInReturnType.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/implicitCastToAnyInReturnType.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/inlinedLambdaAlwaysThrows.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/inlinedLambdaAlwaysThrows.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/irrelevantUnknownClosure.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/irrelevantUnknownClosure.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/labeledReturns.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/labeledReturns.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchFinally.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchFinally.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchs.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchs.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonLocalReturn.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonLocalReturn.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/throwIfNotCalled.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/throwIfNotCalled.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatch.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatch.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatchFinally.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatchFinally.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/unreachableCode.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/unreachableCode.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/valDefiniteReassignment.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/valDefiniteReassignment.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varDefiniteInitialization.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varDefiniteInitialization.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varIndefiniteIntialization.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varIndefiniteIntialization.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteReassignment.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteReassignment.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valIndefiniteInitialization.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valIndefiniteInitialization.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varDefiniteInitalization.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varDefiniteInitalization.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varIndefiniteInitialization.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varIndefiniteInitialization.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/withReceiver.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/withReceiver.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown/unknownInvocations.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown/unknownInvocations.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/booleanComparisons.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/booleanComparisons.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/callInContractDescription.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/callInContractDescription.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nestedConditionalEffects.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nestedConditionalEffects.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/notFirstStatement.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/notFirstStatement.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/unlabeledReceiver.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/unlabeledReceiver.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/useBeforeDeclaration.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/useBeforeDeclaration.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/catchExceptionSpilling.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/catchExceptionSpilling.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/compositions.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/compositions.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/deeplyNested.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/deeplyNested.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectionTypes.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectionTypes.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/implicitIff.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/implicitIff.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/returnsAndCalls.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/returnsAndCalls.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithConstant.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithConstant.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithUnknown.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithUnknown.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/isInstanceOperator.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/isInstanceOperator.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperator.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperator.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithConstant.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithConstant.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithUnknown.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithUnknown.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/partiallyIncorrect.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/partiallyIncorrect.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/typeSmartcastWhenNullability.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/typeSmartcastWhenNullability.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/unreachableBranches.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/unreachableBranches.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withoutSubject.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withoutSubject.txt diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/breakContinuesInInlinedLambda.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/breakContinuesInInlinedLambda.kt new file mode 100644 index 00000000000..97da67e3fcf --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/breakContinuesInInlinedLambda.kt @@ -0,0 +1,50 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun getBoolean(): Boolean = false + +fun test() { + val x: Int + + if (getBoolean()) + myRun { + while (getBoolean()) { + do { + myRun { + if (getBoolean()) { + x = 42 // No reassignment because of break + } + else { + x = 43 // No reassignment because of break + } + } + break + } while (getBoolean()) + // Loop executed exectly once, initializing x + myRun { x.inc() } + + myRun { x = 42 } + break + } + // x is I?D here because loop could've been execited + // VAL_REASSIGNMENT isn't reported because of repeating diagnostic + x = 42 + // x is ID now + } + else + myRun { + x = 42 + } + // x is ID because both branches are ID + + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/breakContinuesInInlinedLambda.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/breakContinuesInInlinedLambda.txt new file mode 100644 index 00000000000..ae579c3e4e1 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/breakContinuesInInlinedLambda.txt @@ -0,0 +1,7 @@ +package + +public fun getBoolean(): kotlin.Boolean +public inline fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.instructions b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.instructions new file mode 100644 index 00000000000..e3b62c6ec2d --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.instructions @@ -0,0 +1,97 @@ +== myRun == +fun myRun(@CalledInPlace block: () -> T): T = block() +--------------------- +L0: + 1 INIT: in: {} out: {} + v(@CalledInPlace block: () -> T) INIT: in: {} out: {block=D} + magic[FAKE_INITIALIZER](@CalledInPlace block: () -> T) -> INIT: in: {block=D} out: {block=D} + w(block|) INIT: in: {block=D} out: {block=ID} USE: in: {block=READ} out: {block=READ} + r(block) -> INIT: in: {block=ID} out: {block=ID} USE: in: {} out: {block=READ} + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + +error: + INIT: in: {} out: {} +sink: + INIT: in: {block=I?} out: {block=I?} USE: in: {} out: {} +===================== +== functionWithExpressionBody == +fun functionWithExpressionBody(x: Int) = myRun { + if (x == 0) return true + if (x == 1) return false + return functionWithExpressionBody(x - 2) +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(x: Int) INIT: in: {} out: {x=D} + magic[FAKE_INITIALIZER](x: Int) -> INIT: in: {x=D} out: {x=D} + w(x|) INIT: in: {x=D} out: {x=ID} + mark({ if (x == 0) return true if (x == 1) return false return functionWithExpressionBody(x - 2) }) INIT: in: {x=ID} out: {x=ID} + jmp?(L2) + d({ if (x == 0) return true if (x == 1) return false return functionWithExpressionBody(x - 2) }) INIT: in: {} out: {} USE: in: {x=READ} out: {x=READ} +L2 [after local declaration]: + r({ if (x == 0) return true if (x == 1) return false return functionWithExpressionBody(x - 2) }) -> INIT: in: {x=ID} out: {x=ID} + mark(myRun { if (x == 0) return true if (x == 1) return false return functionWithExpressionBody(x - 2) }) + call(myRun { if (x == 0) return true if (x == 1) return false return functionWithExpressionBody(x - 2) }, myRun|) -> + ret(*|) L1 +L1: + +error: + INIT: in: {} out: {} +sink: + INIT: in: {x=I?} out: {x=I?} USE: in: {} out: {} +===================== +== anonymous_0 == +{ + if (x == 0) return true + if (x == 1) return false + return functionWithExpressionBody(x - 2) +} +--------------------- +L3: + 2 INIT: in: {x=ID} out: {x=ID} + 3 mark(if (x == 0) return true if (x == 1) return false return functionWithExpressionBody(x - 2)) + mark(if (x == 0) return true) + r(x) -> + r(0) -> + mark(x == 0) + call(x == 0, equals|, ) -> + jf(L5|) USE: in: {x=READ} out: {x=READ} + r(true) -> + ret(*|) L1 USE: in: {} out: {} +- jmp(L6) +L5 [else branch]: + read (Unit) INIT: in: {x=ID} out: {x=ID} +L6 ['if' expression result]: + merge(if (x == 0) return true|!) -> + mark(if (x == 1) return false) + r(x) -> + r(1) -> + mark(x == 1) + call(x == 1, equals|, ) -> + jf(L7|) USE: in: {x=READ} out: {x=READ} + r(false) -> + ret(*|) L1 USE: in: {} out: {} +- jmp(L8) +L7 [else branch]: + read (Unit) INIT: in: {x=ID} out: {x=ID} +L8 ['if' expression result]: + merge(if (x == 1) return false|!) -> USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {} out: {x=READ} + r(2) -> + mark(x - 2) + call(x - 2, minus|, ) -> + mark(functionWithExpressionBody(x - 2)) + call(functionWithExpressionBody(x - 2), functionWithExpressionBody|) -> + ret(*|) L1 USE: in: {} out: {} +- 2 ret(*|!) L4 +L4: + INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.kt new file mode 100644 index 00000000000..6096f812667 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun functionWithExpressionBody(x: Int): Boolean = myRun { + if (x == 0) return true + if (x == 1) return false + return functionWithExpressionBody(x - 2) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.txt new file mode 100644 index 00000000000..55a3d1662d6 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.txt @@ -0,0 +1,5 @@ +package + +public fun functionWithExpressionBody(/*0*/ x: kotlin.Int): kotlin.Boolean +public inline fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/implicitCastToAnyInReturnType.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/implicitCastToAnyInReturnType.kt new file mode 100644 index 00000000000..42f62f9de72 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/implicitCastToAnyInReturnType.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun functionWithSideEffects(x: Int): Int = x + 1 // ...and some other useful side-effects + +fun log(s: String) = Unit // some logging or println or whatever returning Unit + +fun implicitCastWithIf(s: String) { + myRun { if (s == "") functionWithSideEffects(42) else log(s) } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/implicitCastToAnyInReturnType.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/implicitCastToAnyInReturnType.txt new file mode 100644 index 00000000000..e157c9af0dc --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/implicitCastToAnyInReturnType.txt @@ -0,0 +1,7 @@ +package + +public fun functionWithSideEffects(/*0*/ x: kotlin.Int): kotlin.Int +public fun implicitCastWithIf(/*0*/ s: kotlin.String): kotlin.Unit +public fun log(/*0*/ s: kotlin.String): kotlin.Unit +public fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/inlinedLambdaAlwaysThrows.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/inlinedLambdaAlwaysThrows.kt new file mode 100644 index 00000000000..cc523b610d1 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/inlinedLambdaAlwaysThrows.kt @@ -0,0 +1,16 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} + +fun test() { + myRun { throw java.lang.IllegalArgumentException() } + val x: Int = 42 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/inlinedLambdaAlwaysThrows.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/inlinedLambdaAlwaysThrows.txt new file mode 100644 index 00000000000..ccc1d213168 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/inlinedLambdaAlwaysThrows.txt @@ -0,0 +1,6 @@ +package + +public inline fun myRun(/*0*/ block: () -> kotlin.Unit): kotlin.Unit + CallsInPlace(block, EXACTLY_ONCE) + +public fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/irrelevantUnknownClosure.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/irrelevantUnknownClosure.kt new file mode 100644 index 00000000000..78d5b963bd2 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/irrelevantUnknownClosure.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +inline fun unknownRun(block: () -> Unit) { block() } + +fun foo() { + val x: Int + myRun { + unknownRun { println("shouldn't change anything") } + x = 42 + } + println(x) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/irrelevantUnknownClosure.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/irrelevantUnknownClosure.txt new file mode 100644 index 00000000000..2c280bde08d --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/irrelevantUnknownClosure.txt @@ -0,0 +1,7 @@ +package + +public fun foo(): kotlin.Unit +public inline fun myRun(/*0*/ block: () -> kotlin.Unit): kotlin.Unit + CallsInPlace(block, EXACTLY_ONCE) + +public inline fun unknownRun(/*0*/ block: () -> kotlin.Unit): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/labeledReturns.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/labeledReturns.kt new file mode 100644 index 00000000000..91b73d8b03b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/labeledReturns.kt @@ -0,0 +1,85 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +inline fun T.myLet(block: (T) -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block(this) +} + +inline fun unknownRun(block: () -> Unit) = block() + +fun getBool(): Boolean = false + +fun threeLevelsReturnNoInitialization(x: Int?): Int? { + // Inner always jumps to outer + // And middle always calls inner + // So, in fact, middle never finished normally + // Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization + // Hence, outer doesn't performs definite initialization + val y: Int + myRun outer@ { + myRun middle@ { + x.myLet inner@ { + if (it == null) { + y = 42 + return@outer Unit + } + else { + return@outer Unit + } + } + } + // Possible to report unreachable here + y = 54 + } + return y.inc() +} + +fun threeLevelsReturnWithInitialization(x: Int?): Int? { + val y: Int + myRun outer@ { + myRun middle@ { + x.myLet inner@ { + if (it == null) { + y = 42 + return@outer Unit + } + else { + y = 34 + return@outer Unit + } + } + } + } + return y.inc() +} + +fun threeLevelsReturnWithUnknown(x: Int?): Int? { + val y: Int + myRun outer@ { + unknownRun middle@ { + x.myLet inner@ { + if (it == null) { + y = 42 + return@outer Unit + } + else { + y = 34 + return@outer Unit + } + } + } + } + return y.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/labeledReturns.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/labeledReturns.txt new file mode 100644 index 00000000000..558e3e688ee --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/labeledReturns.txt @@ -0,0 +1,13 @@ +package + +public fun getBool(): kotlin.Boolean +public inline fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun threeLevelsReturnNoInitialization(/*0*/ x: kotlin.Int?): kotlin.Int? +public fun threeLevelsReturnWithInitialization(/*0*/ x: kotlin.Int?): kotlin.Int? +public fun threeLevelsReturnWithUnknown(/*0*/ x: kotlin.Int?): kotlin.Int? +public inline fun unknownRun(/*0*/ block: () -> kotlin.Unit): kotlin.Unit +public inline fun T.myLet(/*0*/ block: (T) -> R): R + CallsInPlace(block, EXACTLY_ONCE) + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchFinally.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchFinally.kt new file mode 100644 index 00000000000..0185d1353e5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchFinally.kt @@ -0,0 +1,97 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -INVISIBLE_MEMBER -INVISIBLE_REFERENCE +// !LANGUAGE: +CallsInPlaceEffect + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun innerComputation(): Int = 42 +fun outerComputation(): Int = 52 + +fun log() = Unit + +fun outerFinallyInitializes() { + val x: Int + + try { + myRun { + try { + x = innerComputation() + } catch (e: java.lang.Exception) { + log() + } + // possible reassignment if innerComputation finished + x = 42 + // x is ID here + } + + // Definite reassignment here, cause can get here only if myRun finished + // Not reported because of repeating diagnostic + x = outerComputation() + } catch (e: java.lang.Exception) { + // can catch exception thrown by the inner, so x can be not initalized + x.inc() + log() + } finally { + // Possible reassignment (e.g. if everything finished) + // Not reported because of repeating diagnostic + x = 42 + } + + // Properly initialized + x.inc() +} + +fun innerFinallyInitializes() { + val x: Int + try { + myRun { + try { + innerComputation() + } catch (e: java.lang.Exception) { + log() + } finally { + x = 42 + } + } + + // Properly initialized + x.inc() + } catch (e: java.lang.Exception) { + log() + } + + // Still can be unitialized because we don't know what can happen in try-block + // (e.g., OutOfMemory exception could've happened even before myRun was executed) + x.inc() +} + + +fun innerFinallyInitializesOuterRethrows() { + val x: Int + try { + myRun { + try { + innerComputation() + } catch (e: java.lang.Exception) { + log() + } finally { + x = 42 + } + } + + // Properly initialized + x.inc() + } catch (e: java.lang.Exception) { + log() + throw e + } + + // Guaranteed to be initialized because all catch-clauses are rethrowing + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchFinally.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchFinally.txt new file mode 100644 index 00000000000..2e38a851ca2 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchFinally.txt @@ -0,0 +1,11 @@ +package + +public fun innerComputation(): kotlin.Int +public fun innerFinallyInitializes(): kotlin.Unit +public fun innerFinallyInitializesOuterRethrows(): kotlin.Unit +public fun log(): kotlin.Unit +public inline fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun outerComputation(): kotlin.Int +public fun outerFinallyInitializes(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchs.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchs.kt new file mode 100644 index 00000000000..d2e13e7dd35 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchs.kt @@ -0,0 +1,46 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun innerComputation(): Int = 42 +fun outerComputation(): Int = 52 + +fun innerTryCatchInitializes() { + val x: Int + + try { + myRun { + try { + x = innerComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // Potential reassignment because x.inc() could threw + x = 42 + x.inc() + } + } + // Can get here only when inlined lambda exited properly, i.e. x is initialized + x.inc() + outerComputation() + + } catch (e: java.lang.Exception) { + // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) + // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) + // So, x=I? here + x.inc() + + // Potential reasignment + x = 42 + } + // Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though) + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchs.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchs.txt new file mode 100644 index 00000000000..8db7578ad13 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchs.txt @@ -0,0 +1,8 @@ +package + +public fun innerComputation(): kotlin.Int +public fun innerTryCatchInitializes(): kotlin.Unit +public inline fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun outerComputation(): kotlin.Int diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonLocalReturn.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonLocalReturn.kt new file mode 100644 index 00000000000..8d9c8c9f3bf --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonLocalReturn.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun T.myLet(block: (T) -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block(this) +} + + +fun nonLocalReturnWithElvis(x: Int?): Int? { + x?.myLet { return 42 } + return x?.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonLocalReturn.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonLocalReturn.txt new file mode 100644 index 00000000000..613f43fd44f --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonLocalReturn.txt @@ -0,0 +1,5 @@ +package + +public fun nonLocalReturnWithElvis(/*0*/ x: kotlin.Int?): kotlin.Int? +public inline fun T.myLet(/*0*/ block: (T) -> R): R + CallsInPlace(block, EXACTLY_ONCE) diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.kt new file mode 100644 index 00000000000..8075d253173 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.kt @@ -0,0 +1,33 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun getBool(): Boolean = false + +fun withLabeledReturn() { + val y: Int + + val x = myRun outer@ { + myRun { return@outer Unit } + y = 42 + } + + println(y) + println(x) +} + +fun withLabeledReturn2(y: Int) { + myRun outer@ { + myRun { return@outer Unit } + println(y) + } + println(y) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.txt new file mode 100644 index 00000000000..40b3f64518d --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.txt @@ -0,0 +1,8 @@ +package + +public fun getBool(): kotlin.Boolean +public inline fun myRun(/*0*/ block: () -> kotlin.Unit): kotlin.Unit + CallsInPlace(block, EXACTLY_ONCE) + +public fun withLabeledReturn(): kotlin.Unit +public fun withLabeledReturn2(/*0*/ y: kotlin.Int): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt new file mode 100644 index 00000000000..eb85e12ff64 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt @@ -0,0 +1,78 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun exitOnlyThroughLocalReturns(b: Boolean) { + var x: Int + var s: String + + myRun { + if (b) { + x = 42 + return@myRun + } + + if (!b) { + s = "hello" + x = 42 + return@myRun + } + else { + s = "world" + x = 239 + } + } + + x.inc() + s.length +} + +fun exitOnlyThroughNonLocalReturns(b: Boolean?) { + var x: Int + var s: String + myRun { + if (b == null) { + x = 42 + return + } + + if (b.not()) { + x = 54 + } + + if (x == 42) { + return + } + else { + x = 42 + s = "hello" + return + } + } + + x.inc() + s.length +} + +fun nonLocalReturnAndOrdinaryExit(b: Boolean) { + var x: Int + var s: String + myRun { + if (b) { + x = 42 + return + } + x = 54 + s = "hello" + } + x.inc() + s.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.txt new file mode 100644 index 00000000000..1d4d452aaef --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.txt @@ -0,0 +1,8 @@ +package + +public fun exitOnlyThroughLocalReturns(/*0*/ b: kotlin.Boolean): kotlin.Unit +public fun exitOnlyThroughNonLocalReturns(/*0*/ b: kotlin.Boolean?): kotlin.Unit +public inline fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun nonLocalReturnAndOrdinaryExit(/*0*/ b: kotlin.Boolean): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/throwIfNotCalled.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/throwIfNotCalled.kt new file mode 100644 index 00000000000..780189ca5b2 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/throwIfNotCalled.kt @@ -0,0 +1,47 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} + +inline fun unknownRun(block: () -> T): T = block() + +fun throwIfNotCalled() { + val x: Int + myRun outer@ { + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } + // x *is* initialized here, because if myRun was never called -> exception + // were thrown and control flow wouldn't be here + println(x) +} + +fun catchThrowIfNotCalled() { + val x: Int + try { + myRun outer@ { + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } + } catch (ignored: java.lang.IllegalArgumentException) { } + + // x *isn't* initialized here! + println(x) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/throwIfNotCalled.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/throwIfNotCalled.txt new file mode 100644 index 00000000000..ac2fcb8d3ab --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/throwIfNotCalled.txt @@ -0,0 +1,8 @@ +package + +public fun catchThrowIfNotCalled(): kotlin.Unit +public inline fun myRun(/*0*/ block: () -> kotlin.Unit): kotlin.Unit + CallsInPlace(block, EXACTLY_ONCE) + +public fun throwIfNotCalled(): kotlin.Unit +public inline fun unknownRun(/*0*/ block: () -> T): T diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatch.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatch.kt new file mode 100644 index 00000000000..a7a358f89e5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatch.kt @@ -0,0 +1,57 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun someComputation(): Int = 42 + +fun tryCatchInlined() { + val x: Int + + myRun { + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + x.inc() + } + } + x = 42 + x.inc() +} + +fun possibleReassignmentInTryCatch() { + val x: Int + + myRun { + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + x = 42 + x.inc() + } + x.inc() + } + x.inc() +} + +fun tryCatchOuter() { + val x: Int + try { + myRun { x = someComputation() } + x.inc() + } + catch (e: java.lang.Exception) { + x.inc() + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatch.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatch.txt new file mode 100644 index 00000000000..0d7ff22f8a5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatch.txt @@ -0,0 +1,9 @@ +package + +public fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun possibleReassignmentInTryCatch(): kotlin.Unit +public fun someComputation(): kotlin.Int +public fun tryCatchInlined(): kotlin.Unit +public fun tryCatchOuter(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatchFinally.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatchFinally.kt new file mode 100644 index 00000000000..73cf1d0827e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatchFinally.kt @@ -0,0 +1,33 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -UNUSED_PARAMETER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun someComputation(): Int = 42 + +fun report(x: Int) = Unit + +fun innerTryCatchFinally() { + val x: Int + + myRun { + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } + + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatchFinally.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatchFinally.txt new file mode 100644 index 00000000000..1c45dd6e975 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatchFinally.txt @@ -0,0 +1,8 @@ +package + +public fun innerTryCatchFinally(): kotlin.Unit +public inline fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun report(/*0*/ x: kotlin.Int): kotlin.Unit +public fun someComputation(): kotlin.Int diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.kt new file mode 100644 index 00000000000..dfceb1d2e19 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.kt @@ -0,0 +1,18 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun foo(x: Int): Int = x + 1 + +fun typeMismatchInLambda(y: String): Int { + val x = myRun { foo(y) } + return x +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.txt new file mode 100644 index 00000000000..e65af7a9f71 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.txt @@ -0,0 +1,7 @@ +package + +public fun foo(/*0*/ x: kotlin.Int): kotlin.Int +public fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun typeMismatchInLambda(/*0*/ y: kotlin.String): kotlin.Int diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/unreachableCode.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/unreachableCode.kt new file mode 100644 index 00000000000..55d85bfd7fe --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/unreachableCode.kt @@ -0,0 +1,16 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun throwInLambda(): Int { + val x = myRun { throw java.lang.IllegalArgumentException(); 42 } + return x +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/unreachableCode.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/unreachableCode.txt new file mode 100644 index 00000000000..135fb24d8dc --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/unreachableCode.txt @@ -0,0 +1,6 @@ +package + +public inline fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun throwInLambda(): kotlin.Int diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/valDefiniteReassignment.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/valDefiniteReassignment.kt new file mode 100644 index 00000000000..c28f5e7ae43 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/valDefiniteReassignment.kt @@ -0,0 +1,74 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun runTwice(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.AT_LEAST_ONCE) + } + block() + return block(); +}; + +fun runOnce(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block(); +}; + +fun valueReassignment() { + val x: Int + x.inc() + runTwice { x = 42 } + x.inc() +} + +fun shadowing() { + val x: Int + runTwice { val x: Int; x = 42; x.inc() } + x.inc() +} + +fun branchingFlow(a: Any?) { + val x: Int + x.inc() + if (a is String) { + runTwice { x = 42 } + } + else { + x = 43 + } + x.inc() +} + +fun branchingFlowWithMissingBranches(a: Any?) { + val x: Int + if (a is String) { + runTwice { x = 42 } + } + + x.inc() +} + +fun repeatingFlow(n: Int) { + val x: Int + x.inc() + + for (i in 1..n) { + runTwice { x = 42 } + } + + x.inc() +} + +fun repeatingFlow2(n: Int) { + val x: Int + + for (i in 1..n) { + runTwice { x = 42 } + } + + x.inc() +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/valDefiniteReassignment.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/valDefiniteReassignment.txt new file mode 100644 index 00000000000..ba4888e0dd7 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/valDefiniteReassignment.txt @@ -0,0 +1,14 @@ +package + +public fun branchingFlow(/*0*/ a: kotlin.Any?): kotlin.Unit +public fun branchingFlowWithMissingBranches(/*0*/ a: kotlin.Any?): kotlin.Unit +public fun repeatingFlow(/*0*/ n: kotlin.Int): kotlin.Unit +public fun repeatingFlow2(/*0*/ n: kotlin.Int): kotlin.Unit +public fun runOnce(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun runTwice(/*0*/ block: () -> T): T + CallsInPlace(block, AT_LEAST_ONCE) + +public fun shadowing(): kotlin.Unit +public fun valueReassignment(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varDefiniteInitialization.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varDefiniteInitialization.kt new file mode 100644 index 00000000000..c1fdcd29706 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varDefiniteInitialization.kt @@ -0,0 +1,30 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun runTwice(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.AT_LEAST_ONCE) + } + block() + return block(); +}; + +fun testInitialization() { + var x: Int + x.inc() + runTwice { x = 42 } + x.inc() + x = 43 + x.inc() +} + +fun repeatingFlow(n: Int) { + var x: Int + for (i in 1..n) { + runTwice { x = 42 } + } + x.inc() +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varDefiniteInitialization.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varDefiniteInitialization.txt new file mode 100644 index 00000000000..ae9d7e09f3d --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varDefiniteInitialization.txt @@ -0,0 +1,7 @@ +package + +public fun repeatingFlow(/*0*/ n: kotlin.Int): kotlin.Unit +public fun runTwice(/*0*/ block: () -> T): T + CallsInPlace(block, AT_LEAST_ONCE) + +public fun testInitialization(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varIndefiniteIntialization.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varIndefiniteIntialization.kt new file mode 100644 index 00000000000..6c3afbd874c --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varIndefiniteIntialization.kt @@ -0,0 +1,28 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun runTwice(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.AT_LEAST_ONCE) + } + block() + return block(); +}; + +fun funWithUnknownInvocations(block: () -> T) = block() + +fun indefiniteFlow() { + var x: Int + + funWithUnknownInvocations { runTwice { x = 42 } } + + x.inc() +} + +fun shadowing() { + var x: Int + runTwice { val x: Int; x = 42; x.inc() } + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varIndefiniteIntialization.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varIndefiniteIntialization.txt new file mode 100644 index 00000000000..0f9ea7c3799 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varIndefiniteIntialization.txt @@ -0,0 +1,8 @@ +package + +public fun funWithUnknownInvocations(/*0*/ block: () -> T): T +public fun indefiniteFlow(): kotlin.Unit +public fun runTwice(/*0*/ block: () -> T): T + CallsInPlace(block, AT_LEAST_ONCE) + +public fun shadowing(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.kt new file mode 100644 index 00000000000..3a561aa7384 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.kt @@ -0,0 +1,91 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun initialization() { + val x: Int + myRun { + x = 42 + 42 + } + x.inc() +} + +fun shadowing() { + val x = 42 + myRun { + val x = 43 + x.inc() + } + x.inc() +} + +fun nestedDefiniteAssignment() { + val x: Int + myRun { + val y = "Hello" + myRun { + x = 42 + } + y.length + } + x.inc() +} + +fun deeplyNestedDefiniteAssignment() { + val x: Int + myRun { + val y: String + myRun { + val z: String + myRun { + z = "Hello" + y = "World" + x = 42 + } + z.length + } + y.length + } + x.inc() +} + +fun branchingFlow(a: Any?) { + val x: Int + + if (a is String) { + myRun { x = 42 } + } + else { + myRun { x = 43 } + } + + x.inc() +} + +fun returningValue() { + val x: Int + val hello = myRun { x = 42; "hello" } + x.inc() + hello.length +} + +fun unknownRun(block: () -> Unit) = block() + +class DefiniteInitializationInInitSection { + val x: Int + val y: Int + + init { + myRun { x = 42 } + unknownRun { y = 239 } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.txt new file mode 100644 index 00000000000..d10107c46d7 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.txt @@ -0,0 +1,21 @@ +package + +public fun branchingFlow(/*0*/ a: kotlin.Any?): kotlin.Unit +public fun deeplyNestedDefiniteAssignment(): kotlin.Unit +public fun initialization(): kotlin.Unit +public fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun nestedDefiniteAssignment(): kotlin.Unit +public fun returningValue(): kotlin.Unit +public fun shadowing(): kotlin.Unit +public fun unknownRun(/*0*/ block: () -> kotlin.Unit): kotlin.Unit + +public final class DefiniteInitializationInInitSection { + public constructor DefiniteInitializationInInitSection() + public final val x: kotlin.Int + public final val y: kotlin.Int + 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 +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteReassignment.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteReassignment.kt new file mode 100644 index 00000000000..042c53153aa --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteReassignment.kt @@ -0,0 +1,27 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun reassignmentInUsualFlow() { + val x: Int + myRun { x = 42 } + x = 43 + x.inc() +} + +fun reassignment() { + val x = 42 + myRun { + x = 43 + } + x.inc() +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteReassignment.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteReassignment.txt new file mode 100644 index 00000000000..573552d5117 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteReassignment.txt @@ -0,0 +1,7 @@ +package + +public fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun reassignment(): kotlin.Unit +public fun reassignmentInUsualFlow(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valIndefiniteInitialization.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valIndefiniteInitialization.kt new file mode 100644 index 00000000000..73d8e0a83a2 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valIndefiniteInitialization.kt @@ -0,0 +1,67 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun myRepeat(n: Int, action: () -> Unit) { + contract { + callsInPlace(action) + } + for (i in 1..n) action() +} + +fun branchingIndetermineFlow(a: Any?) { + val x: Int + + if (a is String) { + myRepeat(a.length) { + // Val reassignment because we know that repeat's lambda called in-place + myRun { x = 42 } + } + } + else { + myRun { x = 43 } + } + + x.inc() +} + +fun nonAnonymousLambdas() { + val x: Int + val initializer = { x = 42 } + myRun(initializer) + x.inc() +} + +fun multipleAssignments() { + val x: Int + myRepeat(42) { + // Val reassignment because we know that repeat's lambda called in-place + myRun { x = 42 } + } + x.inc() +} + +fun funWithUnknownInvocations(block: () -> Unit) = block() + +fun nestedIndefiniteAssignment() { + val x: Int + // Captured val initialization reported, because we don't know anything about funWithUnknownInvocations + funWithUnknownInvocations { myRun { x = 42 } } + x.inc() +} + +class InitializationForbiddenInNonInitSection { + val x: Int + + fun setup() { + myRun { x = 42 } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valIndefiniteInitialization.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valIndefiniteInitialization.txt new file mode 100644 index 00000000000..e04945bff42 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valIndefiniteInitialization.txt @@ -0,0 +1,22 @@ +package + +public fun branchingIndetermineFlow(/*0*/ a: kotlin.Any?): kotlin.Unit +public fun funWithUnknownInvocations(/*0*/ block: () -> kotlin.Unit): kotlin.Unit +public fun multipleAssignments(): kotlin.Unit +public fun myRepeat(/*0*/ n: kotlin.Int, /*1*/ action: () -> kotlin.Unit): kotlin.Unit + CallsInPlace(action, UNKNOWN) + +public fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun nestedIndefiniteAssignment(): kotlin.Unit +public fun nonAnonymousLambdas(): kotlin.Unit + +public final class InitializationForbiddenInNonInitSection { + public constructor InitializationForbiddenInNonInitSection() + public final val x: kotlin.Int + 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 final fun setup(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varDefiniteInitalization.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varDefiniteInitalization.kt new file mode 100644 index 00000000000..232fb788d06 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varDefiniteInitalization.kt @@ -0,0 +1,41 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun definiteVarInitialization() { + var x: Int + myRun { x = 42 } + x.inc() +} + +fun definiteVarReassignment() { + var x: Int + myRun { x = 42 } + x.inc() + myRun { x = 43 } + x.inc() + x = 44 + x.inc() +} + +fun nestedVarInitialization() { + var x: Int + myRun { myRun { myRun { x = 42 } } } + x.inc() + myRun { myRun { myRun { x = 42 } } } +} + + +fun notAnExpression() { + var x: Int = 0 + myRun { if (true) x = 42 } + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varDefiniteInitalization.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varDefiniteInitalization.txt new file mode 100644 index 00000000000..2b4e60515a9 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varDefiniteInitalization.txt @@ -0,0 +1,9 @@ +package + +public fun definiteVarInitialization(): kotlin.Unit +public fun definiteVarReassignment(): kotlin.Unit +public fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun nestedVarInitialization(): kotlin.Unit +public fun notAnExpression(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varIndefiniteInitialization.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varIndefiniteInitialization.kt new file mode 100644 index 00000000000..7360af142c9 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varIndefiniteInitialization.kt @@ -0,0 +1,50 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun indefiniteVarReassignment(n: Int) { + var x: Int + repeat(n) { + myRun { x = 42 } + } + x.inc() +} + +fun nonAnonymousLambdas() { + // Named lambdas are not inlined, even in theory it could be done for some simple cases as this one + var x: Int + val initializer = { x = 42 } + myRun(initializer) + x.inc() +} + +fun branchingIndetermineFlow(a: Any) { + var x: Int + + if (a is String) { + repeat(a.length) { + myRun { x = 42 } + } + } + else { + myRun { x = 43 } + } + + x.inc() +} + +fun funWithUnknownInvocations(block: () -> Unit) = block() + +fun nestedIndefiniteAssignment() { + val x: Int + funWithUnknownInvocations { myRun { x = 42 } } + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varIndefiniteInitialization.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varIndefiniteInitialization.txt new file mode 100644 index 00000000000..8751ef4f40b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varIndefiniteInitialization.txt @@ -0,0 +1,10 @@ +package + +public fun branchingIndetermineFlow(/*0*/ a: kotlin.Any): kotlin.Unit +public fun funWithUnknownInvocations(/*0*/ block: () -> kotlin.Unit): kotlin.Unit +public fun indefiniteVarReassignment(/*0*/ n: kotlin.Int): kotlin.Unit +public fun myRun(/*0*/ block: () -> T): T + CallsInPlace(block, EXACTLY_ONCE) + +public fun nestedIndefiniteAssignment(): kotlin.Unit +public fun nonAnonymousLambdas(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/withReceiver.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/withReceiver.kt new file mode 100644 index 00000000000..8b51c366386 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/withReceiver.kt @@ -0,0 +1,27 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun T.myLet(block: (T) -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block(this) +} + +fun initializationWithReceiver(y: String) { + val x: Int + y.myLet { x = 42 } + x.inc() +} + +fun initializationWithSafeCall(y: String?) { + val x: Int + y?.myLet { x = 42 } + x.inc() +} + +fun sanityCheck(x: Int, y: String): Int { + y.let { return x } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/withReceiver.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/withReceiver.txt new file mode 100644 index 00000000000..d0364213bbe --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/withReceiver.txt @@ -0,0 +1,8 @@ +package + +public fun initializationWithReceiver(/*0*/ y: kotlin.String): kotlin.Unit +public fun initializationWithSafeCall(/*0*/ y: kotlin.String?): kotlin.Unit +public fun sanityCheck(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String): kotlin.Int +public fun T.myLet(/*0*/ block: (T) -> R): R + CallsInPlace(block, EXACTLY_ONCE) + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown/unknownInvocations.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown/unknownInvocations.kt new file mode 100644 index 00000000000..6c37ea48427 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown/unknownInvocations.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +CallsInPlaceEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun inPlace(block: () -> T): T { + contract { + callsInPlace(block) + } + return block() +} + +fun reassignmentAndNoInitializaiton() { + val x: Int + inPlace { x = 42 } + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown/unknownInvocations.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown/unknownInvocations.txt new file mode 100644 index 00000000000..cf01fe7a2cd --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown/unknownInvocations.txt @@ -0,0 +1,6 @@ +package + +public fun inPlace(/*0*/ block: () -> T): T + CallsInPlace(block, UNKNOWN) + +public fun reassignmentAndNoInitializaiton(): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/booleanComparisons.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/booleanComparisons.kt new file mode 100644 index 00000000000..92f0882de30 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/booleanComparisons.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun foo(b: Boolean): Boolean { + contract { + // pointless, can be reduced to just "b" + returns(true) implies (b == true) + } + + return b +} + +fun bar(b: Boolean?): Boolean { + contract { + // not pointless, but not supported yet + returns(true) implies (b == true) + } + if (b == null) throw java.lang.IllegalArgumentException("") + return b +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/booleanComparisons.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/booleanComparisons.txt new file mode 100644 index 00000000000..8b1bd685ba5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/booleanComparisons.txt @@ -0,0 +1,4 @@ +package + +public fun bar(/*0*/ b: kotlin.Boolean?): kotlin.Boolean +public fun foo(/*0*/ b: kotlin.Boolean): kotlin.Boolean diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/callInContractDescription.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/callInContractDescription.kt new file mode 100644 index 00000000000..386aa5af7b6 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/callInContractDescription.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun bar(x: Int): Boolean = x == 0 + +fun foo(x: Int): Boolean { + contract { + returns(true) implies (bar(x)) + } + return x == 0 +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/callInContractDescription.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/callInContractDescription.txt new file mode 100644 index 00000000000..0890e6299d1 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/callInContractDescription.txt @@ -0,0 +1,4 @@ +package + +public fun bar(/*0*/ x: kotlin.Int): kotlin.Boolean +public fun foo(/*0*/ x: kotlin.Int): kotlin.Boolean diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nestedConditionalEffects.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nestedConditionalEffects.kt new file mode 100644 index 00000000000..2c54658e3d6 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nestedConditionalEffects.kt @@ -0,0 +1,10 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun foo(boolean: Boolean) { + contract { + (returns() implies (boolean)) implies (!boolean) + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nestedConditionalEffects.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nestedConditionalEffects.txt new file mode 100644 index 00000000000..2c2139f0099 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nestedConditionalEffects.txt @@ -0,0 +1,3 @@ +package + +public fun foo(/*0*/ boolean: kotlin.Boolean): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/notFirstStatement.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/notFirstStatement.kt new file mode 100644 index 00000000000..3b09896c3e8 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/notFirstStatement.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun foo(y: Boolean) { + val x: Int = 42 + contract { + returns() implies y + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/notFirstStatement.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/notFirstStatement.txt new file mode 100644 index 00000000000..f0d1cf6de3a --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/notFirstStatement.txt @@ -0,0 +1,3 @@ +package + +public fun foo(/*0*/ y: kotlin.Boolean): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.kt new file mode 100644 index 00000000000..f8c89cf9697 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +class Foo(val x: Int?) { + fun isXNull(): Boolean { + contract { + returns(false) implies (x != null) + } + return x != null + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.txt new file mode 100644 index 00000000000..30a0cc33134 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.txt @@ -0,0 +1,10 @@ +package + +public final class Foo { + public constructor Foo(/*0*/ x: kotlin.Int?) + public final val x: kotlin.Int? + 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 final fun isXNull(): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/unlabeledReceiver.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/unlabeledReceiver.kt new file mode 100644 index 00000000000..ce272e9c183 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/unlabeledReceiver.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun Any?.foo(): Boolean { + contract { + returns(true) implies (?)!>this != null) + } + return this != null +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/unlabeledReceiver.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/unlabeledReceiver.txt new file mode 100644 index 00000000000..8e4bd7ff902 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/unlabeledReceiver.txt @@ -0,0 +1,4 @@ +package + +public fun kotlin.Any?.foo(): kotlin.Boolean + Returns(TRUE) -> != null diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/useBeforeDeclaration.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/useBeforeDeclaration.kt new file mode 100644 index 00000000000..2a091504f0b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/useBeforeDeclaration.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun test(x: Any?) { + if (isString(x)) { + x.length + } +} + +fun isString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/useBeforeDeclaration.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/useBeforeDeclaration.txt new file mode 100644 index 00000000000..37b96debeed --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/useBeforeDeclaration.txt @@ -0,0 +1,6 @@ +package + +public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun test(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/catchExceptionSpilling.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/catchExceptionSpilling.kt new file mode 100644 index 00000000000..8cfe2bf7b55 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/catchExceptionSpilling.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myAssert(condition: Boolean) { + contract { + returns() implies (condition) + } + if (!condition) throw kotlin.IllegalArgumentException("Assertion failed") +} + +fun testWithCatch(x: Any?) { + try { + myAssert(x is String) + x.length + } catch (e: java.lang.IllegalArgumentException) { } + + x.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/catchExceptionSpilling.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/catchExceptionSpilling.txt new file mode 100644 index 00000000000..f354eb907a9 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/catchExceptionSpilling.txt @@ -0,0 +1,6 @@ +package + +public fun myAssert(/*0*/ condition: kotlin.Boolean): kotlin.Unit + Returns(WILDCARD) -> condition + +public fun testWithCatch(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/compositions.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/compositions.kt new file mode 100644 index 00000000000..79b33770263 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/compositions.kt @@ -0,0 +1,69 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun isString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun testEqualsWithConstant(x: Any?) { + if (isString(x) == true) { + x.length + } + else { + x.length + } +} + +fun testNotEqualsWithConstant(x: Any?) { + if (isString(x) != true) { + x.length + } + else { + x.length + } +} + +fun unknownFunction(): Any? = 42 + +fun testEqualsWithUnknown(x: Any?) { + if (isString(x) == unknownFunction()) { + x.length + } + else { + x.length + } + x.length +} + +fun testNotEqualsWithUnknown(x: Any?) { + if (isString(x) != unknownFunction()) { + x.length + } + else { + x.length + } + x.length +} + +fun testEqualsWithVariable(x: Any?, b: Boolean) { + if (isString(x) == b) { + x.length + } + else { + x.length + } +} + +fun testNotEqualsWithVariable(x: Any?, b: Boolean) { + if (isString(x) != b) { + x.length + } + else { + x.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/compositions.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/compositions.txt new file mode 100644 index 00000000000..2efe5a686b2 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/compositions.txt @@ -0,0 +1,12 @@ +package + +public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun testEqualsWithConstant(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testEqualsWithUnknown(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testEqualsWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit +public fun testNotEqualsWithConstant(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testNotEqualsWithUnknown(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testNotEqualsWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit +public fun unknownFunction(): kotlin.Any? diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/deeplyNested.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/deeplyNested.kt new file mode 100644 index 00000000000..3a0ed45f125 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/deeplyNested.kt @@ -0,0 +1,102 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myAssert(condition: Boolean) { + contract { + returns() implies (condition) + } + if (!condition) throw kotlin.IllegalArgumentException("Assertion failed") +} + +fun isString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun isInt(x: Any?): Boolean { + contract { + returns(true) implies (x is Int) + } + return x is Int +} + +fun notEqualsNull(x: Any?): Boolean { + contract { + returns(true) implies (x != null) + } + return x != null +} + +fun equalsTrue(x: Boolean): Boolean { + contract { + returns(true) implies x + } + return x == true +} + +fun nullWhenNotString(x: Any?): String? { + contract { + returnsNotNull() implies (x is String) + } + return x as? String +} + + + + +// ========== Actual tests ============ + +fun nested1(x: Any?) { + if (equalsTrue(isString(x))) { + x.length + } + else { + x.length + } +} + +fun nested2(x: Any?) { + myAssert(equalsTrue(isString(x))) + x.length +} + +fun nested3(x: Any?) { + myAssert(equalsTrue(notEqualsNull(nullWhenNotString(x)))) + x.length +} + +fun branchedAndNested(x: Any?, y: Any?) { + myAssert(equalsTrue(notEqualsNull(nullWhenNotString(x))) && equalsTrue(isString(y))) + x.length + y.length +} + + +fun br(y: Any?) { + if (myAssert(y is Int) == Unit && myAssert(y is String) == Unit) { + y.length + y.inc() + } +} + +fun branchedAndNestedWithNativeOperators(x: Any?, y: Any?) { + myAssert( + equalsTrue(notEqualsNull(nullWhenNotString(x))) // x is String + && + ( + (myAssert(y is Int) == Unit && myAssert(y is String) == Unit) // y is Int, String + || + equalsTrue(isInt(y) && isString(y)) // y is Int, String + ) + && + (1 == 2 || y is Int || isString(y)) + ) + x.length + y.length + y.inc() +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/deeplyNested.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/deeplyNested.txt new file mode 100644 index 00000000000..b4fde98a32a --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/deeplyNested.txt @@ -0,0 +1,25 @@ +package + +public fun br(/*0*/ y: kotlin.Any?): kotlin.Unit +public fun branchedAndNested(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): kotlin.Unit +public fun branchedAndNestedWithNativeOperators(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): kotlin.Unit +public fun equalsTrue(/*0*/ x: kotlin.Boolean): kotlin.Boolean + Returns(TRUE) -> x + +public fun isInt(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is Int + +public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun myAssert(/*0*/ condition: kotlin.Boolean): kotlin.Unit + Returns(WILDCARD) -> condition + +public fun nested1(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun nested2(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun nested3(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun notEqualsNull(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x != null + +public fun nullWhenNotString(/*0*/ x: kotlin.Any?): kotlin.String? + Returns(NOT_NULL) -> x is String diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.kt new file mode 100644 index 00000000000..e6af8cbadaf --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.kt @@ -0,0 +1,59 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun isString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + + +fun notIsString(x: Any?): Boolean { + contract { + returns(false) implies (x is String) + } + return x !is String +} + +fun notIsInt(x: Any?): Boolean { + contract { + returns(false) implies (x !is Int) + } + return x !is Int +} + +fun intersectingInfo(x: Any?, y: Any?) { + if ((isString(x) && y is String) || (!notIsString(x) && !notIsInt(y))) { + x.length + y.length + y.inc() + } + else { + x.length + y.length + y.inc() + } +} + +fun intersectingInfo2(x: Any?, y: Any?) { + // In each arg of "||"-operator presented fact "x is String" which should lead to smartcast. + // Also there are 3 additional facts: "x is Int", "y is String", "y is Int". One + // of them is absent in each arg of "||"-operator, so they *shouldn't* lead to smartcast + + if ((isString(x) && !notIsInt(x) && y is String) || + (!notIsString(x) && isString(y) && y is Int) || + (x is String && !notIsInt(y) && x is Int)) { + x.length + x.inc() + y.length + y.inc() + } + x.length + x.inc() + y.length + y.inc() +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.txt new file mode 100644 index 00000000000..2fcaae30a27 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.txt @@ -0,0 +1,12 @@ +package + +public fun intersectingInfo(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): kotlin.Unit +public fun intersectingInfo2(/*0*/ x: kotlin.Any?, /*1*/ y: kotlin.Any?): kotlin.Unit +public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun notIsInt(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x !is Int + +public fun notIsString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is String diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectionTypes.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectionTypes.kt new file mode 100644 index 00000000000..97350d5d023 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectionTypes.kt @@ -0,0 +1,43 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun notIsString(x: Any?): Boolean { + contract { + returns(false) implies (x is String) + } + return x !is String +} + +fun notIsInt(x: Any?): Boolean { + contract { + returns(false) implies (x is Int) + } + return x !is Int +} + +fun testDeMorgan(x: Any?) { + // !(x !is String || x !is Int) + // x is String && x is Int + if (!(notIsString(x) || notIsInt(x))) { + x.length + x.inc() + } + else { + x.length + x.inc() + } +} + +fun testDeMorgan2(x: Any?) { + // x !is String || x !is Int + if (notIsString(x) || notIsInt(x)) { + x.length + x.inc() + } + else { + x.length + x.inc() + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectionTypes.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectionTypes.txt new file mode 100644 index 00000000000..782a4e6f54b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectionTypes.txt @@ -0,0 +1,10 @@ +package + +public fun notIsInt(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is Int + +public fun notIsString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is String + +public fun testDeMorgan(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testDeMorgan2(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/implicitIff.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/implicitIff.kt new file mode 100644 index 00000000000..0301183e291 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/implicitIff.kt @@ -0,0 +1,86 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun onlyTrue(b: Boolean): Boolean { + contract { + returns(true) implies (b) + } + return b +} + +fun onlyFalse(b: Boolean): Boolean { + contract { + returns(false) implies (!b) + } + return b +} + +fun trueAndFalse(b: Boolean): Boolean { + contract { + returns(true) implies (b) + returns(false) implies (!b) + } + return b +} + + + +// ==== actual tests ==== + +fun useOnlyTrueInTrueBranch(x: Any?) { + if (onlyTrue(x is String)) { + x.length + } + else { + x.length + } +} + +fun useOnlyTrueInFalseBranch(x: Any?) { + if (onlyTrue(x !is String)) { + x.length + } + else { + // No smartcast here, we don't know that condition is false here + x.length + } +} + +fun useOnlyFalseInTrueBranch(x: Any?) { + if (onlyFalse(x is String)) { + // No smartcast here, we don't know that condition is true here + x.length + } + else { + x.length + } +} + +fun useOnlyFalseInFalseBranch(x: Any?) { + if (onlyFalse(x !is String)) { + x.length + } + else { + x.length + } +} + +fun useTrueAndFalseInTrueBranch(x: Any?) { + if (trueAndFalse(x is String)) { + x.length + } + else { + x.length + } +} + +fun useTrueAndFalseInFalseBranch(x: Any?) { + if (trueAndFalse(x !is String)) { + x.length + } + else { + x.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/implicitIff.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/implicitIff.txt new file mode 100644 index 00000000000..19e2ed4c0b0 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/implicitIff.txt @@ -0,0 +1,18 @@ +package + +public fun onlyFalse(/*0*/ b: kotlin.Boolean): kotlin.Boolean + Returns(FALSE) -> !b + +public fun onlyTrue(/*0*/ b: kotlin.Boolean): kotlin.Boolean + Returns(TRUE) -> b + +public fun trueAndFalse(/*0*/ b: kotlin.Boolean): kotlin.Boolean + Returns(TRUE) -> b + Returns(FALSE) -> !b + +public fun useOnlyFalseInFalseBranch(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun useOnlyFalseInTrueBranch(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun useOnlyTrueInFalseBranch(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun useOnlyTrueInTrueBranch(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun useTrueAndFalseInFalseBranch(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun useTrueAndFalseInTrueBranch(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/returnsAndCalls.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/returnsAndCalls.kt new file mode 100644 index 00000000000..ddb3c3f0a84 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/returnsAndCalls.kt @@ -0,0 +1,67 @@ +// !LANGUAGE: +CallsInPlaceEffect +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } + + block() + return !b +} + + + +fun smartcastAndInitialization(x: Any?) { + val y: Int + + if (callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } else { + println(y) + x.length + } + println(y) +} + +fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) { + val y: Int + + if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} + +fun isPresenceOfLazy2(x: Any?, unknownBoolean: Boolean) { + val y: Int + if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { + x.length + } + else { + println(y) + x.length + } + println(y) +} + +fun isPresenceOfLazy3(x: Any?, unknownBoolean: Boolean) { + val y: Int + if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { + x.length + } + else { + x.length + } + println(y) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/returnsAndCalls.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/returnsAndCalls.txt new file mode 100644 index 00000000000..cf97fc6f9e5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/returnsAndCalls.txt @@ -0,0 +1,11 @@ +package + +public fun callsAndInverts(/*0*/ b: kotlin.Boolean, /*1*/ block: () -> kotlin.Unit): kotlin.Boolean + CallsInPlace(block, EXACTLY_ONCE) + Returns(TRUE) -> !b + Returns(FALSE) -> b + +public fun inPresenceOfLazy(/*0*/ x: kotlin.Any?, /*1*/ unknownBoolean: kotlin.Boolean): kotlin.Unit +public fun isPresenceOfLazy2(/*0*/ x: kotlin.Any?, /*1*/ unknownBoolean: kotlin.Boolean): kotlin.Unit +public fun isPresenceOfLazy3(/*0*/ x: kotlin.Any?, /*1*/ unknownBoolean: kotlin.Boolean): kotlin.Unit +public fun smartcastAndInitialization(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.kt new file mode 100644 index 00000000000..13c61bf314e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.kt @@ -0,0 +1,55 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun nullWhenNull(x: Int?): Int? { + contract { + returnsNotNull() implies (x != null) + } + return x?.inc() +} + +fun testNullWhenNull(x: Int?) { + if (nullWhenNull(x) == null) { + x.dec() + } + else { + x.dec() + } + + if (nullWhenNull(x) != null) { + x.dec() + } + else { + x.dec() + } + + x.dec() +} + +// NB. it is the same function as `nullWhenNull`, but annotations specifies other facet of the function behaviour +fun notNullWhenNotNull (x: Int?): Int? { + contract { + returns(null) implies (x == null) + } + return x?.inc() +} + +fun testNotNullWhenNotNull (x: Int?) { + if (notNullWhenNotNull(x) == null) { + x == null + } + else { + x.dec() + } + + if (notNullWhenNotNull(x) != null) { + x.dec() + } + else { + x == null + } + + x.dec() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.txt new file mode 100644 index 00000000000..c5fc1ae97e7 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.txt @@ -0,0 +1,10 @@ +package + +public fun notNullWhenNotNull(/*0*/ x: kotlin.Int?): kotlin.Int? + Returns(NULL) -> x == null + +public fun nullWhenNull(/*0*/ x: kotlin.Int?): kotlin.Int? + Returns(NOT_NULL) -> x != null + +public fun testNotNullWhenNotNull(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun testNullWhenNull(/*0*/ x: kotlin.Int?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.kt new file mode 100644 index 00000000000..9e6bdc226a5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.kt @@ -0,0 +1,79 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun trueWhenString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun trueWhenInt(x: Any?): Boolean { + contract { + returns(true) implies (x is Int) + } + return x is Int +} + +fun falseWhenString(x: Any?): Boolean { + contract { + returns(false) implies (x is String) + } + return x !is String +} + +fun falseWhenInt(x: Any?): Boolean { + contract { + returns(false) implies (x is Int) + } + return x !is Int +} + + +// ==== Actual tests ==== + +fun truetrue(x: Any?) { + if (trueWhenString(x) && trueWhenInt(x)) { + x.length + x.inc() + } + x.length + x.inc() +} + +fun truefalse(x: Any?) { + if (trueWhenString(x) && falseWhenInt(x)) { + x.length + x.inc() + } + else { + x.length + x.inc() + } +} + +fun falsetrue(x: Any?) { + if (falseWhenString(x) && trueWhenInt(x)) { + x.length + x.inc() + } + else { + x.length + x.inc() + } +} + +fun falsefalse(x: Any?) { + if (falseWhenString(x) && falseWhenInt(x)) { + x.length + x.inc() + } + else { + // Note that we can't argue that we have any of smartcasts here, + // because we don't know which one of both arguments was 'false' to bring us here + x.length + x.inc() + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.txt new file mode 100644 index 00000000000..98be42bbcbb --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.txt @@ -0,0 +1,18 @@ +package + +public fun falseWhenInt(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is Int + +public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is String + +public fun falsefalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun falsetrue(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun trueWhenInt(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is Int + +public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun truefalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun truetrue(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithConstant.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithConstant.kt new file mode 100644 index 00000000000..04298096e5a --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithConstant.kt @@ -0,0 +1,59 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun trueWhenString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun falseWhenString(x: Any?): Boolean { + contract { + returns(false) implies (x is String) + } + return x !is String +} + + + + +fun annotatedTrueAndTrue(x: Any?) { + if (trueWhenString(x) && true) { + x.length + } + else { + x.length + } +} + +fun annotatedTrueAndFalse(x: Any?) { + if (trueWhenString(x) && false) { + // Unreachable + x.length + } + else { + x.length + } +} + +fun annotatedFalseAndTrue(x: Any?) { + if (falseWhenString(x) && true) { + x.length + } + else { + x.length + } +} + +fun annotatedFalseAndFalse(x: Any?) { + if (falseWhenString(x) && false) { + // Unreachable + x.length + } + else { + x.length + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithConstant.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithConstant.txt new file mode 100644 index 00000000000..3e2356c9dea --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithConstant.txt @@ -0,0 +1,11 @@ +package + +public fun annotatedFalseAndFalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun annotatedFalseAndTrue(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun annotatedTrueAndFalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun annotatedTrueAndTrue(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is String + +public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithUnknown.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithUnknown.kt new file mode 100644 index 00000000000..e6e82e34316 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithUnknown.kt @@ -0,0 +1,59 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun trueWhenString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun falseWhenString(x: Any?): Boolean { + contract { + returns(false) implies (x is String) + } + return x !is String +} + +fun unknownFunction(x: Any?) = x == 42 + + + + +fun annotatedTrue(x: Any?) { + if (trueWhenString(x) && unknownFunction(x)) { + x.length + } + else { + x.length + } +} + +fun annotatedFalse(x: Any?) { + if (falseWhenString(x) && unknownFunction(x)) { + x.length + } + else { + x.length + } +} + +fun annotatedTrueWithVariable(x: Any?, b: Boolean) { + if (trueWhenString(x) && b) { + x.length + } + else { + x.length + } +} + +fun annotatedFalseWithVariable(x: Any?, b: Boolean) { + if (falseWhenString(x) && b) { + x.length + } + else { + x.length + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithUnknown.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithUnknown.txt new file mode 100644 index 00000000000..0a80fa39071 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithUnknown.txt @@ -0,0 +1,13 @@ +package + +public fun annotatedFalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun annotatedFalseWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit +public fun annotatedTrue(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun annotatedTrueWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit +public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is String + +public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun unknownFunction(/*0*/ x: kotlin.Any?): kotlin.Boolean diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.kt new file mode 100644 index 00000000000..fda2a6e15cb --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.kt @@ -0,0 +1,45 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myEqualsNull(x: Int?): Boolean { + contract { + returns(false) implies (x != null) + } + return x == null +} + +fun myEqualsNotNull(x: Int?): Boolean { + contract { + returns(true) implies (x != null) + } + return x != null +} + +fun testBasicEquals(x: Int?) { + x.inc() + + if (myEqualsNull(x)) { + x.inc() + } + else { + x.inc() + } + + x.inc() +} + +fun testBasicNotEquals(x: Int?) { + x.inc() + + if (myEqualsNotNull(x)) { + x.inc() + } + else { + x.inc() + } + + x.inc() +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.txt new file mode 100644 index 00000000000..fb987a4a2c7 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.txt @@ -0,0 +1,10 @@ +package + +public fun myEqualsNotNull(/*0*/ x: kotlin.Int?): kotlin.Boolean + Returns(TRUE) -> x != null + +public fun myEqualsNull(/*0*/ x: kotlin.Int?): kotlin.Boolean + Returns(FALSE) -> x != null + +public fun testBasicEquals(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun testBasicNotEquals(/*0*/ x: kotlin.Int?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.kt new file mode 100644 index 00000000000..3e49fa24ec6 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.kt @@ -0,0 +1,68 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun safeIsString(x: Any?): Boolean? { + contract { + returns(true) implies (x is String) + } + return x?.let { it is String } +} + + + + +fun equalsTrue(x: Any?) { + if (safeIsString(x) == true) { + x.length + } + else { + x.length + } +} + +fun equalsFalse(x: Any?) { + if (safeIsString(x) == false) { + x.length + } + else { + x.length + } +} + +fun equalsNull(x: Any?) { + if (safeIsString(x) == null) { + x.length + } + else { + x.length + } +} + +fun notEqualsTrue(x: Any?) { + if (safeIsString(x) != true) { + x.length + } + else { + x.length + } +} + +fun notEqualsFalse(x: Any?) { + if (safeIsString(x) != false) { + x.length + } + else { + x.length + } +} + +fun notEqualsNull(x: Any?) { + if (safeIsString(x) != null) { + x.length + } + else { + x.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.txt new file mode 100644 index 00000000000..abe2ddd88c4 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.txt @@ -0,0 +1,10 @@ +package + +public fun equalsFalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun equalsNull(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun equalsTrue(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun notEqualsFalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun notEqualsNull(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun notEqualsTrue(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun safeIsString(/*0*/ x: kotlin.Any?): kotlin.Boolean? + Returns(TRUE) -> x is String diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/isInstanceOperator.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/isInstanceOperator.kt new file mode 100644 index 00000000000..92c2dd02270 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/isInstanceOperator.kt @@ -0,0 +1,59 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun isString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + + +fun notIsString(x: Any?): Boolean { + contract { + returns(false) implies (x is String) + } + return x !is String +} + + + + +fun testSimple(x: Any?) { + x.length + + if (isString(x)) { + x.length + } + else { + x.length + } +} + +fun testSpilling(x: Any?) { + x.length + + if (isString(x)) x.length + + x.length +} + +fun testInversion(x: Any?) { + if (notIsString(x)) { + x.length + } + else { + x.length + } +} + +fun testInversionSpilling(x: Any?) { + x.length + + if (notIsString(x)) else x.length + + x.length +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/isInstanceOperator.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/isInstanceOperator.txt new file mode 100644 index 00000000000..aba527562b1 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/isInstanceOperator.txt @@ -0,0 +1,12 @@ +package + +public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun notIsString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is String + +public fun testInversion(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testInversionSpilling(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testSimple(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testSpilling(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperator.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperator.kt new file mode 100644 index 00000000000..7344aa03c97 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperator.kt @@ -0,0 +1,76 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun trueWhenString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun trueWhenInt(x: Any?): Boolean { + contract { + returns(true) implies (x is Int) + } + return x is Int +} + +fun falseWhenString(x: Any?): Boolean { + contract { + returns(false) implies (x is String) + } + return x !is String +} + +fun falseWhenInt(x: Any?): Boolean { + contract { + returns(false) implies (x is Int) + } + return x !is Int +} + +fun truetrue(x: Any?) { + if (trueWhenString(x) || trueWhenInt(x)) { + x.length + x.inc() + } + else { + x.length + x.inc() + } +} + +fun truefalse(x: Any?) { + if (trueWhenString(x) || falseWhenInt(x)) { + x.length + x.inc() + } + else { + x.length + x.inc() + } +} + +fun falsetrue(x: Any?) { + if (falseWhenString(x) || trueWhenInt(x)) { + x.length + x.inc() + } + else { + x.length + x.inc() + } +} + +fun falsefalse(x: Any?) { + if (falseWhenString(x) || falseWhenInt(x)) { + x.length + x.inc() + } + else { + x.length + x.inc() + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperator.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperator.txt new file mode 100644 index 00000000000..98be42bbcbb --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperator.txt @@ -0,0 +1,18 @@ +package + +public fun falseWhenInt(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is Int + +public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is String + +public fun falsefalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun falsetrue(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun trueWhenInt(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is Int + +public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun truefalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun truetrue(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithConstant.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithConstant.kt new file mode 100644 index 00000000000..daacf682548 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithConstant.kt @@ -0,0 +1,56 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun trueWhenString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun falseWhenString(x: Any?): Boolean { + contract { + returns(false) implies (x is String) + } + return x !is String +} + +fun annotatedTrueOrTrue(x: Any?) { + if (trueWhenString(x) || true) { + x.length + } + else { + // Unreachable + x.length + } +} + +fun annotatedTrueOrFalse(x: Any?) { + if (trueWhenString(x) || false) { + x.length + } + else { + x.length + } +} + +fun annotatedFalseOrTrue(x: Any?) { + if (falseWhenString(x) || true) { + x.length + } + else { + // Unreachable + x.length + } +} + +fun annotatedFalseOrFalse(x: Any?) { + if (falseWhenString(x) || false) { + x.length + } + else { + x.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithConstant.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithConstant.txt new file mode 100644 index 00000000000..c1bb0222961 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithConstant.txt @@ -0,0 +1,11 @@ +package + +public fun annotatedFalseOrFalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun annotatedFalseOrTrue(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun annotatedTrueOrFalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun annotatedTrueOrTrue(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is String + +public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithUnknown.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithUnknown.kt new file mode 100644 index 00000000000..69b9329f0b0 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithUnknown.kt @@ -0,0 +1,59 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun trueWhenString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun falseWhenString(x: Any?): Boolean { + contract { + returns(false) implies (x is String) + } + return x !is String +} + +fun unknownFunction(x: Any?) = x == 42 + + + + +fun annotatedTrue(x: Any?) { + if (trueWhenString(x) || unknownFunction(x)) { + x.length + } + else { + x.length + } +} + +fun annotatedFalse(x: Any?) { + if (falseWhenString(x) || unknownFunction(x)) { + x.length + } + else { + x.length + } +} + +fun annotatedTrueWithVariable(x: Any?, b: Boolean) { + if (trueWhenString(x) || b) { + x.length + } + else { + x.length + } +} + +fun annotatedFalseWithVariable(x: Any?, b: Boolean) { + if (falseWhenString(x) || b) { + x.length + } + else { + x.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithUnknown.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithUnknown.txt new file mode 100644 index 00000000000..0a80fa39071 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithUnknown.txt @@ -0,0 +1,13 @@ +package + +public fun annotatedFalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun annotatedFalseWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit +public fun annotatedTrue(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun annotatedTrueWithVariable(/*0*/ x: kotlin.Any?, /*1*/ b: kotlin.Boolean): kotlin.Unit +public fun falseWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(FALSE) -> x is String + +public fun trueWhenString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun unknownFunction(/*0*/ x: kotlin.Any?): kotlin.Boolean diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/partiallyIncorrect.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/partiallyIncorrect.kt new file mode 100644 index 00000000000..d0834f6f09c --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/partiallyIncorrect.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun isString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun incorrectPartDoesntMatter(x: Any?) { + if (isString(x) && 1) { + x.length + } + else { + x.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/partiallyIncorrect.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/partiallyIncorrect.txt new file mode 100644 index 00000000000..574d5c95e04 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/partiallyIncorrect.txt @@ -0,0 +1,5 @@ +package + +public fun incorrectPartDoesntMatter(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.kt new file mode 100644 index 00000000000..99df8f78efd --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.kt @@ -0,0 +1,34 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun Any?.isNull(): Boolean { + contract { + returns(false) implies (this@isNull != null) + } + return this == null +} + +fun smartcastOnReceiver(x: Int?) { + if (x.isNull()) { + x.inc() + } + else { + x.dec() + } +} + +class UnstableReceiver { + var x: Int? = 42 + + fun smartcastOnUnstableReceiver() { + if (x.isNull()) { + x.inc() + } + else { + x.dec() + } + } +} + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.txt new file mode 100644 index 00000000000..f3cefcfe7c5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.txt @@ -0,0 +1,14 @@ +package + +public fun smartcastOnReceiver(/*0*/ x: kotlin.Int?): kotlin.Unit +public fun kotlin.Any?.isNull(): kotlin.Boolean + Returns(FALSE) -> != null + +public final class UnstableReceiver { + public constructor UnstableReceiver() + public final var x: kotlin.Int? + 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 final fun smartcastOnUnstableReceiver(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.kt new file mode 100644 index 00000000000..5804aa8a914 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.kt @@ -0,0 +1,65 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun myAssert(condition: Boolean) { + contract { + returns() implies (condition) + } + if (!condition) throw kotlin.IllegalArgumentException("Assertion failed") +} + +fun testAssertSmartcast(x: Any?) { + myAssert(x is String) + x.length +} + +fun testInvertedAssert(x: Any?) { + myAssert(x !is String) + x.length +} + +fun testSpilling(x: Any?) { + if (x != null) { + myAssert(x is String) + x.length + } + x.length +} + +fun testAssertInIf(x: Any?) { + if (myAssert(x is String) == Unit) { + x.length + } + else { + x.length + } +} + +fun testTryCatch(x: Any?) { + try { + myAssert(x is String) + x.length + } catch (e: kotlin.IllegalArgumentException) { + + } + x.length +} + +fun testUncertainFlow(x: Any?) { + repeat(x.toString().length) { + myAssert(x is String) + x.length + } + x.length +} + +fun testAtLeastOnceFlow(x: Any?) { + do { + myAssert(x is String) + x.length + } while (x != null) + + x.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.txt new file mode 100644 index 00000000000..bc9b79e0717 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.txt @@ -0,0 +1,12 @@ +package + +public fun myAssert(/*0*/ condition: kotlin.Boolean): kotlin.Unit + Returns(WILDCARD) -> condition + +public fun testAssertInIf(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testAssertSmartcast(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testAtLeastOnceFlow(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testInvertedAssert(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testSpilling(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testTryCatch(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun testUncertainFlow(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/typeSmartcastWhenNullability.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/typeSmartcastWhenNullability.kt new file mode 100644 index 00000000000..cf2b8cfc216 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/typeSmartcastWhenNullability.kt @@ -0,0 +1,58 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + + +fun nullWhenString(x: Any?): Int? { + contract { + returns(null) implies (x is String) + } + return if (x is String) null else 42 +} + +fun nullWhenNotString(x: Any?): Int? { + contract { + returns(null) implies (x !is String) + } + return if (x !is String) null else 42 +} + + + + + +// ==== Actual tests ===== + + +fun test1(x: Any?) { + // condition == true <=> function returned null <=> 'x' is String + if (nullWhenString(x) == null) { + x.length + } + else { + x.length + } +} + +fun test2(x: Any?) { + // Observe that condition == false <=>* function returned null <=> 'x' is String + // *correct only for at most binary types, which is exactly the case for nullability comparisons + if (nullWhenString(x) != null) { + x.length + } + else { + x.length + } +} + + +fun test3(x: Any?) { + // condition == false <=> function returned not-null, but we don't know anything about when function returns not-null + if (nullWhenNotString(x) == null) { + x.length + } + else { + x.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/typeSmartcastWhenNullability.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/typeSmartcastWhenNullability.txt new file mode 100644 index 00000000000..8f49aa72941 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/typeSmartcastWhenNullability.txt @@ -0,0 +1,11 @@ +package + +public fun nullWhenNotString(/*0*/ x: kotlin.Any?): kotlin.Int? + Returns(NULL) -> x !is String + +public fun nullWhenString(/*0*/ x: kotlin.Any?): kotlin.Int? + Returns(NULL) -> x is String + +public fun test1(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun test2(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun test3(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/unreachableBranches.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/unreachableBranches.kt new file mode 100644 index 00000000000..35039e47315 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/unreachableBranches.kt @@ -0,0 +1,31 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +// ===== Definitions ==== +fun isString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + + +// ==== Actual tests ======= + +fun implicitAlwaysFalse(x: Any?) { + if (isString(x) && !isString(x)) { + x.length + } + else { + x.length + } +} + +fun implicitAlwaysFalseSpilling(x: Any?) { + if (isString(x) && !isString(x)) { + x.length + } + x.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/unreachableBranches.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/unreachableBranches.txt new file mode 100644 index 00000000000..e1281f6aad5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/unreachableBranches.txt @@ -0,0 +1,7 @@ +package + +public fun implicitAlwaysFalse(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun implicitAlwaysFalseSpilling(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.kt new file mode 100644 index 00000000000..b1031da4d42 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.kt @@ -0,0 +1,35 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun isString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun exhaustive(x: Any?) { + when (isString(x)) { + true -> x.length + false -> x.length + } + + when(!isString(x)) { + true -> x.length + false -> x.length + } +} + +fun smartcastInElse(x: Any?) { + when (isString(x)) { + false -> x.length + else -> x.length + } + + when (!isString(x)) { + true -> x.length + else -> x.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.txt new file mode 100644 index 00000000000..a7aff832dd3 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.txt @@ -0,0 +1,7 @@ +package + +public fun exhaustive(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun smartcastInElse(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.kt new file mode 100644 index 00000000000..4bc9cbff6eb --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.kt @@ -0,0 +1,55 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun safeIsString(x: Any?): Boolean? { + contract { + returns(true) implies (x is String) + } + return x?.let { it is String } +} + +fun elseWithNullableResult(x: Any?) { + when (safeIsString(x)) { + false -> x.length + else -> x.length + } + + when (safeIsString(x)) { + true -> x.length + else -> x.length + } + + when (safeIsString(x)) { + true -> x.length + false -> x.length + else -> x.length + } + + when (safeIsString(x)) { + true -> x.length + null -> x.length + else -> x.length + } +} + +fun exhaustiveWithNullableResult(x: Any?) { + when (safeIsString(x)) { + true -> x.length + false -> x.length + null -> x.length + } + + when (safeIsString(x)) { + false -> x.length + true -> x.length + null -> x.length + } + + when (safeIsString(x)) { + false -> x.length + null -> x.length + true -> x.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.txt new file mode 100644 index 00000000000..df73a4afe0e --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.txt @@ -0,0 +1,6 @@ +package + +public fun elseWithNullableResult(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun exhaustiveWithNullableResult(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun safeIsString(/*0*/ x: kotlin.Any?): kotlin.Boolean? + Returns(TRUE) -> x is String diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withoutSubject.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withoutSubject.kt new file mode 100644 index 00000000000..a4d849c7d98 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withoutSubject.kt @@ -0,0 +1,30 @@ +// !LANGUAGE: +ReturnsEffect +// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER + +import kotlin.internal.contracts.* + +fun isString(x: Any?): Boolean { + contract { + returns(true) implies (x is String) + } + return x is String +} + +fun exhaustive(x: Any?) { + when { + isString(x) -> x.length + !isString(x) -> x.length + } + + when { + !isString(x) -> x.length + isString(x) -> x.length + } +} + +fun smartcastInElse(x: Any?) { + when { + !isString(x) -> x.length + else -> x.length + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withoutSubject.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withoutSubject.txt new file mode 100644 index 00000000000..a7aff832dd3 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withoutSubject.txt @@ -0,0 +1,7 @@ +package + +public fun exhaustive(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun isString(/*0*/ x: kotlin.Any?): kotlin.Boolean + Returns(TRUE) -> x is String + +public fun smartcastInElse(/*0*/ x: kotlin.Any?): kotlin.Unit diff --git a/compiler/tests-common/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt b/compiler/tests-common/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt index 7b7f0f18360..9b0ea46f362 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt +++ b/compiler/tests-common/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt @@ -465,7 +465,9 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() { true } - return RECURSIVE.filterRecursion(stepIntoFilter).withValidationStrategy(DescriptorValidator.ValidationVisitor.errorTypesAllowed()) + return RECURSIVE.filterRecursion(stepIntoFilter) + .withValidationStrategy(DescriptorValidator.ValidationVisitor.errorTypesAllowed()) + .checkFunctionContracts(true) } private fun getTopLevelPackagesFromFileList(files: List): Set = diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index a828bceb9fe..7f275c2bca0 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -753,6 +753,471 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW } } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Contracts extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInContracts() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Controlflow extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInControlflow() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FlowInlining extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInFlowInlining() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("breakContinuesInInlinedLambda.kt") + public void testBreakContinuesInInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/breakContinuesInInlinedLambda.kt"); + doTest(fileName); + } + + @TestMetadata("expressionBody.kt") + public void testExpressionBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.kt"); + doTest(fileName); + } + + @TestMetadata("implicitCastToAnyInReturnType.kt") + public void testImplicitCastToAnyInReturnType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/implicitCastToAnyInReturnType.kt"); + doTest(fileName); + } + + @TestMetadata("inlinedLambdaAlwaysThrows.kt") + public void testInlinedLambdaAlwaysThrows() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/inlinedLambdaAlwaysThrows.kt"); + doTest(fileName); + } + + @TestMetadata("irrelevantUnknownClosure.kt") + public void testIrrelevantUnknownClosure() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/irrelevantUnknownClosure.kt"); + doTest(fileName); + } + + @TestMetadata("labeledReturns.kt") + public void testLabeledReturns() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/labeledReturns.kt"); + doTest(fileName); + } + + @TestMetadata("nestedTryCatchFinally.kt") + public void testNestedTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchFinally.kt"); + doTest(fileName); + } + + @TestMetadata("nestedTryCatchs.kt") + public void testNestedTryCatchs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchs.kt"); + doTest(fileName); + } + + @TestMetadata("nonLocalReturn.kt") + public void testNonLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("nonReturningInlinedLambda.kt") + public void testNonReturningInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.kt"); + doTest(fileName); + } + + @TestMetadata("severalJumpOutsFromInlinedLambda.kt") + public void testSeveralJumpOutsFromInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt"); + doTest(fileName); + } + + @TestMetadata("throwIfNotCalled.kt") + public void testThrowIfNotCalled() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/throwIfNotCalled.kt"); + doTest(fileName); + } + + @TestMetadata("tryCatch.kt") + public void testTryCatch() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatch.kt"); + doTest(fileName); + } + + @TestMetadata("tryCatchFinally.kt") + public void testTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatchFinally.kt"); + doTest(fileName); + } + + @TestMetadata("typeMismatch.kt") + public void testTypeMismatch() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.kt"); + doTest(fileName); + } + + @TestMetadata("unreachableCode.kt") + public void testUnreachableCode() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/unreachableCode.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Initialization extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInInitialization() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AtLeastOnce extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInAtLeastOnce() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("valDefiniteReassignment.kt") + public void testValDefiniteReassignment() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/valDefiniteReassignment.kt"); + doTest(fileName); + } + + @TestMetadata("varDefiniteInitialization.kt") + public void testVarDefiniteInitialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varDefiniteInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("varIndefiniteIntialization.kt") + public void testVarIndefiniteIntialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varIndefiniteIntialization.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ExactlyOnce extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInExactlyOnce() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("valDefiniteInitialization.kt") + public void testValDefiniteInitialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("valDefiniteReassignment.kt") + public void testValDefiniteReassignment() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteReassignment.kt"); + doTest(fileName); + } + + @TestMetadata("valIndefiniteInitialization.kt") + public void testValIndefiniteInitialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valIndefiniteInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("varDefiniteInitalization.kt") + public void testVarDefiniteInitalization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varDefiniteInitalization.kt"); + doTest(fileName); + } + + @TestMetadata("varIndefiniteInitialization.kt") + public void testVarIndefiniteInitialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varIndefiniteInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("withReceiver.kt") + public void testWithReceiver() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/withReceiver.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Unknown extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInUnknown() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("unknownInvocations.kt") + public void testUnknownInvocations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown/unknownInvocations.kt"); + doTest(fileName); + } + } + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Dsl extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInDsl() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("useBeforeDeclaration.kt") + public void testUseBeforeDeclaration() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/useBeforeDeclaration.kt"); + doTest(fileName); + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Errors extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInErrors() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("booleanComparisons.kt") + public void testBooleanComparisons() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/booleanComparisons.kt"); + doTest(fileName); + } + + @TestMetadata("callInContractDescription.kt") + public void testCallInContractDescription() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/callInContractDescription.kt"); + doTest(fileName); + } + + @TestMetadata("nestedConditionalEffects.kt") + public void testNestedConditionalEffects() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nestedConditionalEffects.kt"); + doTest(fileName); + } + + @TestMetadata("notFirstStatement.kt") + public void testNotFirstStatement() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/notFirstStatement.kt"); + doTest(fileName); + } + + @TestMetadata("referenceToProperty.kt") + public void testReferenceToProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.kt"); + doTest(fileName); + } + + @TestMetadata("unlabeledReceiver.kt") + public void testUnlabeledReceiver() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/unlabeledReceiver.kt"); + doTest(fileName); + } + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Smartcasts extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInSmartcasts() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("catchExceptionSpilling.kt") + public void testCatchExceptionSpilling() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/catchExceptionSpilling.kt"); + doTest(fileName); + } + + @TestMetadata("compositions.kt") + public void testCompositions() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/compositions.kt"); + doTest(fileName); + } + + @TestMetadata("deeplyNested.kt") + public void testDeeplyNested() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/deeplyNested.kt"); + doTest(fileName); + } + + @TestMetadata("intersectingInfo.kt") + public void testIntersectingInfo() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.kt"); + doTest(fileName); + } + + @TestMetadata("intersectionTypes.kt") + public void testIntersectionTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectionTypes.kt"); + doTest(fileName); + } + + @TestMetadata("nullabilitySmartcastWhenNullability.kt") + public void testNullabilitySmartcastWhenNullability() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.kt"); + doTest(fileName); + } + + @TestMetadata("partiallyIncorrect.kt") + public void testPartiallyIncorrect() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/partiallyIncorrect.kt"); + doTest(fileName); + } + + @TestMetadata("receiver.kt") + public void testReceiver() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.kt"); + doTest(fileName); + } + + @TestMetadata("throwsEffect.kt") + public void testThrowsEffect() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.kt"); + doTest(fileName); + } + + @TestMetadata("typeSmartcastWhenNullability.kt") + public void testTypeSmartcastWhenNullability() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/typeSmartcastWhenNullability.kt"); + doTest(fileName); + } + + @TestMetadata("unreachableBranches.kt") + public void testUnreachableBranches() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/unreachableBranches.kt"); + doTest(fileName); + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Multieffect extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInMultieffect() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("implicitIff.kt") + public void testImplicitIff() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/implicitIff.kt"); + doTest(fileName); + } + + @TestMetadata("returnsAndCalls.kt") + public void testReturnsAndCalls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/returnsAndCalls.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class OperatorsTests extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInOperatorsTests() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("andOperator.kt") + public void testAndOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.kt"); + doTest(fileName); + } + + @TestMetadata("andOperatorWithConstant.kt") + public void testAndOperatorWithConstant() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithConstant.kt"); + doTest(fileName); + } + + @TestMetadata("andOperatorWithUnknown.kt") + public void testAndOperatorWithUnknown() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithUnknown.kt"); + doTest(fileName); + } + + @TestMetadata("equalsOperator.kt") + public void testEqualsOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.kt"); + doTest(fileName); + } + + @TestMetadata("equalsWithNullableBoolean.kt") + public void testEqualsWithNullableBoolean() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.kt"); + doTest(fileName); + } + + @TestMetadata("isInstanceOperator.kt") + public void testIsInstanceOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/isInstanceOperator.kt"); + doTest(fileName); + } + + @TestMetadata("orOperator.kt") + public void testOrOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperator.kt"); + doTest(fileName); + } + + @TestMetadata("orOperatorWithConstant.kt") + public void testOrOperatorWithConstant() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithConstant.kt"); + doTest(fileName); + } + + @TestMetadata("orOperatorWithUnknown.kt") + public void testOrOperatorWithUnknown() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithUnknown.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class When extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInWhen() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("withSubject.kt") + public void testWithSubject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.kt"); + doTest(fileName); + } + + @TestMetadata("withSubjectNullableBoolean.kt") + public void testWithSubjectNullableBoolean() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.kt"); + doTest(fileName); + } + + @TestMetadata("withoutSubject.kt") + public void testWithoutSubject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withoutSubject.kt"); + doTest(fileName); + } + } + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index ab94b74b1b9..f85a3050eb4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -753,6 +753,471 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno } } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Contracts extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInContracts() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Controlflow extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInControlflow() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FlowInlining extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInFlowInlining() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("breakContinuesInInlinedLambda.kt") + public void testBreakContinuesInInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/breakContinuesInInlinedLambda.kt"); + doTest(fileName); + } + + @TestMetadata("expressionBody.kt") + public void testExpressionBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/expressionBody.kt"); + doTest(fileName); + } + + @TestMetadata("implicitCastToAnyInReturnType.kt") + public void testImplicitCastToAnyInReturnType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/implicitCastToAnyInReturnType.kt"); + doTest(fileName); + } + + @TestMetadata("inlinedLambdaAlwaysThrows.kt") + public void testInlinedLambdaAlwaysThrows() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/inlinedLambdaAlwaysThrows.kt"); + doTest(fileName); + } + + @TestMetadata("irrelevantUnknownClosure.kt") + public void testIrrelevantUnknownClosure() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/irrelevantUnknownClosure.kt"); + doTest(fileName); + } + + @TestMetadata("labeledReturns.kt") + public void testLabeledReturns() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/labeledReturns.kt"); + doTest(fileName); + } + + @TestMetadata("nestedTryCatchFinally.kt") + public void testNestedTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchFinally.kt"); + doTest(fileName); + } + + @TestMetadata("nestedTryCatchs.kt") + public void testNestedTryCatchs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nestedTryCatchs.kt"); + doTest(fileName); + } + + @TestMetadata("nonLocalReturn.kt") + public void testNonLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("nonReturningInlinedLambda.kt") + public void testNonReturningInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/nonReturningInlinedLambda.kt"); + doTest(fileName); + } + + @TestMetadata("severalJumpOutsFromInlinedLambda.kt") + public void testSeveralJumpOutsFromInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/severalJumpOutsFromInlinedLambda.kt"); + doTest(fileName); + } + + @TestMetadata("throwIfNotCalled.kt") + public void testThrowIfNotCalled() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/throwIfNotCalled.kt"); + doTest(fileName); + } + + @TestMetadata("tryCatch.kt") + public void testTryCatch() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatch.kt"); + doTest(fileName); + } + + @TestMetadata("tryCatchFinally.kt") + public void testTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/tryCatchFinally.kt"); + doTest(fileName); + } + + @TestMetadata("typeMismatch.kt") + public void testTypeMismatch() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/typeMismatch.kt"); + doTest(fileName); + } + + @TestMetadata("unreachableCode.kt") + public void testUnreachableCode() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/flowInlining/unreachableCode.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Initialization extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInInitialization() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AtLeastOnce extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInAtLeastOnce() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("valDefiniteReassignment.kt") + public void testValDefiniteReassignment() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/valDefiniteReassignment.kt"); + doTest(fileName); + } + + @TestMetadata("varDefiniteInitialization.kt") + public void testVarDefiniteInitialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varDefiniteInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("varIndefiniteIntialization.kt") + public void testVarIndefiniteIntialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/atLeastOnce/varIndefiniteIntialization.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ExactlyOnce extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInExactlyOnce() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("valDefiniteInitialization.kt") + public void testValDefiniteInitialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("valDefiniteReassignment.kt") + public void testValDefiniteReassignment() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valDefiniteReassignment.kt"); + doTest(fileName); + } + + @TestMetadata("valIndefiniteInitialization.kt") + public void testValIndefiniteInitialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/valIndefiniteInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("varDefiniteInitalization.kt") + public void testVarDefiniteInitalization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varDefiniteInitalization.kt"); + doTest(fileName); + } + + @TestMetadata("varIndefiniteInitialization.kt") + public void testVarIndefiniteInitialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/varIndefiniteInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("withReceiver.kt") + public void testWithReceiver() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/exactlyOnce/withReceiver.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Unknown extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInUnknown() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("unknownInvocations.kt") + public void testUnknownInvocations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/controlflow/initialization/unknown/unknownInvocations.kt"); + doTest(fileName); + } + } + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Dsl extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInDsl() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("useBeforeDeclaration.kt") + public void testUseBeforeDeclaration() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/useBeforeDeclaration.kt"); + doTest(fileName); + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Errors extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInErrors() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("booleanComparisons.kt") + public void testBooleanComparisons() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/booleanComparisons.kt"); + doTest(fileName); + } + + @TestMetadata("callInContractDescription.kt") + public void testCallInContractDescription() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/callInContractDescription.kt"); + doTest(fileName); + } + + @TestMetadata("nestedConditionalEffects.kt") + public void testNestedConditionalEffects() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/nestedConditionalEffects.kt"); + doTest(fileName); + } + + @TestMetadata("notFirstStatement.kt") + public void testNotFirstStatement() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/notFirstStatement.kt"); + doTest(fileName); + } + + @TestMetadata("referenceToProperty.kt") + public void testReferenceToProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/referenceToProperty.kt"); + doTest(fileName); + } + + @TestMetadata("unlabeledReceiver.kt") + public void testUnlabeledReceiver() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/unlabeledReceiver.kt"); + doTest(fileName); + } + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Smartcasts extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInSmartcasts() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("catchExceptionSpilling.kt") + public void testCatchExceptionSpilling() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/catchExceptionSpilling.kt"); + doTest(fileName); + } + + @TestMetadata("compositions.kt") + public void testCompositions() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/compositions.kt"); + doTest(fileName); + } + + @TestMetadata("deeplyNested.kt") + public void testDeeplyNested() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/deeplyNested.kt"); + doTest(fileName); + } + + @TestMetadata("intersectingInfo.kt") + public void testIntersectingInfo() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.kt"); + doTest(fileName); + } + + @TestMetadata("intersectionTypes.kt") + public void testIntersectionTypes() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectionTypes.kt"); + doTest(fileName); + } + + @TestMetadata("nullabilitySmartcastWhenNullability.kt") + public void testNullabilitySmartcastWhenNullability() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/nullabilitySmartcastWhenNullability.kt"); + doTest(fileName); + } + + @TestMetadata("partiallyIncorrect.kt") + public void testPartiallyIncorrect() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/partiallyIncorrect.kt"); + doTest(fileName); + } + + @TestMetadata("receiver.kt") + public void testReceiver() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.kt"); + doTest(fileName); + } + + @TestMetadata("throwsEffect.kt") + public void testThrowsEffect() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/throwsEffect.kt"); + doTest(fileName); + } + + @TestMetadata("typeSmartcastWhenNullability.kt") + public void testTypeSmartcastWhenNullability() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/typeSmartcastWhenNullability.kt"); + doTest(fileName); + } + + @TestMetadata("unreachableBranches.kt") + public void testUnreachableBranches() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/unreachableBranches.kt"); + doTest(fileName); + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Multieffect extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInMultieffect() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("implicitIff.kt") + public void testImplicitIff() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/implicitIff.kt"); + doTest(fileName); + } + + @TestMetadata("returnsAndCalls.kt") + public void testReturnsAndCalls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/multieffect/returnsAndCalls.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class OperatorsTests extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInOperatorsTests() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("andOperator.kt") + public void testAndOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperator.kt"); + doTest(fileName); + } + + @TestMetadata("andOperatorWithConstant.kt") + public void testAndOperatorWithConstant() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithConstant.kt"); + doTest(fileName); + } + + @TestMetadata("andOperatorWithUnknown.kt") + public void testAndOperatorWithUnknown() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/andOperatorWithUnknown.kt"); + doTest(fileName); + } + + @TestMetadata("equalsOperator.kt") + public void testEqualsOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsOperator.kt"); + doTest(fileName); + } + + @TestMetadata("equalsWithNullableBoolean.kt") + public void testEqualsWithNullableBoolean() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/equalsWithNullableBoolean.kt"); + doTest(fileName); + } + + @TestMetadata("isInstanceOperator.kt") + public void testIsInstanceOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/isInstanceOperator.kt"); + doTest(fileName); + } + + @TestMetadata("orOperator.kt") + public void testOrOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperator.kt"); + doTest(fileName); + } + + @TestMetadata("orOperatorWithConstant.kt") + public void testOrOperatorWithConstant() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithConstant.kt"); + doTest(fileName); + } + + @TestMetadata("orOperatorWithUnknown.kt") + public void testOrOperatorWithUnknown() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/operatorsTests/orOperatorWithUnknown.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class When extends AbstractDiagnosticsTestWithStdLibUsingJavac { + public void testAllFilesPresentInWhen() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("withSubject.kt") + public void testWithSubject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.kt"); + doTest(fileName); + } + + @TestMetadata("withSubjectNullableBoolean.kt") + public void testWithSubjectNullableBoolean() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubjectNullableBoolean.kt"); + doTest(fileName); + } + + @TestMetadata("withoutSubject.kt") + public void testWithoutSubject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withoutSubject.kt"); + doTest(fileName); + } + } + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)