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:
+6
@@ -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 {
|
||||
|
||||
+27
-1
@@ -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?,
|
||||
|
||||
Vendored
+32
@@ -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) {
|
||||
}
|
||||
}
|
||||
Vendored
+32
@@ -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) {
|
||||
}
|
||||
}
|
||||
Vendored
+26
@@ -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
|
||||
}
|
||||
Generated
+6
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user