Fix IllegalStateException in case of recursive T & Any upper bound
^KT-50542 Fixed
This commit is contained in:
+6
@@ -10259,6 +10259,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/overridesJavaAnnotated.kt");
|
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
|
@Test
|
||||||
@TestMetadata("reifiedArguments.kt")
|
@TestMetadata("reifiedArguments.kt")
|
||||||
public void testReifiedArguments() throws Exception {
|
public void testReifiedArguments() throws Exception {
|
||||||
|
|||||||
+6
@@ -10259,6 +10259,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/overridesJavaAnnotated.kt");
|
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
|
@Test
|
||||||
@TestMetadata("reifiedArguments.kt")
|
@TestMetadata("reifiedArguments.kt")
|
||||||
public void testReifiedArguments() throws Exception {
|
public void testReifiedArguments() throws Exception {
|
||||||
|
|||||||
+6
@@ -10259,6 +10259,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/overridesJavaAnnotated.kt");
|
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
|
@Test
|
||||||
@TestMetadata("reifiedArguments.kt")
|
@TestMetadata("reifiedArguments.kt")
|
||||||
public void testReifiedArguments() throws Exception {
|
public void testReifiedArguments() throws Exception {
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
@@ -668,6 +668,9 @@ public class DescriptorResolver {
|
|||||||
if (FunctionTypesKt.isExtensionFunctionType(upperBoundType)) {
|
if (FunctionTypesKt.isExtensionFunctionType(upperBoundType)) {
|
||||||
trace.report(UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE.on(upperBound));
|
trace.report(UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE.on(upperBound));
|
||||||
}
|
}
|
||||||
|
if (DefinitelyNonNullableTypesKt.containsIncorrectExplicitDefinitelyNonNullableType(upperBoundType)) {
|
||||||
|
trace.report(INCORRECT_LEFT_COMPONENT_OF_INTERSECTION.on(upperBound));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations
|
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.descriptors.impl.VariableDescriptorImpl
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
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.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
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.resolve.source.toSourceElement
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.Variance.*
|
import org.jetbrains.kotlin.types.Variance.*
|
||||||
|
import org.jetbrains.kotlin.types.extensions.TypeAttributeTranslators
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
@@ -325,7 +326,7 @@ class TypeResolver(
|
|||||||
return
|
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()!!))
|
c.trace.report(INCORRECT_LEFT_COMPONENT_OF_INTERSECTION.on(intersectionType.getLeftTypeRef()!!))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -348,6 +349,14 @@ class TypeResolver(
|
|||||||
result = type(definitelyNotNullType)
|
result = type(definitelyNotNullType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun KotlinType.isNullableOrUninitializedTypeParameter(): Boolean {
|
||||||
|
if ((constructor.declarationDescriptor as? TypeParameterDescriptorImpl)?.isInitialized == false) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return isNullable()
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitFunctionType(type: KtFunctionType) {
|
override fun visitFunctionType(type: KtFunctionType) {
|
||||||
val receiverTypeRef = type.receiverTypeReference
|
val receiverTypeRef = type.receiverTypeReference
|
||||||
val receiverType = if (receiverTypeRef?.typeElement == null) null else resolveType(c.noBareTypes(), receiverTypeRef)
|
val receiverType = if (receiverTypeRef?.typeElement == null) null else resolveType(c.noBareTypes(), receiverTypeRef)
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// !LANGUAGE: +DefinitelyNonNullableTypes
|
||||||
|
|
||||||
|
fun <T : Comparable<T & Any>> sort1() {}
|
||||||
|
fun <T : Comparable<T & Any>?> sort2() {}
|
||||||
|
|
||||||
|
class A1<K : Comparable<K & Any>>
|
||||||
|
class A2<K : Comparable<K & Any>?>
|
||||||
|
|
||||||
|
fun <R : T & Any, T> bar() {}
|
||||||
|
|
||||||
|
fun <E : E & Any> baz() {}
|
||||||
Vendored
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// !LANGUAGE: +DefinitelyNonNullableTypes
|
||||||
|
|
||||||
|
fun <T : <!INCORRECT_LEFT_COMPONENT_OF_INTERSECTION!>Comparable<T & Any><!>> sort1() {}
|
||||||
|
fun <T : Comparable<T & Any>?> sort2() {}
|
||||||
|
|
||||||
|
class A1<K : Comparable<<!INCORRECT_LEFT_COMPONENT_OF_INTERSECTION!>K<!> & Any>>
|
||||||
|
class A2<K : Comparable<<!INCORRECT_LEFT_COMPONENT_OF_INTERSECTION!>K<!> & Any>?>
|
||||||
|
|
||||||
|
fun <R : T & Any, T> bar() {}
|
||||||
|
|
||||||
|
fun <<!CYCLIC_GENERIC_UPPER_BOUND!>E : <!INCORRECT_LEFT_COMPONENT_OF_INTERSECTION!>E & Any<!><!>> baz() {}
|
||||||
compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/recursiveBounds.txt
Vendored
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ R : T & Any, /*1*/ T> bar(): kotlin.Unit
|
||||||
|
public fun </*0*/ E : [ERROR : Cyclic upper bounds]> baz(): kotlin.Unit
|
||||||
|
public fun </*0*/ T : kotlin.Comparable<T & Any>> sort1(): kotlin.Unit
|
||||||
|
public fun </*0*/ T : kotlin.Comparable<T & Any>?> sort2(): kotlin.Unit
|
||||||
|
|
||||||
|
public final class A1</*0*/ K : kotlin.Comparable<K>> {
|
||||||
|
public constructor A1</*0*/ K : kotlin.Comparable<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 final class A2</*0*/ K : kotlin.Comparable<K>?> {
|
||||||
|
public constructor A2</*0*/ K : kotlin.Comparable<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
|
||||||
|
}
|
||||||
Generated
+6
@@ -10265,6 +10265,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/overridesJavaAnnotated.kt");
|
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
|
@Test
|
||||||
@TestMetadata("reifiedArguments.kt")
|
@TestMetadata("reifiedArguments.kt")
|
||||||
public void testReifiedArguments() throws Exception {
|
public void testReifiedArguments() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user