Report implicit inferred Nothing only for own type parameters and in delegation resolve
^KT-47724 Fixed
This commit is contained in:
+6
@@ -14228,6 +14228,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reifiedParameterWithRecursiveBound.kt");
|
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
|
@Test
|
||||||
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
|
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
|
||||||
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
|
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
|
||||||
|
|||||||
+6
@@ -14228,6 +14228,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reifiedParameterWithRecursiveBound.kt");
|
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
|
@Test
|
||||||
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
|
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
|
||||||
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
|
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
|
||||||
|
|||||||
+18
-6
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.resolve.calls.checkers
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionOrSuspendFunctionType
|
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.Errors
|
||||||
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnceWrtDiagnosticFactoryList
|
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnceWrtDiagnosticFactoryList
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
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.NewResolvedCallImpl
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.psiExpression
|
import org.jetbrains.kotlin.resolve.calls.tower.psiExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.psiKotlinCall
|
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.DeferredType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
@@ -51,7 +54,7 @@ object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
val resultingDescriptor = resolvedCall.resultingDescriptor
|
val resultingDescriptor = resolvedCall.resultingDescriptor
|
||||||
val expectedType = context.resolutionContext.expectedType
|
val expectedType = context.resolutionContext.expectedType
|
||||||
val inferredReturnType = resultingDescriptor.returnType
|
val inferredReturnType = resultingDescriptor.returnType ?: return false
|
||||||
val isBuiltinFunctionalType =
|
val isBuiltinFunctionalType =
|
||||||
resolvedCall.resultingDescriptor.dispatchReceiverParameter?.value?.type?.isBuiltinFunctionalType == true
|
resolvedCall.resultingDescriptor.dispatchReceiverParameter?.value?.type?.isBuiltinFunctionalType == true
|
||||||
|
|
||||||
@@ -61,12 +64,13 @@ object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
|
|||||||
val lambdasFromArgumentsReturnTypes =
|
val lambdasFromArgumentsReturnTypes =
|
||||||
resolvedCall.candidateDescriptor.valueParameters.filter { it.type.isFunctionOrSuspendFunctionType }
|
resolvedCall.candidateDescriptor.valueParameters.filter { it.type.isFunctionOrSuspendFunctionType }
|
||||||
.map { it.returnType?.arguments?.last()?.type }.toSet()
|
.map { it.returnType?.arguments?.last()?.type }.toSet()
|
||||||
val unsubstitutedReturnType = resultingDescriptor.original.returnType
|
val unsubstitutedReturnType = resultingDescriptor.original.returnType ?: return false
|
||||||
val hasImplicitNothing = inferredReturnType?.isNothingOrNullableNothing() == true &&
|
val hasImplicitNothing = inferredReturnType.isNothingOrNullableNothing()
|
||||||
unsubstitutedReturnType?.isTypeParameter() == true &&
|
&& unsubstitutedReturnType.isTypeParameter()
|
||||||
(TypeUtils.noExpectedType(expectedType) || !expectedType.isNothing())
|
&& (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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +85,14 @@ object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
|
|||||||
return false
|
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? {
|
private fun ResolvedAtom.getResolvedCallAtom(bindingContext: BindingContext): ResolvedCallAtom? {
|
||||||
if (this is SingleCallResolutionResult) return resultCallAtom
|
if (this is SingleCallResolutionResult) return resultCallAtom
|
||||||
|
|
||||||
|
|||||||
+11
@@ -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
|
||||||
|
}
|
||||||
+11
@@ -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
|
||||||
|
}
|
||||||
+12
@@ -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
|
||||||
|
}
|
||||||
+1
-1
@@ -90,7 +90,7 @@ interface Worker<out T>
|
|||||||
interface RenderContext<StateT, in OutputT : Any>
|
interface RenderContext<StateT, in OutputT : Any>
|
||||||
|
|
||||||
val emptyOrNull: List<Nothing>? = null
|
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() }
|
val errorCompletion = { e: Throwable -> throw Exception() }
|
||||||
|
|
||||||
|
|||||||
Generated
+6
@@ -14234,6 +14234,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reifiedParameterWithRecursiveBound.kt");
|
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
|
@Test
|
||||||
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
|
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
|
||||||
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
|
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
|
||||||
|
|||||||
+6
@@ -14228,6 +14228,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/nothingType/reifiedParameterWithRecursiveBound.kt");
|
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
|
@Test
|
||||||
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
|
@TestMetadata("specialCallWithMaterializeAndExpectedType.kt")
|
||||||
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
|
public void testSpecialCallWithMaterializeAndExpectedType() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user