From f702417655a12aab831bc5a3f926b0ed86032648 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 28 May 2019 19:53:22 +0300 Subject: [PATCH] [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, In and verify that T has good only lower constraint or upper constraint, but there are questions for types like Inv>, where T should have lower and upper constraints #KT-31514 Fixed --- .../CoroutineTransformerMethodVisitor.kt | 2 +- .../codegen/inline/SourceCompilerForInline.kt | 2 +- .../fir/FirDiagnosticsSmokeTestGenerated.java | 10 ++++++++ .../calls/components/KotlinCallCompleter.kt | 4 +-- ...ExpressionOfLambdaWithNothingConstraint.kt | 2 +- .../controlStructures/ifElseIntersection.kt | 4 +-- .../constraints/earlyCompletionForCalls.kt | 15 +++++++++++ .../constraints/earlyCompletionForCalls.txt | 25 +++++++++++++++++++ .../inferTypeFromCapturedStarProjection.kt | 5 ++++ .../inferTypeFromCapturedStarProjection.txt | 11 ++++++++ .../testData/diagnostics/tests/when/kt9929.kt | 2 +- .../checkers/DiagnosticsTestGenerated.java | 10 ++++++++ .../DiagnosticsUsingJavacTestGenerated.java | 10 ++++++++ 13 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.kt create mode 100644 compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.txt create mode 100644 compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.kt create mode 100644 compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt index 4229364e790..2b2292d8063 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt @@ -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() } else null } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt index 37084655710..5f3baeb7d13 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/SourceCompilerForInline.kt @@ -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() else additionalInnerClasses, isLambda ) diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index 00f8899cdf3..45baa9c7b9b 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -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"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index 9fe2e4c0114..5bd1871cb98 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -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) diff --git a/compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt b/compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt index dba54837117..9f15e1dba03 100644 --- a/compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt +++ b/compiler/testData/codegen/box/inference/lastExpressionOfLambdaWithNothingConstraint.kt @@ -18,7 +18,7 @@ fun test(b: Boolean): String { } if (b) { - create() + create() } else { null } diff --git a/compiler/testData/diagnostics/tests/controlStructures/ifElseIntersection.kt b/compiler/testData/diagnostics/tests/controlStructures/ifElseIntersection.kt index 5657897fb70..dd65c299a0c 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/ifElseIntersection.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/ifElseIntersection.kt @@ -11,7 +11,7 @@ fun bind(r: Option): Option { // Ideally we should infer Option here (see KT-10896) (if (true) None() else r) checkType { _>() } // Works correctly - if (true) None() else r + if (true) None() else r } else r } @@ -36,7 +36,7 @@ fun bindWhen(r: Option): Option { return when (r) { is Some -> { // Works correctly - if (true) None() else r + if (true) None() else r } else -> r } diff --git a/compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.kt b/compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.kt new file mode 100644 index 00000000000..5213966e75c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.kt @@ -0,0 +1,15 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Parent +interface Inv + +object Child : Parent + +fun wrapper(): Inv = TODO() +fun consume(wrapper: Inv) {} + +fun select(x: S, y: S): S = x + +fun error(f: Inv, w: Inv) { + consume(select(f, wrapper())) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.txt b/compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.txt new file mode 100644 index 00000000000..1744227b473 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/constraints/earlyCompletionForCalls.txt @@ -0,0 +1,25 @@ +package + +public fun consume(/*0*/ wrapper: Inv): kotlin.Unit +public fun error(/*0*/ f: Inv, /*1*/ w: Inv): kotlin.Unit +public fun select(/*0*/ x: S, /*1*/ y: S): S +public fun wrapper(): Inv + +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 { + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.kt b/compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.kt new file mode 100644 index 00000000000..5daaf882c68 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.kt @@ -0,0 +1,5 @@ +interface Box +fun List>.choose(): Box? = TODO() +fun list(): List> = TODO() + +fun f() = list().choose() diff --git a/compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.txt b/compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.txt new file mode 100644 index 00000000000..6a05ae58e98 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/constraints/inferTypeFromCapturedStarProjection.txt @@ -0,0 +1,11 @@ +package + +public fun f(): Box? +public fun list(): kotlin.collections.List> +public fun kotlin.collections.List>.choose(): Box? + +public interface Box { + 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 +} diff --git a/compiler/testData/diagnostics/tests/when/kt9929.kt b/compiler/testData/diagnostics/tests/when/kt9929.kt index c94ac61f194..f1dc2682288 100644 --- a/compiler/testData/diagnostics/tests/when/kt9929.kt +++ b/compiler/testData/diagnostics/tests/when/kt9929.kt @@ -1,5 +1,5 @@ // !WITH_NEW_INFERENCE -val test: Int = if (true) { +val test: Int = if (true) { when (2) { 1 -> 1 else -> null diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index e57c8a3f796..22b88e98256 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 4716bafbf3d..13616606c39 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -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");