[NI] Complete call if return type contains only "good" type variables

This commit is contained in:
Mikhail Zarechenskiy
2019-05-08 03:57:27 +03:00
parent 61bd3a8d03
commit 516fccbe7b
9 changed files with 100 additions and 34 deletions
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
import org.jetbrains.kotlin.types.model.isIntegerLiteralTypeConstructor
import org.jetbrains.kotlin.types.model.typeConstructor
import org.jetbrains.kotlin.types.typeUtil.contains
class KotlinCallCompleter(
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
@@ -197,10 +198,27 @@ class KotlinCallCompleter(
else
ConstraintSystemCompletionMode.PARTIAL
// Return type has proper equal constraints => there is no need in the outer call
containsTypeVariablesWithProperEqualConstraints(currentReturnType) -> ConstraintSystemCompletionMode.FULL
else -> ConstraintSystemCompletionMode.PARTIAL
}
}
private fun KotlinResolutionCandidate.containsTypeVariablesWithProperEqualConstraints(type: UnwrappedType): Boolean {
for ((variableConstructor, variableWithConstraints) in csBuilder.currentStorage().notFixedTypeVariables) {
if (!type.contains { it.constructor == variableConstructor }) continue
val constraints = variableWithConstraints.constraints
val onlyProperEqualConstraints =
constraints.isNotEmpty() && constraints.all { it.kind.isEqual() && csBuilder.isProperType(it.type) }
if (!onlyProperEqualConstraints) return false
}
return true
}
private fun KotlinResolutionCandidate.hasProperNonTrivialLowerConstraints(typeVariable: UnwrappedType): Boolean {
assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" }
@@ -25,7 +25,7 @@ fun <T> bind2(r: Option<T>): Option<T> {
}
fun <T, R> bind3(r: Option<T>): Option<T> {
return <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>if (r is Some) {
return <!NI;TYPE_MISMATCH!>if (r is Some) {
// Diagnoses an error correctly
if (true) <!OI;TYPE_MISMATCH!>None<R>()<!> else r
}
@@ -18,9 +18,9 @@ class A<F> {
fun <Z : F, W : Z?> bar() {
// F
fooInv1<Inv<F>>(Inv<F>())
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<F><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<F>()<!>)
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<F><!>>(Inv<F>())
fooInv1(Inv<F>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<F>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH!>Inv<F>()<!>)
fooIn1<In<F?>>(In<F?>())
fooIn2<In<F?>>(In<F?>())
@@ -33,15 +33,15 @@ class A<F> {
fooOut2(Out<F>())
// Z
fooInv1<<!UPPER_BOUND_VIOLATED!>Inv<Z><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<Z>()<!>)
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<Z><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<Z>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<Z>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<Z>()<!>)
fooInv1<<!UPPER_BOUND_VIOLATED!>Inv<Z><!>>(Inv<Z>())
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<Z><!>>(Inv<Z>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv1<!>(<!NI;TYPE_MISMATCH!>Inv<Z>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH!>Inv<Z>()<!>)
fooIn1<<!UPPER_BOUND_VIOLATED!>In<Z?><!>>(<!NI;TYPE_MISMATCH!>In<Z?>()<!>)
fooIn2<<!UPPER_BOUND_VIOLATED!>In<Z?><!>>(<!NI;TYPE_MISMATCH!>In<Z?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<Z?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<Z?>()<!>)
fooIn1<<!UPPER_BOUND_VIOLATED!>In<Z?><!>>(In<Z?>())
fooIn2<<!UPPER_BOUND_VIOLATED!>In<Z?><!>>(In<Z?>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn1<!>(<!NI;TYPE_MISMATCH!>In<Z?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn2<!>(<!NI;TYPE_MISMATCH!>In<Z?>()<!>)
fooOut1<Out<Z>>(Out<Z>())
fooOut2<Out<Z>>(Out<Z>())
@@ -49,19 +49,19 @@ class A<F> {
fooOut2(Out<Z>())
// W
fooInv1<<!UPPER_BOUND_VIOLATED!>Inv<W><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<W>()<!>)
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<W><!>>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<W>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<W>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<W>()<!>)
fooInv1<<!UPPER_BOUND_VIOLATED!>Inv<W><!>>(Inv<W>())
fooInv2<<!UPPER_BOUND_VIOLATED!>Inv<W><!>>(Inv<W>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv1<!>(<!NI;TYPE_MISMATCH!>Inv<W>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooInv2<!>(<!NI;TYPE_MISMATCH!>Inv<W>()<!>)
fooIn1<<!UPPER_BOUND_VIOLATED!>In<W?><!>>(<!NI;TYPE_MISMATCH!>In<W?>()<!>)
fooIn2<<!UPPER_BOUND_VIOLATED!>In<W?><!>>(<!NI;TYPE_MISMATCH!>In<W?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<W?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<W?>()<!>)
fooIn1<<!UPPER_BOUND_VIOLATED!>In<W?><!>>(In<W?>())
fooIn2<<!UPPER_BOUND_VIOLATED!>In<W?><!>>(In<W?>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn1<!>(<!NI;TYPE_MISMATCH!>In<W?>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooIn2<!>(<!NI;TYPE_MISMATCH!>In<W?>()<!>)
fooOut1<<!UPPER_BOUND_VIOLATED!>Out<W><!>>(<!NI;TYPE_MISMATCH!>Out<W>()<!>)
fooOut1<<!UPPER_BOUND_VIOLATED!>Out<W><!>>(Out<W>())
fooOut2<Out<W>>(Out<W>())
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooOut1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Out<W>()<!>)
<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>fooOut1<!>(<!NI;TYPE_MISMATCH!>Out<W>()<!>)
fooOut2(Out<W>())
}
}
@@ -13,14 +13,14 @@ class A<T> {
}
fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo1<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Out<CharSequence>()<!>)
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo1<!>(<!NI;TYPE_MISMATCH!>Out<CharSequence>()<!>)
a.foo1<<!UPPER_BOUND_VIOLATED!>Out<CharSequence><!>>(<!NI;TYPE_MISMATCH!><!NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER, NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>Out<!>()<!>)
a.foo1(<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>Out<!>())
a.foo1(Out<Nothing>())
a.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>foo2<!>(<!NI;TYPE_MISMATCH!><!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Inv<!>()<!>)
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
a.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
a.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(<!NI;TYPE_MISMATCH!>Inv()<!>)
a.foo3(In())
@@ -32,11 +32,11 @@ fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
b.foo1<Out<CharSequence>>(Out())
b.<!OI;TYPE_INFERENCE_INCORPORATION_ERROR!>foo2<!>(<!NI;TYPE_MISMATCH!><!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Inv<!>()<!>)
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(<!NI;TYPE_MISMATCH!>Inv<CharSequence>()<!>)
b.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(<!NI;TYPE_MISMATCH!>Inv()<!>)
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo3<!>(<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>In<CharSequence>()<!>)
b.<!OI;TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo3<!>(<!NI;TYPE_MISMATCH!>In<CharSequence>()<!>)
b.foo3<<!UPPER_BOUND_VIOLATED!>In<CharSequence><!>>(<!NI;TYPE_MISMATCH!>In()<!>)
b.foo3(In<Any?>())
@@ -1,10 +1,25 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> foo(): @kotlin.internal.NoInfer T = TODO()
private object TopLevelTypeVariable {
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> foo(): @kotlin.internal.NoInfer T = TODO()
fun <K> bar(k: K) {}
fun <K> bar(k: K) {}
fun test() {
bar(foo<Int>())
fun test() {
bar(foo<Int>())
}
}
private object NestedTypeVariable {
class Inv<T>
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <T> foo(): Inv<@kotlin.internal.NoInfer T> = TODO()
fun <K> bar(p: Inv<K>) {}
fun test() {
bar(foo<String>())
}
}
@@ -1,5 +1,28 @@
package
public fun </*0*/ K> bar(/*0*/ k: K): kotlin.Unit
@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun </*0*/ T> foo(): T
public fun test(): kotlin.Unit
private object NestedTypeVariable {
private constructor NestedTypeVariable()
public final fun </*0*/ K> bar(/*0*/ p: NestedTypeVariable.Inv<K>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public final fun </*0*/ T> foo(): NestedTypeVariable.Inv<T>
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun test(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final class Inv</*0*/ T> {
public constructor Inv</*0*/ 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
}
}
private object TopLevelTypeVariable {
private constructor TopLevelTypeVariable()
public final fun </*0*/ K> bar(/*0*/ k: K): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public final fun </*0*/ T> foo(): T
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun test(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -2748,6 +2748,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/onlyInputTypesAnnotationWithPlatformTypes.kt");
}
@TestMetadata("propagationOfNoInferAnnotation.kt")
public void testPropagationOfNoInferAnnotation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/propagationOfNoInferAnnotation.kt");
}
@TestMetadata("resolveWithOnlyInputTypesAnnotation.kt")
public void testResolveWithOnlyInputTypesAnnotation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/resolveWithOnlyInputTypesAnnotation.kt");
@@ -2748,6 +2748,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/onlyInputTypesAnnotationWithPlatformTypes.kt");
}
@TestMetadata("propagationOfNoInferAnnotation.kt")
public void testPropagationOfNoInferAnnotation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/propagationOfNoInferAnnotation.kt");
}
@TestMetadata("resolveWithOnlyInputTypesAnnotation.kt")
public void testResolveWithOnlyInputTypesAnnotation() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/resolveWithOnlyInputTypesAnnotation.kt");
@@ -33,7 +33,7 @@ fun JKNonCodeElementsListOwner.takeNonCodeElementsFrom(other: JKNonCodeElementsL
fun JKTreeElement.commentsFromInside(): List<JKCommentElement> {
val comments = mutableListOf<JKCommentElement>()
fun recurse(element: JKTreeElement): JKTreeElement {
comments += (element.leftNonCodeElements + element.rightNonCodeElements).filterIsInstance()
comments += (element.leftNonCodeElements + element.rightNonCodeElements).filterIsInstance<JKCommentElement>()
return applyRecursive(element, ::recurse)
}
applyRecursive(this, ::recurse)