[FIR IDE] Ensure resolve to CONTRACTS phase in ReturnTypeCalculator

If we want to analyse some function's call, we need to know about its
contracts, otherwise resolving the following code would be broken.
Computing return type of function is a prerequisite to using it in any
sensible way, so it's the best place to resolve it to CONTRACTS

KT-50733
This commit is contained in:
Roman Golyshev
2022-05-27 13:30:19 +04:00
committed by Space
parent e14ac2a062
commit 166c771e1b
59 changed files with 260 additions and 64 deletions
@@ -217,9 +217,12 @@ FILE: classMembers.kt
public final [STATUS] val x: R|kotlin/Int| = LAZY_EXPRESSION public final [STATUS] val x: R|kotlin/Int| = LAZY_EXPRESSION
[STATUS] [ContainingClassKey=A] public get(): R|kotlin/Int| { LAZY_BLOCK } [STATUS] [ContainingClassKey=A] public get(): R|kotlin/Int| { LAZY_BLOCK }
public final [STATUS] fun receive([RAW_FIR] value: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } public final [CONTRACTS] fun receive([RAW_FIR] value: R|kotlin/String|): R|kotlin/Unit| {
}
public final [STATUS] fun functionWithLazyBody(): R|kotlin/String| { LAZY_BLOCK } public final [CONTRACTS] fun functionWithLazyBody(): R|kotlin/String| {
^functionWithLazyBody String(42)
}
} }
@@ -341,8 +341,9 @@ FILE: delegates.kt
R|/variableWithExplicitType| = Int(10) R|/variableWithExplicitType| = Int(10)
R|/variableWithImplicitType| = Int(10) R|/variableWithImplicitType| = Int(10)
} }
public final [STATUS] fun receive([RAW_FIR] value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } public final [CONTRACTS] fun receive([RAW_FIR] value: R|kotlin/Int|): R|kotlin/Unit| {
public final [STATUS] val delegate: R|kotlin/properties/ReadWriteProperty<kotlin/Any?, kotlin/Int>| = object : R|kotlin/properties/ReadWriteProperty<kotlin/Any?, kotlin/Int>| { }
public final [CONTRACTS] val delegate: R|kotlin/properties/ReadWriteProperty<kotlin/Any?, kotlin/Int>| = object : R|kotlin/properties/ReadWriteProperty<kotlin/Any?, kotlin/Int>| {
private [RAW_FIR] [ContainingClassKey=<anonymous>] constructor(): R|<anonymous>| { private [RAW_FIR] [ContainingClassKey=<anonymous>] constructor(): R|<anonymous>| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
@@ -357,19 +358,19 @@ FILE: delegates.kt
} }
[BODY_RESOLVE] public get(): R|kotlin/properties/ReadWriteProperty<kotlin/Any?, kotlin/Int>| [BODY_RESOLVE] public get(): R|kotlin/properties/ReadWriteProperty<kotlin/Any?, kotlin/Int>|
public final [STATUS] val valueWithExplicitType: R|kotlin/Int|by LAZY_EXPRESSION public final [CONTRACTS] val valueWithExplicitType: R|kotlin/Int|by delegate#
[STATUS] public get(): <implicit> { [CONTRACTS] public get(): <implicit> {
^ D|/valueWithExplicitType|.getValue#(Null(null), ::R|/valueWithExplicitType|) ^ D|/valueWithExplicitType|.getValue#(Null(null), ::R|/valueWithExplicitType|)
} }
public final [IMPLICIT_TYPES_BODY_RESOLVE] val valueWithImplicitType: R|kotlin/Int|by R|/delegate| public final [IMPLICIT_TYPES_BODY_RESOLVE] val valueWithImplicitType: R|kotlin/Int|by R|/delegate|
[IMPLICIT_TYPES_BODY_RESOLVE] public get(): R|kotlin/Int| { [IMPLICIT_TYPES_BODY_RESOLVE] public get(): R|kotlin/Int| {
^ D|/valueWithImplicitType|.R|SubstitutionOverride<kotlin/properties/ReadWriteProperty.getValue: R|kotlin/Int|>|(Null(null), ::R|/valueWithImplicitType|) ^ D|/valueWithImplicitType|.R|SubstitutionOverride<kotlin/properties/ReadWriteProperty.getValue: R|kotlin/Int|>|(Null(null), ::R|/valueWithImplicitType|)
} }
public final [STATUS] var variableWithExplicitType: R|kotlin/Int|by LAZY_EXPRESSION public final [CONTRACTS] var variableWithExplicitType: R|kotlin/Int|by delegate#
[STATUS] public get(): <implicit> { [CONTRACTS] public get(): <implicit> {
^ D|/variableWithExplicitType|.getValue#(Null(null), ::R|/variableWithExplicitType|) ^ D|/variableWithExplicitType|.getValue#(Null(null), ::R|/variableWithExplicitType|)
} }
[STATUS] public set([RAW_FIR] <set-?>: <implicit>): R|kotlin/Unit| { [CONTRACTS] public set([RAW_FIR] <set-?>: <implicit>): R|kotlin/Unit| {
D|/variableWithExplicitType|.setValue#(Null(null), ::R|/variableWithExplicitType|, R|<local>/variableWithExplicitType|) D|/variableWithExplicitType|.setValue#(Null(null), ::R|/variableWithExplicitType|, R|<local>/variableWithExplicitType|)
} }
public final [IMPLICIT_TYPES_BODY_RESOLVE] var variableWithImplicitType: R|kotlin/Int|by R|/delegate| public final [IMPLICIT_TYPES_BODY_RESOLVE] var variableWithImplicitType: R|kotlin/Int|by R|/delegate|
@@ -87,9 +87,12 @@ FILE: propertyWithGetter.kt
public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| {
R|/receive|(R|/withGetter|) R|/receive|(R|/withGetter|)
} }
public final [STATUS] fun receive([RAW_FIR] value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } public final [CONTRACTS] fun receive([RAW_FIR] value: R|kotlin/Int|): R|kotlin/Unit| {
public final [STATUS] val withGetter: R|kotlin/Int| }
[STATUS] public get(): R|kotlin/Int| { LAZY_BLOCK } public final [CONTRACTS] val withGetter: R|kotlin/Int|
[CONTRACTS] public get(): R|kotlin/Int| {
^ IntegerLiteral(42)
}
FILE RAW TO BODY: FILE RAW TO BODY:
FILE: propertyWithGetter.kt FILE: propertyWithGetter.kt
@@ -102,10 +102,15 @@ FILE: propertyWithGetterAndSetter.kt
R|/receive|(R|/withGetterAndSetter|) R|/receive|(R|/withGetterAndSetter|)
R|/withGetterAndSetter| = Int(123) R|/withGetterAndSetter| = Int(123)
} }
public final [STATUS] fun receive([RAW_FIR] value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } public final [CONTRACTS] fun receive([RAW_FIR] value: R|kotlin/Int|): R|kotlin/Unit| {
public final [STATUS] var withGetterAndSetter: R|kotlin/Int| = LAZY_EXPRESSION }
[STATUS] public get(): R|kotlin/Int| { LAZY_BLOCK } public final [CONTRACTS] var withGetterAndSetter: R|kotlin/Int| = IntegerLiteral(42)
[STATUS] public set([RAW_FIR] value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } [CONTRACTS] public get(): R|kotlin/Int| {
^ field#
}
[CONTRACTS] public set([RAW_FIR] value: R|kotlin/Int|): R|kotlin/Unit| {
field# = value#
}
FILE RAW TO BODY: FILE RAW TO BODY:
FILE: propertyWithGetterAndSetter.kt FILE: propertyWithGetterAndSetter.kt
@@ -76,7 +76,7 @@ FILE: propertyWithInitializer.kt
public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| {
<Unresolved name: receive>#(R|/property|) <Unresolved name: receive>#(R|/property|)
} }
public final [STATUS] val property: R|kotlin/Int| = LAZY_EXPRESSION public final [CONTRACTS] val property: R|kotlin/Int| = IntegerLiteral(10)
[BODY_RESOLVE] public get(): R|kotlin/Int| [BODY_RESOLVE] public get(): R|kotlin/Int|
FILE RAW TO BODY: FILE RAW TO BODY:
@@ -142,7 +142,8 @@ FILE: secondaryConstructor.kt
public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| {
R|/receive|(R|/A.A|(Int(42))) R|/receive|(R|/A.A|(Int(42)))
} }
public final [STATUS] fun receive([RAW_FIR] value: R|A|): R|kotlin/Unit| { LAZY_BLOCK } public final [CONTRACTS] fun receive([RAW_FIR] value: R|A|): R|kotlin/Unit| {
}
public final [STATUS] class A : R|kotlin/Any| { public final [STATUS] class A : R|kotlin/Any| {
public [STATUS] [ContainingClassKey=A] constructor([RAW_FIR] x: R|kotlin/Int|): R|A| { public [STATUS] [ContainingClassKey=A] constructor([RAW_FIR] x: R|kotlin/Int|): R|A| {
super<R|kotlin/Any|>() super<R|kotlin/Any|>()
@@ -76,8 +76,11 @@ FILE: topLevelFunctions.kt
public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| {
R|/receive|(R|/functionWithLazyBody|()) R|/receive|(R|/functionWithLazyBody|())
} }
public final [STATUS] fun receive([RAW_FIR] value: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } public final [CONTRACTS] fun receive([RAW_FIR] value: R|kotlin/String|): R|kotlin/Unit| {
public final [STATUS] fun functionWithLazyBody(): R|kotlin/String| { LAZY_BLOCK } }
public final [CONTRACTS] fun functionWithLazyBody(): R|kotlin/String| {
^functionWithLazyBody String(42)
}
FILE RAW TO BODY: FILE RAW TO BODY:
FILE: topLevelFunctions.kt FILE: topLevelFunctions.kt
@@ -76,8 +76,11 @@ FILE: topLevelFunctionsWithExpressionBodyAndExplicitType.kt
public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| {
R|/receive|(R|/functionWithLazyBody|()) R|/receive|(R|/functionWithLazyBody|())
} }
public final [STATUS] fun receive([RAW_FIR] value: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } public final [CONTRACTS] fun receive([RAW_FIR] value: R|kotlin/String|): R|kotlin/Unit| {
public final [STATUS] fun functionWithLazyBody(): R|kotlin/String| { LAZY_BLOCK } }
public final [CONTRACTS] fun functionWithLazyBody(): R|kotlin/String| {
^functionWithLazyBody String(42)
}
FILE RAW TO BODY: FILE RAW TO BODY:
FILE: topLevelFunctionsWithExpressionBodyAndExplicitType.kt FILE: topLevelFunctionsWithExpressionBodyAndExplicitType.kt
@@ -76,7 +76,8 @@ FILE: topLevelFunctionsWithImplicitType.kt
public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| {
R|/receive|(R|/functionWithLazyBody|()) R|/receive|(R|/functionWithLazyBody|())
} }
public final [STATUS] fun receive([RAW_FIR] value: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } public final [CONTRACTS] fun receive([RAW_FIR] value: R|kotlin/String|): R|kotlin/Unit| {
}
public final [IMPLICIT_TYPES_BODY_RESOLVE] fun functionWithLazyBody(): R|kotlin/String| { public final [IMPLICIT_TYPES_BODY_RESOLVE] fun functionWithLazyBody(): R|kotlin/String| {
^functionWithLazyBody String(42) ^functionWithLazyBody String(42)
} }
@@ -1257,6 +1257,18 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/contracts"), Pattern.compile("^([^.]+)\\.kt$"), null, true); KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/contracts"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
} }
@Test
@TestMetadata("contractFromOtherModule.kt")
public void testContractFromOtherModule() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule.kt");
}
@Test
@TestMetadata("contractFromOtherModule_samePackage.kt")
public void testContractFromOtherModule_samePackage() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule_samePackage.kt");
}
@Test @Test
@TestMetadata("genericContract.kt") @TestMetadata("genericContract.kt")
public void testGenericContract() throws Exception { public void testGenericContract() throws Exception {
@@ -1092,6 +1092,16 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/contracts"), Pattern.compile("^([^.]+)\\.kt$"), null, true); KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/contracts"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
} }
@TestMetadata("contractFromOtherModule.kt")
public void testContractFromOtherModule() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule.kt");
}
@TestMetadata("contractFromOtherModule_samePackage.kt")
public void testContractFromOtherModule_samePackage() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule_samePackage.kt");
}
@TestMetadata("genericContract.kt") @TestMetadata("genericContract.kt")
public void testGenericContract() throws Exception { public void testGenericContract() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/genericContract.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/contracts/genericContract.kt");
@@ -0,0 +1,25 @@
Module: lib
FILE: module_lib_contractFromOtherModule.kt
package lib
public final fun requireIsTrue(value: R|kotlin/Boolean|): R|kotlin/Unit|
[R|Contract description]
<
Returns(WILDCARD) -> value
>
{
when () {
R|<local>/value|.R|kotlin/Boolean.not|() -> {
throw R|java/lang/IllegalArgumentException.IllegalArgumentException|()
}
}
}
Module: main
FILE: module_main_contractFromOtherModule.kt
package main
public final fun test(s: R|kotlin/Any|): R|kotlin/Unit| {
R|lib/requireIsTrue|((R|<local>/s| is R|kotlin/String|))
R|<local>/s|.R|kotlin/String.length|
}
@@ -0,0 +1,26 @@
// SKIP_JAVAC
// This directive is needed to skip this test in LazyBodyIsNotTouchedTilContractsPhaseTestGenerated,
// because it fails to parse module structure of multimodule test
// WITH_STDLIB
// MODULE: lib
package lib
import kotlin.contracts.*
fun requireIsTrue(value: Boolean) contract [
returns() implies value
] {
if (!value) throw IllegalArgumentException()
}
// MODULE: main(lib)
package main
import lib.requireIsTrue
fun test(s: Any) {
requireIsTrue(s is String)
s.length
}
@@ -0,0 +1,25 @@
Module: lib
FILE: module_lib_contractFromOtherModule_samePackage.kt
package main
public final fun requireIsTrue(value: R|kotlin/Boolean|): R|kotlin/Unit|
[R|Contract description]
<
Returns(WILDCARD) -> value
>
{
when () {
R|<local>/value|.R|kotlin/Boolean.not|() -> {
throw R|java/lang/IllegalArgumentException.IllegalArgumentException|()
}
}
}
Module: main
FILE: module_main_contractFromOtherModule_samePackage.kt
package main
public final fun test(s: R|kotlin/Any|): R|kotlin/Unit| {
R|main/requireIsTrue|((R|<local>/s| is R|kotlin/String|))
R|<local>/s|.R|kotlin/String.length|
}
@@ -0,0 +1,24 @@
// SKIP_JAVAC
// This directive is needed to skip this test in LazyBodyIsNotTouchedTilContractsPhaseTestGenerated,
// because it fails to parse module structure of multimodule test
// WITH_STDLIB
// MODULE: lib
package main
import kotlin.contracts.*
fun requireIsTrue(value: Boolean) contract [
returns() implies value
] {
if (!value) throw IllegalArgumentException()
}
// MODULE: main(lib)
package main
fun test(s: Any) {
requireIsTrue(s is String)
s.length
}
@@ -1257,6 +1257,18 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/contracts"), Pattern.compile("^([^.]+)\\.kt$"), null, true); KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/contracts"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
} }
@Test
@TestMetadata("contractFromOtherModule.kt")
public void testContractFromOtherModule() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule.kt");
}
@Test
@TestMetadata("contractFromOtherModule_samePackage.kt")
public void testContractFromOtherModule_samePackage() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule_samePackage.kt");
}
@Test @Test
@TestMetadata("genericContract.kt") @TestMetadata("genericContract.kt")
public void testGenericContract() throws Exception { public void testGenericContract() throws Exception {
@@ -1257,6 +1257,18 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/contracts"), Pattern.compile("^([^.]+)\\.kt$"), null, true); KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/contracts"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
} }
@Test
@TestMetadata("contractFromOtherModule.kt")
public void testContractFromOtherModule() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule.kt");
}
@Test
@TestMetadata("contractFromOtherModule_samePackage.kt")
public void testContractFromOtherModule_samePackage() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/contracts/contractFromOtherModule_samePackage.kt");
}
@Test @Test
@TestMetadata("genericContract.kt") @TestMetadata("genericContract.kt")
public void testGenericContract() throws Exception { public void testGenericContract() throws Exception {
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField import org.jetbrains.kotlin.fir.declarations.utils.hasExplicitBackingField
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.resolve.FirRegularTowerDataContexts import org.jetbrains.kotlin.fir.resolve.FirRegularTowerDataContexts
@@ -22,6 +23,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.TransformImplicitType
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.runContractResolveForLocalClass import org.jetbrains.kotlin.fir.resolve.transformers.contracts.runContractResolveForLocalClass
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.fakeOverrideSubstitution import org.jetbrains.kotlin.fir.scopes.fakeOverrideSubstitution
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
@@ -225,6 +227,8 @@ private class ReturnTypeCalculatorWithJump(
) )
} }
resolvedToContractsIfNecessary(declaration)
val returnTypeRef = declaration.returnTypeRef val returnTypeRef = declaration.returnTypeRef
if (returnTypeRef is FirResolvedTypeRef) return returnTypeRef if (returnTypeRef is FirResolvedTypeRef) return returnTypeRef
@@ -257,6 +261,20 @@ private class ReturnTypeCalculatorWithJump(
} }
} }
private fun resolvedToContractsIfNecessary(declaration: FirCallableDeclaration) {
if (declaration.resolvePhase >= FirResolvePhase.CONTRACTS) return
val canHaveContracts = when {
declaration is FirProperty && !declaration.isLocal -> true
declaration is FirSimpleFunction && !declaration.isLocal -> true
else -> false
}
if (canHaveContracts) {
declaration.ensureResolved(FirResolvePhase.CONTRACTS)
}
}
@OptIn(PrivateForInline::class) @OptIn(PrivateForInline::class)
private fun computeReturnTypeRef(declaration: FirCallableDeclaration): FirResolvedTypeRef { private fun computeReturnTypeRef(declaration: FirCallableDeclaration): FirResolvedTypeRef {
// To properly transform and resolve declaration's type, we need to use its module's session // To properly transform and resolve declaration's type, we need to use its module's session
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect // !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER // !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect // !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER // !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes // LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// FIR_IDENTICAL // FIR_IDENTICAL
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// FIR_IDENTICAL // FIR_IDENTICAL
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// FILE: contracts.kt // FILE: contracts.kt
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
/* /*
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// FILE: contracts.kt // FILE: contracts.kt
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
/* /*
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// SKIP_TXT // SKIP_TXT
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// FILE: contracts.kt // FILE: contracts.kt
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes // LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// FILE: contracts.kt // FILE: contracts.kt
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
/* /*
@@ -1,4 +1,3 @@
// FIR_IDE_IGNORE
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
import kotlin.contracts.* import kotlin.contracts.*
@@ -16,6 +15,15 @@ fun case_2_1(x: Number?) {
println(x.toByte()) println(x.toByte())
} }
// TESTCASE NUMBER: 3
class Child : Base() {
fun case_3_1(x: Any?) {
if (case_3_2(x)) {
x.length
}
}
}
// TESTCASE NUMBER: 1 // TESTCASE NUMBER: 1
fun case_1_2(x: Any?): Boolean { fun case_1_2(x: Any?): Boolean {
contract { returns(true) implies (x is String) } contract { returns(true) implies (x is String) }
@@ -27,3 +35,11 @@ fun case_2_2(x: Any?) {
contract { returns() implies(x != null) } contract { returns() implies(x != null) }
if (x == null) throw Exception() if (x == null) throw Exception()
} }
// TESTCASE NUMBER: 3
open class Base {
fun case_3_2(x: Any?): Boolean {
contract { returns(true) implies (x is String) }
return x is String
}
}
@@ -1,5 +1,4 @@
// !OPT_IN: kotlin.contracts.ExperimentalContracts // !OPT_IN: kotlin.contracts.ExperimentalContracts
// FIR_IDE_IGNORE
/* /*
* KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE) * KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE)
@@ -24,6 +23,15 @@ fun case_2_1(x: Number?) {
println(<!DEBUG_INFO_SMARTCAST!>x<!>.toByte()) println(<!DEBUG_INFO_SMARTCAST!>x<!>.toByte())
} }
// TESTCASE NUMBER: 3
class Child : Base() {
fun case_3_1(x: Any?) {
if (case_3_2(x)) {
<!DEBUG_INFO_SMARTCAST!>x<!>.length
}
}
}
// TESTCASE NUMBER: 1 // TESTCASE NUMBER: 1
fun case_1_2(x: Any?): Boolean { fun case_1_2(x: Any?): Boolean {
contract { returns(true) implies (x is String) } contract { returns(true) implies (x is String) }
@@ -36,4 +44,10 @@ fun case_2_2(x: Any?) {
if (x == null) throw Exception() if (x == null) throw Exception()
} }
// TESTCASE NUMBER: 3
open class Base {
fun case_3_2(x: Any?): Boolean {
contract { returns(true) implies (x is String) }
return x is String
}
}
@@ -8,3 +8,23 @@ public fun case_2_1(/*0*/ x: kotlin.Number?): kotlin.Unit
public fun case_2_2(/*0*/ x: kotlin.Any?): kotlin.Unit public fun case_2_2(/*0*/ x: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> x != null Returns(WILDCARD) -> x != null
public open class Base {
public constructor Base()
public final fun case_3_2(/*0*/ x: kotlin.Any?): kotlin.Boolean
Returns(TRUE) -> x is String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Child : Base {
public constructor Child()
public final fun case_3_1(/*0*/ x: kotlin.Any?): kotlin.Unit
public final override /*1*/ /*fake_override*/ fun case_3_2(/*0*/ x: kotlin.Any?): kotlin.Boolean
Returns(TRUE) -> x is String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}