From e0a1f1c4058e3efc4579f2ce3f68cbe3d6778b5d Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Mon, 18 Apr 2022 12:07:27 +0300 Subject: [PATCH] [FE] Review fixes --- .../kotlin/fir/types/ConeInferenceContext.kt | 4 +- .../fir/resolve/calls/ResolutionStages.kt | 6 +- .../rendering/DefaultErrorMessages.java | 2 +- .../ConstraintSystemCompletionContext.kt | 2 +- .../model/ConstraintPositionAndErrors.kt | 4 +- .../calls/tower/CandidateApplicability.kt | 1 - .../calls/components/ResolutionParts.kt | 7 +- ...romCovariantAndContravariantTypes.diag.txt | 2 +- .../tests/inference/kt45461.diag.txt | 2 +- .../tests/inference/kt45461_12.diag.txt | 2 +- .../tests/inference/kt45461_15.diag.txt | 2 +- .../tests/inference/kt45461_19.diag.txt | 2 +- .../tests/inference/kt45461_2.diag.txt | 2 +- .../tests/inference/kt45461_21.diag.txt | 2 +- .../tests/inference/kt45461_24.diag.txt | 2 +- .../tests/inference/kt45461_25.diag.txt | 2 +- .../tests/inference/kt45461_26.diag.txt | 2 +- .../tests/inference/kt45461_5.diag.txt | 2 +- .../tests/inference/kt45461_8.diag.txt | 2 +- .../tests/inference/kt45461_9.diag.txt | 2 +- .../tests/inference/kt48765.diag.txt | 2 +- .../tests/inference/kt49661.diag.txt | 2 +- .../kotlin/types/EmptyIntersectionTypeKind.kt | 4 +- .../kotlin/types/model/TypeSystemContext.kt | 75 +++++++++---------- 24 files changed, 60 insertions(+), 75 deletions(-) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt index 453c629d924..257849a7e35 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt @@ -385,10 +385,10 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo } override fun KotlinTypeMarker.eraseContainingTypeParameters(): KotlinTypeMarker { - val erasedTypeParameters = this.extractTypeParameters() + val typeParameterErasureMap = this.extractTypeParameters() .map { (it as ConeTypeParameterLookupTag).typeParameterSymbol } .eraseToUpperBoundsAssociated(session, intersectUpperBounds = true, eraseRecursively = true) - return ConeSubstitutorByMap(erasedTypeParameters, session).safeSubstitute(this) + return ConeSubstitutorByMap(typeParameterErasureMap, session).safeSubstitute(this) } override fun TypeConstructorMarker.isTypeParameterTypeConstructor(): Boolean { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index b8cc70fb4ef..b3e9adf12a0 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -580,10 +580,8 @@ internal object CheckLowPriorityInOverloadResolution : CheckerStage() { internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() { override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) = with(candidate.system.asConstraintSystemCompleterContext()) { - val typeVariables = candidate.system.notFixedTypeVariables.values.takeIf { it.isNotEmpty() } ?: return - - for (variableWithConstraints in typeVariables) { - val upperTypes = variableWithConstraints.constraints.extractUpperTypes() + for (variableWithConstraints in candidate.system.notFixedTypeVariables.values) { + val upperTypes = variableWithConstraints.constraints.extractUpperTypesToCheckIntersectionEmptiness() if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) { sink.yieldDiagnostic( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index f8a97fab308..0171c9f4235 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -964,7 +964,7 @@ public class DefaultErrorMessages { MAP.put(TYPE_INFERENCE_INCORPORATION_ERROR, "Type inference failed. Please try to specify type arguments explicitly."); MAP.put(TYPE_INFERENCE_ONLY_INPUT_TYPES, "Type inference failed. The value of the type parameter {0} should be mentioned in input types " + "(argument types, receiver type or expected type). Try to specify it explicitly.", NAME); - MAP.put(INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION, "Type argument for a type parameter {0} can''t be inferred because it''s upper bounded by incompatible types: {1}", TO_STRING, RENDER_COLLECTION_OF_TYPES); + MAP.put(INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION, "Type argument for a type parameter {0} can''t be inferred because it has incompatible upper bounds: {1}", TO_STRING, RENDER_COLLECTION_OF_TYPES); MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER); MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, "Type inference failed. Expected type mismatch: inferred type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE); MAP.put(TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG, "Please use spread operator to pass an array as vararg. It will be an error in 1.5."); diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintSystemCompletionContext.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintSystemCompletionContext.kt index 2e4b9b68d0e..cfde65da96e 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintSystemCompletionContext.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintSystemCompletionContext.kt @@ -107,7 +107,7 @@ abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Contex postponedArguments: List ) = postponedArguments.firstOrNull { argument -> argument.inputTypes.all { containsOnlyFixedVariables(it) } } - fun List.extractUpperTypes(): List = + fun List.extractUpperTypesToCheckIntersectionEmptiness(): List = filter { constraint -> constraint.kind == ConstraintKind.UPPER && !constraint.type.contains { !it.typeConstructor().isClassTypeConstructor() && !it.typeConstructor().isTypeParameterTypeConstructor() diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt index 6382b2bedbd..4dade3583b1 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt @@ -113,7 +113,7 @@ class NewConstraintWarning( override val lowerType: KotlinTypeMarker, override val upperType: KotlinTypeMarker, override val position: IncorporationConstraintPosition, -) : ConstraintSystemError(RESOLVED_WITH_WARNING), NewConstraintMismatch +) : ConstraintSystemError(RESOLVED), NewConstraintMismatch class CapturedTypeFromSubtyping( val typeVariable: TypeVariableMarker, @@ -143,7 +143,7 @@ sealed interface InferredEmptyIntersection { class InferredEmptyIntersectionWarning( override val incompatibleTypes: Collection, override val typeVariable: TypeVariableMarker -) : ConstraintSystemError(RESOLVED_WITH_WARNING), InferredEmptyIntersection +) : ConstraintSystemError(RESOLVED), InferredEmptyIntersection class InferredEmptyIntersectionError( override val incompatibleTypes: Collection, diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt index dfc0cedde30..36731392dd3 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/tower/CandidateApplicability.kt @@ -29,7 +29,6 @@ enum class CandidateApplicability { PROPERTY_AS_OPERATOR, // using property of functional type as an operator. From resolution perspective, this is considered successful. RESOLVED_NEED_PRESERVE_COMPATIBILITY, // call resolved successfully, but using new features that changes resolve RESOLVED_WITH_ERROR, // call has error, but it is still successful from resolution perspective - RESOLVED_WITH_WARNING, // generally call is successful, but there are additional resolution warnings (e.g. for deprecation something) RESOLVED, // call success or has uncompleted inference or in other words possible successful candidate } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index 73486b0451d..cf3076e7820 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.types.error.ErrorUtils import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.compactIfPossible import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -882,10 +881,8 @@ internal object CheckContextReceiversResolutionPart : ResolutionPart() { internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionPart() { override fun ResolutionCandidate.process(workIndex: Int) = with(getSystem().asConstraintSystemCompleterContext()) { - val typeVariables = getSystem().getBuilder().currentStorage().notFixedTypeVariables.values.takeIf { it.isNotEmpty() } ?: return - - for (variableWithConstraints in typeVariables) { - val upperTypes = variableWithConstraints.constraints.extractUpperTypes() + for (variableWithConstraints in getSystem().getBuilder().currentStorage().notFixedTypeVariables.values) { + val upperTypes = variableWithConstraints.constraints.extractUpperTypesToCheckIntersectionEmptiness() if (upperTypes.computeEmptyIntersectionTypeKind().isDefinitelyEmpty()) { val isInferredEmptyIntersectionForbidden = diff --git a/compiler/testData/diagnostics/tests/inference/commonSystem/selectFromCovariantAndContravariantTypes.diag.txt b/compiler/testData/diagnostics/tests/inference/commonSystem/selectFromCovariantAndContravariantTypes.diag.txt index 1c0121e86fc..e962f8de3d3 100644 --- a/compiler/testData/diagnostics/tests/inference/commonSystem/selectFromCovariantAndContravariantTypes.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/commonSystem/selectFromCovariantAndContravariantTypes.diag.txt @@ -7,6 +7,6 @@ fun genericIn(x: In) {} /selectFromCovariantAndContravariantTypes.kt:13:20: warning: parameter 'x' is never used fun genericOut(x: Out) {} ^ -/selectFromCovariantAndContravariantTypes.kt:16:5: warning: type argument for a type parameter V can't be inferred because it's upper bounded by incompatible types: A, B. This will become an error in Kotlin 1.9 +/selectFromCovariantAndContravariantTypes.kt:16:5: warning: type argument for a type parameter V can't be inferred because it has incompatible upper bounds: A, B. This will become an error in Kotlin 1.9 genericIn(select(a, b)) ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461.diag.txt index 01e1b9d13de..9058817500f 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461.diag.txt @@ -1,6 +1,6 @@ /kt45461.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461.kt:10:19: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: String, Int. This will become an error in Kotlin 1.9 +/kt45461.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, Int. This will become an error in Kotlin 1.9 Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_12.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_12.diag.txt index 4016201980a..738a99557ef 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_12.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_12.diag.txt @@ -1,7 +1,7 @@ /kt45461_12.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_12.kt:12:19: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: String, K. This will become an error in Kotlin 1.8 +/kt45461_12.kt:12:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K. This will become an error in Kotlin 1.9 Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_15.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_15.diag.txt index 6d2ac79d1ba..d82bcc6ce3f 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_15.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_15.diag.txt @@ -1,6 +1,6 @@ /kt45461_15.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_15.kt:14:21: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Inv, K. This will become an error in Kotlin 1.9 +/kt45461_15.kt:14:21: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv, K. This will become an error in Kotlin 1.9 Bar>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_19.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_19.diag.txt index bcaeb0f8aec..d3157fb7ca6 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_19.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_19.diag.txt @@ -1,6 +1,6 @@ /kt45461_19.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_19.kt:13:26: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Out>, K. This will become an error in Kotlin 1.9 +/kt45461_19.kt:13:26: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Out>, K. This will become an error in Kotlin 1.9 Bar>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_2.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_2.diag.txt index 2269aabe174..40f6db97030 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_2.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_2.diag.txt @@ -4,7 +4,7 @@ /kt45461_2.kt:8:10: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined fun main() { ^ -/kt45461_2.kt:10:19: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: String, K. This will become an error in Kotlin 1.9 +/kt45461_2.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K. This will become an error in Kotlin 1.9 Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_21.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_21.diag.txt index 80aeb9550ce..72b6a50b5f1 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_21.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_21.diag.txt @@ -1,6 +1,6 @@ /kt45461_21.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_21.kt:13:25: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: In>, K. This will become an error in Kotlin 1.9 +/kt45461_21.kt:13:25: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: In>, K. This will become an error in Kotlin 1.9 Bar>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_24.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_24.diag.txt index 9b08fd4a468..b80e61d727b 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_24.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_24.diag.txt @@ -4,6 +4,6 @@ /kt45461_24.kt:10:10: warning: 'Inv>' is a final type, and thus a value of the type parameter is predetermined fun >> main() { ^ -/kt45461_24.kt:12:35: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Inv>, K. This will become an error in Kotlin 1.9 +/kt45461_24.kt:12:35: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv>, K. This will become an error in Kotlin 1.9 Bar>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_25.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_25.diag.txt index 3cbaaa007a6..728abc814fe 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_25.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_25.diag.txt @@ -1,3 +1,3 @@ -/kt45461_25.kt:11:34: error: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: String, K, Float +/kt45461_25.kt:11:34: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K, Float val x: Float = Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_26.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_26.diag.txt index e20b20051da..f404a5b6fbe 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_26.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_26.diag.txt @@ -1,4 +1,4 @@ -/kt45461_26.kt:13:44: error: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Out, K, Out +/kt45461_26.kt:13:44: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Out, K, Out val x: Out = Bar>().takeFoo(foo) ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_5.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_5.diag.txt index 56d82edb652..53a82992858 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_5.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_5.diag.txt @@ -1,6 +1,6 @@ /kt45461_5.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_5.kt:10:19: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: String, K. This will become an error in Kotlin 1.9 +/kt45461_5.kt:10:19: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K. This will become an error in Kotlin 1.9 Bar().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_8.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_8.diag.txt index 4bd649a4ead..99b5c109a45 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_8.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_8.diag.txt @@ -4,6 +4,6 @@ /kt45461_8.kt:10:28: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined fun , L : N, N: Int> main() { ^ -/kt45461_8.kt:12:24: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Inv, K. This will become an error in Kotlin 1.9 +/kt45461_8.kt:12:24: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv, K. This will become an error in Kotlin 1.9 Bar>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt45461_9.diag.txt b/compiler/testData/diagnostics/tests/inference/kt45461_9.diag.txt index 18810e64d8a..5b0199c6867 100644 --- a/compiler/testData/diagnostics/tests/inference/kt45461_9.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt45461_9.diag.txt @@ -1,7 +1,7 @@ /kt45461_9.kt:5:25: warning: parameter 'foo' is never used fun takeFoo(foo: Foo) {} ^ -/kt45461_9.kt:12:21: warning: type argument for a type parameter S can't be inferred because it's upper bounded by incompatible types: Inv, Inv. This will become an error in Kotlin 1.9 +/kt45461_9.kt:12:21: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv, Inv. This will become an error in Kotlin 1.9 Bar>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31 ^ diff --git a/compiler/testData/diagnostics/tests/inference/kt48765.diag.txt b/compiler/testData/diagnostics/tests/inference/kt48765.diag.txt index 9cdd3d42adb..b21b6a0e868 100644 --- a/compiler/testData/diagnostics/tests/inference/kt48765.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt48765.diag.txt @@ -4,7 +4,7 @@ /kt48765.kt:4:52: warning: parameter 'x2' is never used fun > foo(x1: T2, x2: T1) {} ^ -/kt48765.kt:8:13: warning: type argument for a type parameter T can't be inferred because it's upper bounded by incompatible types: String, Number. This will become an error in Kotlin 1.9 +/kt48765.kt:8:13: warning: type argument for a type parameter T can't be inferred because it has incompatible upper bounds: String, Number. This will become an error in Kotlin 1.9 B().foo(x, foo()) ^ /kt48765.kt:12:9: warning: 'String' is a final type, and thus a value of the type parameter is predetermined diff --git a/compiler/testData/diagnostics/tests/inference/kt49661.diag.txt b/compiler/testData/diagnostics/tests/inference/kt49661.diag.txt index 05869b84ec2..50ae1d0c34c 100644 --- a/compiler/testData/diagnostics/tests/inference/kt49661.diag.txt +++ b/compiler/testData/diagnostics/tests/inference/kt49661.diag.txt @@ -1,4 +1,4 @@ -/kt49661.kt:10:5: warning: type argument for a type parameter T can't be inferred because it's upper bounded by incompatible types: Foo, Int. This will become an error in Kotlin 1.9 +/kt49661.kt:10:5: warning: type argument for a type parameter T can't be inferred because it has incompatible upper bounds: Foo, Int. This will become an error in Kotlin 1.9 f { g() } ^ diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt index 9b86ee1305a..9e65ac4d384 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/EmptyIntersectionTypeKind.kt @@ -5,8 +5,6 @@ package org.jetbrains.kotlin.types -enum class EmptyIntersectionTypeKind { NOT_EMPTY_INTERSECTION, MULTIPLE_CLASSES, SINGLE_FINAL_CLASS } +enum class EmptyIntersectionTypeKind { NOT_EMPTY_INTERSECTION, MULTIPLE_CLASSES } // TODO: add `SINGLE_FINAL_CLASS` later fun EmptyIntersectionTypeKind.isDefinitelyEmpty(): Boolean = this == EmptyIntersectionTypeKind.MULTIPLE_CLASSES - -fun EmptyIntersectionTypeKind.isPossibleEmpty(): Boolean = this == EmptyIntersectionTypeKind.SINGLE_FINAL_CLASS diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt index b3b6050fe15..f6bd55ac53f 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt @@ -321,52 +321,47 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui if (this.isEmpty()) return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION - val types = this.withIndex() + val types = this.toList() - for ((i, firstType) in types) { - if (!firstType.typeConstructor().mayCauseEmptyIntersection()) - continue + for (i in 0 until types.size) { + val firstType = types[i] + if (!firstType.typeConstructor().mayCauseEmptyIntersection()) continue - val doesFirstTypeContainTypeParameters by lazy { firstType.contains { it.typeConstructor().isTypeParameterTypeConstructor() } } val firstSubstitutedType by lazy { firstType.eraseContainingTypeParameters() } - for ((j, secondType) in types) { - if (i >= j || !secondType.typeConstructor().mayCauseEmptyIntersection()) continue + for (j in i + 1 until types.size) { + val secondType = types[j] + if (!secondType.typeConstructor().mayCauseEmptyIntersection()) continue - val doesSecondTypeContainTypeParameters = secondType.contains { it.typeConstructor().isTypeParameterTypeConstructor() } - val secondSubstitutedType by lazy { secondType.eraseContainingTypeParameters() } - val anyContainingTypeParameter = doesFirstTypeContainTypeParameters || doesSecondTypeContainTypeParameters + val secondSubstitutedType = secondType.eraseContainingTypeParameters() - when { - !anyContainingTypeParameter && !canHaveSubtype(listOf(firstType, secondType)) -> - return EmptyIntersectionTypeKind.MULTIPLE_CLASSES - anyContainingTypeParameter && !canHaveSubtype(listOf(firstSubstitutedType, secondSubstitutedType)) -> - return EmptyIntersectionTypeKind.MULTIPLE_CLASSES - } + if (!canHaveCommonSubtype(firstSubstitutedType, secondSubstitutedType)) + return EmptyIntersectionTypeKind.MULTIPLE_CLASSES } } return EmptyIntersectionTypeKind.NOT_EMPTY_INTERSECTION } - private fun canHaveSubtype(types: List): Boolean { - val expandedTypes = types.map { - if (it.typeConstructor() is IntersectionTypeConstructorMarker) { - it.typeConstructor().supertypes().toList() - } else listOf(it) - }.flatten().withIndex() + private fun canHaveCommonSubtype(first: KotlinTypeMarker, second: KotlinTypeMarker): Boolean { + fun extractIntersectionComponentsIfNeeded(type: KotlinTypeMarker) = + if (type.typeConstructor() is IntersectionTypeConstructorMarker) { + type.typeConstructor().supertypes().toList() + } else listOf(type) + + val expandedTypes = extractIntersectionComponentsIfNeeded(first) + extractIntersectionComponentsIfNeeded(second) val typeCheckerState = newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = true) - for ((i, firstType) in expandedTypes) { + for (i in 0 until expandedTypes.size) { + val firstType = expandedTypes[i] val firstTypeConstructor = firstType.typeConstructor() if (!firstTypeConstructor.mayCauseEmptyIntersection()) continue - for ((j, secondType) in expandedTypes) { - if (i >= j) continue - + for (j in i + 1 until expandedTypes.size) { + val secondType = expandedTypes[j] val secondTypeConstructor = secondType.typeConstructor() if (!secondTypeConstructor.mayCauseEmptyIntersection()) @@ -375,14 +370,12 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui if (areEqualTypeConstructors(firstTypeConstructor, secondTypeConstructor) && secondTypeConstructor.parametersCount() == 0) continue - // Below is determining having subtypes for two classes - // A class type may have only one supertype of class-based type constructor val superTypeByFirstConstructor = AbstractTypeChecker.findCorrespondingSupertypes( typeCheckerState, firstType.lowerBoundIfFlexible(), secondTypeConstructor - ).takeIf { it.isNotEmpty() }?.single() + ).singleOrNull() val superTypeBySecondConstructor = AbstractTypeChecker.findCorrespondingSupertypes( typeCheckerState, secondType.lowerBoundIfFlexible(), firstTypeConstructor - ).takeIf { it.isNotEmpty() }?.single() + ).singleOrNull() if (superTypeByFirstConstructor == null && superTypeBySecondConstructor == null) return false @@ -390,7 +383,7 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui if (superTypeByFirstConstructor == null || superTypeBySecondConstructor == null) continue // first or second is actually subtype of another - if (!areTypeArgumentsCompatibleToHaveSubtypes(superTypeByFirstConstructor, superTypeBySecondConstructor)) { + if (!checkArgumentsOfTypesToBeAbleToHaveCommonSubtype(superTypeByFirstConstructor, superTypeBySecondConstructor)) { return false } } @@ -417,20 +410,20 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui variance1: TypeVariance, variance2: TypeVariance, ): Boolean { - val argumentOfFirst = firstType.getArgument(argumentIndex).uncaptureIfNeeded() - val parameterOfFirst = firstType.typeConstructor().getParameter(argumentIndex) + fun getEffectiveVariance(type: KotlinTypeMarker): TypeVariance? { + val argument = type.getArgument(argumentIndex).uncaptureIfNeeded() + val parameter = type.typeConstructor().getParameter(argumentIndex) + return AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance()) + } - val argumentOfSecond = secondType.getArgument(argumentIndex).uncaptureIfNeeded() - val parameterOfSecond = secondType.typeConstructor().getParameter(argumentIndex) - - val effectiveVariance1 = AbstractTypeChecker.effectiveVariance(parameterOfFirst.getVariance(), argumentOfFirst.getVariance()) - val effectiveVariance2 = AbstractTypeChecker.effectiveVariance(parameterOfSecond.getVariance(), argumentOfSecond.getVariance()) + val effectiveVariance1 = getEffectiveVariance(firstType) + val effectiveVariance2 = getEffectiveVariance(secondType) return (effectiveVariance1 == variance1 && effectiveVariance2 == variance2) || (effectiveVariance1 == variance2 && effectiveVariance2 == variance1) } - private fun areTypeArgumentsCompatibleToHaveSubtypes(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean { + private fun checkArgumentsOfTypesToBeAbleToHaveCommonSubtype(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker): Boolean { require(firstType.typeConstructor() == secondType.typeConstructor()) { "Type constructors of the passed types should be the same to compare their arguments" } @@ -467,13 +460,13 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui if (!isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond)) { return false } - } else if (!canHaveSubtype(listOf(argumentTypeOfFirst, argumentTypeOfSecond))) { + } else if (!canHaveCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)) { return false } } areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.OUT, TypeVariance.OUT) || areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.IN) -> { - if (!canHaveSubtype(listOf(argumentTypeOfFirst, argumentTypeOfSecond))) { + if (!canHaveCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)) { return false } }