diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt index 2e1fd389be1..d0c5ba94164 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt @@ -27,7 +27,8 @@ import org.jetbrains.kotlin.types.checker.intersectTypes import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType class ResultTypeResolver( - val typeApproximator: TypeApproximator + val typeApproximator: TypeApproximator, + val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle ) { interface Context { fun isProperType(type: UnwrappedType): Boolean @@ -77,6 +78,9 @@ class ResultTypeResolver( if (!isProperType(constraint.type)) continue if (!checkConstraint(constraint.type, constraint.kind, resultType)) return false } + + if (!trivialConstraintTypeInferenceOracle.isSuitableResultedType(resultType)) return false + return true } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt index 417447504fb..14b02efcfed 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt @@ -19,6 +19,13 @@ class TrivialConstraintTypeInferenceOracle { // TODO: probably we also can take into account `T <: Any(?)` constraints return constraint.kind == ConstraintKind.LOWER && constraint.type.isNothingOrNullableNothing() } + + // This function controls the choice between sub and super result type + // Even that Nothing(?) is the most specific type for subtype, it doesn't bring valuable information to the user, + // therefore it is discriminated in favor of supertype + fun isSuitableResultedType(resultType: UnwrappedType): Boolean { + return !resultType.isNothingOrNullableNothing() + } } private fun UnwrappedType.isNothingOrNullableNothing(): Boolean = diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.kt b/compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.kt new file mode 100644 index 00000000000..52abf154c34 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.kt @@ -0,0 +1,12 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE + +fun select2(x: K, y: K): K = TODO() +fun select3(x: K, y: K, z: K): K = TODO() + +fun test2(f: ((String) -> Int)?) { + val a0: ((Int) -> Int)? = select2({ it -> it }, null) + val b0: ((Nothing) -> Unit)? = select2({ it -> it }, null) + + select3({ it.length }, f, null) +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.txt b/compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.txt new file mode 100644 index 00000000000..3d489348554 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.txt @@ -0,0 +1,5 @@ +package + +public fun select2(/*0*/ x: K, /*1*/ y: K): K +public fun select3(/*0*/ x: K, /*1*/ y: K, /*2*/ z: K): K +public fun test2(/*0*/ f: ((kotlin.String) -> kotlin.Int)?): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/nothingWithCallableReference.kt b/compiler/testData/diagnostics/tests/inference/nothingType/nothingWithCallableReference.kt index ec96bfb1418..33e9f9ffc45 100644 --- a/compiler/testData/diagnostics/tests/inference/nothingType/nothingWithCallableReference.kt +++ b/compiler/testData/diagnostics/tests/inference/nothingType/nothingWithCallableReference.kt @@ -22,8 +22,7 @@ fun test(f1: (Int) -> Unit, f2: kotlin.Function1) { dependantSelect2(null, ::foo) dependantSelect3(null, ::foo, ::cloneFoo) dependantSelect3(null, f1, ::bar) - // Here we have LOWER(Nothing?), UPPER(Function1) and therefore type variable is fixed to the former - dependantSelect3(null, ::bar, f1) + dependantSelect3(null, ::bar, f1) // These errors are actually can be fixed (and, probably, should) if we force resolution of callable reference dependantSelect3(null, ::foo, ::bar) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 8783b5e8bef..076f24956ec 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -9962,6 +9962,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/nothingType/complexDependancyOnVariableWithTrivialConstraint.kt"); } + @TestMetadata("lambdaNothingAndExpectedType.kt") + public void testLambdaNothingAndExpectedType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.kt"); + } + @TestMetadata("nothingWithCallableReference.kt") public void testNothingWithCallableReference() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/nothingType/nothingWithCallableReference.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index dd204d970fd..2c41bcd16ed 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -9962,6 +9962,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/nothingType/complexDependancyOnVariableWithTrivialConstraint.kt"); } + @TestMetadata("lambdaNothingAndExpectedType.kt") + public void testLambdaNothingAndExpectedType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/lambdaNothingAndExpectedType.kt"); + } + @TestMetadata("nothingWithCallableReference.kt") public void testNothingWithCallableReference() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/nothingType/nothingWithCallableReference.kt");