NI: remove separation of variable fixation order by constraint kind
The commit partially reverts ec4d9d2f1f
^KT-37914 Fixed
This commit is contained in:
+5
@@ -10534,6 +10534,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/commonSystem/boundOnNullableVariable.kt");
|
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")
|
@TestMetadata("cstFromNullableChildAndNonParameterizedType.kt")
|
||||||
public void testCstFromNullableChildAndNonParameterizedType() throws Exception {
|
public void testCstFromNullableChildAndNonParameterizedType() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/commonSystem/cstFromNullableChildAndNonParameterizedType.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/commonSystem/cstFromNullableChildAndNonParameterizedType.kt");
|
||||||
|
|||||||
+7
-17
@@ -54,8 +54,7 @@ class VariableFixationFinder(
|
|||||||
enum class TypeVariableFixationReadiness {
|
enum class TypeVariableFixationReadiness {
|
||||||
FORBIDDEN,
|
FORBIDDEN,
|
||||||
WITHOUT_PROPER_ARGUMENT_CONSTRAINT, // proper constraint from arguments -- not from upper bound for type parameters
|
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<S> <: T
|
WITH_COMPLEX_DEPENDENCY, // if type variable T has constraint with non fixed type variable inside (non-top-level): T <: Foo<S>
|
||||||
WITH_COMPLEX_DEPENDENCY_UPPER, // T <: Foo<S>
|
|
||||||
WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS, // proper trivial constraint from arguments, Nothing <: T
|
WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS, // proper trivial constraint from arguments, Nothing <: T
|
||||||
RELATED_TO_ANY_OUTPUT_TYPE,
|
RELATED_TO_ANY_OUTPUT_TYPE,
|
||||||
READY_FOR_FIXATION,
|
READY_FOR_FIXATION,
|
||||||
@@ -69,8 +68,7 @@ class VariableFixationFinder(
|
|||||||
!notFixedTypeVariables.contains(variable) ||
|
!notFixedTypeVariables.contains(variable) ||
|
||||||
dependencyProvider.isVariableRelatedToTopLevelType(variable) -> TypeVariableFixationReadiness.FORBIDDEN
|
dependencyProvider.isVariableRelatedToTopLevelType(variable) -> TypeVariableFixationReadiness.FORBIDDEN
|
||||||
!variableHasProperArgumentConstraints(variable) -> TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT
|
!variableHasProperArgumentConstraints(variable) -> TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT
|
||||||
hasDependencyToOtherTypeVariables(variable, ConstraintKind.LOWER) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY_LOWER
|
hasDependencyToOtherTypeVariables(variable) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY
|
||||||
hasDependencyToOtherTypeVariables(variable, ConstraintKind.UPPER) -> TypeVariableFixationReadiness.WITH_COMPLEX_DEPENDENCY_UPPER
|
|
||||||
variableHasTrivialOrNonProperConstraints(variable) -> TypeVariableFixationReadiness.WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS
|
variableHasTrivialOrNonProperConstraints(variable) -> TypeVariableFixationReadiness.WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS
|
||||||
dependencyProvider.isVariableRelatedToAnyOutputType(variable) -> TypeVariableFixationReadiness.RELATED_TO_ANY_OUTPUT_TYPE
|
dependencyProvider.isVariableRelatedToAnyOutputType(variable) -> TypeVariableFixationReadiness.RELATED_TO_ANY_OUTPUT_TYPE
|
||||||
isReified(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_REIFIED
|
isReified(variable) -> TypeVariableFixationReadiness.READY_FOR_FIXATION_REIFIED
|
||||||
@@ -114,12 +112,6 @@ class VariableFixationFinder(
|
|||||||
return when (candidateReadiness) {
|
return when (candidateReadiness) {
|
||||||
TypeVariableFixationReadiness.FORBIDDEN -> null
|
TypeVariableFixationReadiness.FORBIDDEN -> null
|
||||||
TypeVariableFixationReadiness.WITHOUT_PROPER_ARGUMENT_CONSTRAINT -> VariableForFixation(candidate, false)
|
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 ->
|
TypeVariableFixationReadiness.WITH_TRIVIAL_OR_NON_PROPER_CONSTRAINTS ->
|
||||||
VariableForFixation(candidate, hasProperConstraint = true, hasOnlyTrivialProperConstraint = true)
|
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) {
|
for (constraint in notFixedTypeVariables[typeVariable]?.constraints ?: return false) {
|
||||||
if (constraint.kind != kind || constraint.kind == ConstraintKind.EQUALITY) continue
|
val dependencyPresenceCondition = { type: KotlinTypeMarker ->
|
||||||
if (constraint.type.lowerBoundIfFlexible().argumentsCount() != 0
|
type.typeConstructor() != typeVariable && notFixedTypeVariables.containsKey(type.typeConstructor())
|
||||||
&& constraint.type.contains {
|
|
||||||
it.typeConstructor() != typeVariable && notFixedTypeVariables.containsKey(it.typeConstructor())
|
|
||||||
}) {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
if (constraint.type.lowerBoundIfFlexible().argumentsCount() != 0 && constraint.type.contains(dependencyPresenceCondition))
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// !DIAGNOSTICS: -UNCHECKED_CAST
|
||||||
|
// Issue: KT-37914
|
||||||
|
|
||||||
|
interface I
|
||||||
|
|
||||||
|
fun <R, U : R> castToSubtype(obj: R) = obj as U
|
||||||
|
|
||||||
|
fun <T> select(vararg x: T) = x[0]
|
||||||
|
|
||||||
|
fun <S> 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(P)> >: TypeVariable(U)
|
||||||
|
T:
|
||||||
|
Foo<Any> <: TypeVariable(T)
|
||||||
|
Bar<TypeVariable(P)> <: 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<Any>` instead of `I`).
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface Foo<T> : I
|
||||||
|
|
||||||
|
class Bar<T>(val x: Foo<T>) : Foo<T>
|
||||||
|
|
||||||
|
fun main2() {
|
||||||
|
select(
|
||||||
|
materialize<Foo<Any>>(),
|
||||||
|
Bar(
|
||||||
|
castToSubtype(materialize<I>()) // NI: "required – Foo<Any>, found – I" afther the commit, OI – OK
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case 2 (using deep supertype)
|
||||||
|
|
||||||
|
interface Foo1<Y> : I
|
||||||
|
interface Foo2<Y> : Foo1<Y>
|
||||||
|
|
||||||
|
class Bar1<P>(val x: Foo2<P>) : Foo2<P>
|
||||||
|
|
||||||
|
fun main1() {
|
||||||
|
select(
|
||||||
|
materialize<Foo2<Any>>(),
|
||||||
|
Bar1(
|
||||||
|
castToSubtype(materialize<I>()) // NI: "required – Foo<Any>, found – I" afther the commit, OI – OK
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ R, /*1*/ U : R> castToSubtype(/*0*/ obj: R): U
|
||||||
|
public fun main1(): kotlin.Unit
|
||||||
|
public fun main2(): kotlin.Unit
|
||||||
|
public fun </*0*/ S> materialize(): S
|
||||||
|
public fun </*0*/ T> select(/*0*/ vararg x: T /*kotlin.Array<out T>*/): T
|
||||||
|
|
||||||
|
public final class Bar</*0*/ T> : Foo<T> {
|
||||||
|
public constructor Bar</*0*/ T>(/*0*/ x: Foo<T>)
|
||||||
|
public final val x: Foo<T>
|
||||||
|
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</*0*/ P> : Foo2<P> {
|
||||||
|
public constructor Bar1</*0*/ P>(/*0*/ x: Foo2<P>)
|
||||||
|
public final val x: Foo2<P>
|
||||||
|
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</*0*/ T> : 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</*0*/ Y> : 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</*0*/ Y> : Foo1<Y> {
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -10541,6 +10541,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/commonSystem/boundOnNullableVariable.kt");
|
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")
|
@TestMetadata("cstFromNullableChildAndNonParameterizedType.kt")
|
||||||
public void testCstFromNullableChildAndNonParameterizedType() throws Exception {
|
public void testCstFromNullableChildAndNonParameterizedType() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/commonSystem/cstFromNullableChildAndNonParameterizedType.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/commonSystem/cstFromNullableChildAndNonParameterizedType.kt");
|
||||||
|
|||||||
Generated
+5
@@ -10536,6 +10536,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/commonSystem/boundOnNullableVariable.kt");
|
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")
|
@TestMetadata("cstFromNullableChildAndNonParameterizedType.kt")
|
||||||
public void testCstFromNullableChildAndNonParameterizedType() throws Exception {
|
public void testCstFromNullableChildAndNonParameterizedType() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/commonSystem/cstFromNullableChildAndNonParameterizedType.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/commonSystem/cstFromNullableChildAndNonParameterizedType.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user