diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index fea281218e9..93c6faa5af0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability import org.jetbrains.kotlin.resolve.calls.tower.isSuccess +import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -230,7 +231,12 @@ private fun ConstraintSystemError.toDiagnostic( } argument?.let { - return FirErrors.ARGUMENT_TYPE_MISMATCH.on(it.source ?: source, lowerConeType, upperConeType) + return FirErrors.ARGUMENT_TYPE_MISMATCH.on( + it.source ?: source, + lowerConeType, + upperConeType, + isArgumentTypeMismatchDueToNullability(lowerConeType, upperConeType, typeContext) + ) } when (position) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index 9c2171c1aa7..55a636e0315 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -333,6 +333,18 @@ private fun Candidate.captureTypeFromExpressionOrNull(argumentType: ConeKotlinTy ) as? ConeKotlinType } +fun isArgumentTypeMismatchDueToNullability( + argumentType: ConeKotlinType, + actualExpectedType: ConeKotlinType, + typeContext: ConeTypeContext +): Boolean { + return AbstractTypeChecker.isSubtypeOf( + typeContext, + argumentType, + actualExpectedType.withNullability(ConeNullability.NULLABLE, typeContext) + ) +} + private fun checkApplicabilityForArgumentType( csBuilder: ConstraintSystemBuilder, argument: FirExpression, @@ -375,18 +387,14 @@ private fun checkApplicabilityForArgumentType( return type } - // Reaching here means argument types mismatch, and we want to record whether it's due to the nullability by checking a subtype - // relation with nullable expected type. - val isMismatchDueToNullability = argumentType.canBeNull && !actualExpectedType.isNullable && AbstractTypeChecker.isSubtypeOf( - context.session.typeContext, - argumentType, - actualExpectedType.withNullability(ConeNullability.NULLABLE, context.session.typeContext) - ) + return ArgumentTypeMismatch( tryGetConeTypeThatCompatibleWithKtType(actualExpectedType), tryGetConeTypeThatCompatibleWithKtType(argumentType), argument, - isMismatchDueToNullability + // Reaching here means argument types mismatch, and we want to record whether it's due to the nullability by checking a subtype + // relation with nullable expected type. + isArgumentTypeMismatchDueToNullability(argumentType, actualExpectedType, context.session.typeContext) ) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArguments.kt index 8d47c364430..94bf5f1a348 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/PostponedArguments.kt @@ -8,15 +8,14 @@ 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.calls.* import org.jetbrains.kotlin.fir.resolve.createFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition +import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible +import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.utils.addToStdlib.safeAs fun Candidate.preprocessLambdaArgument( @@ -57,7 +56,14 @@ fun Candidate.preprocessLambdaArgument( csBuilder.addSubtypeConstraint(lambdaType, expectedType, position) } else { if (!csBuilder.addSubtypeConstraintIfCompatible(lambdaType, expectedType, position)) { - sink.reportDiagnostic(ArgumentTypeMismatch(lambdaType, expectedType, argument)) + sink.reportDiagnostic( + ArgumentTypeMismatch( + lambdaType, + expectedType, + argument, + isArgumentTypeMismatchDueToNullability(lambdaType, expectedType, context.session.typeContext) + ) + ) } } }