Report warning about implicitly inferred nothing only for return position

^KT-31535 Fixed
This commit is contained in:
victor.petukhov
2019-05-20 18:46:28 +03:00
parent 72f7287ad2
commit d4515031de
29 changed files with 125 additions and 96 deletions
@@ -9,8 +9,11 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
private val SPECIAL_FUNCTION_NAMES = ControlStructureTypingUtils.ResolveConstruct.values().map { it.specialFunctionName }.toSet()
@@ -32,16 +35,21 @@ object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
* }
*/
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
if (resolvedCall.candidateDescriptor.name !in SPECIAL_FUNCTION_NAMES && resolvedCall.call.typeArguments.isEmpty()) {
val resultingDescriptor = resolvedCall.resultingDescriptor
val inferredReturnType = resultingDescriptor.returnType
if (inferredReturnType is DeferredType)
return
if (resultingDescriptor.name !in SPECIAL_FUNCTION_NAMES && resolvedCall.call.typeArguments.isEmpty()) {
val lambdasFromArgumentsReturnTypes =
resolvedCall.candidateDescriptor.valueParameters.filter { it.type.isFunctionType }
.map { it.returnType?.arguments?.last()?.type }.toSet()
val unsubstitutedReturnType = resultingDescriptor.original.returnType
val expectedType = context.resolutionContext.expectedType
val hasImplicitNothing = inferredReturnType?.isNothing() == true &&
unsubstitutedReturnType?.isTypeParameter() == true &&
(TypeUtils.noExpectedType(expectedType) || !expectedType.isNothing())
val hasImplicitNothingExceptLambdaReturnTypes = resolvedCall.typeArguments.any { (unsubstitutedType, resultingType) ->
resultingType.isNothing() && unsubstitutedType.defaultType !in lambdasFromArgumentsReturnTypes
}
if (hasImplicitNothingExceptLambdaReturnTypes) {
if (hasImplicitNothing && unsubstitutedReturnType !in lambdasFromArgumentsReturnTypes) {
context.trace.report(Errors.IMPLICIT_NOTHING_AS_TYPE_PARAMETER.on(reportOn))
}
}