[NI] Make subtyping algorithm more robust to error types
During subtyping/incorporation we transform types (e.g. changing nullability, form of the type) and, basically, we're doing this to some FIXPOINT. It's important that we use `KotlinType.hashCode()` to compare types, but for error types hashCode is a hashCode of its supertype and, for example, `makeNullableAsSpecified` method recreate type every time. So, we continue to generate new constraints and we'll never stop incorporation algorithm
This commit is contained in:
+5
@@ -154,6 +154,11 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val
|
||||
?: error("Should by type variableConstructor: $typeVariableConstructor. ${c.allTypeVariables.values}")
|
||||
|
||||
var targetType = type
|
||||
if (targetType.isError) {
|
||||
c.addError(ConstrainingTypeIsError(typeVariable, targetType, position))
|
||||
return
|
||||
}
|
||||
|
||||
if (type.contains(this::isCapturedTypeFromSubtyping)) {
|
||||
// TypeVariable <: type -> if TypeVariable <: subType => TypeVariable <: type
|
||||
if (kind == UPPER) {
|
||||
|
||||
+7
-1
@@ -92,4 +92,10 @@ class CapturedTypeFromSubtyping(
|
||||
val position: ConstraintPosition
|
||||
) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
|
||||
|
||||
class NotEnoughInformationForTypeParameter(val typeVariable: NewTypeVariable) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
|
||||
class NotEnoughInformationForTypeParameter(val typeVariable: NewTypeVariable) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
|
||||
|
||||
class ConstrainingTypeIsError(
|
||||
val typeVariable: NewTypeVariable,
|
||||
val constraintType: UnwrappedType,
|
||||
val position: IncorporationConstraintPosition
|
||||
) : ConstraintSystemCallDiagnostic(INAPPLICABLE)
|
||||
@@ -1,6 +1,6 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ tr: Tr): [ERROR : G]
|
||||
public fun test(/*0*/ tr: Tr): Tr
|
||||
|
||||
public interface G</*0*/ T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
|
||||
+5
-6
@@ -1,4 +1,3 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// See KT-6665: unresolved reference (v.bar) should not produce "unreachable code" after it
|
||||
|
||||
fun foo(): Int {
|
||||
@@ -29,14 +28,14 @@ fun foo3(): Int {
|
||||
fun bar(): Int {
|
||||
val v = 1
|
||||
val c = v.<!UNRESOLVED_REFERENCE!>bar<!> ?: 42
|
||||
return <!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>c<!>
|
||||
return c
|
||||
}
|
||||
|
||||
fun bar2(): Int {
|
||||
val v = 1
|
||||
val c = if (true) v.<!UNRESOLVED_REFERENCE!>bar<!> else 3
|
||||
val b = <!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>c<!>
|
||||
return <!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>b<!>
|
||||
val b = c
|
||||
return b
|
||||
}
|
||||
|
||||
fun bar3(): Int {
|
||||
@@ -45,6 +44,6 @@ fun bar3(): Int {
|
||||
true -> v.<!UNRESOLVED_REFERENCE!>bar<!>
|
||||
else -> 3
|
||||
}
|
||||
val b = <!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>c<!>
|
||||
return <!NI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>b<!>
|
||||
val b = c
|
||||
return b
|
||||
}
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// !WITH_NEW_INFERENCE
|
||||
// NI_EXPECTED_FILE
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
var a: Int by A()
|
||||
var a1 by <!OI;DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE!>A()<!>
|
||||
var a1 by <!DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE!>A()<!>
|
||||
|
||||
var b: Int by B()
|
||||
|
||||
|
||||
Vendored
+3
-3
@@ -1,18 +1,18 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun test() {
|
||||
run {<!RETURN_NOT_ALLOWED!>return<!>}
|
||||
run {}
|
||||
<!NI;UNREACHABLE_CODE!>run {}<!>
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
run {<!RETURN_NOT_ALLOWED!>return@test2<!>}
|
||||
run {}
|
||||
<!NI;UNREACHABLE_CODE!>run {}<!>
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
fun test4() {
|
||||
run {<!RETURN_NOT_ALLOWED!>return@test3<!>}
|
||||
run {}
|
||||
<!NI;UNREACHABLE_CODE!>run {}<!>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
|
||||
// FILE: Sam.java
|
||||
|
||||
public interface Sam<K> {
|
||||
Sam.Result<K> compute();
|
||||
|
||||
public static class Result<V> {
|
||||
public static <V> Sam.Result<V> create(V value) {}
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Foo.java
|
||||
|
||||
public class Foo {
|
||||
public static <T> void foo(Sam<T> var1) {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
fun test(e: <!UNRESOLVED_REFERENCE!>ErrorType<!>) {
|
||||
Foo.foo {
|
||||
Sam.Result.create(<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>e<!>)
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package
|
||||
|
||||
public fun test(/*0*/ e: [ERROR : ErrorType]): kotlin.Unit
|
||||
|
||||
public open class Foo {
|
||||
public constructor 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
|
||||
|
||||
// Static members
|
||||
public open fun </*0*/ T : kotlin.Any!> foo(/*0*/ var1: Sam<T!>!): kotlin.Unit
|
||||
}
|
||||
|
||||
public interface Sam</*0*/ K : kotlin.Any!> {
|
||||
public abstract fun compute(): Sam.Result<K!>!
|
||||
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 Result</*0*/ V : kotlin.Any!> {
|
||||
public constructor Result</*0*/ V : kotlin.Any!>()
|
||||
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
|
||||
|
||||
// Static members
|
||||
public open fun </*0*/ V : kotlin.Any!> create(/*0*/ value: V!): Sam.Result<V!>!
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -57,7 +57,7 @@ fun test3(z: Z) {
|
||||
//'in' operation
|
||||
fun test4(collection: Collection<A<*>>) {
|
||||
id(<!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>newA<!>() in collection)
|
||||
id(newA<Int>() in collection)
|
||||
<!NI;UNREACHABLE_CODE!>id(newA<Int>() in collection)<!>
|
||||
}
|
||||
|
||||
//boolean operations
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ fun foo() {
|
||||
fun bar1() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar1<!>()<!>
|
||||
|
||||
fun bar2() = 1 <!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar2<!>()<!>
|
||||
fun bar3() = id(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar3<!>()<!>)
|
||||
fun <!NI;IMPLICIT_NOTHING_RETURN_TYPE!>bar3<!>() = id(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!><!NI;DEBUG_INFO_MISSING_UNRESOLVED!>bar3<!>()<!>)
|
||||
}
|
||||
|
||||
fun <T> id(x: T) = x
|
||||
|
||||
+1
-2
@@ -1,5 +1,4 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -SENSELESS_COMPARISON, -UNUSED_PARAMETER
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
// FILE: J.java
|
||||
|
||||
@@ -62,7 +61,7 @@ fun test() {
|
||||
takeNotNull(J.getNAny() ?: J())
|
||||
|
||||
val x = <!UNRESOLVED_REFERENCE!>unresolved<!> ?: null
|
||||
<!OI;UNREACHABLE_CODE!>val y =<!> <!UNRESOLVED_REFERENCE!>unresolved<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>foo<!> ?: return
|
||||
<!UNREACHABLE_CODE!>val y =<!> <!UNRESOLVED_REFERENCE!>unresolved<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>foo<!> ?: return
|
||||
}
|
||||
|
||||
fun takeNotNull(s: J) {}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ class A {
|
||||
val a get() = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>b<!>
|
||||
val b get() = <!NI;DEBUG_INFO_MISSING_UNRESOLVED, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>a<!>
|
||||
|
||||
val z1 get() = id(<!NI;DEBUG_INFO_MISSING_UNRESOLVED, OI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>z1<!>)
|
||||
val <!NI;IMPLICIT_NOTHING_PROPERTY_TYPE!>z1<!> get() = id(<!NI;DEBUG_INFO_MISSING_UNRESOLVED, OI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>z1<!>)
|
||||
val z2 get() = l(<!NI;DEBUG_INFO_MISSING_UNRESOLVED, OI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>z2<!>)
|
||||
|
||||
val u get() = <!UNRESOLVED_REFERENCE!>field<!>
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ public final class A {
|
||||
public final val b: [ERROR : Error function type]
|
||||
public final val u: [ERROR : Error function type]
|
||||
public final val y: [ERROR : Error function type]
|
||||
public final val z1: [ERROR : Error type for ParseError-argument VALUE_ARGUMENT]
|
||||
public final val z2: kotlin.collections.List<[ERROR : Error type for ParseError-argument VALUE_ARGUMENT]>
|
||||
public final val z1: kotlin.Nothing
|
||||
public final val z2: kotlin.collections.List<kotlin.Nothing>
|
||||
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
|
||||
|
||||
@@ -9565,6 +9565,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/equalityConstraintOnNullableType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("errorUpperBoundConstraint.kt")
|
||||
public void testErrorUpperBoundConstraint() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/errorUpperBoundConstraint.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ignoreConstraintFromImplicitInNothing.kt")
|
||||
public void testIgnoreConstraintFromImplicitInNothing() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/ignoreConstraintFromImplicitInNothing.kt");
|
||||
|
||||
Generated
+5
@@ -9565,6 +9565,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/equalityConstraintOnNullableType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("errorUpperBoundConstraint.kt")
|
||||
public void testErrorUpperBoundConstraint() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/errorUpperBoundConstraint.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ignoreConstraintFromImplicitInNothing.kt")
|
||||
public void testIgnoreConstraintFromImplicitInNothing() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/ignoreConstraintFromImplicitInNothing.kt");
|
||||
|
||||
Reference in New Issue
Block a user