From 964cf937c3a4b6de67fc2dba7b9bf298c673ea49 Mon Sep 17 00:00:00 2001 From: "Denis.Zharkov" Date: Tue, 11 Jan 2022 18:20:19 +0300 Subject: [PATCH] Fix IllegalStateException in case of recursive T & Any upper bound ^KT-50542 Fixed --- ...CompilerTestFE10TestdataTestGenerated.java | 6 ++++++ ...irOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 ++++++ .../resolve/DefinitelyNonNullableTypes.kt | 16 +++++++++++++++ .../kotlin/resolve/DescriptorResolver.java | 3 +++ .../jetbrains/kotlin/resolve/TypeResolver.kt | 13 ++++++++++-- .../recursiveBounds.fir.kt | 11 ++++++++++ .../recursiveBounds.kt | 11 ++++++++++ .../recursiveBounds.txt | 20 +++++++++++++++++++ .../test/runners/DiagnosticTestGenerated.java | 6 ++++++ 10 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/DefinitelyNonNullableTypes.kt create mode 100644 compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.fir.kt create mode 100644 compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.kt create mode 100644 compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.txt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 9068c94c483..4761bd841a9 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -10259,6 +10259,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/overridesJavaAnnotated.kt"); } + @Test + @TestMetadata("recursiveBounds.kt") + public void testRecursiveBounds() throws Exception { + runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.kt"); + } + @Test @TestMetadata("reifiedArguments.kt") public void testReifiedArguments() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index d76f7b5e202..87bfd05d05c 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -10259,6 +10259,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/overridesJavaAnnotated.kt"); } + @Test + @TestMetadata("recursiveBounds.kt") + public void testRecursiveBounds() throws Exception { + runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.kt"); + } + @Test @TestMetadata("reifiedArguments.kt") public void testReifiedArguments() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index a52b610a5e4..72f9116b78f 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -10259,6 +10259,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/overridesJavaAnnotated.kt"); } + @Test + @TestMetadata("recursiveBounds.kt") + public void testRecursiveBounds() throws Exception { + runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.kt"); + } + @Test @TestMetadata("reifiedArguments.kt") public void testReifiedArguments() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DefinitelyNonNullableTypes.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DefinitelyNonNullableTypes.kt new file mode 100644 index 00000000000..5fe63243676 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DefinitelyNonNullableTypes.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2022 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 + +import org.jetbrains.kotlin.types.DefinitelyNotNullType +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.isNullable +import org.jetbrains.kotlin.types.typeUtil.contains +import org.jetbrains.kotlin.types.typeUtil.isTypeParameter + +fun KotlinType.containsIncorrectExplicitDefinitelyNonNullableType(): Boolean = contains { + it is DefinitelyNotNullType && it.original.isTypeParameter() && !it.original.isNullable() +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index ce8ad158e1e..bf86eb3ff71 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -668,6 +668,9 @@ public class DescriptorResolver { if (FunctionTypesKt.isExtensionFunctionType(upperBoundType)) { trace.report(UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE.on(upperBound)); } + if (DefinitelyNonNullableTypesKt.containsIncorrectExplicitDefinitelyNonNullableType(upperBoundType)) { + trace.report(INCORRECT_LEFT_COMPONENT_OF_INTERSECTION.on(upperBound)); + } } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index 79d4ea2398d..ead606698b5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -25,10 +25,10 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations +import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.VariableDescriptorImpl import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors.* -import org.jetbrains.kotlin.types.extensions.TypeAttributeTranslators import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* @@ -56,6 +56,7 @@ import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.Variance.* +import org.jetbrains.kotlin.types.extensions.TypeAttributeTranslators import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.utils.addToStdlib.safeAs import kotlin.math.min @@ -325,7 +326,7 @@ class TypeResolver( return } - if (!leftType.isTypeParameter() || leftType.isMarkedNullable || !TypeUtils.isNullableType(leftType)) { + if (!leftType.isTypeParameter() || leftType.isMarkedNullable || !leftType.isNullableOrUninitializedTypeParameter()) { c.trace.report(INCORRECT_LEFT_COMPONENT_OF_INTERSECTION.on(intersectionType.getLeftTypeRef()!!)) return } @@ -348,6 +349,14 @@ class TypeResolver( result = type(definitelyNotNullType) } + private fun KotlinType.isNullableOrUninitializedTypeParameter(): Boolean { + if ((constructor.declarationDescriptor as? TypeParameterDescriptorImpl)?.isInitialized == false) { + return true + } + + return isNullable() + } + override fun visitFunctionType(type: KtFunctionType) { val receiverTypeRef = type.receiverTypeReference val receiverType = if (receiverTypeRef?.typeElement == null) null else resolveType(c.noBareTypes(), receiverTypeRef) diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.fir.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.fir.kt new file mode 100644 index 00000000000..113f6b79cf0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.fir.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +DefinitelyNonNullableTypes + +fun > sort1() {} +fun ?> sort2() {} + +class A1> +class A2?> + +fun bar() {} + +fun baz() {} diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.kt new file mode 100644 index 00000000000..5851f0dcd6e --- /dev/null +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +DefinitelyNonNullableTypes + +fun Comparable> sort1() {} +fun ?> sort2() {} + +class A1K & Any>> +class A2K & Any>?> + +fun bar() {} + +fun <E : E & Any> baz() {} diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.txt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.txt new file mode 100644 index 00000000000..06eb2d5a4f7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.txt @@ -0,0 +1,20 @@ +package + +public fun bar(): kotlin.Unit +public fun baz(): kotlin.Unit +public fun > sort1(): kotlin.Unit +public fun ?> sort2(): kotlin.Unit + +public final class A1> { + public constructor A1>() + 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 A2?> { + public constructor A2?>() + 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-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 9c35fa76023..cd534010db8 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -10265,6 +10265,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/overridesJavaAnnotated.kt"); } + @Test + @TestMetadata("recursiveBounds.kt") + public void testRecursiveBounds() throws Exception { + runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.kt"); + } + @Test @TestMetadata("reifiedArguments.kt") public void testReifiedArguments() throws Exception {