Report implicit inferred Nothing only for own type parameters and in delegation resolve

^KT-47724 Fixed
This commit is contained in:
Victor Petukhov
2021-07-14 17:40:58 +03:00
parent 7bb4612149
commit ea4ab46765
9 changed files with 77 additions and 7 deletions
@@ -14228,6 +14228,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reifiedParameterWithRecursiveBound.kt");
}
@Test
@TestMetadata("reportImplicitNothingOnlyForOwnTypeParameters.kt")
public void testReportImplicitNothingOnlyForOwnTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reportImplicitNothingOnlyForOwnTypeParameters.kt");
}
@Test
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
@@ -14228,6 +14228,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reifiedParameterWithRecursiveBound.kt");
}
@Test
@TestMetadata("reportImplicitNothingOnlyForOwnTypeParameters.kt")
public void testReportImplicitNothingOnlyForOwnTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reportImplicitNothingOnlyForOwnTypeParameters.kt");
}
@Test
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.resolve.calls.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
import org.jetbrains.kotlin.builtins.isFunctionOrSuspendFunctionType
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnceWrtDiagnosticFactoryList
import org.jetbrains.kotlin.resolve.BindingContext
@@ -19,6 +21,7 @@ import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.tower.psiExpression
import org.jetbrains.kotlin.resolve.calls.tower.psiKotlinCall
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
@@ -51,7 +54,7 @@ object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
): Boolean {
val resultingDescriptor = resolvedCall.resultingDescriptor
val expectedType = context.resolutionContext.expectedType
val inferredReturnType = resultingDescriptor.returnType
val inferredReturnType = resultingDescriptor.returnType ?: return false
val isBuiltinFunctionalType =
resolvedCall.resultingDescriptor.dispatchReceiverParameter?.value?.type?.isBuiltinFunctionalType == true
@@ -61,12 +64,13 @@ object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
val lambdasFromArgumentsReturnTypes =
resolvedCall.candidateDescriptor.valueParameters.filter { it.type.isFunctionOrSuspendFunctionType }
.map { it.returnType?.arguments?.last()?.type }.toSet()
val unsubstitutedReturnType = resultingDescriptor.original.returnType
val hasImplicitNothing = inferredReturnType?.isNothingOrNullableNothing() == true &&
unsubstitutedReturnType?.isTypeParameter() == true &&
(TypeUtils.noExpectedType(expectedType) || !expectedType.isNothing())
val unsubstitutedReturnType = resultingDescriptor.original.returnType ?: return false
val hasImplicitNothing = inferredReturnType.isNothingOrNullableNothing()
&& unsubstitutedReturnType.isTypeParameter()
&& (isOwnTypeParameter(unsubstitutedReturnType, resultingDescriptor.original) || isDelegationContext(context))
&& (TypeUtils.noExpectedType(expectedType) || !expectedType.isNothing())
if (inferredReturnType?.isNullableNothing() == true && unsubstitutedReturnType?.isMarkedNullable == false) {
if (inferredReturnType.isNullableNothing() && !unsubstitutedReturnType.isMarkedNullable) {
return false
}
@@ -81,6 +85,14 @@ object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
return false
}
private fun isOwnTypeParameter(type: KotlinType, declaration: CallableDescriptor): Boolean {
val typeParameter = type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false
return typeParameter.containingDeclaration == declaration
}
private fun isDelegationContext(context: CallCheckerContext) =
context.resolutionContext.scope.kind == LexicalScopeKind.PROPERTY_DELEGATE_METHOD
private fun ResolvedAtom.getResolvedCallAtom(bindingContext: BindingContext): ResolvedCallAtom? {
if (this is SingleCallResolutionResult) return resultCallAtom
@@ -0,0 +1,11 @@
fun <R> runCatching(block: () -> R) = null as Result<R>
class Result<out T> {
fun getOrNull(): T? = null
}
fun main() {
runCatching {
null
}.getOrNull() // don't report IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION
}
@@ -0,0 +1,11 @@
fun <R> runCatching(block: () -> R) = null <!CAST_NEVER_SUCCEEDS!>as<!> Result<R>
class Result<out T> {
fun getOrNull(): T? = null
}
fun main() {
runCatching {
null
}.getOrNull() // don't report IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION
}
@@ -0,0 +1,12 @@
package
public fun main(): kotlin.Unit
public fun </*0*/ R> runCatching(/*0*/ block: () -> R): Result<R>
public final class Result</*0*/ out T> {
public constructor Result</*0*/ out T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun getOrNull(): T?
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -90,7 +90,7 @@ interface Worker<out T>
interface RenderContext<StateT, in OutputT : Any>
val emptyOrNull: List<Nothing>? = null
val x = emptyOrNull?.<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>get<!>(0)
val x = emptyOrNull?.get(0)
val errorCompletion = { e: Throwable -> throw Exception() }
@@ -14234,6 +14234,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reifiedParameterWithRecursiveBound.kt");
}
@Test
@TestMetadata("reportImplicitNothingOnlyForOwnTypeParameters.kt")
public void testReportImplicitNothingOnlyForOwnTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reportImplicitNothingOnlyForOwnTypeParameters.kt");
}
@Test
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
@@ -14228,6 +14228,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reifiedParameterWithRecursiveBound.kt");
}
@Test
@TestMetadata("reportImplicitNothingOnlyForOwnTypeParameters.kt")
public void testReportImplicitNothingOnlyForOwnTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reportImplicitNothingOnlyForOwnTypeParameters.kt");
}
@Test
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {