Propagate nullness flexibility into the result type from type variables in other constraints during result type finding, to prevent variable fixation to less flexible type

^KT-44540 Fixed
This commit is contained in:
Victor Petukhov
2021-01-26 19:10:48 +03:00
parent ce1f9882df
commit 977ac7cbe7
6 changed files with 129 additions and 1 deletions
@@ -20213,6 +20213,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/platformTypes/override.kt");
}
@Test
@TestMetadata("propagateFlexibilityFromOtherConstraints.kt")
public void testPropagateFlexibilityFromOtherConstraints() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/propagateFlexibilityFromOtherConstraints.kt");
}
@Test
@TestMetadata("rawOverrides.kt")
public void testRawOverrides() throws Exception {
@@ -40,7 +40,9 @@ class ResultTypeResolver(
findResultIfThereIsEqualsConstraint(c, variableWithConstraints)?.let { return it }
val subType = c.findSubType(variableWithConstraints)
val superType = c.findSuperType(variableWithConstraints)
// Super type should be the most flexible, sub type should be the least one
val superType = c.findSuperType(variableWithConstraints).makeFlexibleIfNecessary(c, variableWithConstraints.constraints)
return if (direction == ResolveDirection.TO_SUBTYPE || direction == ResolveDirection.UNKNOWN) {
c.resultType(subType, superType, variableWithConstraints)
} else {
@@ -48,6 +50,30 @@ class ResultTypeResolver(
}
}
/*
* We propagate nullness flexibility into the result type from type variables in other constraints
* to prevent variable fixation into less flexible type.
* Constraints:
* UPPER(TypeVariable(T)..TypeVariable(T)?)
* UPPER(Foo?)
* Result type = makeFlexibleIfNecessary(Foo?) = Foo!
*
* We don't propagate nullness flexibility in depth as it's non-determined for now (see KT-35534):
* CST(Bar<Foo>, Bar<Foo!>) = Bar<Foo!>
* CST(Bar<Foo!>, Bar<Foo>) = Bar<Foo>
* But: CST(Foo, Foo!) = CST(Foo!, Foo) = Foo!
*/
private fun KotlinTypeMarker?.makeFlexibleIfNecessary(c: Context, constraints: List<Constraint>) = with(c) {
when (val type = this@makeFlexibleIfNecessary) {
is SimpleTypeMarker -> {
if (constraints.any { it.type.typeConstructor().isTypeVariable() && it.type.hasFlexibleNullability() }) {
createFlexibleType(type.makeSimpleTypeDefinitelyNotNullOrNotNull(), type.withNullability(true))
} else type
}
else -> type
}
}
private fun Context.resultType(
firstCandidate: KotlinTypeMarker?,
secondCandidate: KotlinTypeMarker?,
@@ -0,0 +1,32 @@
// FULL_JDK
// FILE: test.kt
@file:Suppress("UNUSED_PARAMETER")
import java.util.Comparator
abstract class DataView {
abstract val presentationName: String
}
fun <A> comboBox(
model: SortedComboBoxModel<A>,
graphProperty: GraphProperty<A>,
) {}
class GraphProperty<B>
fun test() {
val presentationName: (DataView) -> String = { it.presentationName }
val parentComboBoxModel/*: SortedComboBoxModel<DataView>*/ = SortedComboBoxModel(Comparator.comparing(presentationName))
comboBox(parentComboBoxModel, GraphProperty<DataView>())
}
// FILE: SortedComboBoxModel.java
import java.util.Comparator;
public class SortedComboBoxModel<C> {
public SortedComboBoxModel(Comparator<? super C> comparator) {
}
}
@@ -0,0 +1,32 @@
// FULL_JDK
// FILE: test.kt
@file:Suppress("UNUSED_PARAMETER")
import java.util.Comparator
abstract class DataView {
abstract val presentationName: String
}
fun <A> comboBox(
model: SortedComboBoxModel<A>,
graphProperty: GraphProperty<A>,
) {}
class GraphProperty<B>
fun test() {
val presentationName: (DataView) -> String = { it.presentationName }
val parentComboBoxModel/*: SortedComboBoxModel<DataView>*/ = SortedComboBoxModel(Comparator.<!INTERFACE_STATIC_METHOD_CALL_FROM_JAVA6_TARGET_ERROR!>comparing<!>(presentationName))
comboBox(parentComboBoxModel, GraphProperty<DataView>())
}
// FILE: SortedComboBoxModel.java
import java.util.Comparator;
public class SortedComboBoxModel<C> {
public SortedComboBoxModel(Comparator<? super C> comparator) {
}
}
@@ -0,0 +1,26 @@
package
public fun </*0*/ A> comboBox(/*0*/ model: SortedComboBoxModel<A>, /*1*/ graphProperty: GraphProperty<A>): kotlin.Unit
public fun test(): kotlin.Unit
public abstract class DataView {
public constructor DataView()
public abstract val presentationName: kotlin.String
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 GraphProperty</*0*/ B> {
public constructor GraphProperty</*0*/ B>()
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 open class SortedComboBoxModel</*0*/ C : kotlin.Any!> {
public constructor SortedComboBoxModel</*0*/ C : kotlin.Any!>(/*0*/ comparator: java.util.Comparator<in C!>!)
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
}
@@ -20219,6 +20219,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/platformTypes/override.kt");
}
@Test
@TestMetadata("propagateFlexibilityFromOtherConstraints.kt")
public void testPropagateFlexibilityFromOtherConstraints() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/propagateFlexibilityFromOtherConstraints.kt");
}
@Test
@TestMetadata("rawOverrides.kt")
public void testRawOverrides() throws Exception {