FIR: Refine diagnostics in case argument type mismatch on lambda

Report ArgumentTypeMismatch instead of imprecise NEW_INFERENCE_ERROR
This commit is contained in:
Denis.Zharkov
2021-04-27 14:34:04 +03:00
committed by teamcityserver
parent 2b806e717d
commit 91806c0a68
3 changed files with 36 additions and 13 deletions
@@ -6,11 +6,15 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.lookupTracker
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
@@ -18,12 +22,12 @@ import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclarati
import org.jetbrains.kotlin.fir.returnExpressions
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
@@ -103,7 +107,7 @@ fun Candidate.resolveArgumentExpression(
else
preprocessCallableReference(argument, expectedType, context)
// TODO:!
is FirAnonymousFunction -> preprocessLambdaArgument(csBuilder, argument, expectedType, expectedTypeRef, context)
is FirAnonymousFunction -> preprocessLambdaArgument(csBuilder, argument, expectedType, expectedTypeRef, context, sink)
// TODO:!
//TODO: Collection literal
is FirWrappedArgumentExpression -> resolveArgumentExpression(
@@ -8,12 +8,15 @@ package org.jetbrains.kotlin.fir.resolve.inference
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.resolve.calls.ArgumentTypeMismatch
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
import org.jetbrains.kotlin.fir.resolve.calls.CheckerSink
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
import org.jetbrains.kotlin.fir.resolve.createFunctionalType
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun Candidate.preprocessLambdaArgument(
@@ -22,16 +25,23 @@ fun Candidate.preprocessLambdaArgument(
expectedType: ConeKotlinType?,
expectedTypeRef: FirTypeRef?,
context: ResolutionContext,
forceResolution: Boolean = false,
sink: CheckerSink?,
duringCompletion: Boolean = false,
returnTypeVariable: ConeTypeVariableForLambdaReturnType? = null
): PostponedResolvedAtom {
if (expectedType != null && expectedTypeRef != null && !forceResolution && csBuilder.isTypeVariable(expectedType)) {
if (expectedType != null && expectedTypeRef != null && !duringCompletion && csBuilder.isTypeVariable(expectedType)) {
return LambdaWithTypeVariableAsExpectedTypeAtom(argument, expectedType, expectedTypeRef, this)
}
val resolvedArgument =
extractLambdaInfoFromFunctionalType(expectedType, expectedTypeRef, argument, returnTypeVariable, context.bodyResolveComponents, this)
?: extraLambdaInfo(expectedType, argument, csBuilder, context.session, this)
extractLambdaInfoFromFunctionalType(
expectedType,
expectedTypeRef,
argument,
returnTypeVariable,
context.bodyResolveComponents,
this
) ?: extraLambdaInfo(expectedType, argument, csBuilder, context.session, this)
if (expectedType != null) {
// TODO: add SAM conversion processing
@@ -41,7 +51,15 @@ fun Candidate.preprocessLambdaArgument(
resolvedArgument.returnType,
isSuspend = resolvedArgument.isSuspend
)
csBuilder.addSubtypeConstraint(lambdaType, expectedType, SimpleConstraintSystemConstraintPosition)
val position = ConeArgumentConstraintPosition(resolvedArgument.atom)
if (duringCompletion || sink == null) {
csBuilder.addSubtypeConstraint(lambdaType, expectedType, position)
} else {
if (!csBuilder.addSubtypeConstraintIfCompatible(lambdaType, expectedType, position)) {
sink.reportDiagnostic(ArgumentTypeMismatch(lambdaType, expectedType, argument))
}
}
}
return resolvedArgument
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.recordTypeResolveAsLookup
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedReferenceError
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeLambdaArgumentConstraintPosition
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.StoreNameReference
import org.jetbrains.kotlin.fir.types.*
@@ -21,7 +22,6 @@ import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzerContext
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.model.CoroutinePosition
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
import org.jetbrains.kotlin.types.model.StubTypeMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
import org.jetbrains.kotlin.types.model.freshTypeConstructor
@@ -201,7 +201,7 @@ class PostponedArgumentsAnalyzer(
c.getBuilder().addEqualityConstraint(
lambdaReturnType,
components.session.builtinTypes.unitType.type,
SimpleConstraintSystemConstraintPosition
ConeLambdaArgumentConstraintPosition(lambda.atom)
)
}
@@ -230,7 +230,8 @@ fun LambdaWithTypeVariableAsExpectedTypeAtom.transformToResolvedLambda(
fixedExpectedType,
expectedTypeRef,
context,
forceResolution = true,
sink = null,
duringCompletion = true,
returnTypeVariable = returnTypeVariable
) as ResolvedLambdaAtom
analyzed = true