[NI] Discriminate resulting type Nothing(?) at fixation stage
This commit is contained in:
+5
-1
@@ -27,7 +27,8 @@ import org.jetbrains.kotlin.types.checker.intersectTypes
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
||||||
|
|
||||||
class ResultTypeResolver(
|
class ResultTypeResolver(
|
||||||
val typeApproximator: TypeApproximator
|
val typeApproximator: TypeApproximator,
|
||||||
|
val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
|
||||||
) {
|
) {
|
||||||
interface Context {
|
interface Context {
|
||||||
fun isProperType(type: UnwrappedType): Boolean
|
fun isProperType(type: UnwrappedType): Boolean
|
||||||
@@ -77,6 +78,9 @@ class ResultTypeResolver(
|
|||||||
if (!isProperType(constraint.type)) continue
|
if (!isProperType(constraint.type)) continue
|
||||||
if (!checkConstraint(constraint.type, constraint.kind, resultType)) return false
|
if (!checkConstraint(constraint.type, constraint.kind, resultType)) return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!trivialConstraintTypeInferenceOracle.isSuitableResultedType(resultType)) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
@@ -19,6 +19,13 @@ class TrivialConstraintTypeInferenceOracle {
|
|||||||
// TODO: probably we also can take into account `T <: Any(?)` constraints
|
// TODO: probably we also can take into account `T <: Any(?)` constraints
|
||||||
return constraint.kind == ConstraintKind.LOWER && constraint.type.isNothingOrNullableNothing()
|
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 =
|
private fun UnwrappedType.isNothingOrNullableNothing(): Boolean =
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// !LANGUAGE: +NewInference
|
||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
|
fun <K> select2(x: K, y: K): K = TODO()
|
||||||
|
fun <K> 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 -> <!UNUSED_EXPRESSION!>it<!> }, null)
|
||||||
|
|
||||||
|
select3({ it.length }, f, null)
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ K> select2(/*0*/ x: K, /*1*/ y: K): K
|
||||||
|
public fun </*0*/ K> select3(/*0*/ x: K, /*1*/ y: K, /*2*/ z: K): K
|
||||||
|
public fun test2(/*0*/ f: ((kotlin.String) -> kotlin.Int)?): kotlin.Unit
|
||||||
+1
-2
@@ -22,8 +22,7 @@ fun test(f1: (Int) -> Unit, f2: kotlin.Function1<Int, Unit>) {
|
|||||||
dependantSelect2(null, ::foo)
|
dependantSelect2(null, ::foo)
|
||||||
dependantSelect3(null, ::foo, ::cloneFoo)
|
dependantSelect3(null, ::foo, ::cloneFoo)
|
||||||
dependantSelect3(null, f1, ::bar)
|
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, <!TYPE_MISMATCH!>::bar<!>, f1)
|
|
||||||
|
|
||||||
// These errors are actually can be fixed (and, probably, should) if we force resolution of callable reference
|
// These errors are actually can be fixed (and, probably, should) if we force resolution of callable reference
|
||||||
dependantSelect3(null, ::foo, <!TYPE_MISMATCH!>::bar<!>)
|
dependantSelect3(null, ::foo, <!TYPE_MISMATCH!>::bar<!>)
|
||||||
|
|||||||
@@ -9962,6 +9962,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/nothingType/complexDependancyOnVariableWithTrivialConstraint.kt");
|
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")
|
@TestMetadata("nothingWithCallableReference.kt")
|
||||||
public void testNothingWithCallableReference() throws Exception {
|
public void testNothingWithCallableReference() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/nothingType/nothingWithCallableReference.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/nothingType/nothingWithCallableReference.kt");
|
||||||
|
|||||||
Generated
+5
@@ -9962,6 +9962,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/nothingType/complexDependancyOnVariableWithTrivialConstraint.kt");
|
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")
|
@TestMetadata("nothingWithCallableReference.kt")
|
||||||
public void testNothingWithCallableReference() throws Exception {
|
public void testNothingWithCallableReference() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/nothingType/nothingWithCallableReference.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/nothingType/nothingWithCallableReference.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user