From 7567597be673155eecb240f2931abcf949c6d610 Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Tue, 27 Jul 2021 16:07:00 +0300 Subject: [PATCH] Java nullability checker: take type arguments' types from resolution atom if possible, instead of from resolved call directly ^KT-47833 Fixed --- .../jvm/checkers/JavaNullabilityChecker.kt | 11 ++++++- .../TypeArgumentsToParametersMapper.kt | 10 ++++++- .../foreignAnnotationsTests/tests/kt47833.kt | 30 +++++++++++++++++++ ...nAnnotationsCompiledJavaTestGenerated.java | 6 ++++ ...dJavaWithPsiClassReadingTestGenerated.java | 6 ++++ ...ignAnnotationsSourceJavaTestGenerated.java | 6 ++++ 6 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/diagnostics/foreignAnnotationsTests/tests/kt47833.kt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt index c85a86a2512..690c202cac7 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/JavaNullabilityChecker.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability +import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue @@ -135,10 +136,18 @@ class JavaNullabilityChecker(val upperBoundChecker: UpperBoundChecker) : Additio ?: return val resolvedCall = c.trace.bindingContext[BindingContext.RESOLVED_CALL, call] ?: return - for ((typeParameter, typeArgument) in resolvedCall.typeArguments) { + val typeArguments = if (resolvedCall is NewResolvedCallImpl<*>) { + resolvedCall.resolvedCallAtom.typeArgumentMappingByOriginal + } else { + resolvedCall.typeArguments.entries + } + + for ((typeParameter, typeArgument) in typeArguments) { // continue if we don't have explicit type arguments val typeReference = call.typeArguments.getOrNull(typeParameter.index)?.typeReference ?: continue + if (typeArgument == null) continue + upperBoundChecker.checkBounds( typeReference, typeArgument, typeParameter, TypeSubstitutor.create(typeArgument), c.trace, withOnlyCheckForWarning = true ) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/TypeArgumentsToParametersMapper.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/TypeArgumentsToParametersMapper.kt index 4e4c7773692..9ce42c8a2a1 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/TypeArgumentsToParametersMapper.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/TypeArgumentsToParametersMapper.kt @@ -19,16 +19,22 @@ package org.jetbrains.kotlin.resolve.calls.components import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.resolve.calls.model.* +import org.jetbrains.kotlin.types.KotlinType class TypeArgumentsToParametersMapper { - sealed class TypeArgumentsMapping(val diagnostics: List) { + sealed class TypeArgumentsMapping(val diagnostics: List) : + Iterable> { abstract fun getTypeArgument(typeParameterDescriptor: TypeParameterDescriptor): TypeArgument object NoExplicitArguments : TypeArgumentsMapping(emptyList()) { + private val emptyIterator = mapOf().iterator() + override fun getTypeArgument(typeParameterDescriptor: TypeParameterDescriptor): TypeArgument = TypeArgumentPlaceholder + + override fun iterator() = emptyIterator } class TypeArgumentsMappingImpl( @@ -37,6 +43,8 @@ class TypeArgumentsToParametersMapper { ) : TypeArgumentsMapping(diagnostics) { override fun getTypeArgument(typeParameterDescriptor: TypeParameterDescriptor): TypeArgument = typeParameterToArgumentMap[typeParameterDescriptor] ?: TypeArgumentPlaceholder + + override fun iterator() = typeParameterToArgumentMap.mapValues { (it.value as? SimpleTypeArgument)?.type }.iterator() } } diff --git a/compiler/testData/diagnostics/foreignAnnotationsTests/tests/kt47833.kt b/compiler/testData/diagnostics/foreignAnnotationsTests/tests/kt47833.kt new file mode 100644 index 00000000000..5aef0474858 --- /dev/null +++ b/compiler/testData/diagnostics/foreignAnnotationsTests/tests/kt47833.kt @@ -0,0 +1,30 @@ +// FILE: main.kt +sealed class ClientBootResult + +object ClientBootSuccess : ClientBootResult() + +fun example(): Single { + return Single.just(true).map { ClientBootSuccess } +} + +// FILE: Single.java +import io.reactivex.rxjava3.annotations.NonNull; + +public class Single<@NonNull T> { + @NonNull + public static <@NonNull T> Single just(T item) { + return null; + } + @NonNull + public final <@NonNull R> Single map(@NonNull Function mapper) { + return null; + } +} + +// FILE: Function.java +import io.reactivex.rxjava3.annotations.NonNull; + +@FunctionalInterface +public interface Function<@NonNull T, @NonNull R> { + R apply(T t) throws Throwable; +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsCompiledJavaTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsCompiledJavaTestGenerated.java index 59527912ef1..b091b798330 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsCompiledJavaTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsCompiledJavaTestGenerated.java @@ -86,6 +86,12 @@ public class ForeignAnnotationsCompiledJavaTestGenerated extends AbstractForeign runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/kt47920.kt"); } + @Test + @TestMetadata("kt47833.kt") + public void testKt47833() throws Exception { + runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/kt47833.kt"); + } + @Test @TestMetadata("lombokSimple.kt") public void testLombokSimple() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsCompiledJavaWithPsiClassReadingTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsCompiledJavaWithPsiClassReadingTestGenerated.java index b2a47a62f45..c8d3a90b0a0 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsCompiledJavaWithPsiClassReadingTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsCompiledJavaWithPsiClassReadingTestGenerated.java @@ -86,6 +86,12 @@ public class ForeignAnnotationsCompiledJavaWithPsiClassReadingTestGenerated exte runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/kt47920.kt"); } + @Test + @TestMetadata("kt47833.kt") + public void testKt47833() throws Exception { + runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/kt47833.kt"); + } + @Test @TestMetadata("lombokSimple.kt") public void testLombokSimple() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsSourceJavaTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsSourceJavaTestGenerated.java index 53a0c9d701b..33d337ec566 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsSourceJavaTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ForeignAnnotationsSourceJavaTestGenerated.java @@ -86,6 +86,12 @@ public class ForeignAnnotationsSourceJavaTestGenerated extends AbstractForeignAn runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/kt47920.kt"); } + @Test + @TestMetadata("kt47833.kt") + public void testKt47833() throws Exception { + runTest("compiler/testData/diagnostics/foreignAnnotationsTests/tests/kt47833.kt"); + } + @Test @TestMetadata("lombokSimple.kt") public void testLombokSimple() throws Exception {