diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index d61973d0317..9560d51ab1b 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -10689,6 +10689,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariable.kt"); } + @TestMetadata("nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.kt") + public void testNullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.kt"); + } + @TestMetadata("overApproximationForInCaptured.kt") public void testOverApproximationForInCaptured() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/overApproximationForInCaptured.kt"); diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceComponents.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceComponents.kt index 751be9f2af3..10c7d4b44c6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceComponents.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceComponents.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirSessionComponent import org.jetbrains.kotlin.fir.NoMutableState import org.jetbrains.kotlin.fir.types.ConeInferenceContext import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext +import org.jetbrains.kotlin.resolve.calls.inference.InferenceCompatibilityChecker import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintIncorporator import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver @@ -24,7 +25,13 @@ class InferenceComponents(val session: FirSession) : FirSessionComponent { val approximator: AbstractTypeApproximator = object : AbstractTypeApproximator(ctx) {} val trivialConstraintTypeInferenceOracle = TrivialConstraintTypeInferenceOracle.create(ctx) private val incorporator = ConstraintIncorporator(approximator, trivialConstraintTypeInferenceOracle, ConeConstraintSystemUtilContext) - private val injector = ConstraintInjector(incorporator, approximator) + private val injector = ConstraintInjector( + incorporator, + approximator, + object : InferenceCompatibilityChecker { + override val isCompatibilityModeEnabled = true + } + ) val resultTypeResolver = ResultTypeResolver(approximator, trivialConstraintTypeInferenceOracle) val constraintSystemFactory = ConstraintSystemFactory() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt index f003deba97b..461c6c49e66 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/PlatformConfiguratorBase.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve import org.jetbrains.kotlin.builtins.PlatformToKotlinClassMapper import org.jetbrains.kotlin.container.* import org.jetbrains.kotlin.resolve.calls.checkers.* +import org.jetbrains.kotlin.resolve.calls.inference.InferenceCompatibilityCheckerImpl import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator import org.jetbrains.kotlin.resolve.checkers.* import org.jetbrains.kotlin.resolve.lazy.DelegationFilter @@ -107,6 +108,7 @@ abstract class PlatformConfiguratorBase( override fun configureModuleDependentCheckers(container: StorageComponentContainer) { container.useImpl() + container.useImpl() } fun configureExtensionsAndCheckers(container: StorageComponentContainer) { diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/InferenceCompatibilityChecker.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/InferenceCompatibilityChecker.kt new file mode 100644 index 00000000000..0263ad00cf0 --- /dev/null +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/InferenceCompatibilityChecker.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve.calls.inference + +interface InferenceCompatibilityChecker { + val isCompatibilityModeEnabled: Boolean +} diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt index a1fe386674a..422bf4945da 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/AbstractTypeCheckerContextForConstraintSystem.kt @@ -21,6 +21,8 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck override val isStubTypeEqualsToAnything: Boolean get() = true + abstract val isInferenceCompatibilityEnabled: Boolean + abstract fun isMyTypeVariable(type: SimpleTypeMarker): Boolean // super and sub type isSingleClassifierType @@ -209,16 +211,20 @@ abstract class AbstractTypeCheckerContextForConstraintSystem : AbstractTypeCheck if (typeVariable.isMarkedNullable()) { val typeVariableTypeConstructor = typeVariable.typeConstructor() val subTypeConstructor = subType.typeConstructor() - val resultType = if ( - !subTypeConstructor.isTypeVariable() && - typeVariableTypeConstructor.isTypeVariable() && - (typeVariableTypeConstructor as TypeVariableTypeConstructorMarker).isContainedInInvariantOrContravariantPositions() - ) { - subType.withNullability(false) - } else { + val needToMakeDefNotNull = subTypeConstructor.isTypeVariable() || + typeVariableTypeConstructor !is TypeVariableTypeConstructorMarker || + !typeVariableTypeConstructor.isContainedInInvariantOrContravariantPositions() + + val resultType = if (needToMakeDefNotNull) { subType.makeDefinitelyNotNullOrNotNull() + } else { + if (!isInferenceCompatibilityEnabled && subType is CapturedTypeMarker) { + subType.withNotNullProjection() + } else { + subType.withNullability(false) + } } - if (resultType is CapturedTypeMarker) resultType.withNotNullProjection() else resultType + if (isInferenceCompatibilityEnabled && resultType is CapturedTypeMarker) resultType.withNotNullProjection() else resultType } else subType is FlexibleTypeMarker -> { diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt index 20a3674a58d..7a04c644acb 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation +import org.jetbrains.kotlin.resolve.calls.inference.InferenceCompatibilityChecker import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind.* import org.jetbrains.kotlin.types.AbstractTypeApproximator @@ -19,7 +20,8 @@ import kotlin.math.max class ConstraintInjector( val constraintIncorporator: ConstraintIncorporator, - val typeApproximator: AbstractTypeApproximator + val typeApproximator: AbstractTypeApproximator, + val inferenceCompatibilityChecker: InferenceCompatibilityChecker ) { private val ALLOWED_DEPTH_DELTA_FOR_INCORPORATION = 1 @@ -129,6 +131,8 @@ class ConstraintInjector( // We use `var` intentionally to avoid extra allocations as this property is quite "hot" private var possibleNewConstraints: MutableList>? = null + override val isInferenceCompatibilityEnabled = inferenceCompatibilityChecker.isCompatibilityModeEnabled + private var baseLowerType = position.initialConstraint.a private var baseUpperType = position.initialConstraint.b diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/InferenceCompatibilityCheckerImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/InferenceCompatibilityCheckerImpl.kt new file mode 100644 index 00000000000..f9252502a4d --- /dev/null +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/InferenceCompatibilityCheckerImpl.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.resolve.calls.inference + +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersionSettings + +class InferenceCompatibilityCheckerImpl(val languageVersionSettings: LanguageVersionSettings) : InferenceCompatibilityChecker { + override val isCompatibilityModeEnabled: Boolean + get() = languageVersionSettings.getFeatureSupport(LanguageFeature.InferenceCompatibility) == LanguageFeature.State.ENABLED +} diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariable.fir.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariable.fir.kt new file mode 100644 index 00000000000..ef82b2a74eb --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariable.fir.kt @@ -0,0 +1,39 @@ +// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -REDUNDANT_PROJECTION +// !LANGUAGE: +InferenceCompatibility + +// FILE: Foo.java +public class Foo extends Bar { + public Foo(L x) { + super(x); + } +} + +// FILE: main.kt +fun Bar.foo(): T = null as T +fun Bar.bar(): T = null as T +fun Foo.boo1(): T = null as T +fun Foo.boo2(): T = null as T + +open class Bar(val x: K) + +fun main(x: Foo, y: Bar, z1: Foo, z2: Bar) { + x.foo() + x.bar() + x.boo1() + x.boo2() + + y.foo() + y.bar() + y.boo1() + y.boo2() + + z1.foo() + z1.bar() + z1.boo1() + z1.boo2() + + z2.foo() + z2.bar() + z2.boo1() + z2.boo2() +} diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariable.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariable.kt index 927fe761cfd..f5fc6649b1b 100644 --- a/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariable.kt +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariable.kt @@ -1,4 +1,5 @@ // !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -REDUNDANT_PROJECTION +// !LANGUAGE: +InferenceCompatibility // FILE: Foo.java public class Foo extends Bar { diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.fir.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.fir.kt new file mode 100644 index 00000000000..f833d34d8f8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.fir.kt @@ -0,0 +1,39 @@ +// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -REDUNDANT_PROJECTION +// !LANGUAGE: -InferenceCompatibility + +// FILE: Foo.java +public class Foo extends Bar { + public Foo(L x) { + super(x); + } +} + +// FILE: main.kt +fun Bar.foo(): T = null as T +fun Bar.bar(): T = null as T +fun Foo.boo1(): T = null as T +fun Foo.boo2(): T = null as T + +open class Bar(val x: K) + +fun main(x: Foo, y: Bar, z1: Foo, z2: Bar) { + x.foo() + x.bar() + x.boo1() + x.boo2() + + y.foo() + y.bar() + y.boo1() + y.boo2() + + z1.foo() + z1.bar() + z1.boo1() + z1.boo2() + + z2.foo() + z2.bar() + z2.boo1() + z2.boo2() +} diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.kt new file mode 100644 index 00000000000..acc6daa6911 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.kt @@ -0,0 +1,39 @@ +// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -REDUNDANT_PROJECTION +// !LANGUAGE: -InferenceCompatibility + +// FILE: Foo.java +public class Foo extends Bar { + public Foo(L x) { + super(x); + } +} + +// FILE: main.kt +fun Bar.foo(): T = null as T +fun Bar.bar(): T = null as T +fun Foo.boo1(): T = null as T +fun Foo.boo2(): T = null as T + +open class Bar(val x: K) + +fun main(x: Foo, y: Bar, z1: Foo, z2: Bar) { + x.foo() + x.bar() + x.boo1() + x.boo2() + + y.foo() + y.bar() + y.boo1() + y.boo2() + + z1.foo() + z1.bar() + z1.boo1() + z1.boo2() + + z2.foo() + z2.bar() + z2.boo1() + z2.boo2() +} diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.txt new file mode 100644 index 00000000000..255dde6e5ba --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.txt @@ -0,0 +1,23 @@ +package + +public fun main(/*0*/ x: Foo, /*1*/ y: Bar, /*2*/ z1: Foo, /*3*/ z2: Bar): kotlin.Unit +public fun Bar.bar(): T +public fun Foo.boo1(): T +public fun Foo.boo2(): T +public fun Bar.foo(): T + +public open class Bar { + public constructor Bar(/*0*/ x: K) + public final val x: K + 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 open class Foo : Bar { + public constructor Foo(/*0*/ x: L!) + public final override /*1*/ /*fake_override*/ val x: L! + 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/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 6fd2a9076f0..51cc0f60769 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10696,6 +10696,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariable.kt"); } + @TestMetadata("nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.kt") + public void testNullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.kt"); + } + @TestMetadata("overApproximationForInCaptured.kt") public void testOverApproximationForInCaptured() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/overApproximationForInCaptured.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 7111a668576..37729482f3d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10691,6 +10691,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariable.kt"); } + @TestMetadata("nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.kt") + public void testNullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/nullableCaptruredTypeAgainstNullableVariableWithDisabledComplatibilityFlag.kt"); + } + @TestMetadata("overApproximationForInCaptured.kt") public void testOverApproximationForInCaptured() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/overApproximationForInCaptured.kt");