[NI] Relax rules for call completion: require at least one constraint
It's enough to have at least one good constraint. Note that the whole algorithm can be a bit more general: we could check also Out<T>, In<T> and verify that T has good only lower constraint or upper constraint, but there are questions for types like Inv<Out<T>>, where T should have lower and upper constraints #KT-31514 Fixed
This commit is contained in:
+1
-1
@@ -995,7 +995,7 @@ private fun findSafelyReachableReturns(methodNode: MethodNode, sourceFrames: Arr
|
||||
|
||||
if (!insn.isMeaningful || insn.opcode in SAFE_OPCODES || insn.isInvisibleInDebugVarInsn(methodNode) ||
|
||||
isInlineMarker(insn)) {
|
||||
setOf()
|
||||
setOf<Int>()
|
||||
} else null
|
||||
}
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
codegen.parentCodegen.className
|
||||
else
|
||||
state.typeMapper.mapImplementationOwner(descriptor).internalName,
|
||||
if (isLambda) emptyList() else additionalInnerClasses,
|
||||
if (isLambda) emptyList<ClassDescriptor>() else additionalInnerClasses,
|
||||
isLambda
|
||||
)
|
||||
|
||||
|
||||
+10
@@ -10029,6 +10029,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/constraintOnFunctionLiteral.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("earlyCompletionForCalls.kt")
|
||||
public void testEarlyCompletionForCalls() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("equalityConstraintOnNullableType.kt")
|
||||
public void testEqualityConstraintOnNullableType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/equalityConstraintOnNullableType.kt");
|
||||
@@ -10044,6 +10049,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/ignoreConstraintFromImplicitInNothing.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inferTypeFromCapturedStarProjection.kt")
|
||||
public void testInferTypeFromCapturedStarProjection() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt6320.kt")
|
||||
public void testKt6320() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/kt6320.kt");
|
||||
|
||||
+2
-2
@@ -214,7 +214,7 @@ class KotlinCallCompleter(
|
||||
|
||||
val constraints = variableWithConstraints.constraints
|
||||
val onlyProperEqualConstraints =
|
||||
constraints.isNotEmpty() && constraints.all { it.kind.isEqual() && csBuilder.isProperType(it.type) }
|
||||
constraints.isNotEmpty() && constraints.any { it.kind.isEqual() && csBuilder.isProperType(it.type) }
|
||||
|
||||
if (!onlyProperEqualConstraints) return false
|
||||
}
|
||||
@@ -229,7 +229,7 @@ class KotlinCallCompleter(
|
||||
val constructor = typeVariable.constructor
|
||||
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false
|
||||
val constraints = variableWithConstraints.constraints
|
||||
return constraints.isNotEmpty() && constraints.all {
|
||||
return constraints.isNotEmpty() && constraints.any {
|
||||
!it.type.typeConstructor(context).isIntegerLiteralTypeConstructor(context) &&
|
||||
(it.kind.isLower() || it.kind.isEqual()) &&
|
||||
csBuilder.isProperType(it.type)
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ fun test(b: Boolean): String {
|
||||
}
|
||||
|
||||
if (b) {
|
||||
create()
|
||||
create<String>()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ fun <T> bind(r: Option<T>): Option<T> {
|
||||
// Ideally we should infer Option<T> here (see KT-10896)
|
||||
(<!OI;TYPE_INFERENCE_FAILED_ON_SPECIAL_CONSTRUCT!>if<!> (true) <!OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>None()<!> else <!DEBUG_INFO_SMARTCAST!>r<!>) checkType { <!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER, OI;TYPE_MISMATCH!>_<!><Option<T>>() }
|
||||
// Works correctly
|
||||
if (true) None() else r
|
||||
if (true) None() else <!NI;DEBUG_INFO_SMARTCAST!>r<!>
|
||||
}
|
||||
else r
|
||||
}
|
||||
@@ -36,7 +36,7 @@ fun <T> bindWhen(r: Option<T>): Option<T> {
|
||||
return when (r) {
|
||||
is Some -> {
|
||||
// Works correctly
|
||||
if (true) None() else r
|
||||
if (true) None() else <!NI;DEBUG_INFO_SMARTCAST!>r<!>
|
||||
}
|
||||
else -> r
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
interface Parent
|
||||
interface Inv<T>
|
||||
|
||||
object Child : Parent
|
||||
|
||||
fun <K : Parent> wrapper(): Inv<K> = TODO()
|
||||
fun <T : Parent> consume(wrapper: Inv<T>) {}
|
||||
|
||||
fun <S> select(x: S, y: S): S = x
|
||||
|
||||
fun error(f: Inv<out Parent>, w: Inv<Child>) {
|
||||
consume(select(f, wrapper<Child>()))
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T : Parent> consume(/*0*/ wrapper: Inv<T>): kotlin.Unit
|
||||
public fun error(/*0*/ f: Inv<out Parent>, /*1*/ w: Inv<Child>): kotlin.Unit
|
||||
public fun </*0*/ S> select(/*0*/ x: S, /*1*/ y: S): S
|
||||
public fun </*0*/ K : Parent> wrapper(): Inv<K>
|
||||
|
||||
public object Child : Parent {
|
||||
private constructor Child()
|
||||
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 interface 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
|
||||
}
|
||||
|
||||
public interface Parent {
|
||||
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
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
interface Box<out R>
|
||||
fun <R> List<Box<R>>.choose(): Box<R>? = TODO()
|
||||
fun list(): List<Box<*>> = TODO()
|
||||
|
||||
fun f() = list().choose()
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public fun f(): Box<kotlin.Any?>?
|
||||
public fun list(): kotlin.collections.List<Box<*>>
|
||||
public fun </*0*/ R> kotlin.collections.List<Box<R>>.choose(): Box<R>?
|
||||
|
||||
public interface Box</*0*/ out R> {
|
||||
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
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
val test: Int = <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>if (true) {
|
||||
val test: Int = <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>if (true) {
|
||||
when (2) {
|
||||
1 -> 1
|
||||
else -> <!OI;NULL_FOR_NONNULL_TYPE!>null<!>
|
||||
|
||||
@@ -10036,6 +10036,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/constraintOnFunctionLiteral.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("earlyCompletionForCalls.kt")
|
||||
public void testEarlyCompletionForCalls() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("equalityConstraintOnNullableType.kt")
|
||||
public void testEqualityConstraintOnNullableType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/equalityConstraintOnNullableType.kt");
|
||||
@@ -10051,6 +10056,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/ignoreConstraintFromImplicitInNothing.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inferTypeFromCapturedStarProjection.kt")
|
||||
public void testInferTypeFromCapturedStarProjection() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt6320.kt")
|
||||
public void testKt6320() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/kt6320.kt");
|
||||
|
||||
Generated
+10
@@ -10031,6 +10031,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/constraintOnFunctionLiteral.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("earlyCompletionForCalls.kt")
|
||||
public void testEarlyCompletionForCalls() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("equalityConstraintOnNullableType.kt")
|
||||
public void testEqualityConstraintOnNullableType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/equalityConstraintOnNullableType.kt");
|
||||
@@ -10046,6 +10051,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/ignoreConstraintFromImplicitInNothing.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inferTypeFromCapturedStarProjection.kt")
|
||||
public void testInferTypeFromCapturedStarProjection() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt6320.kt")
|
||||
public void testKt6320() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/constraints/kt6320.kt");
|
||||
|
||||
Reference in New Issue
Block a user