[FE 1.0] Don't lose diagnostics during lambda analysis at the overload resolution by return type stage

^KT-49658 Fixed
This commit is contained in:
Victor Petukhov
2022-01-11 15:22:03 +03:00
committed by teamcity
parent 7820b268fb
commit 37d163d417
17 changed files with 212 additions and 21 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
@@ -31,7 +32,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.same
class KotlinCallCompleter(
private val postponedArgumentsAnalyzer: PostponedArgumentsAnalyzer,
private val kotlinConstraintSystemCompleter: KotlinConstraintSystemCompleter,
private val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
private val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle,
private val languageVersionSettings: LanguageVersionSettings
) {
fun runCompletion(
@@ -127,6 +129,7 @@ class KotlinCallCompleter(
ConstraintSystemCompletionMode.FULL,
diagnosticHolderForLambda,
)
propagateLambdaAnalysisDiagnostics(diagnosticHolderForLambda, firstCandidate)
while (iterator.hasNext()) {
val (candidate, atom) = iterator.next()
@@ -137,6 +140,7 @@ class KotlinCallCompleter(
ConstraintSystemCompletionMode.FULL,
diagnosticHolderForLambda
)
propagateLambdaAnalysisDiagnostics(diagnosticHolderForLambda, candidate)
}
val errorCandidates = mutableSetOf<SimpleResolutionCandidate>()
@@ -155,6 +159,24 @@ class KotlinCallCompleter(
}
}
private fun propagateLambdaAnalysisDiagnostics(
diagnosticHolder: KotlinDiagnosticsHolder.SimpleHolder,
candidate: SimpleResolutionCandidate
) {
val dontLoseDiagnosticsDuringOverloadResolutionByReturnType =
languageVersionSettings.supportsFeature(LanguageFeature.DontLoseDiagnosticsDuringOverloadResolutionByReturnType)
for (diagnostic in diagnosticHolder.getDiagnostics()) {
if (diagnostic is TransformableToWarning<*>) {
val transformedDiagnostic =
if (dontLoseDiagnosticsDuringOverloadResolutionByReturnType) diagnostic else diagnostic.transformToWarning()
if (transformedDiagnostic != null) {
candidate.addDiagnostic(transformedDiagnostic)
}
}
}
}
private fun SimpleResolutionCandidate.getInputTypesOfLambdaAtom(atom: ResolvedLambdaAtom): List<UnwrappedType> {
val result = mutableListOf<UnwrappedType>()
val substitutor = getSystem().getBuilder().buildCurrentSubstitutor()
@@ -85,7 +85,7 @@ private fun checkExpressionArgument(
if (argumentType.isMarkedNullable) {
if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, actualExpectedType, position)) return null
if (csBuilder.addSubtypeConstraintIfCompatible(argumentType.makeNotNullable(), actualExpectedType, position)) {
return ArgumentNullabilityMismatchDiagnostic(actualExpectedType, argumentType, expressionArgument)
return ArgumentNullabilityErrorDiagnostic(actualExpectedType, argumentType, expressionArgument)
}
}
@@ -97,7 +97,7 @@ private fun checkExpressionArgument(
// Used only for arguments with @NotNull annotation
if (expectedType is NotNullTypeParameter && argumentType.isMarkedNullable) {
diagnosticsHolder.addDiagnostic(ArgumentNullabilityMismatchDiagnostic(expectedType, argumentType, expressionArgument))
diagnosticsHolder.addDiagnostic(ArgumentNullabilityErrorDiagnostic(expectedType, argumentType, expressionArgument))
}
if (expressionArgument.isSafeCall) {
@@ -23,12 +23,18 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.components.candidate.CallableReferenceResolutionCandidate
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintSystemError
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintError
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintWarning
import org.jetbrains.kotlin.resolve.calls.inference.model.transformToWarning
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability.*
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType
interface TransformableToWarning<T : KotlinCallDiagnostic> {
fun transformToWarning(): T?
}
abstract class InapplicableArgumentDiagnostic : KotlinCallDiagnostic(INAPPLICABLE) {
abstract val argument: KotlinCallArgument
@@ -227,11 +233,29 @@ class NonApplicableCallForBuilderInferenceDiagnostic(val kotlinCall: KotlinCall)
}
}
class ArgumentNullabilityMismatchDiagnostic(
val expectedType: UnwrappedType,
val actualType: UnwrappedType,
sealed interface ArgumentNullabilityMismatchDiagnostic {
val expectedType: UnwrappedType
val actualType: UnwrappedType
val expressionArgument: ExpressionKotlinCallArgument
) : KotlinCallDiagnostic(UNSAFE_CALL) {
}
class ArgumentNullabilityErrorDiagnostic(
override val expectedType: UnwrappedType,
override val actualType: UnwrappedType,
override val expressionArgument: ExpressionKotlinCallArgument
) : KotlinCallDiagnostic(UNSAFE_CALL), TransformableToWarning<ArgumentNullabilityWarningDiagnostic>, ArgumentNullabilityMismatchDiagnostic {
override fun report(reporter: DiagnosticReporter) {
reporter.onCallArgument(expressionArgument, this)
}
override fun transformToWarning() = ArgumentNullabilityWarningDiagnostic(expectedType, actualType, expressionArgument)
}
class ArgumentNullabilityWarningDiagnostic(
override val expectedType: UnwrappedType,
override val actualType: UnwrappedType,
override val expressionArgument: ExpressionKotlinCallArgument
) : KotlinCallDiagnostic(RESOLVED), ArgumentNullabilityMismatchDiagnostic {
override fun report(reporter: DiagnosticReporter) {
reporter.onCallArgument(expressionArgument, this)
}
@@ -287,8 +311,11 @@ class MultipleArgumentsApplicableForContextReceiver(val receiverDescriptor: Rece
class KotlinConstraintSystemDiagnostic(
val error: ConstraintSystemError
) : KotlinCallDiagnostic(error.applicability) {
) : KotlinCallDiagnostic(error.applicability), TransformableToWarning<KotlinConstraintSystemDiagnostic> {
override fun report(reporter: DiagnosticReporter) = reporter.constraintError(error)
override fun transformToWarning(): KotlinConstraintSystemDiagnostic? =
if (error is NewConstraintError) KotlinConstraintSystemDiagnostic(error.transformToWarning()) else null
}
val KotlinCallDiagnostic.constraintSystemError: ConstraintSystemError?