[NI] Complete call if return type contains only "good" type variables
This commit is contained in:
+18
@@ -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" }
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
+20
-20
@@ -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>())
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -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?>())
|
||||
|
||||
+20
-5
@@ -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>())
|
||||
}
|
||||
}
|
||||
+26
-3
@@ -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
|
||||
}
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
Generated
+5
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user