NI: Add constraints which contain constraining type without projection

^KT-32243 Fixed
^KT-35172 Fixed
This commit is contained in:
Victor Petukhov
2019-11-30 20:24:46 +03:00
committed by victor.petukhov
parent 65cc0fa463
commit 775eb67219
8 changed files with 61 additions and 14 deletions
@@ -10434,6 +10434,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
runTest("compiler/testData/diagnostics/tests/inference/constraints/recursiveJavaTypeWithStarProjection.kt");
}
@TestMetadata("remainConstraintContainingTypeWithoutProjection.kt")
public void testRemainConstraintContainingTypeWithoutProjection() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/constraints/remainConstraintContainingTypeWithoutProjection.kt");
}
@TestMetadata("returnLambdaFromLambda.kt")
public void testReturnLambdaFromLambda() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/constraints/returnLambdaFromLambda.kt");
@@ -157,7 +157,6 @@ class ConstraintIncorporator(
isSubtype: Boolean
) {
if (targetVariable in getNestedTypeVariables(newConstraint)) return
if (!containsConstrainingTypeWithoutProjection(newConstraint, otherConstraint)) return
if (trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(
baseConstraint, otherConstraint, newConstraint, isSubtype
)
@@ -173,15 +172,6 @@ class ConstraintIncorporator(
addNewIncorporatedConstraint(targetVariable, newConstraint, ConstraintContext(kind, derivedFrom))
}
fun Context.containsConstrainingTypeWithoutProjection(
newConstraint: KotlinTypeMarker,
otherConstraint: Constraint
): Boolean {
return getNestedArguments(newConstraint).any {
it.getType().typeConstructor() == otherConstraint.type.typeConstructor() && it.getVariance() == TypeVariance.INV
}
}
fun Context.getNestedTypeVariables(type: KotlinTypeMarker): List<TypeVariableMarker> =
getNestedArguments(type).mapNotNull { getTypeVariable(it.getType().typeConstructor()) }
@@ -1,5 +1,5 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNCHECKED_CAST
interface ISample
@@ -9,15 +9,16 @@ fun <K> elvisSimple(x: K?, y: K): K = y
fun <K> elvisExact(x: K?, y: K): @kotlin.internal.Exact K = y
fun <T : Number> materialize(): T? = null
fun <T> Any?.materialize(): T = null as T
fun test(nullableSample: ISample, any: Any) {
<!DEBUG_INFO_EXPRESSION_TYPE("ISample")!><!TYPE_MISMATCH!>elvisSimple<!>(
<!DEBUG_INFO_EXPRESSION_TYPE("ISample?")!>elvisSimple(
nullableSample,
<!DEBUG_INFO_EXPRESSION_TYPE("{ISample & Number}?")!>materialize()<!>
)<!>
elvisSimple(
<!DEBUG_INFO_EXPRESSION_TYPE("ISample")!><!TYPE_MISMATCH!>elvisSimple<!>(nullableSample, materialize())<!>,
<!DEBUG_INFO_EXPRESSION_TYPE("ISample?")!>elvisSimple(nullableSample, materialize())<!>,
any
)
@@ -25,4 +26,14 @@ fun test(nullableSample: ISample, any: Any) {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>elvisExact(nullableSample, materialize())<!>,
any
)
val a: String? = null
val x1: String? = run {
a ?: <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String?")!>a?.materialize()<!>
}
val x2 = run {
a ?: <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String?")!>a?.materialize()<!>
}
}
@@ -4,6 +4,7 @@ package
public fun </*0*/ K> elvisSimple(/*0*/ x: K?, /*1*/ y: K): K
public fun </*0*/ T : kotlin.Number> materialize(): T?
public fun test(/*0*/ nullableSample: ISample, /*1*/ any: kotlin.Any): kotlin.Unit
public fun </*0*/ T> kotlin.Any?.materialize(): T
public interface ISample {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -20,7 +20,7 @@ public class Foo {
// FILE: test.kt
fun test(e: <!UNRESOLVED_REFERENCE!>ErrorType<!>) {
Foo.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!> {
Foo.foo {
Sam.Result.create(<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>e<!>)
}
}
@@ -0,0 +1,30 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS
// SKIP_TXT
// FILE: Test.java
import java.util.Collection;
public class Test {
static <T> Inv<Collection<? extends T>> bar() {
return null;
}
}
// FILE: main.kt
class Inv<E>
fun <R> foo(x: R, y: Inv<R>) {}
fun main() {
val values: List<Int> = null as List<Int>
/*
* Before the fix, there was type mismatch during checking `Test.bar()` to pass to `foo`:
* Required: Inv<List<Int>>
* Found: Inv<(MutableCollection<out Int!>..Collection<Int!>?)>
* Constraint `(MutableCollection<out T!>..Collection<T!>?)` from 'Found' (for TypeVariable(R)) has been removed
* during fixation TypeVariable(T) due to the constraint for R contained TypeVariable(T).
* The problem was that TypeVariable(T) wan't substituted due to `containsConstrainingTypeWithoutProjection` optimization.
*/
foo(values, Test.bar())
}
@@ -10441,6 +10441,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
runTest("compiler/testData/diagnostics/tests/inference/constraints/recursiveJavaTypeWithStarProjection.kt");
}
@TestMetadata("remainConstraintContainingTypeWithoutProjection.kt")
public void testRemainConstraintContainingTypeWithoutProjection() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/constraints/remainConstraintContainingTypeWithoutProjection.kt");
}
@TestMetadata("returnLambdaFromLambda.kt")
public void testReturnLambdaFromLambda() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/constraints/returnLambdaFromLambda.kt");
@@ -10436,6 +10436,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/inference/constraints/recursiveJavaTypeWithStarProjection.kt");
}
@TestMetadata("remainConstraintContainingTypeWithoutProjection.kt")
public void testRemainConstraintContainingTypeWithoutProjection() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/constraints/remainConstraintContainingTypeWithoutProjection.kt");
}
@TestMetadata("returnLambdaFromLambda.kt")
public void testReturnLambdaFromLambda() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/constraints/returnLambdaFromLambda.kt");