From 12db3d6e835fceccdfac7b2cc8d33b61ea714490 Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Tue, 19 May 2020 21:09:17 +0300 Subject: [PATCH] NI: remove separation of variable fixation order by constraint kind The commit partially reverts ec4d9d2f1fd5463030190db15ddcf8acfaaadffd ^KT-37914 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 5 ++ .../components/VariableFixationFinder.kt | 24 +++----- .../inference/commonSystem/castToSubtype.kt | 60 +++++++++++++++++++ .../inference/commonSystem/castToSubtype.txt | 47 +++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 5 ++ .../DiagnosticsUsingJavacTestGenerated.java | 5 ++ 6 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.kt create mode 100644 compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.txt 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 531310ae261..96ff152e587 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 @@ -10534,6 +10534,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/commonSystem/boundOnNullableVariable.kt"); } + @TestMetadata("castToSubtype.kt") + public void testCastToSubtype() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.kt"); + } + @TestMetadata("cstFromNullableChildAndNonParameterizedType.kt") public void testCstFromNullableChildAndNonParameterizedType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/commonSystem/cstFromNullableChildAndNonParameterizedType.kt"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt index 177a1221de8..f9dfc4c6987 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt @@ -54,8 +54,7 @@ class VariableFixationFinder( enum class TypeVariableFixationReadiness { FORBIDDEN, WITHOUT_PROPER_ARGUMENT_CONSTRAINT, // proper constraint from arguments -- not from upper bound for type parameters - WITH_COMPLEX_DEPENDENCY_LOWER, // if type variable T has constraint with non fixed type variable inside (non-top-level): Foo <: T - WITH_COMPLEX_DEPENDENCY_UPPER, // T <: Foo + WITH_COMPLEX_DEPENDENCY, // if type variable T has constraint with non fixed type variable inside (non-top-level): T <: Foo WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS, // proper trivial constraint from arguments, Nothing <: T RELATED_TO_ANY_OUTPUT_TYPE, READY_FOR_FIXATION, @@ -69,8 +68,7 @@ class VariableFixationFinder( !notFixedTypeVariables.contains(variable) || dependencyProvider.isVariableRelatedToTopLevelType(variable) -> TypeVariableFixationReadiness.FORBIDDEN !variableHasProperArgumentConstraints(variable) -> TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT - hasDependencyToOtherTypeVariables(variable, ConstraintKind.LOWER) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY_LOWER - hasDependencyToOtherTypeVariables(variable, ConstraintKind.UPPER) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY_UPPER + hasDependencyToOtherTypeVariables(variable) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY variableHasTrivialOrNonProperConstraints(variable) -> TypeVariableFixationReadiness.WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS dependencyProvider.isVariableRelatedToAnyOutputType(variable) -> TypeVariableFixationReadiness.RELATED_TO_ANY_OUTPUT_TYPE isReified(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_REIFIED @@ -114,12 +112,6 @@ class VariableFixationFinder( return when (candidateReadiness) { TypeVariableFixationReadiness.FORBIDDEN -> null TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT -> VariableForFixation(candidate, false) - TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY_UPPER, - TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY_LOWER -> VariableForFixation( - candidate, - hasProperConstraint = variableHasProperArgumentConstraints(candidate), - hasOnlyTrivialProperConstraint = variableHasTrivialOrNonProperConstraints(candidate) - ) TypeVariableFixationReadiness.WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS -> VariableForFixation(candidate, hasProperConstraint = true, hasOnlyTrivialProperConstraint = true) @@ -127,15 +119,13 @@ class VariableFixationFinder( } } - private fun Context.hasDependencyToOtherTypeVariables(typeVariable: TypeConstructorMarker, kind: ConstraintKind): Boolean { + private fun Context.hasDependencyToOtherTypeVariables(typeVariable: TypeConstructorMarker): Boolean { for (constraint in notFixedTypeVariables[typeVariable]?.constraints ?: return false) { - if (constraint.kind != kind || constraint.kind == ConstraintKind.EQUALITY) continue - if (constraint.type.lowerBoundIfFlexible().argumentsCount() != 0 - && constraint.type.contains { - it.typeConstructor() != typeVariable && notFixedTypeVariables.containsKey(it.typeConstructor()) - }) { - return true + val dependencyPresenceCondition = { type: KotlinTypeMarker -> + type.typeConstructor() != typeVariable && notFixedTypeVariables.containsKey(type.typeConstructor()) } + if (constraint.type.lowerBoundIfFlexible().argumentsCount() != 0 && constraint.type.contains(dependencyPresenceCondition)) + return true } return false } diff --git a/compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.kt b/compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.kt new file mode 100644 index 00000000000..b082e76f8b1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.kt @@ -0,0 +1,60 @@ +// FIR_IDENTICAL +// !DIAGNOSTICS: -UNCHECKED_CAST +// Issue: KT-37914 + +interface I + +fun castToSubtype(obj: R) = obj as U + +fun select(vararg x: T) = x[0] + +fun materialize(): S = null as S + +// Case 1 (using intermediate supertype) + +/* + Constraint system: + R: + TypeVariable(U) <: TypeVariable(R) + I <: TypeVariable(R) + U: + I >: TypeVariable(U) + Foo >: TypeVariable(U) + T: + Foo <: TypeVariable(T) + Bar <: TypeVariable(T) + + Fixation order before the fix: R, U, T, P + Fixation order after the fix: R, T, P, U + + `U` has begun to have lower priority so it can be fixed to more specific type (to `Foo` instead of `I`). + */ + +interface Foo : I + +class Bar(val x: Foo) : Foo + +fun main2() { + select( + materialize>(), + Bar( + castToSubtype(materialize()) // NI: "required – Foo, found – I" afther the commit, OI – OK + ) + ) +} + +// Case 2 (using deep supertype) + +interface Foo1 : I +interface Foo2 : Foo1 + +class Bar1

(val x: Foo2

) : Foo2

+ +fun main1() { + select( + materialize>(), + Bar1( + castToSubtype(materialize()) // NI: "required – Foo, found – I" afther the commit, OI – OK + ) + ) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.txt b/compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.txt new file mode 100644 index 00000000000..5ab8a82a1cf --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.txt @@ -0,0 +1,47 @@ +package + +public fun castToSubtype(/*0*/ obj: R): U +public fun main1(): kotlin.Unit +public fun main2(): kotlin.Unit +public fun materialize(): S +public fun select(/*0*/ vararg x: T /*kotlin.Array*/): T + +public final class Bar : Foo { + public constructor Bar(/*0*/ x: Foo) + public final val x: Foo + 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 Bar1 : Foo2

{ + public constructor Bar1(/*0*/ x: Foo2

) + public final val x: Foo2

+ 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 interface Foo : I { + 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 interface Foo1 : I { + 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 interface Foo2 : Foo1 { + 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 interface I { + 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 765ad65246b..1e8b4f0ae85 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10541,6 +10541,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/commonSystem/boundOnNullableVariable.kt"); } + @TestMetadata("castToSubtype.kt") + public void testCastToSubtype() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.kt"); + } + @TestMetadata("cstFromNullableChildAndNonParameterizedType.kt") public void testCstFromNullableChildAndNonParameterizedType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/commonSystem/cstFromNullableChildAndNonParameterizedType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 8ff9a177009..e319c370084 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10536,6 +10536,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/commonSystem/boundOnNullableVariable.kt"); } + @TestMetadata("castToSubtype.kt") + public void testCastToSubtype() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/commonSystem/castToSubtype.kt"); + } + @TestMetadata("cstFromNullableChildAndNonParameterizedType.kt") public void testCstFromNullableChildAndNonParameterizedType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/commonSystem/cstFromNullableChildAndNonParameterizedType.kt");