diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt index 994d3036409..6b8ae44a4c1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CandidateResolver.kt @@ -53,6 +53,7 @@ import org.jetbrains.kotlin.types.checker.ErrorTypesAreEqualToAnything import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver import org.jetbrains.kotlin.types.typeUtil.containsTypeProjectionsInTopLevelArguments +import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import java.util.* class CandidateResolver( @@ -376,7 +377,7 @@ class CandidateResolver( if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) { val smartCast = smartCastValueArgumentTypeIfPossible(expression, newContext.expectedType, type, newContext) if (smartCast == null) { - resultStatus = OTHER_ERROR + resultStatus = tryNotNullableArgument(type, expectedType) ?: OTHER_ERROR matchStatus = ArgumentMatchStatus.TYPE_MISMATCH } else { @@ -417,6 +418,14 @@ class CandidateResolver( } } + private fun tryNotNullableArgument(argumentType: KotlinType, parameterType: KotlinType): ResolutionStatus? { + if (!argumentType.isMarkedNullable || parameterType.isMarkedNullable) return null + + val notNullableArgumentType = argumentType.makeNotNullable() + val isApplicable = ArgumentTypeResolver.isSubtypeOfForArgumentType(notNullableArgumentType, parameterType) + return if (isApplicable) NULLABLE_ARGUMENT_TYPE_MISMATCH else null + } + private fun CallCandidateResolutionContext<*>.checkReceiverTypeError(): Unit = check { val extensionReceiver = candidateDescriptor.extensionReceiverParameter val dispatchReceiver = candidateDescriptor.dispatchReceiverParameter diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionStatus.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionStatus.java index 0de1683a96a..ccab2b636a4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionStatus.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/results/ResolutionStatus.java @@ -26,6 +26,7 @@ public enum ResolutionStatus { WRONG_NUMBER_OF_TYPE_ARGUMENTS_ERROR, UNSTABLE_SMARTCAST_ERROR, INVISIBLE_MEMBER_ERROR, + NULLABLE_ARGUMENT_TYPE_MISMATCH, OTHER_ERROR, ARGUMENTS_MAPPING_ERROR, // '1.foo()' shouldn't be resolved to 'fun String.foo()' @@ -44,6 +45,7 @@ public enum ResolutionStatus { EnumSet.of(WRONG_NUMBER_OF_TYPE_ARGUMENTS_ERROR), EnumSet.of(UNSTABLE_SMARTCAST_ERROR), EnumSet.of(INVISIBLE_MEMBER_ERROR), + EnumSet.of(NULLABLE_ARGUMENT_TYPE_MISMATCH), EnumSet.of(OTHER_ERROR), EnumSet.of(ARGUMENTS_MAPPING_ERROR), EnumSet.of(RECEIVER_TYPE_ERROR), diff --git a/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterPlatform.kt b/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterPlatform.kt new file mode 100644 index 00000000000..33ded986920 --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterPlatform.kt @@ -0,0 +1,17 @@ +// FILE: J.java + +import org.jetbrains.annotations.*; + +public class J { + void foo(String x) {} + void foo(@NotNull Double x) {} + void foo(@Nullable Byte x) {} +} + +// FILE: test.kt + +fun test(j: J, nullStr: String?, nullByte: Byte?, nullDouble: Double?) { + j.foo(nullStr) + j.foo(nullDouble) + j.foo(nullByte) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterPlatform.txt b/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterPlatform.txt new file mode 100644 index 00000000000..20519e7bd6d --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterPlatform.txt @@ -0,0 +1,13 @@ +package + +public fun test(/*0*/ j: J, /*1*/ nullStr: kotlin.String?, /*2*/ nullByte: kotlin.Byte?, /*3*/ nullDouble: kotlin.Double?): kotlin.Unit + +public open class J { + public constructor J() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public/*package*/ open fun foo(/*0*/ @org.jetbrains.annotations.Nullable x: kotlin.Byte?): kotlin.Unit + public/*package*/ open fun foo(/*0*/ @org.jetbrains.annotations.NotNull x: kotlin.Double): kotlin.Unit + public/*package*/ open fun foo(/*0*/ x: kotlin.String!): kotlin.Unit + 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/nullableTypes/nullableArgumentToNonNullParameterSimple.kt b/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterSimple.kt new file mode 100644 index 00000000000..b27e57887a3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterSimple.kt @@ -0,0 +1,12 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun foo(x: String) {} +fun foo(x: Int) {} +fun foo(x: Int, y: String) {} + +fun bar(nullX: Int?, nullY: String?, notNullY: String) { + foo(nullX) + foo(nullX, notNullY) + foo(nullX, nullY) + foo() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterSimple.txt b/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterSimple.txt new file mode 100644 index 00000000000..80d5f7b4f3b --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterSimple.txt @@ -0,0 +1,6 @@ +package + +public fun bar(/*0*/ nullX: kotlin.Int?, /*1*/ nullY: kotlin.String?, /*2*/ notNullY: kotlin.String): kotlin.Unit +public fun foo(/*0*/ x: kotlin.Int): kotlin.Unit +public fun foo(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String): kotlin.Unit +public fun foo(/*0*/ x: kotlin.String): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.kt index 3bd7234f6fe..8f9b3ca4031 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/arithmetic.kt @@ -33,7 +33,7 @@ fun test() { platformJ++ 1 + platformNN - 1 + platformN + 1 + platformN 1 + platformJ platformNN + 1 @@ -41,7 +41,7 @@ fun test() { platformJ + 1 1 plus platformNN - 1 plus platformN + 1 plus platformN 1 plus platformJ platformNN plus 1 diff --git a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/plusplusMinusminus.kt b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/plusplusMinusminus.kt index 98bbe9f7ac8..b68a453dfad 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/varnotnull/plusplusMinusminus.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/varnotnull/plusplusMinusminus.kt @@ -14,7 +14,7 @@ fun bar(arg: Long?): Long { return i-- + i } if (i++ == 7L) { - return i++ + i + return i++ + i } return 0L } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/ParameterTypeAnnotation.kt b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/ParameterTypeAnnotation.kt index c52da3235d0..196fa9da4e7 100644 --- a/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/ParameterTypeAnnotation.kt +++ b/compiler/testData/diagnostics/tests/syntheticExtensions/samAdapters/ParameterTypeAnnotation.kt @@ -1,6 +1,6 @@ // FILE: KotlinFile.kt fun foo(javaInterface: JavaInterface) { - javaInterface.doIt(null) { } + javaInterface.doIt(null) { } javaInterface.doIt("", null) } diff --git a/compiler/testData/resolvedCalls/enhancedSignatures/map/mapMerge.txt b/compiler/testData/resolvedCalls/enhancedSignatures/map/mapMerge.txt index addf39b8908..719573e25f8 100644 --- a/compiler/testData/resolvedCalls/enhancedSignatures/map/mapMerge.txt +++ b/compiler/testData/resolvedCalls/enhancedSignatures/map/mapMerge.txt @@ -11,9 +11,9 @@ fun valuesNullable(map: MutableMap) { // ORIGINAL: fun merge(K, V, (V, V) -> V?): V? defined in kotlin.collections.MutableMap // SUBSTITUTED: fun merge(Int, String, (String, String) -> String?): String? defined in kotlin.collections.MutableMap map.merge(1, null) { old, new -> old + new } - // OTHER_ERROR - // ORIGINAL: fun merge(K, V, BiFunction): V? defined in kotlin.collections.MutableMap - // SUBSTITUTED: fun merge(Int, String, BiFunction): String? defined in kotlin.collections.MutableMap + // NULLABLE_ARGUMENT_TYPE_MISMATCH + // ORIGINAL: fun merge(K, V, (V, V) -> V?): V? defined in kotlin.collections.MutableMap + // SUBSTITUTED: fun merge(Int, String, (String, String) -> String?): String? defined in kotlin.collections.MutableMap } fun valuesT(map: MutableMap, newValue: T) { @@ -32,9 +32,9 @@ fun valuesTNotNull(map: MutableMap, newValue: T) { fun valuesTNullable(map: MutableMap, newValue: T?) { map.merge(1, newValue) { old, new -> new } - // OTHER_ERROR - // ORIGINAL: fun merge(K, V, BiFunction): V? defined in kotlin.collections.MutableMap - // SUBSTITUTED: fun merge(Int, T, BiFunction): T? defined in kotlin.collections.MutableMap + // NULLABLE_ARGUMENT_TYPE_MISMATCH + // ORIGINAL: fun merge(K, V, (V, V) -> V?): V? defined in kotlin.collections.MutableMap + // SUBSTITUTED: fun merge(Int, T, (T, T) -> T?): T? defined in kotlin.collections.MutableMap map.merge(1, newValue!!) { old, new -> new } // SUCCESS // ORIGINAL: fun merge(K, V, (V, V) -> V?): V? defined in kotlin.collections.MutableMap diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 6ff4ec339b2..f3df628988e 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -14011,6 +14011,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("nullableArgumentToNonNullParameterPlatform.kt") + public void testNullableArgumentToNonNullParameterPlatform() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterPlatform.kt"); + doTest(fileName); + } + + @TestMetadata("nullableArgumentToNonNullParameterSimple.kt") + public void testNullableArgumentToNonNullParameterSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/nullableTypes/nullableArgumentToNonNullParameterSimple.kt"); + doTest(fileName); + } + @TestMetadata("redundantNullable.kt") public void testRedundantNullable() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/nullableTypes/redundantNullable.kt");