[NI] Report error about unknown parameter type of lambda argument

KT-34335
This commit is contained in:
Pavel Kirpichenkov
2020-01-24 19:16:11 +03:00
parent 9fb8579252
commit eec039f5a2
25 changed files with 260 additions and 29 deletions
@@ -21,7 +21,8 @@ interface InferenceSession {
override fun currentConstraintSystem(): ConstraintStorage = ConstraintStorage.Empty
override fun inferPostponedVariables(
lambda: ResolvedLambdaAtom,
initialStorage: ConstraintStorage
initialStorage: ConstraintStorage,
diagnosticsHolder: KotlinDiagnosticsHolder
): Map<TypeConstructor, UnwrappedType> = emptyMap()
override fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean = false
@@ -35,7 +36,12 @@ interface InferenceSession {
fun addCompletedCallInfo(callInfo: CompletedCallInfo)
fun addErrorCallInfo(callInfo: ErrorCallInfo)
fun currentConstraintSystem(): ConstraintStorage
fun inferPostponedVariables(lambda: ResolvedLambdaAtom, initialStorage: ConstraintStorage): Map<TypeConstructor, UnwrappedType>
fun inferPostponedVariables(
lambda: ResolvedLambdaAtom,
initialStorage: ConstraintStorage,
diagnosticsHolder: KotlinDiagnosticsHolder
): Map<TypeConstructor, UnwrappedType>
fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean
fun callCompleted(resolvedAtom: ResolvedAtom): Boolean
fun shouldCompleteResolvedSubAtomsOf(resolvedCallAtom: ResolvedCallAtom): Boolean
@@ -131,7 +131,8 @@ class KotlinCallCompleter(
constraintSystem.asConstraintSystemCompleterContext(),
completionMode,
listOf(resolvedCallAtom),
returnType
returnType,
diagnosticsHolder
) {
if (collectAllCandidatesMode) {
it.setEmptyAnalyzedResults()
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosi
import org.jetbrains.kotlin.resolve.calls.inference.model.LHSArgumentConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.builtIns
@@ -40,7 +41,7 @@ fun resolveKtPrimitive(
checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
is LambdaKotlinCallArgument ->
preprocessLambdaArgument(csBuilder, argument, expectedType)
preprocessLambdaArgument(csBuilder, argument, expectedType, diagnosticsHolder)
is CallableReferenceKotlinCallArgument ->
preprocessCallableReference(csBuilder, argument, expectedType, diagnosticsHolder)
@@ -57,6 +58,7 @@ private fun preprocessLambdaArgument(
csBuilder: ConstraintSystemBuilder,
argument: LambdaKotlinCallArgument,
expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder,
forceResolution: Boolean = false,
returnTypeVariable: TypeVariableForLambdaReturnType? = null
): ResolvedAtom {
@@ -65,7 +67,7 @@ private fun preprocessLambdaArgument(
}
val resolvedArgument = extractLambdaInfoFromFunctionalType(expectedType, argument, returnTypeVariable)
?: extraLambdaInfo(expectedType, argument, csBuilder)
?: extraLambdaInfo(expectedType, argument, csBuilder, diagnosticsHolder)
if (expectedType != null) {
val lambdaType = createFunctionType(
@@ -81,7 +83,8 @@ private fun preprocessLambdaArgument(
private fun extraLambdaInfo(
expectedType: UnwrappedType?,
argument: LambdaKotlinCallArgument,
csBuilder: ConstraintSystemBuilder
csBuilder: ConstraintSystemBuilder,
diagnosticsHolder: KotlinDiagnosticsHolder
): ResolvedLambdaAtom {
val builtIns = csBuilder.builtIns
val isSuspend = expectedType?.isSuspendFunctionType ?: false
@@ -96,7 +99,14 @@ private fun extraLambdaInfo(
argumentAsFunctionExpression?.returnType ?: expectedType?.arguments?.singleOrNull()?.type?.unwrap()?.takeIf { isFunctionSupertype }
?: typeVariable.defaultType
val parameters = argument.parametersTypes?.map { it ?: builtIns.nothingType } ?: emptyList()
val parameters = argument.parametersTypes?.mapIndexed { index, parameterType ->
if (parameterType != null) {
parameterType
} else {
diagnosticsHolder.addDiagnostic(NotEnoughInformationForLambdaParameter(argument, index))
ErrorUtils.createErrorType("<Unknown lambda parameter type>")
}
} ?: emptyList()
val newTypeVariableUsed = returnType == typeVariable.defaultType
if (newTypeVariableUsed) csBuilder.registerVariable(typeVariable)
@@ -177,6 +187,7 @@ private fun extractLambdaInfoFromFunctionalType(
fun LambdaWithTypeVariableAsExpectedTypeAtom.transformToResolvedLambda(
csBuilder: ConstraintSystemBuilder,
diagnosticsHolder: KotlinDiagnosticsHolder,
expectedType: UnwrappedType? = null,
returnTypeVariable: TypeVariableForLambdaReturnType? = null
): ResolvedLambdaAtom {
@@ -186,6 +197,7 @@ fun LambdaWithTypeVariableAsExpectedTypeAtom.transformToResolvedLambda(
csBuilder,
atom,
fixedExpectedType,
diagnosticsHolder,
forceResolution = true,
returnTypeVariable = returnTypeVariable
) as ResolvedLambdaAtom
@@ -51,7 +51,7 @@ class PostponedArgumentsAnalyzer(
is LambdaWithTypeVariableAsExpectedTypeAtom ->
analyzeLambda(
c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder()), diagnosticsHolder
c, resolutionCallbacks, argument.transformToResolvedLambda(c.getBuilder(), diagnosticsHolder), diagnosticsHolder
)
is ResolvedCallableReferenceAtom ->
@@ -147,7 +147,7 @@ class PostponedArgumentsAnalyzer(
if (inferenceSession != null) {
val storageSnapshot = c.getBuilder().currentStorage()
val postponedVariables = inferenceSession.inferPostponedVariables(lambda, storageSnapshot)
val postponedVariables = inferenceSession.inferPostponedVariables(lambda, storageSnapshot, diagnosticHolder)
for ((constructor, resultType) in postponedVariables) {
val variableWithConstraints = storageSnapshot.notFixedTypeVariables[constructor] ?: continue
@@ -49,13 +49,34 @@ class KotlinConstraintSystemCompleter(
completionMode: ConstraintSystemCompletionMode,
topLevelAtoms: List<ResolvedAtom>,
topLevelType: UnwrappedType,
diagnosticsHolder: KotlinDiagnosticsHolder,
analyze: (PostponedResolvedAtom) -> Unit
) {
runCompletion(c, completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext = false, analyze = analyze)
runCompletion(
c,
completionMode,
topLevelAtoms,
topLevelType,
diagnosticsHolder,
collectVariablesFromContext = false,
analyze = analyze
)
}
fun completeConstraintSystem(c: Context, topLevelType: UnwrappedType, topLevelAtoms: List<ResolvedAtom>) {
runCompletion(c, ConstraintSystemCompletionMode.FULL, topLevelAtoms, topLevelType, collectVariablesFromContext = true) {
fun completeConstraintSystem(
c: Context,
topLevelType: UnwrappedType,
topLevelAtoms: List<ResolvedAtom>,
diagnosticsHolder: KotlinDiagnosticsHolder
) {
runCompletion(
c,
ConstraintSystemCompletionMode.FULL,
topLevelAtoms,
topLevelType,
diagnosticsHolder,
collectVariablesFromContext = true,
) {
error("Shouldn't be called in complete constraint system mode")
}
}
@@ -65,6 +86,7 @@ class KotlinConstraintSystemCompleter(
completionMode: ConstraintSystemCompletionMode,
topLevelAtoms: List<ResolvedAtom>,
topLevelType: UnwrappedType,
diagnosticsHolder: KotlinDiagnosticsHolder,
collectVariablesFromContext: Boolean,
analyze: (PostponedResolvedAtom) -> Unit
) {
@@ -80,7 +102,13 @@ class KotlinConstraintSystemCompleter(
if (
completionMode == ConstraintSystemCompletionMode.FULL &&
resolveLambdaOrCallableReferenceWithTypeVariableAsExpectedType(c, variableForFixation, topLevelAtoms, analyze)
resolveLambdaOrCallableReferenceWithTypeVariableAsExpectedType(
c,
variableForFixation,
topLevelAtoms,
diagnosticsHolder,
analyze
)
) {
continue
}
@@ -104,7 +132,7 @@ class KotlinConstraintSystemCompleter(
getOrderedNotAnalyzedPostponedArguments(topLevelAtoms).forEach(analyze)
if (c.notFixedTypeVariables.isNotEmpty() && c.postponedTypeVariables.isEmpty()) {
runCompletion(c, completionMode, topLevelAtoms, topLevelType, analyze)
runCompletion(c, completionMode, topLevelAtoms, topLevelType, diagnosticsHolder, analyze)
}
}
}
@@ -116,6 +144,7 @@ class KotlinConstraintSystemCompleter(
c: Context,
variableForFixation: VariableFixationFinder.VariableForFixation,
topLevelAtoms: List<ResolvedAtom>,
diagnosticsHolder: KotlinDiagnosticsHolder,
analyze: (PostponedResolvedAtom) -> Unit
): Boolean {
val variable = variableForFixation.variable as TypeConstructor
@@ -156,7 +185,7 @@ class KotlinConstraintSystemCompleter(
isSuitable = KotlinType::isBuiltinFunctionalType,
typeVariableCreator = { TypeVariableForLambdaReturnType(postponedAtom.atom, builtIns, "_R") },
newAtomCreator = { returnVariable, expectedType ->
postponedAtom.transformToResolvedLambda(csBuilder, expectedType, returnVariable)
postponedAtom.transformToResolvedLambda(csBuilder, diagnosticsHolder, expectedType, returnVariable)
}
)
else -> return false
@@ -209,3 +209,12 @@ class ResolvedToSamWithVarargDiagnostic(val argument: KotlinCallArgument) : Kotl
reporter.onCallArgument(argument, this)
}
}
class NotEnoughInformationForLambdaParameter(
val lambdaArgument: LambdaKotlinCallArgument,
val parameterIndex: Int
) : KotlinCallDiagnostic(INAPPLICABLE) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCallArgument(lambdaArgument, this)
}
}