NI: Improve postponed arguments analysis

Introduce seven stages:
1) Analyze postponed arguments with fixed parameter types
2) Collect parameter types from constraints and lambda parameters' declaration
3) Fix not postponed variables for parameter types of all postponed arguments
4) Create atoms with revised expected types if needed
5) Analyze the first ready postponed argument and rerun stages if it has been analyzed
6) Force fixation remaining type variables: fix if possible or report not enough information
7) Force analysis remaining not analyzed postponed arguments and rerun stages if there are

^KT-37952 Fixed
^KT-32156 Fixed
^KT-37249 Fixed
^KT-37341 Fixed
This commit is contained in:
Victor Petukhov
2020-03-28 20:40:29 +03:00
parent 50151e0e01
commit 260683c20e
70 changed files with 2619 additions and 352 deletions
@@ -10741,6 +10741,44 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
public void testWithExact() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/withExact.kt");
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PostponedArgumentsAnalysis extends AbstractFirOldFrontendDiagnosticsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPostponedArgumentsAnalysis() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("basic.kt")
public void testBasic() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.kt");
}
@TestMetadata("callableReferenceLambdaCombinationInsideCall.kt")
public void testCallableReferenceLambdaCombinationInsideCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/callableReferenceLambdaCombinationInsideCall.kt");
}
@TestMetadata("callableReferences.kt")
public void testCallableReferences() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/callableReferences.kt");
}
@TestMetadata("lackOfDeepIncorporation.kt")
public void testLackOfDeepIncorporation() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/lackOfDeepIncorporation.kt");
}
@TestMetadata("lambdasInTryCatch.kt")
public void testLambdasInTryCatch() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/lambdasInTryCatch.kt");
}
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/constraints")
@@ -2059,6 +2059,82 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/completion")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Completion extends AbstractFirOldFrontendDiagnosticsTestWithStdlib {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCompletion() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/inference/completion"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PostponedArgumentsAnalysis extends AbstractFirOldFrontendDiagnosticsTestWithStdlib {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPostponedArgumentsAnalysis() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("callableReferences.kt")
public void testCallableReferences() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/callableReferences.kt");
}
@TestMetadata("complexInterdependentInputOutputTypes.kt")
public void testComplexInterdependentInputOutputTypes() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/complexInterdependentInputOutputTypes.kt");
}
@TestMetadata("deepLambdas.kt")
public void testDeepLambdas() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/deepLambdas.kt");
}
@TestMetadata("fixIndependentVariables.kt")
public void testFixIndependentVariables() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/fixIndependentVariables.kt");
}
@TestMetadata("fixInputTypeToMoreSpecificType.kt")
public void testFixInputTypeToMoreSpecificType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/fixInputTypeToMoreSpecificType.kt");
}
@TestMetadata("fixReceiverToMoreSpecificType.kt")
public void testFixReceiverToMoreSpecificType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/fixReceiverToMoreSpecificType.kt");
}
@TestMetadata("moreSpecificOutputType.kt")
public void testMoreSpecificOutputType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/moreSpecificOutputType.kt");
}
@TestMetadata("rerunStagesAfterFixationInFullMode.kt")
public void testRerunStagesAfterFixationInFullMode() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/rerunStagesAfterFixationInFullMode.kt");
}
@TestMetadata("rerunStagesAfterFixationInPartialMode.kt")
public void testRerunStagesAfterFixationInPartialMode() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/rerunStagesAfterFixationInPartialMode.kt");
}
@TestMetadata("suspendFunctions.kt")
public void testSuspendFunctions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/suspendFunctions.kt");
}
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/delegates")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -204,6 +204,8 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
return this.typeConstructor().isUnitTypeConstructor() && !this.isNullable
}
override fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype() = TODO()
override fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker {
require(this is ConeKotlinType)
return this.withNullability(ConeNullability.create(nullable), this@ConeInferenceContext)
@@ -93,7 +93,7 @@ private fun extraLambdaInfo(
val isFunctionSupertype = expectedType != null && KotlinBuiltIns.isNotNullOrNullableFunctionSupertype(expectedType)
val argumentAsFunctionExpression = argument.safeAs<FunctionExpression>()
val typeVariable = TypeVariableForLambdaReturnType(argument, builtIns, "_L")
val typeVariable = TypeVariableForLambdaReturnType(builtIns, "_L")
val receiverType = argumentAsFunctionExpression?.receiverType
val returnType =
@@ -150,10 +150,7 @@ class PostponedArgumentsAnalyzer(
val subResolvedKtPrimitives = allReturnArguments.map {
resolveKtPrimitive(
c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, ReceiverInfo.notReceiver, convertedType = null
).apply {
if (this is LambdaWithTypeVariableAsExpectedTypeAtom)
isReturnArgumentOfAnotherLambda = true
}
)
}
if (!returnArgumentsInfo.returnArgumentsExist) {
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.resolve.calls.components.KotlinCallCompleter
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.PostponedArgumentInputTypesResolver
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
@@ -35,4 +36,5 @@ interface NewConstraintSystem {
fun asConstraintSystemCompleterContext(): KotlinConstraintSystemCompleter.Context
fun asPostponedArgumentsAnalyzerContext(): PostponedArgumentsAnalyzer.Context
fun asPostponedArgumentInputTypesResolverContext(): PostponedArgumentInputTypesResolver.Context
}
@@ -5,28 +5,23 @@
package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.resolve.calls.components.transformToResolvedLambda
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import kotlin.collections.LinkedHashSet
class KotlinConstraintSystemCompleter(
private val resultTypeResolver: ResultTypeResolver,
val variableFixationFinder: VariableFixationFinder,
) {
private val postponedArgumentInputTypesResolver = PostponedArgumentInputTypesResolver(resultTypeResolver, variableFixationFinder)
enum class ConstraintSystemCompletionMode {
FULL,
PARTIAL
@@ -37,6 +32,8 @@ class KotlinConstraintSystemCompleter(
override val notFixedTypeVariables: Map<TypeConstructorMarker, VariableWithConstraints>
override val postponedTypeVariables: List<TypeVariableMarker>
fun getBuilder(): ConstraintSystemBuilder
// type can be proper if it not contains not fixed type variables
fun canBeProper(type: KotlinTypeMarker): Boolean
@@ -46,6 +43,8 @@ class KotlinConstraintSystemCompleter(
fun addError(error: KotlinCallDiagnostic)
fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker, atom: ResolvedAtom?)
fun asPostponedArgumentInputTypesResolverContext(): PostponedArgumentInputTypesResolver.Context
}
fun runCompletion(
@@ -56,8 +55,7 @@ class KotlinConstraintSystemCompleter(
diagnosticsHolder: KotlinDiagnosticsHolder,
analyze: (PostponedResolvedAtom) -> Unit
) {
runCompletion(
c,
c.runCompletion(
completionMode,
topLevelAtoms,
topLevelType,
@@ -73,8 +71,7 @@ class KotlinConstraintSystemCompleter(
topLevelAtoms: List<ResolvedAtom>,
diagnosticsHolder: KotlinDiagnosticsHolder
) {
runCompletion(
c,
c.runCompletion(
ConstraintSystemCompletionMode.FULL,
topLevelAtoms,
topLevelType,
@@ -85,8 +82,8 @@ class KotlinConstraintSystemCompleter(
}
}
private fun runCompletion(
c: Context,
// TODO: investigate type variables fixation order and incorporation depth (see `diagnostics/tests/inference/completion/postponedArgumentsAnalysis/lackOfDeepIncorporation.kt`)
private fun Context.runCompletion(
completionMode: ConstraintSystemCompletionMode,
topLevelAtoms: List<ResolvedAtom>,
topLevelType: UnwrappedType,
@@ -94,241 +91,242 @@ class KotlinConstraintSystemCompleter(
collectVariablesFromContext: Boolean,
analyze: (PostponedResolvedAtom) -> Unit
) {
while (true) {
if (analyzePostponeArgumentIfPossible(c, topLevelAtoms, analyze)) continue
completion@ while (true) {
val postponedArguments = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
val allTypeVariables = getOrderedAllTypeVariables(c, collectVariablesFromContext, topLevelAtoms)
val postponedKtPrimitives = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
val variableForFixation =
variableFixationFinder.findFirstVariableForFixation(
c, allTypeVariables, postponedKtPrimitives, completionMode, topLevelType
) ?: break
if (
completionMode == ConstraintSystemCompletionMode.FULL &&
c.resolveLambdaByAdditionalConditions(
variableForFixation,
topLevelAtoms,
diagnosticsHolder,
analyze,
variableFixationFinder
)
) {
// Stage 1: analyze postponed arguments with fixed parameter types
if (analyzeArgumentWithFixedParameterTypes(postponedArguments, analyze))
continue
val isThereAnyReadyForFixationVariable = isThereAnyReadyForFixationVariable(
completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, postponedArguments
)
// If there aren't any postponed arguments and ready for fixation variables, then completion isn't needed: nothing to do
if (postponedArguments.isEmpty() && !isThereAnyReadyForFixationVariable)
break
val postponedArgumentsWithRevisableType = postponedArguments.filterIsInstance<PostponedAtomWithRevisableExpectedType>()
val dependencyProvider =
TypeVariableDependencyInformationProvider(notFixedTypeVariables, postponedArguments, topLevelType, this)
// Stage 2: collect parameter types for postponed arguments
postponedArgumentInputTypesResolver.collectParameterTypesAndBuildNewExpectedTypes(
asPostponedArgumentInputTypesResolverContext(), postponedArgumentsWithRevisableType, completionMode, dependencyProvider
)
if (completionMode == ConstraintSystemCompletionMode.FULL) {
// Stage 3: fix variables for parameter types of all postponed arguments
for (argument in postponedArguments) {
val wasFixedSomeVariable = postponedArgumentInputTypesResolver.fixNextReadyVariableForParameterTypeIfNeeded(
asPostponedArgumentInputTypesResolverContext(),
argument,
postponedArguments,
topLevelType,
topLevelAtoms,
dependencyProvider
)
if (wasFixedSomeVariable)
continue@completion
}
// Stage 4: create atoms with revised expected types if needed
for (argument in postponedArgumentsWithRevisableType) {
postponedArgumentInputTypesResolver.transformToAtomWithNewFunctionalExpectedType(
asPostponedArgumentInputTypesResolverContext(), argument, diagnosticsHolder
)
}
}
if (variableForFixation.hasProperConstraint || completionMode == ConstraintSystemCompletionMode.FULL) {
val variableWithConstraints = c.notFixedTypeVariables.getValue(variableForFixation.variable)
if (variableForFixation.hasProperConstraint)
fixVariable(c, variableWithConstraints, topLevelAtoms)
else
processVariableWhenNotEnoughInformation(c, variableWithConstraints, topLevelAtoms)
/*
* We should get not analyzed postponed arguments again because they can be changed by
* the stage of fixation type variables for parameters or analysing postponed arguments with fixed parameter types (see stage #1 and #4)
*/
val revisedPostponedArguments = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
// Stage 5: analyze the next ready postponed argument
if (analyzeNextReadyPostponedArgument(revisedPostponedArguments, completionMode, analyze))
continue
// Stage 6: fix type variables fix if possible or report not enough information (if completion mode is full)
val wasFixedSomeVariable = fixVariablesOrReportNotEnoughInformation(
completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, revisedPostponedArguments, diagnosticsHolder
)
if (wasFixedSomeVariable)
continue
// Stage 7: force analysis of remaining not analyzed postponed arguments and rerun stages if there are
if (completionMode == ConstraintSystemCompletionMode.FULL) {
if (analyzeRemainingNotAnalyzedPostponedArgument(revisedPostponedArguments, analyze))
continue
}
break
}
if (completionMode == ConstraintSystemCompletionMode.FULL) {
// force resolution for all not-analyzed argument's
getOrderedNotAnalyzedPostponedArguments(topLevelAtoms).forEach(analyze)
if (c.notFixedTypeVariables.isNotEmpty() && c.postponedTypeVariables.isEmpty()) {
runCompletion(c, completionMode, topLevelAtoms, topLevelType, diagnosticsHolder, analyze)
}
}
}
/*
* returns true -> analyzed
*/
private fun Context.resolveLambdaByAdditionalConditions(
variableForFixation: VariableFixationFinder.VariableForFixation,
topLevelAtoms: List<ResolvedAtom>,
diagnosticsHolder: KotlinDiagnosticsHolder,
analyze: (PostponedResolvedAtom) -> Unit,
fixationFinder: VariableFixationFinder
): Boolean {
val postponedArguments = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
if (postponedArguments.isEmpty())
return false
val groupedPostponedArguments = postponedArguments.filterIsInstance<LambdaWithTypeVariableAsExpectedTypeAtom>()
.ifEmpty { postponedArguments.filter { it !is LambdaWithTypeVariableAsExpectedTypeAtom } }
if (groupedPostponedArguments.isEmpty())
return false
fun shouldAnalyzeLambdaWithTypeVariableAsExpectedType(argument: PostponedResolvedAtom): Boolean {
val hasProperAtom = when (argument) {
is LambdaWithTypeVariableAsExpectedTypeAtom, is PostponedCallableReferenceAtom ->
argument.expectedType?.constructor == variableForFixation.variable
else -> false
}
return hasProperAtom || !variableForFixation.hasProperConstraint || variableForFixation.hasOnlyTrivialProperConstraint
}
fun shouldAnalyzeLambdaWhichIsReturnArgument(argument: PostponedResolvedAtom): Boolean {
val isReturnArgumentOfAnotherLambda =
argument is LambdaWithTypeVariableAsExpectedTypeAtom && argument.isReturnArgumentOfAnotherLambda
val atomExpectedType = argument.expectedType
return isReturnArgumentOfAnotherLambda && atomExpectedType != null &&
with(fixationFinder) { variableHasTrivialOrNonProperConstraints(atomExpectedType.constructor) }
}
return resolveLambdaByCondition(
variableForFixation, groupedPostponedArguments, diagnosticsHolder, analyze, ::shouldAnalyzeLambdaWithTypeVariableAsExpectedType
) || resolveLambdaByCondition(
variableForFixation, groupedPostponedArguments, diagnosticsHolder, analyze, ::shouldAnalyzeLambdaWhichIsReturnArgument
)
}
/*
* returns true -> analyzed
*/
private fun Context.resolveLambdaByCondition(
variableForFixation: VariableFixationFinder.VariableForFixation,
private fun Context.analyzeArgumentWithFixedParameterTypes(
postponedArguments: List<PostponedResolvedAtom>,
diagnosticsHolder: KotlinDiagnosticsHolder,
analyze: (PostponedResolvedAtom) -> Unit,
shouldAnalyze: (PostponedResolvedAtom) -> Boolean
): Boolean {
val variable = variableForFixation.variable as? TypeConstructor ?: return false
return postponedArguments.all { argument ->
if (!shouldAnalyze(argument))
return@all false
val expectedTypeVariable = argument.expectedType?.constructor?.takeIf { it in allTypeVariables } ?: variable
val preparedAtom =
preparePostponedAtom(expectedTypeVariable, argument, expectedTypeVariable.builtIns, diagnosticsHolder)
?: return@all false
analyze(preparedAtom)
true
}
}
private fun Context.preparePostponedAtom(
expectedTypeVariable: TypeConstructor,
postponedAtom: PostponedResolvedAtom,
builtIns: KotlinBuiltIns,
diagnosticsHolder: KotlinDiagnosticsHolder
): PostponedResolvedAtom? {
val csBuilder = (this as? NewConstraintSystem)?.getBuilder() ?: return null
return when (postponedAtom) {
is PostponedCallableReferenceAtom -> postponedAtom.preparePostponedAtomWithTypeVariableAsExpectedType(
this, csBuilder, expectedTypeVariable,
parameterTypes = null,
isSuitable = KotlinType::isBuiltinFunctionalTypeOrSubtype,
typeVariableCreator = { TypeVariableForCallableReferenceReturnType(builtIns, "_Q") },
newAtomCreator = { returnVariable, expectedType ->
CallableReferenceWithTypeVariableAsExpectedTypeAtom(postponedAtom.atom, expectedType, returnVariable).also {
postponedAtom.setAnalyzedResults(null, listOf(it))
}
}
)
is LambdaWithTypeVariableAsExpectedTypeAtom -> postponedAtom.preparePostponedAtomWithTypeVariableAsExpectedType(
this, csBuilder, expectedTypeVariable,
parameterTypes = postponedAtom.atom.parametersTypes,
isSuitable = KotlinType::isBuiltinFunctionalType,
typeVariableCreator = { TypeVariableForLambdaReturnType(postponedAtom.atom, builtIns, "_R") },
newAtomCreator = { returnVariable, expectedType ->
postponedAtom.transformToResolvedLambda(csBuilder, diagnosticsHolder, expectedType, returnVariable)
}
)
else -> null
}
}
private inline fun <T : PostponedResolvedAtom, V : NewTypeVariable> T.preparePostponedAtomWithTypeVariableAsExpectedType(
c: Context,
csBuilder: ConstraintSystemBuilder,
variable: TypeConstructor,
parameterTypes: Array<out KotlinType?>?,
isSuitable: KotlinType.() -> Boolean,
typeVariableCreator: () -> V,
newAtomCreator: (V, SimpleType) -> PostponedResolvedAtom
): PostponedResolvedAtom {
val functionalType = resultTypeResolver.findResultType(
c,
c.notFixedTypeVariables.getValue(variable),
TypeVariableDirectionCalculator.ResolveDirection.TO_SUPERTYPE
) as KotlinType
val isExtensionFunction = functionalType.isExtensionFunctionType
val isExtensionFunctionWithReceiverAsDeclaredParameter =
isExtensionFunction && functionalType.arguments.size - 1 == parameterTypes?.count { it != null }
if (parameterTypes?.all { it != null } == true && (!isExtensionFunction || isExtensionFunctionWithReceiverAsDeclaredParameter)) return this
if (!functionalType.isSuitable()) return this
val returnVariable = typeVariableCreator()
csBuilder.registerVariable(returnVariable)
val expectedType = KotlinTypeFactory.simpleType(
functionalType.annotations,
functionalType.constructor,
functionalType.arguments.dropLast(1) + returnVariable.defaultType.asTypeProjection(),
functionalType.isMarkedNullable
)
csBuilder.addSubtypeConstraint(
expectedType,
variable.typeForTypeVariable(),
ArgumentConstraintPosition(atom as KotlinCallArgument)
)
return newAtomCreator(returnVariable, expectedType)
}
// true if we do analyze
private fun analyzePostponeArgumentIfPossible(
c: Context,
topLevelAtoms: List<ResolvedAtom>,
analyze: (PostponedResolvedAtom) -> Unit
): Boolean {
for (argument in getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
if (canWeAnalyzeIt(c, argument)) {
analyze(argument)
return true
}
val argumentWithFixedOrPostponedInputTypes = findPostponedArgumentWithFixedOrPostponedInputTypes(postponedArguments)
if (argumentWithFixedOrPostponedInputTypes != null) {
analyze(argumentWithFixedOrPostponedInputTypes)
return true
}
return false
}
private fun getOrderedAllTypeVariables(
private fun Context.analyzeNextReadyPostponedArgument(
postponedArguments: List<PostponedResolvedAtom>,
completionMode: ConstraintSystemCompletionMode,
analyze: (PostponedResolvedAtom) -> Unit
): Boolean {
if (completionMode == ConstraintSystemCompletionMode.FULL) {
val argumentWithTypeVariableAsExpectedType = findPostponedArgumentWithRevisableExpectedType(postponedArguments)
if (argumentWithTypeVariableAsExpectedType != null) {
analyze(argumentWithTypeVariableAsExpectedType)
return true
}
}
return analyzeArgumentWithFixedParameterTypes(postponedArguments, analyze)
}
private fun analyzeRemainingNotAnalyzedPostponedArgument(
postponedArguments: List<PostponedResolvedAtom>,
analyze: (PostponedResolvedAtom) -> Unit
): Boolean {
val remainingNotAnalyzedPostponedArgument = postponedArguments.firstOrNull { !it.analyzed }
if (remainingNotAnalyzedPostponedArgument != null) {
analyze(remainingNotAnalyzedPostponedArgument)
return true
}
return false
}
private fun findPostponedArgumentWithRevisableExpectedType(postponedArguments: List<PostponedResolvedAtom>) =
postponedArguments.firstOrNull { argument -> argument is PostponedAtomWithRevisableExpectedType }
private fun Context.findPostponedArgumentWithFixedOrPostponedInputTypes(postponedArguments: List<PostponedResolvedAtom>) =
postponedArguments.firstOrNull { argument -> argument.inputTypes.all { containsOnlyFixedOrPostponedVariables(it) } }
private fun fixVariable(
c: Context,
variableWithConstraints: VariableWithConstraints,
topLevelAtoms: List<ResolvedAtom>
) {
fixVariable(c, variableWithConstraints, TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN, topLevelAtoms)
}
private fun fixVariable(
c: Context,
variableWithConstraints: VariableWithConstraints,
direction: TypeVariableDirectionCalculator.ResolveDirection,
topLevelAtoms: List<ResolvedAtom>
) {
val resultType = resultTypeResolver.findResultType(c, variableWithConstraints, direction)
val resolvedAtom = findResolvedAtomBy(variableWithConstraints.typeVariable, topLevelAtoms) ?: topLevelAtoms.firstOrNull()
c.fixVariable(variableWithConstraints.typeVariable, resultType, resolvedAtom)
}
private fun Context.fixVariablesOrReportNotEnoughInformation(
completionMode: ConstraintSystemCompletionMode,
topLevelAtoms: List<ResolvedAtom>,
topLevelType: UnwrappedType,
collectVariablesFromContext: Boolean,
postponedArguments: List<PostponedResolvedAtom>,
diagnosticsHolder: KotlinDiagnosticsHolder
): Boolean {
while (true) {
val variableForFixation = getVariableReadyForFixation(
completionMode,
topLevelAtoms,
topLevelType,
collectVariablesFromContext,
postponedArguments
) ?: break
if (!variableForFixation.hasProperConstraint && completionMode == ConstraintSystemCompletionMode.PARTIAL)
break
val variableWithConstraints = notFixedTypeVariables.getValue(variableForFixation.variable)
if (variableForFixation.hasProperConstraint) {
fixVariable(this, variableWithConstraints, topLevelAtoms)
return true
} else {
processVariableWhenNotEnoughInformation(this, variableWithConstraints, topLevelAtoms, diagnosticsHolder)
}
}
return false
}
private fun processVariableWhenNotEnoughInformation(
c: Context,
variableWithConstraints: VariableWithConstraints,
topLevelAtoms: List<ResolvedAtom>,
diagnosticsHolder: KotlinDiagnosticsHolder
) {
val typeVariable = variableWithConstraints.typeVariable
val resolvedAtom = findResolvedAtomBy(typeVariable, topLevelAtoms) ?: topLevelAtoms.firstOrNull()
if (resolvedAtom != null) {
c.addError(NotEnoughInformationForTypeParameter(typeVariable, resolvedAtom))
}
val resultErrorType = when {
typeVariable is TypeVariableFromCallableDescriptor ->
ErrorUtils.createUninferredParameterType(typeVariable.originalTypeParameter)
typeVariable is TypeVariableForLambdaParameterType && typeVariable.atom is LambdaKotlinCallArgument -> {
diagnosticsHolder.addDiagnostic(
NotEnoughInformationForLambdaParameter(typeVariable.atom, typeVariable.index)
)
ErrorUtils.createErrorType("Cannot infer lambda parameter type")
}
else -> ErrorUtils.createErrorType("Cannot infer type variable $typeVariable")
}
c.fixVariable(typeVariable, resultErrorType, resolvedAtom)
}
private fun Context.getOrderedAllTypeVariables(
collectVariablesFromContext: Boolean,
topLevelAtoms: List<ResolvedAtom>
): List<TypeConstructorMarker> {
if (collectVariablesFromContext) return c.notFixedTypeVariables.keys.toList()
if (collectVariablesFromContext)
return notFixedTypeVariables.keys.toList()
fun getVariablesFromRevisedExpectedType(revisedExpectedType: KotlinType?) =
revisedExpectedType?.arguments?.map { it.type.constructor }?.filterIsInstance<TypeVariableTypeConstructor>()
fun ResolvedAtom.process(to: LinkedHashSet<TypeConstructor>) {
val typeVariables = when (this) {
is ResolvedCallAtom -> freshVariablesSubstitutor.freshVariables
is CallableReferenceWithTypeVariableAsExpectedTypeAtom -> mutableListOf<NewTypeVariable>().apply {
addIfNotNull(typeVariableForReturnType)
addAll(candidate?.freshSubstitutor?.freshVariables.orEmpty())
}
is ResolvedCallableReferenceAtom -> candidate?.freshSubstitutor?.freshVariables.orEmpty()
is ResolvedLambdaAtom -> listOfNotNull(typeVariableForLambdaReturnType)
is LambdaWithTypeVariableAsExpectedTypeAtom -> getVariablesFromRevisedExpectedType(revisedExpectedType).orEmpty()
is ResolvedCallAtom -> freshVariablesSubstitutor.freshVariables.map { it.freshTypeConstructor }
is PostponedCallableReferenceAtom ->
getVariablesFromRevisedExpectedType(revisedExpectedType).orEmpty() +
candidate?.freshSubstitutor?.freshVariables?.map { it.freshTypeConstructor }.orEmpty()
is ResolvedCallableReferenceAtom -> candidate?.freshSubstitutor?.freshVariables?.map { it.freshTypeConstructor }.orEmpty()
is ResolvedLambdaAtom -> listOfNotNull(typeVariableForLambdaReturnType?.freshTypeConstructor)
else -> emptyList()
}
typeVariables.mapNotNullTo(to) {
val typeConstructor = it.freshTypeConstructor
typeConstructor.takeIf { c.notFixedTypeVariables.containsKey(typeConstructor) }
it.takeIf { notFixedTypeVariables.containsKey(it) }
}
/*
* Hack for completing error candidates in delegate resolve
*/
if (this is StubResolvedAtom && typeVariable in c.notFixedTypeVariables) {
if (this is StubResolvedAtom && typeVariable in notFixedTypeVariables) {
to += typeVariable
}
@@ -343,86 +341,35 @@ class KotlinConstraintSystemCompleter(
primitive.process(result)
}
assert(result.size == c.notFixedTypeVariables.size) {
val notFoundTypeVariables = c.notFixedTypeVariables.keys.toMutableSet().apply { removeAll(result) }
assert(result.size == notFixedTypeVariables.size) {
val notFoundTypeVariables = notFixedTypeVariables.keys.toMutableSet().apply { removeAll(result) }
"Not all type variables found: $notFoundTypeVariables"
}
return result.toList()
}
private fun Context.getVariableReadyForFixation(
completionMode: ConstraintSystemCompletionMode,
topLevelAtoms: List<ResolvedAtom>,
topLevelType: UnwrappedType,
collectVariablesFromContext: Boolean,
postponedArguments: List<PostponedResolvedAtom>
) = variableFixationFinder.findFirstVariableForFixation(
this,
getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms),
postponedArguments,
completionMode,
topLevelType
)
private fun canWeAnalyzeIt(c: Context, argument: PostponedResolvedAtom): Boolean {
if (argument.analyzed) return false
return argument.inputTypes.all { c.containsOnlyFixedOrPostponedVariables(it) }
}
private fun fixVariable(
c: Context,
variableWithConstraints: VariableWithConstraints,
topLevelAtoms: List<ResolvedAtom>
) {
fixVariable(c, variableWithConstraints, TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN, topLevelAtoms)
}
fun fixVariable(
c: Context,
variableWithConstraints: VariableWithConstraints,
direction: TypeVariableDirectionCalculator.ResolveDirection,
topLevelAtoms: List<ResolvedAtom>
) {
val resultType = resultTypeResolver.findResultType(c, variableWithConstraints, direction)
val resolvedAtom = findResolvedAtomBy(variableWithConstraints.typeVariable, topLevelAtoms) ?: topLevelAtoms.firstOrNull()
c.fixVariable(variableWithConstraints.typeVariable, resultType, resolvedAtom)
}
private fun processVariableWhenNotEnoughInformation(
c: Context,
variableWithConstraints: VariableWithConstraints,
topLevelAtoms: List<ResolvedAtom>
) {
val typeVariable = variableWithConstraints.typeVariable
val resolvedAtom = findResolvedAtomBy(typeVariable, topLevelAtoms) ?: topLevelAtoms.firstOrNull()
if (resolvedAtom != null) {
c.addError(NotEnoughInformationForTypeParameter(typeVariable, resolvedAtom))
}
val resultErrorType = if (typeVariable is TypeVariableFromCallableDescriptor)
ErrorUtils.createUninferredParameterType(typeVariable.originalTypeParameter)
else
ErrorUtils.createErrorType("Cannot infer type variable $typeVariable")
c.fixVariable(typeVariable, resultErrorType, resolvedAtom)
}
private fun findResolvedAtomBy(typeVariable: TypeVariableMarker, topLevelAtoms: List<ResolvedAtom>): ResolvedAtom? {
fun ResolvedAtom.check(): ResolvedAtom? {
val suitableCall = when (this) {
is ResolvedCallAtom -> typeVariable in freshVariablesSubstitutor.freshVariables
is ResolvedCallableReferenceAtom -> candidate?.freshSubstitutor?.freshVariables?.let { typeVariable in it } ?: false
is ResolvedLambdaAtom -> typeVariable == typeVariableForLambdaReturnType
else -> false
}
if (suitableCall) {
return this
}
subResolvedAtoms?.forEach { subResolvedAtom ->
subResolvedAtom.check()?.let { result -> return@check result }
}
return null
}
for (topLevelAtom in topLevelAtoms) {
topLevelAtom.check()?.let { return it }
}
return null
}
private fun Context.isThereAnyReadyForFixationVariable(
completionMode: ConstraintSystemCompletionMode,
topLevelAtoms: List<ResolvedAtom>,
topLevelType: UnwrappedType,
collectVariablesFromContext: Boolean,
postponedArguments: List<PostponedResolvedAtom>
) = getVariableReadyForFixation(completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, postponedArguments) != null
companion object {
fun getOrderedNotAnalyzedPostponedArguments(topLevelAtoms: List<ResolvedAtom>): List<PostponedResolvedAtom> {
@@ -441,5 +388,32 @@ class KotlinConstraintSystemCompleter(
return notAnalyzedArguments
}
fun findResolvedAtomBy(typeVariable: TypeVariableMarker, topLevelAtoms: List<ResolvedAtom>): ResolvedAtom? {
fun ResolvedAtom.check(): ResolvedAtom? {
val suitableCall = when (this) {
is ResolvedCallAtom -> typeVariable in freshVariablesSubstitutor.freshVariables
is ResolvedCallableReferenceAtom -> candidate?.freshSubstitutor?.freshVariables?.let { typeVariable in it } ?: false
is ResolvedLambdaAtom -> typeVariable == typeVariableForLambdaReturnType
else -> false
}
if (suitableCall) {
return this
}
subResolvedAtoms?.forEach { subResolvedAtom ->
subResolvedAtom.check()?.let { result -> return@check result }
}
return null
}
for (topLevelAtom in topLevelAtoms) {
topLevelAtom.check()?.let { return it }
}
return null
}
}
}
}
@@ -0,0 +1,473 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.resolve.calls.components.transformToResolvedLambda
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class PostponedArgumentInputTypesResolver(
private val resultTypeResolver: ResultTypeResolver,
private val variableFixationFinder: VariableFixationFinder
) {
interface Context : KotlinConstraintSystemCompleter.Context
data class ParameterTypesInfo(
val parametersFromDeclaration: List<UnwrappedType?>?,
val parametersFromDeclarationOfRelatedLambdas: Set<List<UnwrappedType?>>?,
val parametersFromConstraints: Set<List<TypeWithKind>>?,
val annotations: Annotations,
val isSuspend: Boolean,
val isNullable: Boolean
)
data class TypeWithKind(
val type: KotlinType,
val direction: ConstraintKind = ConstraintKind.UPPER
)
private fun Context.findFunctionalTypesInConstraints(
variable: VariableWithConstraints,
variableDependencyProvider: TypeVariableDependencyInformationProvider
): List<TypeWithKind>? {
fun List<Constraint>.extractFunctionalTypes() = mapNotNull { constraint ->
val type = constraint.type as? KotlinType ?: return@mapNotNull null
TypeWithKind(type.extractFunctionalTypeFromSupertypes(), constraint.kind)
}
val typeVariableTypeConstructor = variable.typeVariable.freshTypeConstructor() as? TypeVariableTypeConstructor ?: return null
val dependentVariables =
variableDependencyProvider.getShallowlyDependentVariables(typeVariableTypeConstructor).orEmpty() + typeVariableTypeConstructor
return dependentVariables.mapNotNull { type ->
val constraints = notFixedTypeVariables[type]?.constraints ?: return@mapNotNull null
val constraintsWithFunctionalType = constraints.filter { (it.type as? KotlinType)?.isBuiltinFunctionalTypeOrSubtype == true }
constraintsWithFunctionalType.extractFunctionalTypes()
}.flatten()
}
private fun extractParameterTypesFromDeclaration(atom: ResolutionAtom) =
when (atom) {
is FunctionExpression -> {
val receiverType = atom.receiverType
if (receiverType != null) listOf(receiverType) + atom.parametersTypes else atom.parametersTypes.toList()
}
is LambdaKotlinCallArgument -> atom.parametersTypes?.toList()
else -> null
}
private fun Context.extractParameterTypesInfo(
argument: PostponedAtomWithRevisableExpectedType,
postponedArguments: List<PostponedAtomWithRevisableExpectedType>,
variableDependencyProvider: TypeVariableDependencyInformationProvider
): ParameterTypesInfo? {
val expectedType = argument.expectedType ?: return null
val variableWithConstraints = notFixedTypeVariables[expectedType.constructor] ?: return null
// We shouldn't collect functional types from constraints for anonymous functions as they have fully explicit declaration form
val functionalTypesFromConstraints = if (!isAnonymousFunction(argument)) {
findFunctionalTypesInConstraints(variableWithConstraints, variableDependencyProvider)
} else null
// Don't create functional expected type for further error reporting about a different number of arguments
if (functionalTypesFromConstraints != null && functionalTypesFromConstraints.distinctBy { it.type.argumentsCount() }.size > 1)
return null
val parameterTypesFromDeclaration =
if (argument is LambdaWithTypeVariableAsExpectedTypeAtom) argument.parameterTypesFromDeclaration else null
val parameterTypesFromConstraints = functionalTypesFromConstraints?.map { typeWithKind ->
typeWithKind.type.getPureArgumentsForFunctionalTypeOrSubtype().map {
// We should use opposite kind as lambda's parameters are contravariant
TypeWithKind(it, typeWithKind.direction.opposite())
}
}?.toSet()
val annotations = functionalTypesFromConstraints?.run {
Annotations.create(map { it.type.annotations }.flatten())
}
val parameterTypesFromDeclarationOfRelatedLambdas =
getDeclaredParametersFromRelatedLambdas(argument, postponedArguments, variableDependencyProvider)
return ParameterTypesInfo(
parameterTypesFromDeclaration,
parameterTypesFromDeclarationOfRelatedLambdas,
parameterTypesFromConstraints,
annotations ?: Annotations.EMPTY,
isSuspend = !functionalTypesFromConstraints.isNullOrEmpty() && functionalTypesFromConstraints.any { it.type.isSuspendFunctionTypeOrSubtype },
isNullable = !functionalTypesFromConstraints.isNullOrEmpty() && functionalTypesFromConstraints.all { it.type.isMarkedNullable }
)
}
private fun Context.getDeclaredParametersFromRelatedLambdas(
argument: PostponedAtomWithRevisableExpectedType,
postponedArguments: List<PostponedAtomWithRevisableExpectedType>,
dependencyProvider: TypeVariableDependencyInformationProvider
): Set<List<UnwrappedType?>>? {
fun PostponedAtomWithRevisableExpectedType.getExpectedTypeConstructor() = expectedType?.typeConstructor()
val parameterTypesFromDeclarationOfRelatedLambdas = postponedArguments
.filterIsInstance<LambdaWithTypeVariableAsExpectedTypeAtom>()
.filter { it.parameterTypesFromDeclaration != null && it != argument }
.mapNotNull { anotherArgument ->
val argumentExpectedTypeConstructor = argument.getExpectedTypeConstructor() ?: return@mapNotNull null
val anotherArgumentExpectedTypeConstructor = anotherArgument.getExpectedTypeConstructor() ?: return@mapNotNull null
val areTypeVariablesRelated = dependencyProvider.areVariablesDependentShallowly(
argumentExpectedTypeConstructor,
anotherArgumentExpectedTypeConstructor
)
if (areTypeVariablesRelated) anotherArgument.parameterTypesFromDeclaration else null
}
return parameterTypesFromDeclarationOfRelatedLambdas.toSet().takeIf { it.isNotEmpty() }
}
private fun Context.createTypeVariableForReturnType(argument: PostponedAtomWithRevisableExpectedType): NewTypeVariable {
val expectedType = argument.expectedType
?: throw IllegalStateException("Postponed argument's expected type must not be null")
return when (argument) {
is LambdaWithTypeVariableAsExpectedTypeAtom -> TypeVariableForLambdaReturnType(
expectedType.builtIns,
TYPE_VARIABLE_NAME_FOR_LAMBDA_RETURN_TYPE
)
is PostponedCallableReferenceAtom -> TypeVariableForCallableReferenceReturnType(
expectedType.builtIns,
TYPE_VARIABLE_NAME_FOR_CR_RETURN_TYPE
)
else -> throw IllegalStateException("Unsupported postponed argument type of $argument")
}.also { getBuilder().registerVariable(it) }
}
private fun Context.createTypeVariableForParameterType(
argument: PostponedAtomWithRevisableExpectedType,
index: Int
): NewTypeVariable {
val expectedType = argument.expectedType
?: throw IllegalStateException("Postponed argument's expected type must not be null")
return when (argument) {
is LambdaWithTypeVariableAsExpectedTypeAtom -> TypeVariableForLambdaParameterType(
argument.atom,
index,
expectedType.builtIns,
TYPE_VARIABLE_NAME_PREFIX_FOR_LAMBDA_PARAMETER_TYPE + (index + 1)
)
is PostponedCallableReferenceAtom -> TypeVariableForCallableReferenceParameterType(
expectedType.builtIns,
TYPE_VARIABLE_NAME_PREFIX_FOR_CR_PARAMETER_TYPE + (index + 1)
)
else -> throw IllegalStateException("Unsupported postponed argument type of $argument")
}.also { getBuilder().registerVariable(it) }
}
private fun Context.createTypeVariablesForParameters(
argument: PostponedAtomWithRevisableExpectedType,
parameterTypes: List<List<TypeWithKind?>>
): List<TypeProjection> {
val atom = argument.atom
val csBuilder = getBuilder()
val allGroupedParameterTypes = parameterTypes.first().indices.map { i -> parameterTypes.map { it.getOrNull(i) } }
return allGroupedParameterTypes.mapIndexed { index, types ->
val parameterTypeVariable = createTypeVariableForParameterType(argument, index)
for (typeWithKind in types.filterNotNull()) {
when (typeWithKind.direction) {
ConstraintKind.EQUALITY -> csBuilder.addEqualityConstraint(
parameterTypeVariable.defaultType, typeWithKind.type, ArgumentConstraintPosition(atom)
)
ConstraintKind.UPPER -> csBuilder.addSubtypeConstraint(
parameterTypeVariable.defaultType, typeWithKind.type, ArgumentConstraintPosition(atom)
)
ConstraintKind.LOWER -> csBuilder.addSubtypeConstraint(
typeWithKind.type, parameterTypeVariable.defaultType, ArgumentConstraintPosition(atom)
)
}
}
parameterTypeVariable.defaultType.asTypeProjection()
}
}
private fun Context.computeResultingFunctionalConstructor(
argument: PostponedAtomWithRevisableExpectedType,
parametersNumber: Int,
isSuspend: Boolean,
resultTypeResolver: ResultTypeResolver
): TypeConstructor {
val expectedType = argument.expectedType
?: throw IllegalStateException("Postponed argument's expected type must not be null")
val expectedTypeConstructor = expectedType.constructor
return when (argument) {
is LambdaWithTypeVariableAsExpectedTypeAtom ->
getFunctionDescriptor(expectedTypeConstructor.builtIns, parametersNumber, isSuspend).typeConstructor
is PostponedCallableReferenceAtom -> {
val computedResultType = resultTypeResolver.findResultType(
this,
notFixedTypeVariables.getValue(expectedTypeConstructor),
TypeVariableDirectionCalculator.ResolveDirection.TO_SUPERTYPE
)
// Avoid KFunction<...>/Function<...> types
if (computedResultType.isBuiltinFunctionalTypeOrSubtype() && computedResultType.argumentsCount() > 1) {
computedResultType.typeConstructor() as TypeConstructor
} else {
getKFunctionDescriptor(expectedTypeConstructor.builtIns, parametersNumber, isSuspend).typeConstructor
}
}
else -> throw IllegalStateException("Unsupported postponed argument type of $argument")
}
}
private fun Context.buildNewFunctionalExpectedType(
argument: PostponedAtomWithRevisableExpectedType,
parameterTypesInfo: ParameterTypesInfo
): UnwrappedType? {
val expectedType = argument.expectedType
if (expectedType == null || expectedType.constructor !in notFixedTypeVariables)
return null
val atom = argument.atom
val parametersFromConstraints = parameterTypesInfo.parametersFromConstraints
val parametersFromDeclaration = getDeclaredParametersConsideringExtensionFunctionsPresence(parameterTypesInfo)
val areAllParameterTypesSpecified = !parametersFromDeclaration.isNullOrEmpty() && parametersFromDeclaration.all { it != null }
val isExtensionFunction = parameterTypesInfo.annotations.hasExtensionFunctionAnnotation()
val parametersFromDeclarations = parameterTypesInfo.parametersFromDeclarationOfRelatedLambdas.orEmpty() + parametersFromDeclaration
/*
* We shouldn't create synthetic functional type if all lambda's parameter types are specified explicitly
*
* TODO: regarding anonymous functions: see info about need for analysis in partial mode in `collectParameterTypesAndBuildNewExpectedTypes`
*/
if (areAllParameterTypesSpecified && !isExtensionFunction && !isAnonymousFunction(argument))
return null
val allParameterTypes =
(parametersFromConstraints.orEmpty() + parametersFromDeclarations.map { parameters -> parameters?.map { it.wrapToTypeWithKind() } }).filterNotNull()
if (allParameterTypes.isEmpty())
return null
val variablesForParameterTypes = createTypeVariablesForParameters(argument, allParameterTypes)
val variableForReturnType = createTypeVariableForReturnType(argument)
val functionalConstructor = computeResultingFunctionalConstructor(
argument,
variablesForParameterTypes.size,
parameterTypesInfo.isSuspend,
resultTypeResolver
)
val isExtensionFunctionType = parameterTypesInfo.annotations.hasExtensionFunctionAnnotation()
val areParametersNumberInDeclarationAndConstraintsEqual =
!parametersFromDeclaration.isNullOrEmpty() && !parametersFromConstraints.isNullOrEmpty()
&& parametersFromDeclaration.size == parametersFromConstraints.first().size
/*
* We need to exclude further considering a postponed argument as an extension function
* to support cases with explicitly specified receiver as a value parameter (only if all parameter types are specified)
*
* Example: `val x: String.() -> Int = id { x: String -> 42 }`
*/
val shouldDiscriminateExtensionFunctionAnnotation =
isExtensionFunctionType && areAllParameterTypesSpecified && areParametersNumberInDeclarationAndConstraintsEqual
/*
* We need to add an extension function annotation for anonymous functions with an explicitly specified receiver
*
* Example: `val x = id(fun String.() = this)`
*/
val shouldAddExtensionFunctionAnnotation = atom is FunctionExpression && atom.receiverType != null
val annotations = when {
shouldDiscriminateExtensionFunctionAnnotation ->
parameterTypesInfo.annotations.withoutExtensionFunctionAnnotation()
shouldAddExtensionFunctionAnnotation ->
parameterTypesInfo.annotations.withExtensionFunctionAnnotation(expectedType.builtIns)
else -> parameterTypesInfo.annotations
}
val nexExpectedType = KotlinTypeFactory.simpleType(
annotations,
functionalConstructor,
variablesForParameterTypes + variableForReturnType.defaultType.asTypeProjection(),
parameterTypesInfo.isNullable
)
getBuilder().addSubtypeConstraint(
nexExpectedType,
expectedType,
ArgumentConstraintPosition(argument.atom)
)
return nexExpectedType
}
fun collectParameterTypesAndBuildNewExpectedTypes(
c: Context,
postponedArguments: List<PostponedAtomWithRevisableExpectedType>,
completionMode: KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode,
dependencyProvider: TypeVariableDependencyInformationProvider
) {
// We can collect parameter types from declaration in any mode, they can't change during completion.
val postponedArgumentsToCollectTypesFromDeclaredParameters = postponedArguments
.filterIsInstance<LambdaWithTypeVariableAsExpectedTypeAtom>()
.filter { it.parameterTypesFromDeclaration == null }
for (argument in postponedArgumentsToCollectTypesFromDeclaredParameters) {
argument.parameterTypesFromDeclaration = extractParameterTypesFromDeclaration(argument.atom)
}
/*
* We can build new functional expected types in partial mode only for anonymous functions,
* because more exact type can't appear from constraints in full mode (anonymous functions have fully explicit declaration).
* It can be so for lambdas: for instance, an extension function type can appear in full mode (it may not be known in partial mode).
*
* TODO: investigate why we can't do it for anonymous functions in full mode always (see `diagnostics/tests/resolve/resolveWithSpecifiedFunctionLiteralWithId.kt`)
*/
val postponedArgumentsToCollectParameterTypesAndBuildNewExpectedType =
if (completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL) {
postponedArguments.filter(::isAnonymousFunction)
} else {
postponedArguments
}
do {
val wasTransformedSomePostponedArgument =
postponedArgumentsToCollectParameterTypesAndBuildNewExpectedType.filter { it.revisedExpectedType == null }.any { argument ->
val parameterTypesInfo =
c.extractParameterTypesInfo(argument, postponedArguments, dependencyProvider) ?: return@any false
val newExpectedType =
c.buildNewFunctionalExpectedType(argument, parameterTypesInfo) ?: return@any false
argument.revisedExpectedType = newExpectedType
true
}
} while (wasTransformedSomePostponedArgument)
}
fun transformToAtomWithNewFunctionalExpectedType(
c: Context,
argument: PostponedAtomWithRevisableExpectedType,
diagnosticsHolder: KotlinDiagnosticsHolder
) {
val revisedExpectedType = argument.revisedExpectedType?.takeIf { it.isFunctionOrKFunctionTypeWithAnySuspendability } ?: return
when (argument) {
is PostponedCallableReferenceAtom ->
CallableReferenceWithRevisedExpectedTypeAtom(argument.atom, revisedExpectedType).also {
argument.setAnalyzedResults(null, listOf(it))
}
is LambdaWithTypeVariableAsExpectedTypeAtom ->
argument.transformToResolvedLambda(c.getBuilder(), diagnosticsHolder, revisedExpectedType)
else -> throw IllegalStateException("Unsupported postponed argument type of $argument")
}
}
private fun getAllDeeplyRelatedTypeVariables(
type: KotlinType,
variableDependencyProvider: TypeVariableDependencyInformationProvider
): List<TypeVariableTypeConstructor> {
val typeConstructor = type.constructor
return when {
typeConstructor is TypeVariableTypeConstructor -> {
val relatedVariables = variableDependencyProvider.getDeeplyDependentVariables(typeConstructor).orEmpty()
listOf(typeConstructor) + relatedVariables.filterIsInstance<TypeVariableTypeConstructor>()
}
type.arguments.isNotEmpty() -> {
type.arguments.map { getAllDeeplyRelatedTypeVariables(it.type, variableDependencyProvider) }.flatten()
}
else -> listOf()
}
}
private fun getDeclaredParametersConsideringExtensionFunctionsPresence(parameterTypesInfo: ParameterTypesInfo): List<UnwrappedType?>? {
val (parametersFromDeclaration, _, parametersFromConstraints, annotations) = parameterTypesInfo
if (parametersFromConstraints.isNullOrEmpty() || parametersFromDeclaration.isNullOrEmpty())
return parametersFromDeclaration
val oneLessParameterInDeclarationThanInConstraints = parametersFromConstraints.first().size == parametersFromDeclaration.size + 1
return if (oneLessParameterInDeclarationThanInConstraints && annotations.hasExtensionFunctionAnnotation()) {
listOf(null) + parametersFromDeclaration
} else {
parametersFromDeclaration
}
}
fun fixNextReadyVariableForParameterTypeIfNeeded(
c: Context,
argument: PostponedResolvedAtom,
postponedArguments: List<PostponedResolvedAtom>,
topLevelType: UnwrappedType,
topLevelAtoms: List<ResolvedAtom>,
dependencyProvider: TypeVariableDependencyInformationProvider
): Boolean {
val expectedType = argument.run { safeAs<PostponedAtomWithRevisableExpectedType>()?.revisedExpectedType ?: expectedType }
if (expectedType != null && expectedType.isFunctionOrKFunctionTypeWithAnySuspendability) {
val wasFixedSomeVariable =
c.fixNextReadyVariableForParameterType(expectedType, postponedArguments, topLevelType, topLevelAtoms, dependencyProvider)
if (wasFixedSomeVariable)
return true
}
return false
}
private fun Context.fixNextReadyVariableForParameterType(
type: KotlinType,
postponedArguments: List<PostponedResolvedAtom>,
topLevelType: UnwrappedType,
topLevelAtoms: List<ResolvedAtom>,
dependencyProvider: TypeVariableDependencyInformationProvider
): Boolean {
val relatedVariables = type.getPureArgumentsForFunctionalTypeOrSubtype()
.map { getAllDeeplyRelatedTypeVariables(it, dependencyProvider) }.flatten()
val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
this, relatedVariables, postponedArguments, KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL, topLevelType
)
if (variableForFixation == null || !variableForFixation.hasProperConstraint)
return false
val variableWithConstraints = notFixedTypeVariables.getValue(variableForFixation.variable)
val resultType =
resultTypeResolver.findResultType(this, variableWithConstraints, TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN)
val resolvedAtom = KotlinConstraintSystemCompleter.findResolvedAtomBy(variableWithConstraints.typeVariable, topLevelAtoms)
?: topLevelAtoms.firstOrNull()
fixVariable(variableWithConstraints.typeVariable, resultType, resolvedAtom)
return true
}
private fun KotlinType?.wrapToTypeWithKind() = this?.let { TypeWithKind(it) }
private fun isAnonymousFunction(argument: PostponedAtomWithRevisableExpectedType) = argument.atom is FunctionExpression
companion object {
private const val TYPE_VARIABLE_NAME_PREFIX_FOR_LAMBDA_PARAMETER_TYPE = "_RP"
private const val TYPE_VARIABLE_NAME_FOR_LAMBDA_RETURN_TYPE = "_R"
private const val TYPE_VARIABLE_NAME_PREFIX_FOR_CR_PARAMETER_TYPE = "_QP"
private const val TYPE_VARIABLE_NAME_FOR_CR_RETURN_TYPE = "_Q"
}
}
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
import org.jetbrains.kotlin.types.model.freshTypeConstructor
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.utils.SmartSet
class TypeVariableDependencyInformationProvider(
@@ -30,10 +27,19 @@ class TypeVariableDependencyInformationProvider(
private val topLevelType: KotlinTypeMarker?,
private val typeSystemContext: TypeSystemInferenceExtensionContext
) {
// not oriented edges
private val constrainEdges: MutableMap<TypeConstructorMarker, MutableSet<TypeConstructorMarker>> = hashMapOf()
/*
* Not oriented edges
* TypeVariable(A) has UPPER(Function1<TypeVariable(B), R>) => A and B are related deeply
*/
private val deepTypeVariableDependencies: MutableMap<TypeConstructorMarker, MutableSet<TypeConstructorMarker>> = hashMapOf()
// oriented edges
/*
* Not oriented edges
* TypeVariable(A) has UPPER(TypeVariable(B)) => A and B are related shallowly
*/
private val shallowTypeVariableDependencies: MutableMap<TypeConstructorMarker, MutableSet<TypeConstructorMarker>> = hashMapOf()
// Oriented edges
private val postponeArgumentsEdges: MutableMap<TypeConstructorMarker, MutableSet<TypeConstructorMarker>> = hashMapOf()
private val relatedToAllOutputTypes: MutableSet<TypeConstructorMarker> = hashSetOf()
@@ -49,21 +55,43 @@ class TypeVariableDependencyInformationProvider(
fun isVariableRelatedToTopLevelType(variable: TypeConstructorMarker) = relatedToTopLevelType.contains(variable)
fun isVariableRelatedToAnyOutputType(variable: TypeConstructorMarker) = relatedToAllOutputTypes.contains(variable)
fun getDeeplyDependentVariables(variable: TypeConstructorMarker) = deepTypeVariableDependencies[variable]
fun getShallowlyDependentVariables(variable: TypeConstructorMarker) = shallowTypeVariableDependencies[variable]
fun areVariablesDependentShallowly(a: TypeConstructorMarker, b: TypeConstructorMarker): Boolean {
if (a == b) return true
val shallowDependencies = shallowTypeVariableDependencies[a] ?: return false
return shallowDependencies.any { it == b } ||
shallowTypeVariableDependencies.values.any { dependencies -> a in dependencies && b in dependencies }
}
private fun computeConstraintEdges() {
fun addConstraintEdge(from: TypeConstructorMarker, to: TypeConstructorMarker) {
constrainEdges.getOrPut(from) { hashSetOf() }.add(to)
constrainEdges.getOrPut(to) { hashSetOf() }.add(from)
fun addConstraintEdgeForDeepDependency(from: TypeConstructorMarker, to: TypeConstructorMarker) {
deepTypeVariableDependencies.getOrPut(from) { linkedSetOf() }.add(to)
deepTypeVariableDependencies.getOrPut(to) { linkedSetOf() }.add(from)
}
fun addConstraintEdgeForShallowDependency(from: TypeConstructorMarker, to: TypeConstructorMarker) {
shallowTypeVariableDependencies.getOrPut(from) { linkedSetOf() }.add(to)
shallowTypeVariableDependencies.getOrPut(to) { linkedSetOf() }.add(from)
}
for (variableWithConstraints in notFixedTypeVariables.values) {
val from = variableWithConstraints.typeVariable.freshTypeConstructor(typeSystemContext)
for (constraint in variableWithConstraints.constraints) {
val constraintTypeConstructor = constraint.type.typeConstructor(typeSystemContext)
constraint.type.forAllMyTypeVariables {
if (isMyTypeVariable(it)) {
addConstraintEdge(from, it)
addConstraintEdgeForDeepDependency(from, it)
}
}
if (isMyTypeVariable(constraintTypeConstructor)) {
addConstraintEdgeForShallowDependency(from, constraintTypeConstructor)
}
}
}
}
@@ -118,7 +146,7 @@ class TypeVariableDependencyInformationProvider(
}
private fun getConstraintEdges(from: TypeConstructorMarker): Set<TypeConstructorMarker> = constrainEdges[from] ?: emptySet()
private fun getConstraintEdges(from: TypeConstructorMarker): Set<TypeConstructorMarker> = deepTypeVariableDependencies[from] ?: emptySet()
private fun getPostponeEdges(from: TypeConstructorMarker): Set<TypeConstructorMarker> = postponeArgumentsEdges[from] ?: emptySet()
private fun addAllRelatedNodes(to: MutableSet<TypeConstructorMarker>, node: TypeConstructorMarker, includePostponedEdges: Boolean) {
@@ -61,6 +61,12 @@ enum class ConstraintKind {
fun isLower(): Boolean = this == LOWER
fun isUpper(): Boolean = this == UPPER
fun isEqual(): Boolean = this == EQUALITY
fun opposite() = when (this) {
LOWER -> UPPER
UPPER -> LOWER
EQUALITY -> EQUALITY
}
}
class Constraint(
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.*
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
import org.jetbrains.kotlin.resolve.calls.inference.components.PostponedArgumentInputTypesResolver
import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
import org.jetbrains.kotlin.resolve.calls.model.OnlyInputTypesDiagnostic
@@ -31,6 +32,7 @@ class NewConstraintSystemImpl(
ConstraintInjector.Context,
ResultTypeResolver.Context,
KotlinConstraintSystemCompleter.Context,
PostponedArgumentInputTypesResolver.Context,
PostponedArgumentsAnalyzer.Context {
private val storage = MutableConstraintStorage()
private var state = State.BUILDING
@@ -87,6 +89,8 @@ class NewConstraintSystemImpl(
override fun asPostponedArgumentsAnalyzerContext() = apply { checkState(State.BUILDING) }
override fun asPostponedArgumentInputTypesResolverContext() = apply { checkState(State.BUILDING) }
// ConstraintSystemOperation
override fun registerVariable(variable: TypeVariableMarker) {
checkState(State.BUILDING, State.COMPLETION, State.TRANSACTION)
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.model.CallableReferenceKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.model.PostponableKotlinCallArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.hasOnlyInputTypesAnnotation
import org.jetbrains.kotlin.types.KotlinType
@@ -79,7 +80,15 @@ class TypeVariableFromCallableDescriptor(
}
class TypeVariableForLambdaReturnType(
val lambdaArgument: LambdaKotlinCallArgument,
builtIns: KotlinBuiltIns,
name: String
) : NewTypeVariable(builtIns, name) {
override fun hasOnlyInputTypesAnnotation(): Boolean = false
}
class TypeVariableForLambdaParameterType(
val atom: PostponableKotlinCallArgument,
val index: Int,
builtIns: KotlinBuiltIns,
name: String
) : NewTypeVariable(builtIns, name) {
@@ -92,3 +101,10 @@ class TypeVariableForCallableReferenceReturnType(
) : NewTypeVariable(builtIns, name) {
override fun hasOnlyInputTypesAnnotation(): Boolean = false
}
class TypeVariableForCallableReferenceParameterType(
builtIns: KotlinBuiltIns,
name: String
) : NewTypeVariable(builtIns, name) {
override fun hasOnlyInputTypesAnnotation(): Boolean = false
}
@@ -13,10 +13,7 @@ import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMa
import org.jetbrains.kotlin.resolve.calls.components.extractInputOutputTypesFromCallableReferenceExpectedType
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintError
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForCallableReferenceReturnType
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
import org.jetbrains.kotlin.types.KotlinType
@@ -98,6 +95,12 @@ interface PostponedResolvedAtomMarker {
val analyzed: Boolean
}
interface PostponedAtomWithRevisableExpectedType {
var revisedExpectedType: UnwrappedType?
val expectedType: UnwrappedType?
val atom: PostponableKotlinCallArgument
}
sealed class PostponedResolvedAtom : ResolvedAtom(), PostponedResolvedAtomMarker {
abstract override val inputTypes: Collection<UnwrappedType>
abstract override val outputType: UnwrappedType?
@@ -107,10 +110,13 @@ sealed class PostponedResolvedAtom : ResolvedAtom(), PostponedResolvedAtomMarker
class LambdaWithTypeVariableAsExpectedTypeAtom(
override val atom: LambdaKotlinCallArgument,
override val expectedType: UnwrappedType
) : PostponedResolvedAtom() {
) : PostponedResolvedAtom(), PostponedAtomWithRevisableExpectedType {
override val inputTypes: Collection<UnwrappedType> get() = listOf(expectedType)
override val outputType: UnwrappedType? get() = null
var isReturnArgumentOfAnotherLambda: Boolean = false
override var revisedExpectedType: UnwrappedType? = null
var parameterTypesFromDeclaration: List<UnwrappedType?>? = null
fun setAnalyzed(resolvedLambdaAtom: ResolvedLambdaAtom) {
setAnalyzedResults(listOf(resolvedLambdaAtom))
@@ -180,15 +186,16 @@ sealed class AbstractPostponedCallableReferenceAtom(
get() = extractInputOutputTypesFromCallableReferenceExpectedType(expectedType)?.outputType
}
class CallableReferenceWithTypeVariableAsExpectedTypeAtom(
class CallableReferenceWithRevisedExpectedTypeAtom(
atom: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?,
val typeVariableForReturnType: TypeVariableForCallableReferenceReturnType?
) : AbstractPostponedCallableReferenceAtom(atom, expectedType)
class PostponedCallableReferenceAtom(
eagerCallableReferenceAtom: EagerCallableReferenceAtom
) : AbstractPostponedCallableReferenceAtom(eagerCallableReferenceAtom.atom, eagerCallableReferenceAtom.expectedType)
) : AbstractPostponedCallableReferenceAtom(eagerCallableReferenceAtom.atom, eagerCallableReferenceAtom.expectedType), PostponedAtomWithRevisableExpectedType {
override var revisedExpectedType: UnwrappedType? = null
}
class ResolvedCollectionLiteralAtom(
override val atom: CollectionLiteralKotlinCallArgument,
@@ -19,6 +19,4 @@ fun test() {
baz<(Int) -> Unit>(id(::foo), id(id(::foo)))
baz(id(::foo), id(id<(Int) -> Unit>(::foo)))
baz(id(::foo), id<(Int) -> Unit>(id(::foo)))
baz(id { it.inv() }, id<(Int) -> Unit> { })
}
@@ -19,6 +19,4 @@ fun test() {
baz<(Int) -> Unit>(id(::foo), id(id(::foo)))
baz(id(::foo), id(id<(Int) -> Unit>(::foo)))
baz(id(::foo), id<(Int) -> Unit>(id(::foo)))
baz(id { it.inv() }, id<(Int) -> Unit> { })
}
@@ -34,6 +34,6 @@ val bbb = null ?: ( l() <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>)
val bbbb = ( l() <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>) ?: ( l() <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>)
fun f(x : Long?): Long {
var a = x ?: (<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, TYPE_MISMATCH!>fun() {}<!> <!USELESS_ELVIS!>?: <!NI;TYPE_MISMATCH, TYPE_MISMATCH!>fun() {}<!><!>)
return <!OI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a<!>
var a = x ?: (<!OI;TYPE_MISMATCH!>fun() {}<!> <!USELESS_ELVIS!>?: <!OI;TYPE_MISMATCH!>fun() {}<!><!>)
return <!NI;TYPE_MISMATCH, OI;DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a<!>
}
@@ -0,0 +1,11 @@
Failures detected in FirBodyResolveTransformerAdapter, file: /basic.fir.kt
Cause: java.lang.RuntimeException: While resolving call R?C|/selectFloat|(R?C|/id|(<L> = id@fun <implicit>.<anonymous>(): <implicit> {
^@id Unit
}
), R?C|/id|(<L> = id@fun <implicit>.<anonymous>(x: <implicit>): <implicit> {
^@id Unit
}
), R?C|/id|(<L> = id@fun <implicit>.<anonymous>(): <implicit> {
it#
}
))
@@ -0,0 +1,195 @@
import kotlin.reflect.KFunction1
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
fun foo(i: Int) {}
fun foo(s: String) {}
fun foo2(i: Int) {}
fun foo3(i: Number) {}
fun <K> id(x: K): K = x
fun <K> id1(x: K): K = x
fun <L> id2(x: L): L = x
fun <T> baz1(x: T, y: T): T = TODO()
fun <T> baz2(x: T, y: Inv<T>): T = TODO()
fun <T> select(vararg x: T) = x[0]
fun <T, R> takeInterdependentLambdas(x: (T) -> R, y: (R) -> T) {}
fun <T> takeDependentLambdas(x: (T) -> Int, y: (Int) -> T) {}
class Inv<T>(val x: T)
fun test1() {
val x1: (Int) -> Unit = id(id(::foo))
val x2: (Int) -> Unit = baz1(id(::foo), ::foo)
val x3: (Int) -> Unit = baz1(id(::foo), id(id(::foo)))
val x4: (String) -> Unit = baz1(id(::foo), id(id(::foo)))
id<(Int) -> Unit>(id(id(::foo)))
id(id<(Int) -> Unit>(::foo))
baz1<(Int) -> Unit>(id(::foo), id(id(::foo)))
baz1(id(::foo), id(id<(Int) -> Unit>(::foo)))
baz1(id(::foo), id<(Int) -> Unit>(id(::foo)))
baz1(id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id<(Int) -> Unit> { })
baz1(id1 { x -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x<!>.inv() }, id2 { x: Int -> })
baz1(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id2 { x: Int -> })
baz2(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id2(Inv { x: Int -> }))
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2 { x: Int -> x }))
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2(::foo2)))
select(id1 { x: Inv<out Number> -> TODO() }, id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>it<!>.x.inv() }, id1 { x: Inv<Int> -> TODO() })
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("{Inv<Int> & Inv<Number>}")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>select(id1(::foo), id(::foo3), id1(id2(::foo2)))<!>
select({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> TODO() })
// Interdependent postponed arguments are unsupported
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({}, {})
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({ <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!> }, { 10 })
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({ 10 }, { <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!> })
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({ 10 }, { <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!> })
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({ <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> 10 }, { <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!> })
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({ <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!> }, { <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> 10 })
takeDependentLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { it })
takeDependentLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>it<!>.length }, { "it" })
takeDependentLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>it<!>; 10 }, { })
select({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, fun(x: Int) = 1)
val x5: (Int) -> Unit = select({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Number -> Unit })
val x6 = select(id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, id(id<(Int) -> Unit> { x: Number -> Unit }))
select(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id(id { x: Int -> x }))
val x7: (Int) -> Unit = selectNumber(id {}, id {}, id {})
val x8: (Int) -> Unit = selectNumber(id { x -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!> }, id { x -> }, id { x -> })
val x9: (Int) -> Unit = selectNumber(id { }, id { x -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>it<!> })
val x10: (Int) -> Unit = selectFloat(id { }, id { x -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("{Comparable<*> & Number}")!>it<!> })
val x11: (B) -> Unit = selectC(id { }, id { x -> <!DEBUG_INFO_EXPRESSION_TYPE("A")!>x<!> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> })
/*
* Upper constraint is less specific than lower (it's error):
* K <: (A) -> Unit -> TypeVariable(_RP1) >: A
* K >: (C) -> TypeVariable(_R) -> TypeVariable(_RP1) <: C
*/
val x12 = selectC(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }<!>, id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!EXPECTED_PARAMETER_TYPE_MISMATCH, EXPECTED_PARAMETER_TYPE_MISMATCH!>x: B<!> -> }<!><!NO_VALUE_FOR_PARAMETER!>)<!>
val x13 = selectA(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> }<!>, id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!EXPECTED_PARAMETER_TYPE_MISMATCH, EXPECTED_PARAMETER_TYPE_MISMATCH!>x: C<!> -> }<!><!NO_VALUE_FOR_PARAMETER!>)<!>
// one upper constraint and one lower
val x14 = selectC(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, id { x: A -> }, { x -> x })
val x15 = selectC(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, { x: A -> }, id { x -> x })
/*
* Two upper constraints and one lower
* K <: (C) -> Unit -> TypeVariable(_RP1) >: C
* K <: (B) -> Unit -> TypeVariable(_RP1) >: B
* K >: (A) -> TypeVariable(_R) -> TypeVariable(_RP1) <: A
* K == intersect(CST(C, B), A) == A
*/
val x16: (C) -> Unit = selectB(id { <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> }, { x -> }, id { x: A -> x })
/*
* two upper constraints and one equality (it's error)
* K <: (C) -> Unit -> TypeVariable(_RP1) >: C
* K == (B) -> Unit -> TypeVariable(_RP1) == B
*/
val x17: (C) -> Unit = <!TYPE_MISMATCH, TYPE_MISMATCH!>selectB(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("B")!>it<!> }<!>, id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ it }<!>, id<(B) -> Unit> { x -> x })<!>
val x18: (C) -> Unit = <!TYPE_MISMATCH!>select(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }<!>, <!TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }<!>, id<(B) -> Unit> { x -> x })<!>
val x19: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String.() -> kotlin.Unit")!>id {}<!>, <!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.String) -> kotlin.Unit")!>id(fun(x: String) {})<!>)
val x20: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String.() -> kotlin.Unit")!>{}<!>, <!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.String) -> kotlin.Unit")!>(fun(x: String) {})<!>)
val x21: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.String) -> kotlin.Unit")!>id(fun(x: String) {})<!>, <!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.String) -> kotlin.Unit")!>id(fun(x: String) {})<!>)
val x22 = select(id<String.() -> Unit>(fun(x: String) {}), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String.() -> kotlin.Unit")!>id(fun(x: String) {})<!>)
val x23 = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String.(kotlin.String) -> kotlin.Unit")!>id(fun String.(x: String) {})<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String.(kotlin.String) -> kotlin.Unit")!>id(fun(x: String, y: String) {})<!>)
val x24 = select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), { x: String -> this })
val x25 = select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), { x: String, y: String -> x })
// It isn't related with posponed arguments, see KT-38439
val x26: Int.(String) -> Int = fun (x: String) = 10
val x27: Int.(String) -> Int = <!TYPE_MISMATCH!>id(<!TYPE_MISMATCH, TYPE_MISMATCH!>fun (x: String) = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>10<!><!>)<!>
val x28 = select(id { x, y -> x.inv() + y.toByte() }, { x: Int, y -> y.toByte() }, { x, y: Number -> x.inv() })
val x29 = select(id { x, y -> x.inv() + y.toByte() }, id { x: Int, y -> y.toByte() }, id { x, y: Number -> x.inv() })
val x30 = select({ x, y -> x.inv() + y.toByte() }, id { x: Int, y -> y.toByte() }, id { x, y: Number -> x.inv() })
val x31 = select(
id { x, y -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x<!>.inv() + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>y<!>.toByte() },
id<(Int, Number) -> Int> { x, y -> x.inv() },
{} <!UNCHECKED_CAST!>as (Number, Number) -> Int<!>
)
val x32 = selectPosponedArgument({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { x: Int -> }, { x: Nothing -> x })
val x33 = selectPosponedArgument({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } <!UNCHECKED_CAST!>as (Int) -> Unit<!>, { x: Nothing -> x })
val x34 = selectPosponedArgument({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } <!UNCHECKED_CAST!>as (Nothing) -> Unit<!>, { x: Int -> x })
val x35 = selectPosponedArgument({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } <!UNCHECKED_CAST!>as (Int) -> Unit<!>, { } <!UNCHECKED_CAST!>as (Nothing) -> Unit<!>)
val x36 = selectPosponedArgument3({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> x })
val x37 = selectPosponedArgument3({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Number -> x }, { x: Int -> x })
val x38 = selectPosponedArgument3Revert({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> x })
val x39 = selectPosponedArgument3Revert({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>it<!> }, { x: Number -> x }, { x: Int -> x })
val x40 = select(id<Int.(String) -> Unit> {}, { x: Int, y: String -> x })
val x41 = select(A2(), { a, b, c -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>a<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Float")!>c<!> })
val x42 = select(A3(), { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>it<!> }, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>a<!> })
val x43 = select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>)
val x44 = select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("{A3 & Number}")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("{A3 & Number}")!>it<!> })
val x45 = select(A4(), { x: Number -> "" })
val x46 = select(A5<Int, Int>(), { x: Number, y: Int -> "" })
val x47 = select(A2(), id { a, b, c -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>a<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Float")!>c<!> })
val x48 = select(id(A3()), { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>it<!> }, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>a<!> })
val x49 = select(A3(), id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>))
val x50 = select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("{A3 & Number}")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("{A3 & Number}")!>it<!> })
val x51 = select(A4(), id { x: Number -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!> })
val x52 = select(id(A5<Int, Int>()), id { x: Number, y: Int -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!> })
val x53 = select(id(A5<Int, Int>()), id { x, y -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!> })
val x54 = select(id(<!DEBUG_INFO_EXPRESSION_TYPE("A5<kotlin.Number, kotlin.Int>")!>A5()<!>), id { x: Number, y: Int -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!> })
val x55: Function2<Number, Int, Float> = select(id(A5()), id { x, y -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!>; 1f })
}
fun <T: (Number) -> Unit> selectNumber(arg1: T, arg2: T, arg3: T) = arg1
fun <T: (Float) -> Unit> selectFloat(arg1: T, arg2: T, arg3: T) = arg2
fun <T: (A) -> Unit> selectA(arg1: T, arg2: T, arg3: T) = arg2
fun <T: (B) -> Unit> selectB(arg1: T, arg2: T, arg3: T) = arg2
fun <T: (C) -> Unit> selectC(arg1: T, arg2: T, arg3: T) = arg2
fun <T> selectPosponedArgument(vararg x: (T) -> Unit) = x[0]
fun <T : R, R : L, L> selectPosponedArgument3(x: (T) -> Unit, y: (R) -> Unit, z: (L) -> Unit) = x
fun <T, R: T, L: R> selectPosponedArgument3Revert(x: (T) -> Unit, y: (R) -> Unit, z: (L) -> Unit) = x
interface A
class B: A
class C: A
class A2: Function3<Int, String, Float, Float> {
override fun invoke(p1: Int, p2: String, p3: Float): Float = 4f
}
class A3: KFunction1<Number, String> {
override fun invoke(p1: Number): String = TODO()
override val name: String = TODO()
fun foo1(x: Int) {}
fun foo1(x: Any?) {}
}
class A4: Function1<Int, Float> {
override fun invoke(p1: Int): Float = TODO()
}
class A5<K, Q>: Function2<K, Q, Float> {
override fun invoke(p1: K, p2: Q): Float = 5f
}
@@ -0,0 +1,223 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER -UNCHECKED_CAST
import kotlin.reflect.KFunction1
fun withOverload(i: Int) {}
fun withOverload(s: String) {}
fun takeInt(i: Int) {}
fun takeNumber(i: Number) {}
fun <K> id(x: K): K = x
fun <K> id1(x: K): K = x
fun <L> id2(x: L): L = x
fun <T> selectWithInv(x: T, y: Inv<T>): T = TODO()
fun <T> select(vararg x: T) = x[0]
fun <T> takeLambdas(vararg x: (T) -> Unit) = x[0]
fun <T : R, R : L, L> takeLambdasWithDirectlyDependentTypeParameters(x: (T) -> Unit, y: (R) -> Unit, z: (L) -> Unit) = x
fun <T, R: T, L: R> takeLambdasWithInverselyDependentTypeParameters(x: (T) -> Unit, y: (R) -> Unit, z: (L) -> Unit) = x
fun <T, R> takeInterdependentLambdas(x: (T) -> R, y: (R) -> T) {}
fun <T> takeDependentLambdas(x: (T) -> Int, y: (Int) -> T) {}
class Inv<T>(val x: T)
fun <T: (Number) -> Unit> selectNumber(arg1: T, arg2: T, arg3: T) = arg1
fun <T: (Float) -> Unit> selectFloat(arg1: T, arg2: T, arg3: T) = arg2
fun <T: (A) -> Unit> selectA(arg1: T, arg2: T, arg3: T) = arg2
fun <T: (B) -> Unit> selectB(arg1: T, arg2: T, arg3: T) = arg2
fun <T: (C) -> Unit> selectC(arg1: T, arg2: T, arg3: T) = arg2
interface A
class B: A
class C: A
class A2: Function3<Int, String, Float, Float> {
override fun invoke(p1: Int, p2: String, p3: Float): Float = 4f
}
class A3: KFunction1<Number, String> {
override fun invoke(p1: Number): String = TODO()
override val name: String = TODO()
fun foo1(x: Int) {}
fun foo1(x: Any?) {}
companion object {
fun foo2(x: Int) {}
fun foo2(x: Any?) {}
}
}
class A4: Function1<Int, Float> {
override fun invoke(p1: Int): Float = TODO()
}
class A5<K, Q>: Function2<K, Q, Float> {
override fun invoke(p1: K, p2: Q): Float = 5f
}
fun test1() {
// Inferring lambda parameter types by other lambda explicit parameters; expected type is type variable
select(id1 { x -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x<!>.inv() }, id2 { x: Int -> })
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id2 { x: Int -> })
selectWithInv(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id2(Inv { x: Int -> }))
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2 { x: Int -> x }))
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2(::takeInt)))
select(id1 { x: Inv<out Number> -> TODO() }, id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>it<!>.x.inv() }, id1 { x: Inv<Int> -> TODO() })
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("{Inv<Int> & Inv<Number>}")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
select(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id(id { x: Int -> x }))
// Disambiguating callable references by other callable references without overloads
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>select(id(::withOverload), id(::takeInt), id(id(::takeNumber)))<!>
// Interdependent lambdas by input-output types aren't supported
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({}, {})
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({ <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!> }, { 10 })
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({ 10 }, { <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!> })
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({ 10 }, { <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!> })
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({ <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> 10 }, { <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!> })
<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>takeInterdependentLambdas<!>({ <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>it<!> }, { <!CANNOT_INFER_PARAMETER_TYPE!>x<!> -> 10 })
// Dependent lambdas by input-output types
takeDependentLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { it })
takeDependentLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>it<!>.length }, { "it" })
takeDependentLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>it<!>; 10 }, { })
// Inferring lambda parameter types by anonymous function parameters
select({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, fun(x: Int) = 1)
// Inferring lambda parameter types by other lambda explicit parameters (lower constraints) and expected type (upper constraints)
val x5: (Int) -> Unit = select({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Number -> Unit })
// Inferring lambda parameter types by other lambda explicit parameters (lower constraints) and specified type arguments (equality constraints)
select(id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, id(id<(Int) -> Unit> { x: Number -> Unit }))
// Inferring lambda parameter types by specified type arguments (equality constraints) of other lambdas
select(id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id<(Int) -> Unit> { })
select(
id { x, y -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x<!>.inv() + <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>y<!>.toByte() },
id<(Int, Number) -> Int> { x, y -> x.inv() },
{} as (Number, Number) -> Int
)
// Inferring lambda parameter types by a few expected types (a few upper constraints)
val x7: (Int) -> Unit = <!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Number) -> kotlin.Unit")!>selectNumber(id {}, id {}, id {})<!>
val x8: (Int) -> Unit = selectNumber(id { x -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!> }, id { x -> }, id { x -> })
val x9: (Int) -> Unit = selectNumber(id { }, id { x -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>it<!> })
val x10: (Int) -> Unit = selectFloat(id { }, id { x -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("{Comparable<*> & Number}")!>it<!> })
val x11: (B) -> Unit = selectC(id { }, id { x -> <!DEBUG_INFO_EXPRESSION_TYPE("A")!>x<!> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> })
// Inferring lambda parameter types by expected types (upper constraints) and other lambda explicit parameters (lower constraints)
/*
* Upper constraint is less specific than lower (it's error):
* K <: (A) -> Unit -> TypeVariable(_RP1) >: A
* K >: (C) -> TypeVariable(_R) -> TypeVariable(_RP1) <: C
*/
val x12 = selectC(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }<!>, id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ x: B -> }<!><!NO_VALUE_FOR_PARAMETER!>)<!>
val x13 = selectA(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> }<!>, id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ x: C -> }<!><!NO_VALUE_FOR_PARAMETER!>)<!>
val x14 = selectC(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, id { x: A -> }, { x -> x })
val x15 = selectC(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, { x: A -> }, id { x -> x })
/*
* Two upper constraints and one lower
* K <: (C) -> Unit -> TypeVariable(_RP1) >: C
* K <: (B) -> Unit -> TypeVariable(_RP1) >: B
* K >: (A) -> TypeVariable(_R) -> TypeVariable(_RP1) <: A
* K == intersect(CST(C, B), A) == A
*/
val x16: (C) -> Unit = selectB(id { <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> }, { x -> }, id { x: A -> x })
// Inferring lambda parameter types by expected types (upper constraints) and specified type arguments (equality constraints) of other lambdas
/*
* two upper constraints and one equality (it's error)
* K <: (C) -> Unit -> TypeVariable(_RP1) >: C
* K == (B) -> Unit -> TypeVariable(_RP1) == B
*/
val x17: (C) -> Unit = <!TYPE_MISMATCH, TYPE_MISMATCH!>selectB(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("B")!>it<!> }<!>, id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ it }<!>, id<(B) -> Unit> { x -> x })<!>
val x18: (C) -> Unit = <!TYPE_MISMATCH!>select(id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }<!>, <!TYPE_MISMATCH, TYPE_MISMATCH!>{ <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }<!>, id<(B) -> Unit> { x -> x })<!>
// Resolution of extension/non-extension functions combination
val x19: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String.() -> kotlin.Unit")!>id {}<!>, <!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.String) -> kotlin.Unit")!>id(fun(x: String) {})<!>)
val x20: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String.() -> kotlin.Unit")!>{}<!>, <!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.String) -> kotlin.Unit")!>(fun(x: String) {})<!>)
val x21: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.String) -> kotlin.Unit")!>id(fun(x: String) {})<!>, <!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.String) -> kotlin.Unit")!>id(fun(x: String) {})<!>)
select(id<String.() -> Unit>(fun(x: String) {}), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String.() -> kotlin.Unit")!>id(fun(x: String) {})<!>)
select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String.(kotlin.String) -> kotlin.Unit")!>id(fun String.(x: String) {})<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String.(kotlin.String) -> kotlin.Unit")!>id(fun(x: String, y: String) {})<!>)
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), { x: String -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String"), DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>this<!> })
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), { x -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String"), DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>this<!> })
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), { x: String, y: String -> x })
// Convert to extension lambda is impossible because the lambda parameter types aren't specified explicitly
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), <!TYPE_MISMATCH!>{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!>x, <!CANNOT_INFER_PARAMETER_TYPE!>y<!><!> -> x }<!>)
select(id(id(fun(x: String, y: String) { }), <!TOO_MANY_ARGUMENTS!>fun String.(x: String) {}<!>), { x, y -> x })
val x26: Int.(String) -> Int = fun (x: String) = 10 // it must be error, see KT-38439
// Receiver must be specified in anonymous function declaration
val x27: Int.(String) -> Int = <!TYPE_MISMATCH!>id(<!TYPE_MISMATCH, TYPE_MISMATCH!>fun (x: String) = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>10<!><!>)<!>
select(id<Int.(String) -> Unit> {}, { x: Int, y: String -> x })
// Inferring lambda parameter types by partially specified parameter types of other lambdas
select(id { x, y -> x.inv() + y.toByte() }, { x: Int, y -> y.toByte() }, { x, y: Number -> x.inv() })
select(id { x, y -> x.inv() + y.toByte() }, id { x: Int, y -> y.toByte() }, id { x, y: Number -> x.inv() })
select({ x, y -> x.inv() + y.toByte() }, id { x: Int, y -> y.toByte() }, id { x, y: Number -> x.inv() })
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { x: Int -> }, { x: Nothing -> x })
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { x: Nothing -> x })
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Nothing) -> Unit, { x: Int -> x })
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { } as (Nothing) -> Unit)
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types; dependent type parameters
takeLambdasWithDirectlyDependentTypeParameters({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> x })
takeLambdasWithDirectlyDependentTypeParameters({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Number -> x }, { x: Int -> x })
takeLambdasWithInverselyDependentTypeParameters({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> x })
/*
* Interesting test case: variable can be fixed to different types randomly (`Int` or `Number`; it depends on variable fixation order)
* if in `TypeVariableDependencyInformationProvider` `hashSet` instead of `linkedSet` for `deepTypeVariableDependencies` and `shallowTypeVariableDependencies` will be used
*/
takeLambdasWithInverselyDependentTypeParameters({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>it<!> }, { x: Number -> x }, { x: Int -> x })
// Inferring lambda parameter types by subtypes of functional type
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int, kotlin.String, kotlin.Float) -> kotlin.Float")!>select(A2(), { a, b, c -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>a<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Float")!>c<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Number) -> java.io.Serializable")!>select(A3(), { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>it<!> }, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>a<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction<kotlin.Any>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>)<!>
// Should be error as `A3::foo1` is `KFunction2`, but the remaining arguments are `KFuncion1` or `Function1`
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>, { <!CANNOT_INFER_PARAMETER_TYPE!>a<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[ERROR : <Unknown lambda parameter type>]")!>a<!> }, { <!CANNOT_INFER_PARAMETER_TYPE!>it<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[ERROR : <Unknown lambda parameter type>]")!>it<!> })<!>
// It's OK because `A3::foo2` is from companion of `A3`
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int) -> kotlin.Any")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>A3::foo2<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int) -> {Comparable<*> & java.io.Serializable}")!>select(A4(), { x: Number -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int, kotlin.Int) -> {Comparable<*> & java.io.Serializable}")!>select(A5<Int, Int>(), { x: Number, y: Int -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int, kotlin.String, kotlin.Float) -> kotlin.Float")!>select(A2(), id { a, b, c -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>a<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Float")!>c<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Number) -> java.io.Serializable")!>select(id(A3()), { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>it<!> }, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>a<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction<kotlin.Any>")!>select(A3(), id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>))<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>, id { <!CANNOT_INFER_PARAMETER_TYPE!>a<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[ERROR : <Unknown lambda parameter type>]")!>a<!> }, { <!CANNOT_INFER_PARAMETER_TYPE!>it<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[ERROR : <Unknown lambda parameter type>]")!>it<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>, { <!CANNOT_INFER_PARAMETER_TYPE!>a<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[ERROR : <Unknown lambda parameter type>]")!>a<!> }, id { <!CANNOT_INFER_PARAMETER_TYPE!>it<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[ERROR : <Unknown lambda parameter type>]")!>it<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select(id(A3()), id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>), { <!CANNOT_INFER_PARAMETER_TYPE!>a<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[ERROR : <Unknown lambda parameter type>]")!>a<!> }, { <!CANNOT_INFER_PARAMETER_TYPE!>it<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[ERROR : <Unknown lambda parameter type>]")!>it<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select(id(A3()), id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>), { <!CANNOT_INFER_PARAMETER_TYPE!>a<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[ERROR : <Unknown lambda parameter type>]")!>a<!> }, id { <!CANNOT_INFER_PARAMETER_TYPE!>it<!> -> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, DEBUG_INFO_EXPRESSION_TYPE("[ERROR : <Unknown lambda parameter type>]")!>it<!> })<!>
// If lambdas' parameters are specified explicitly, we don't report an error, because there is proper CST Function<Unit>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select(id(A3()), id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>), { a: Number -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>a<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select(id(A3()), id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>), id { a: Number -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>a<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int) -> kotlin.Number")!>select(A4(), id { x: Number -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int, kotlin.Int) -> {Comparable<*> & Number}")!>select(id(A5<Int, Int>()), id { x: Number, y: Int -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int, kotlin.Int) -> {Comparable<*> & Number}")!>select(id(A5<Int, Int>()), id { x, y -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Number, kotlin.Int) -> {Comparable<*> & Number}")!>select(id(<!DEBUG_INFO_EXPRESSION_TYPE("A5<kotlin.Number, kotlin.Int>")!>A5()<!>), id { x: Number, y: Int -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!> })<!>
val x55: Function2<Number, Int, Float> = select(id(A5()), id { x, y -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>y<!>; 1f })
// Diffrerent lambda's parameters with proper CST
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<*, kotlin.Unit>")!>select({ x: Int -> }, { x: String -> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Unit>")!>select({ x: Int -> }, { x: Int, y: Number -> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<*, kotlin.Unit>")!>select(id { x: Int -> }, { x: String -> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Unit>")!>select({ x: Int -> }, id { x: Int, y: Number -> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<*, kotlin.Unit>")!>select(id { x: Int -> }, id { x: String -> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Unit>")!>select(id { x: Int -> }, id { x: Int, y: Number -> })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<*, {Comparable<*> & java.io.Serializable}>")!>select({ x: Int -> 1 }, { x: String -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<{Comparable<*> & Number}>")!>select({ x: Int -> 1 }, { x: Int, y: Number -> 1f })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<*, Inv<out {Comparable<*> & java.io.Serializable}>>")!>select(id { x: Int -> Inv(10) }, { x: String -> Inv("") })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any>")!>select({ x: Int -> TODO() }, id { x: Int, y: Number -> Any() })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<*, kotlin.String?>")!>select(id { x: Int -> null }, id { x: String -> "" })<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Int>")!>select(id { x: Int -> 10 }, id { x: Int, y: Number -> TODO() })<!>
val x68: String.(String) -> String = select(id { x: String, y: String -> "10" }, id { x: String, y: String -> "TODO()" })
}
@@ -0,0 +1,94 @@
package
public fun </*0*/ K> id(/*0*/ x: K): K
public fun </*0*/ K> id1(/*0*/ x: K): K
public fun </*0*/ L> id2(/*0*/ x: L): L
public fun </*0*/ T> select(/*0*/ vararg x: T /*kotlin.Array<out T>*/): T
public fun </*0*/ T : (A) -> kotlin.Unit> selectA(/*0*/ arg1: T, /*1*/ arg2: T, /*2*/ arg3: T): T
public fun </*0*/ T : (B) -> kotlin.Unit> selectB(/*0*/ arg1: T, /*1*/ arg2: T, /*2*/ arg3: T): T
public fun </*0*/ T : (C) -> kotlin.Unit> selectC(/*0*/ arg1: T, /*1*/ arg2: T, /*2*/ arg3: T): T
public fun </*0*/ T : (kotlin.Float) -> kotlin.Unit> selectFloat(/*0*/ arg1: T, /*1*/ arg2: T, /*2*/ arg3: T): T
public fun </*0*/ T : (kotlin.Number) -> kotlin.Unit> selectNumber(/*0*/ arg1: T, /*1*/ arg2: T, /*2*/ arg3: T): T
public fun </*0*/ T> selectWithInv(/*0*/ x: T, /*1*/ y: Inv<T>): T
public fun </*0*/ T> takeDependentLambdas(/*0*/ x: (T) -> kotlin.Int, /*1*/ y: (kotlin.Int) -> T): kotlin.Unit
public fun takeInt(/*0*/ i: kotlin.Int): kotlin.Unit
public fun </*0*/ T, /*1*/ R> takeInterdependentLambdas(/*0*/ x: (T) -> R, /*1*/ y: (R) -> T): kotlin.Unit
public fun </*0*/ T> takeLambdas(/*0*/ vararg x: (T) -> kotlin.Unit /*kotlin.Array<out (T) -> kotlin.Unit>*/): (T) -> kotlin.Unit
public fun </*0*/ T : R, /*1*/ R : L, /*2*/ L> takeLambdasWithDirectlyDependentTypeParameters(/*0*/ x: (T) -> kotlin.Unit, /*1*/ y: (R) -> kotlin.Unit, /*2*/ z: (L) -> kotlin.Unit): (T) -> kotlin.Unit
public fun </*0*/ T, /*1*/ R : T, /*2*/ L : R> takeLambdasWithInverselyDependentTypeParameters(/*0*/ x: (T) -> kotlin.Unit, /*1*/ y: (R) -> kotlin.Unit, /*2*/ z: (L) -> kotlin.Unit): (T) -> kotlin.Unit
public fun takeNumber(/*0*/ i: kotlin.Number): kotlin.Unit
public fun test1(): kotlin.Unit
public fun withOverload(/*0*/ i: kotlin.Int): kotlin.Unit
public fun withOverload(/*0*/ s: kotlin.String): kotlin.Unit
public interface A {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class A2 : (kotlin.Int, kotlin.String, kotlin.Float) -> kotlin.Float {
public constructor A2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ fun invoke(/*0*/ p1: kotlin.Int, /*1*/ p2: kotlin.String, /*2*/ p3: kotlin.Float): kotlin.Float
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class A3 : kotlin.reflect.KFunction1<kotlin.Number, kotlin.String> {
public constructor A3()
public open override /*1*/ val name: kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo1(/*0*/ x: kotlin.Any?): kotlin.Unit
public final fun foo1(/*0*/ x: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ fun invoke(/*0*/ p1: kotlin.Number): kotlin.String
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public companion object Companion {
private constructor Companion()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo2(/*0*/ x: kotlin.Any?): kotlin.Unit
public final fun foo2(/*0*/ x: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
public final class A4 : (kotlin.Int) -> kotlin.Float {
public constructor A4()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ fun invoke(/*0*/ p1: kotlin.Int): kotlin.Float
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class A5</*0*/ K, /*1*/ Q> : (K, Q) -> kotlin.Float {
public constructor A5</*0*/ K, /*1*/ Q>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ fun invoke(/*0*/ p1: K, /*1*/ p2: Q): kotlin.Float
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class B : A {
public constructor B()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class C : A {
public constructor C()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Inv</*0*/ T> {
public constructor Inv</*0*/ T>(/*0*/ x: T)
public final val x: T
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,10 @@
// FIR_IDENTICAL
fun <T> select(vararg x: T) = x[0]
fun <T> id1(x: T): T = x
fun <T> id2(x: T): T = x
fun test() {
fun foo() {}
select(id1(::foo), id2 { })
}
@@ -0,0 +1,6 @@
package
public fun </*0*/ T> id1(/*0*/ x: T): T
public fun </*0*/ T> id2(/*0*/ x: T): T
public fun </*0*/ T> select(/*0*/ vararg x: T /*kotlin.Array<out T>*/): T
public fun test(): kotlin.Unit
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS -UNUSED_VARIABLE
class Foo<T>
class P<K, T>(x: K, y: T)
val Foo<Int>.bar: Foo<Int> get() = this
fun <T> Foo<T>.bar(x: String) = null as Foo<Int>
fun main() {
val x: P<String, Foo<Int>.() -> Foo<Int>> = P("", Foo<Int>::bar)
}
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -CAST_NEVER_SUCCEEDS -UNUSED_VARIABLE
class Foo<T>
class P<K, T>(x: K, y: T)
val Foo<Int>.bar: Foo<Int> get() = this
fun <T> Foo<T>.bar(x: String) = null as Foo<Int>
fun main() {
val x: P<String, Foo<Int>.() -> Foo<Int>> = P("", <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KProperty1<Foo<kotlin.Int>, Foo<kotlin.Int>>")!>Foo<Int>::bar<!>)
}
@@ -0,0 +1,19 @@
package
public val Foo<kotlin.Int>.bar: Foo<kotlin.Int>
public fun main(): kotlin.Unit
public fun </*0*/ T> Foo<T>.bar(/*0*/ x: kotlin.String): Foo<kotlin.Int>
public final class Foo</*0*/ T> {
public constructor Foo</*0*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class P</*0*/ K, /*1*/ T> {
public constructor P</*0*/ K, /*1*/ T>(/*0*/ x: K, /*1*/ y: T)
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,59 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_EXPRESSION -UNCHECKED_CAST -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
fun <T> materialize(): T = null as T
class Foo<out A> {
fun <B> product(other: Foo<(A) -> B>) = materialize<Foo<B>>()
fun <B, R> foo1(other1: Foo<B>, function: (A, B) -> R) {
val x = product<R>(
other1.product(
bar { b -> { a -> function(a, b) } }
)
)
x
}
fun <B, C, R> foo2(other1: Foo<B>, other2: Foo<C>, function: (A, B, C) -> R) {
val x = product<R>(
other1.product(
other2.product(
bar { c -> { b -> { a -> function(a, b, c) } } }
)
)
)
x
}
fun <B, C, D, E, R> foo3(other1: Foo<B>, other2: Foo<C>, other3: Foo<D>, other4: Foo<E>, function: (A, B, C, D) -> R) {
val x = product<R>(
other1.product(
other2.product(
other3.product(
bar { d -> { c -> { b -> { a -> function(a, b, c, d) } } } }
)
)
)
)
x
}
fun <B, C, D, E, R> foo4(other1: Foo<B>, other2: Foo<C>, other3: Foo<D>, other4: Foo<E>, function: (A, B, C, D, E) -> R) {
val x = product<R>(
other1.product(
other2.product(
other3.product(
other4.product(
bar { e -> { d -> { c -> { b -> { a -> function(a, b, c, d, e) } } } } }
)
)
)
)
)
x
}
companion object {
fun <A> bar(x: A) = materialize<Foo<A>>()
}
}
@@ -0,0 +1,59 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_EXPRESSION -UNCHECKED_CAST -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
fun <T> materialize(): T = null as T
class Foo<out A> {
fun <B> product(other: Foo<(A) -> B>) = materialize<Foo<B>>()
fun <B, R> foo1(other1: Foo<B>, function: (A, B) -> R) {
val x = product<R>(
other1.product(
bar { b -> { a -> function(<!DEBUG_INFO_EXPRESSION_TYPE("A")!>a<!>, <!DEBUG_INFO_EXPRESSION_TYPE("B")!>b<!>) } }
)
)
<!DEBUG_INFO_EXPRESSION_TYPE("Foo<R>")!>x<!>
}
fun <B, C, R> foo2(other1: Foo<B>, other2: Foo<C>, function: (A, B, C) -> R) {
val x = product<R>(
other1.product(
other2.product(
bar { c -> { b -> { a -> function(<!DEBUG_INFO_EXPRESSION_TYPE("A")!>a<!>, <!DEBUG_INFO_EXPRESSION_TYPE("B")!>b<!>, <!DEBUG_INFO_EXPRESSION_TYPE("C")!>c<!>) } } }
)
)
)
<!DEBUG_INFO_EXPRESSION_TYPE("Foo<R>")!>x<!>
}
fun <B, C, D, E, R> foo3(other1: Foo<B>, other2: Foo<C>, other3: Foo<D>, other4: Foo<E>, function: (A, B, C, D) -> R) {
val x = product<R>(
other1.product(
other2.product(
other3.product(
<!TYPE_MISMATCH, TYPE_MISMATCH!>bar { d -> { c -> { b -> { a -> function(<!DEBUG_INFO_EXPRESSION_TYPE("A")!>a<!>, <!DEBUG_INFO_EXPRESSION_TYPE("B")!>b<!>, <!DEBUG_INFO_EXPRESSION_TYPE("C")!>c<!>, <!DEBUG_INFO_EXPRESSION_TYPE("D")!>d<!>) } } } }<!>
)
)
)
)
<!DEBUG_INFO_EXPRESSION_TYPE("Foo<R>")!>x<!>
}
fun <B, C, D, E, R> foo4(other1: Foo<B>, other2: Foo<C>, other3: Foo<D>, other4: Foo<E>, function: (A, B, C, D, E) -> R) {
val x = product<R>(
other1.product(
other2.product(
other3.product(
<!TYPE_MISMATCH, TYPE_MISMATCH!>other4.product(
bar { e -> { d -> { c -> { b -> { a -> function(<!DEBUG_INFO_EXPRESSION_TYPE("A")!>a<!>, <!DEBUG_INFO_EXPRESSION_TYPE("B")!>b<!>, <!DEBUG_INFO_EXPRESSION_TYPE("C")!>c<!>, <!DEBUG_INFO_EXPRESSION_TYPE("D")!>d<!>, <!DEBUG_INFO_EXPRESSION_TYPE("E")!>e<!>) } } } } }
)<!>
)
)
)
)
<!DEBUG_INFO_EXPRESSION_TYPE("Foo<R>")!>x<!>
}
companion object {
fun <A> bar(x: A) = materialize<Foo<A>>()
}
}
@@ -0,0 +1,23 @@
package
public fun </*0*/ T> materialize(): T
public final class Foo</*0*/ out A> {
public constructor Foo</*0*/ out A>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun </*0*/ B, /*1*/ R> foo1(/*0*/ other1: Foo<B>, /*1*/ function: (A, B) -> R): kotlin.Unit
public final fun </*0*/ B, /*1*/ C, /*2*/ R> foo2(/*0*/ other1: Foo<B>, /*1*/ other2: Foo<C>, /*2*/ function: (A, B, C) -> R): kotlin.Unit
public final fun </*0*/ B, /*1*/ C, /*2*/ D, /*3*/ E, /*4*/ R> foo3(/*0*/ other1: Foo<B>, /*1*/ other2: Foo<C>, /*2*/ other3: Foo<D>, /*3*/ other4: Foo<E>, /*4*/ function: (A, B, C, D) -> R): kotlin.Unit
public final fun </*0*/ B, /*1*/ C, /*2*/ D, /*3*/ E, /*4*/ R> foo4(/*0*/ other1: Foo<B>, /*1*/ other2: Foo<C>, /*2*/ other3: Foo<D>, /*3*/ other4: Foo<E>, /*4*/ function: (A, B, C, D, E) -> R): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun </*0*/ B> product(/*0*/ other: Foo<(A) -> B>): Foo<B>
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public companion object Companion {
private constructor Companion()
public final fun </*0*/ A> bar(/*0*/ x: A): Foo<A>
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,41 @@
// !DIAGNOSTICS: -UNUSED_LAMBDA_EXPRESSION, -UNUSED_EXPRESSION
fun case1(x: Any){
when (x){
1 -> try { {"1"}; ""; 1} catch (e: Exception) { { }}
"1" -> try { 1 } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
when (x){
1 -> try { {"1"}; ""} catch (e: Exception) { { }}
"1" -> try { 1 } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
}
fun case2(x: Any){
when (x){
1 -> try { {"1"}; ""; TODO()} catch (e: Exception) { { }}
"1" -> try { 1 } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
when (x){
1 -> try { {"1"}; ""; TODO(); ""} catch (e: Exception) { { }}
"1" -> try { 1 } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
when (x){
1 -> try { {"1"}; ""; TODO()} catch (e: Exception) { { }}
"1" -> try { 1; "" } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
}
fun case3(x: Any){
when (x){
1 -> try { {"1"}} catch (e: Exception) { { }}
"1" -> try { 1 } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
}
@@ -0,0 +1,41 @@
// !DIAGNOSTICS: -UNUSED_LAMBDA_EXPRESSION, -UNUSED_EXPRESSION
fun case1(x: Any){
when (x){
1 -> try { {"1"}; ""; 1} catch (e: Exception) { { }}
"1" -> try { 1 } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
when (x){
1 -> try { {"1"}; ""} catch (e: Exception) { { }}
"1" -> try { 1 } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
}
fun case2(x: Any){
when (x){
1 -> try { {"1"}; ""; TODO()} catch (e: Exception) { { }}
"1" -> try { 1 } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
when (x){
1 -> try { {"1"}; ""; TODO(); <!UNREACHABLE_CODE!>""<!>} catch (e: Exception) { { }}
"1" -> try { 1 } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
when (x){
1 -> try { {"1"}; ""; TODO()} catch (e: Exception) { { }}
"1" -> try { 1; "" } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
}
fun case3(x: Any){
when (x){
1 -> try { {"1"}} catch (e: Exception) { { }}
"1" -> try { 1 } catch (e: Exception) { { }}
else -> try { 1 } catch (e: Exception) { {1 }}
}
}
@@ -0,0 +1,5 @@
package
public fun case1(/*0*/ x: kotlin.Any): kotlin.Unit
public fun case2(/*0*/ x: kotlin.Any): kotlin.Unit
public fun case3(/*0*/ x: kotlin.Any): kotlin.Unit
@@ -7,6 +7,8 @@ fun main() {
val x2: String.() -> String = if (true) {{ -> this }} else {{ -> this }}
val x3: () -> String = if (true) {{ -> "this" }} else {{ -> "this" }}
val x4: String.() -> String = if (true) {{ str: String -> "this" }} else {{ str: String -> "this" }}
val x41: String.(String) -> String = if (true) {{ str: String, str2: String -> "this" }} else {{ str: String, str2: String -> "this" }}
val x42: String.(String) -> String = if (true) {{ str, str2 -> "this" }} else {{ str, str2 -> "this" }}
val x5: String.() -> String = if (true) {{ str -> "this" }} else {{ str -> "this" }}
val x6: String.() -> String = if (true) {{ str -> "this" }} else {{ "this" }}
val x7: String.() -> String = select({ -> this }, { -> this })
@@ -7,6 +7,8 @@ fun main() {
val x2: String.() -> String = if (true) {{ -> this }} else {{ -> this }}
val x3: () -> String = if (true) {{ -> "this" }} else {{ -> "this" }}
val x4: String.() -> String = if (true) {{ str: String -> "this" }} else {{ str: String -> "this" }}
val x41: String.(String) -> String = if (true) {{ str: String, str2: String -> "this" }} else {{ str: String, str2: String -> "this" }}
val x42: String.(String) -> String = if (true) <!TYPE_MISMATCH!>{{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!>str, <!CANNOT_INFER_PARAMETER_TYPE!>str2<!><!> -> "this" }}<!> else <!TYPE_MISMATCH!>{{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!>str, <!CANNOT_INFER_PARAMETER_TYPE!>str2<!><!> -> "this" }}<!>
val x5: String.() -> String = if (true) <!TYPE_MISMATCH!>{{ <!CANNOT_INFER_PARAMETER_TYPE, EXPECTED_PARAMETERS_NUMBER_MISMATCH!>str<!> -> "this" }}<!> else <!TYPE_MISMATCH!>{{ <!CANNOT_INFER_PARAMETER_TYPE, EXPECTED_PARAMETERS_NUMBER_MISMATCH!>str<!> -> "this" }}<!>
val x6: String.() -> String = if (true) <!TYPE_MISMATCH!>{{ <!CANNOT_INFER_PARAMETER_TYPE, EXPECTED_PARAMETERS_NUMBER_MISMATCH!>str<!> -> "this" }}<!> else {{ "this" }}
val x7: String.() -> String = select({ -> this }, { -> this })
@@ -22,11 +22,11 @@ fun foo(i: Int, f: (Int) -> Int) = f(i)
fun <T> id(t: T) = t
fun test() {
<!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(1, id(fun(x1: Int) =
<!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(2, id(fun(x2: Int) =
<!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(3, id(fun(x3: Int) =
<!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(4, id(fun(x4: Int) =
<!NI;OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(5, id(fun(x5: Int) =
foo(1, id(fun(x1: Int) =
foo(2, id(fun(x2: Int) =
foo(3, id(fun(x3: Int) =
foo(4, id(fun(x4: Int) =
foo(5, id(fun(x5: Int) =
x1 + x2 + x3 + x4 + x5 + A.iii
))
))
@@ -0,0 +1,8 @@
Failures detected in FirBodyResolveTransformerAdapter, file: /callableReferences.fir.kt
Cause: java.lang.RuntimeException: While resolving call R?C|/selectNumber|(R?C|/id|(::R?C|/foo6|), R?C|/id|(<L> = id@fun <implicit>.<anonymous>(x: <implicit>): <implicit> {
x#
}
), R?C|/id|(<L> = id@fun <implicit>.<anonymous>(): <implicit> {
it#
}
))
@@ -0,0 +1,57 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
import kotlin.reflect.*
fun <T>id(x: T) = x
fun <T> select(vararg x: T) = x[0]
fun foo(x: Int) {}
fun foo2(x: Number) {}
fun foo3(x: Int) {}
fun foo3(x: Number) {}
interface A
interface B
fun foo4(x: A) {}
fun foo4(x: B) {}
interface C: A, B
fun foo5(x: A) {}
fun foo5(x: B) {}
fun foo5(x: C) {}
fun <T: (Float) -> Unit> selectNumber(vararg x: T) = x[0]
fun foo6(x: Int) {}
fun foo6(x: Float) {}
fun foo6(x: Number) {}
fun main() {
select(::foo, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
select(id(::foo), { x: Number -> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
val x1 = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>id(::foo)<!>, <!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Number) -> kotlin.Number")!>id { x: Number -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!> }<!>)
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int) -> kotlin.Any")!>x1<!>
val x11 = select(id(::foo), id { x: Number -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int) -> kotlin.Any")!>x11<!>
select(id(::foo2), id { x: Int -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
select(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>::foo3<!>), id { x: Int -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
select(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>::foo3<!>), id { x: Number -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
select(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>::foo3<!>), id { x: Number -> }, id { x: Int -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
select(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<A, kotlin.Unit>")!>::foo4<!>), id { x: A -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> })
select(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<B, kotlin.Unit>")!>::foo4<!>), id { x: B -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("B")!>it<!> })
// Expected ambiguity
select(id(::<!CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY!>foo4<!>), id { x: A -> }, id { x: B -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("{A & B}")!>it<!> })
select(id(::foo5), id { x: A -> }, id { x: B -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> })
val x2: (Int) -> Unit = selectNumber(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Number, kotlin.Unit>")!>::foo6<!>), id { x -> <!DEBUG_INFO_EXPRESSION_TYPE("{Comparable<*> & Number}")!>x<!> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("{Comparable<*> & Number}")!>it<!> })
}
@@ -0,0 +1,57 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
import kotlin.reflect.*
fun <T>id(x: T) = x
fun <T> select(vararg x: T) = x[0]
fun foo(x: Int) {}
fun foo2(x: Number) {}
fun foo3(x: Int) {}
fun foo3(x: Number) {}
interface A
interface B
fun foo4(x: A) {}
fun foo4(x: B) {}
interface C: A, B
fun foo5(x: A) {}
fun foo5(x: B) {}
fun foo5(x: C) {}
fun <T: (Float) -> Unit> selectNumber(vararg x: T) = x[0]
fun foo6(x: Int) {}
fun foo6(x: Float) {}
fun foo6(x: Number) {}
fun main() {
select(::foo, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
select(id(::foo), { x: Number -> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
val x1 = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>id(::foo)<!>, <!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Number) -> kotlin.Number")!>id { x: Number -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!> }<!>)
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int) -> kotlin.Any")!>x1<!>
val x11 = select(id(::foo), id { x: Number -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Int) -> kotlin.Any")!>x11<!>
select(id(::foo2), id { x: Int -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
select(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>::foo3<!>), id { x: Int -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
select(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>::foo3<!>), id { x: Number -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
select(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Int, kotlin.Unit>")!>::foo3<!>), id { x: Number -> }, id { x: Int -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> })
select(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<A, kotlin.Unit>")!>::foo4<!>), id { x: A -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> })
select(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<B, kotlin.Unit>")!>::foo4<!>), id { x: B -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("B")!>it<!> })
// Expected ambiguity
select(id(::<!CALLABLE_REFERENCE_RESOLUTION_AMBIGUITY!>foo4<!>), id { x: A -> }, id { x: B -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("{A & B}")!>it<!> })
select(id(::foo5), id { x: A -> }, id { x: B -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> })
val x2: (Int) -> Unit = selectNumber(id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<kotlin.Number, kotlin.Unit>")!>::foo6<!>), id { x -> <!DEBUG_INFO_EXPRESSION_TYPE("{Comparable<*> & Number}")!>x<!> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("{Comparable<*> & Number}")!>it<!> })
}
@@ -0,0 +1,36 @@
package
public fun foo(/*0*/ x: kotlin.Int): kotlin.Unit
public fun foo2(/*0*/ x: kotlin.Number): kotlin.Unit
public fun foo3(/*0*/ x: kotlin.Int): kotlin.Unit
public fun foo3(/*0*/ x: kotlin.Number): kotlin.Unit
public fun foo4(/*0*/ x: A): kotlin.Unit
public fun foo4(/*0*/ x: B): kotlin.Unit
public fun foo5(/*0*/ x: A): kotlin.Unit
public fun foo5(/*0*/ x: B): kotlin.Unit
public fun foo5(/*0*/ x: C): kotlin.Unit
public fun foo6(/*0*/ x: kotlin.Float): kotlin.Unit
public fun foo6(/*0*/ x: kotlin.Int): kotlin.Unit
public fun foo6(/*0*/ x: kotlin.Number): kotlin.Unit
public fun </*0*/ T> id(/*0*/ x: T): T
public fun main(): kotlin.Unit
public fun </*0*/ T> select(/*0*/ vararg x: T /*kotlin.Array<out T>*/): T
public fun </*0*/ T : (kotlin.Float) -> kotlin.Unit> selectNumber(/*0*/ vararg x: T /*kotlin.Array<out T>*/): T
public interface A {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C : A, B {
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,41 @@
// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -UNUSED_PARAMETER
interface AssertionPlant<out T : Any>
interface AssertionPlantNullable<out T : Any?>: BaseAssertionPlant<T, AssertionPlantNullable<T>>
interface BaseAssertionPlant<out T : Any?, out A : BaseAssertionPlant<T, A>>
interface BaseCollectingAssertionPlant<out T, out A : BaseAssertionPlant<T, A>, out C : BaseCollectingAssertionPlant<T, A, C>> : BaseAssertionPlant<T, A>
interface CreatorLike<TSubject, T, A : BaseAssertionPlant<T, A>, C : BaseCollectingAssertionPlant<T, A, C>>
interface ParameterObjectOption {
fun <TSubject : Any, T : Any?> withParameterObjectNullable(
parameterObject: ParameterObject<TSubject, T>
) = null as CreatorNullable<TSubject, T>
}
class ParameterObject<TSubject, T>
interface CollectingAssertionPlantNullable<out T> : AssertionPlantNullable<T>,
BaseCollectingAssertionPlant<T, AssertionPlantNullable<T>, CollectingAssertionPlantNullable<T>>
interface CreatorNullable<TSubject, T>: CreatorLike<TSubject, T, AssertionPlantNullable<T>, CollectingAssertionPlantNullable<T>>
fun <K, V, M, A : BaseAssertionPlant<V, A>, C : BaseCollectingAssertionPlant<V, A, C>> contains(
pairs: List<Pair<K, M>>,
parameterObjectOption: (ParameterObjectOption, K) -> CreatorLike<Map<out K, V>, V, A, C>,
assertionCreator: C.(M) -> Unit
) {}
private fun <K, V> createGetParameterObject(
plant: AssertionPlant<Map<out K, V>>,
key: K
) = null as ParameterObject<Map<out K, V>, V>
private fun <K, V : Any, M> containsNullable(
plant: AssertionPlant<Map<out K, V?>>,
pairs: List<Pair<K, M>>,
assertionCreator: AssertionPlantNullable<V?>.(M) -> Unit
) = contains(
pairs,
{ option, key -> option.withParameterObjectNullable(createGetParameterObject(plant, key)) },
assertionCreator
)
@@ -0,0 +1,41 @@
// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -UNUSED_PARAMETER
interface AssertionPlant<out T : Any>
interface AssertionPlantNullable<out T : Any?>: BaseAssertionPlant<T, AssertionPlantNullable<T>>
interface BaseAssertionPlant<out T : Any?, out A : BaseAssertionPlant<T, A>>
interface BaseCollectingAssertionPlant<out T, out A : BaseAssertionPlant<T, A>, out C : BaseCollectingAssertionPlant<T, A, C>> : BaseAssertionPlant<T, A>
interface CreatorLike<TSubject, T, A : BaseAssertionPlant<T, A>, C : BaseCollectingAssertionPlant<T, A, C>>
interface ParameterObjectOption {
fun <TSubject : Any, T : Any?> withParameterObjectNullable(
parameterObject: ParameterObject<TSubject, T>
) = null as CreatorNullable<TSubject, T>
}
class ParameterObject<TSubject, T>
interface CollectingAssertionPlantNullable<out T> : AssertionPlantNullable<T>,
BaseCollectingAssertionPlant<T, AssertionPlantNullable<T>, CollectingAssertionPlantNullable<T>>
interface CreatorNullable<TSubject, T>: CreatorLike<TSubject, T, AssertionPlantNullable<T>, CollectingAssertionPlantNullable<T>>
fun <K, V, M, A : BaseAssertionPlant<V, A>, C : BaseCollectingAssertionPlant<V, A, C>> contains(
pairs: List<Pair<K, M>>,
parameterObjectOption: (ParameterObjectOption, K) -> CreatorLike<Map<out K, V>, V, A, C>,
assertionCreator: C.(M) -> Unit
) {}
private fun <K, V> createGetParameterObject(
plant: AssertionPlant<Map<out K, V>>,
key: K
) = null as ParameterObject<Map<out K, V>, V>
private fun <K, V : Any, M> containsNullable(
plant: AssertionPlant<Map<out K, V?>>,
pairs: List<Pair<K, M>>,
assertionCreator: AssertionPlantNullable<V?>.(M) -> Unit
) = contains(
pairs,
{ option, key -> <!DEBUG_INFO_EXPRESSION_TYPE("CreatorNullable<kotlin.collections.Map<out K, V?>, V?>")!>option.withParameterObjectNullable(createGetParameterObject(plant, key))<!> },
assertionCreator
)
@@ -0,0 +1,61 @@
package
public fun </*0*/ K, /*1*/ V, /*2*/ M, /*3*/ A : BaseAssertionPlant<V, A>, /*4*/ C : BaseCollectingAssertionPlant<V, A, C>> contains(/*0*/ pairs: kotlin.collections.List<kotlin.Pair<K, M>>, /*1*/ parameterObjectOption: (ParameterObjectOption, K) -> CreatorLike<kotlin.collections.Map<out K, V>, V, A, C>, /*2*/ assertionCreator: C.(M) -> kotlin.Unit): kotlin.Unit
private fun </*0*/ K, /*1*/ V : kotlin.Any, /*2*/ M> containsNullable(/*0*/ plant: AssertionPlant<kotlin.collections.Map<out K, V?>>, /*1*/ pairs: kotlin.collections.List<kotlin.Pair<K, M>>, /*2*/ assertionCreator: AssertionPlantNullable<V?>.(M) -> kotlin.Unit): kotlin.Unit
private fun </*0*/ K, /*1*/ V> createGetParameterObject(/*0*/ plant: AssertionPlant<kotlin.collections.Map<out K, V>>, /*1*/ key: K): ParameterObject<kotlin.collections.Map<out K, V>, V>
public interface AssertionPlant</*0*/ out T : kotlin.Any> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface AssertionPlantNullable</*0*/ out T> : BaseAssertionPlant<T, AssertionPlantNullable<T>> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface BaseAssertionPlant</*0*/ out T, /*1*/ out A : BaseAssertionPlant<T, A>> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface BaseCollectingAssertionPlant</*0*/ out T, /*1*/ out A : BaseAssertionPlant<T, A>, /*2*/ out C : BaseCollectingAssertionPlant<T, A, C>> : BaseAssertionPlant<T, A> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface CollectingAssertionPlantNullable</*0*/ out T> : AssertionPlantNullable<T>, BaseCollectingAssertionPlant<T, AssertionPlantNullable<T>, CollectingAssertionPlantNullable<T>> {
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface CreatorLike</*0*/ TSubject, /*1*/ T, /*2*/ A : BaseAssertionPlant<T, A>, /*3*/ C : BaseCollectingAssertionPlant<T, A, C>> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface CreatorNullable</*0*/ TSubject, /*1*/ T> : CreatorLike<TSubject, T, AssertionPlantNullable<T>, CollectingAssertionPlantNullable<T>> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class ParameterObject</*0*/ TSubject, /*1*/ T> {
public constructor ParameterObject</*0*/ TSubject, /*1*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface ParameterObjectOption {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public open fun </*0*/ TSubject : kotlin.Any, /*1*/ T> withParameterObjectNullable(/*0*/ parameterObject: ParameterObject<TSubject, T>): CreatorNullable<TSubject, T>
}
@@ -0,0 +1,14 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun useList(list: List<Any?>) { }
fun useMap(map: Map<String, Any?>) { }
enum class Color {BLUE}
fun Color.grayValue() {}
fun test() {
useList(listOf({ x: Color -> x.grayValue() }, Color.BLUE))
useMap(mapOf("a" to { x: Color -> x.grayValue() }, "b" to Color.BLUE))
}
@@ -0,0 +1,25 @@
package
public fun test(): kotlin.Unit
public fun useList(/*0*/ list: kotlin.collections.List<kotlin.Any?>): kotlin.Unit
public fun useMap(/*0*/ map: kotlin.collections.Map<kotlin.String, kotlin.Any?>): kotlin.Unit
public fun Color.grayValue(): kotlin.Unit
public final enum class Color : kotlin.Enum<Color> {
enum entry BLUE
private constructor Color()
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Color): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<Color!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Color
public final /*synthesized*/ fun values(): kotlin.Array<Color>
}
@@ -0,0 +1,11 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNCHECKED_CAST
fun <T : Any> foo(items: List<T>, handler: (T) -> Unit) {}
class Foo<T>(x: T)
fun <T> materialize(): T = null as T
fun main(x: List<String>?) {
foo(x?.map { Foo(it) } ?: listOf(materialize<Foo<Nothing>>())) {}
}
@@ -0,0 +1,11 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNCHECKED_CAST
fun <T : Any> foo(items: List<T>, handler: (T) -> Unit) {}
class Foo<T>(x: T)
fun <T> materialize(): T = null as T
fun main(x: List<String>?) {
foo(x?.map { Foo(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>it<!>) } ?: listOf(materialize<Foo<Nothing>>())) {}
}
@@ -0,0 +1,12 @@
package
public fun </*0*/ T : kotlin.Any> foo(/*0*/ items: kotlin.collections.List<T>, /*1*/ handler: (T) -> kotlin.Unit): kotlin.Unit
public fun main(/*0*/ x: kotlin.collections.List<kotlin.String>?): kotlin.Unit
public fun </*0*/ T> materialize(): T
public final class Foo</*0*/ T> {
public constructor Foo</*0*/ T>(/*0*/ x: T)
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,10 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -UNUSED_PARAMETER -UNCHECKED_CAST
fun <T> materialize() = null as T
val x: Map<String, String> = materialize<List<Map<String, String>>>().fold(mutableMapOf()) { m, x ->
val (s, action) = x.entries.first()
m[s] = action
m
}
@@ -0,0 +1,4 @@
package
public val x: kotlin.collections.Map<kotlin.String, kotlin.String>
public fun </*0*/ T> materialize(): T
@@ -0,0 +1,9 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
fun <T : Any> xSelectButton2(items: (matcher: String) -> List<T>, handler: T.() -> Unit) {}
fun main() {
val x: List<Int>? = listOf()
xSelectButton2({ matcher -> x ?: emptyList() }) { this.inv() }
}
@@ -0,0 +1,4 @@
package
public fun main(): kotlin.Unit
public fun </*0*/ T : kotlin.Any> xSelectButton2(/*0*/ items: (matcher: kotlin.String) -> kotlin.collections.List<T>, /*1*/ handler: T.() -> kotlin.Unit): kotlin.Unit
@@ -0,0 +1,6 @@
// FIR_IDENTICAL
interface ObservableSet<out T> : Set<T> {}
fun <K> test(x: List<ObservableSet<K>>) {
x.reduce { acc: Set<K>, set: Set<K> -> acc + set }
}
@@ -0,0 +1,14 @@
package
public fun </*0*/ K> test(/*0*/ x: kotlin.collections.List<ObservableSet<K>>): kotlin.Unit
public interface ObservableSet</*0*/ out T> : kotlin.collections.Set<T> {
public abstract override /*1*/ /*fake_override*/ val size: kotlin.Int
public abstract override /*1*/ /*fake_override*/ fun contains(/*0*/ element: T): kotlin.Boolean
public abstract override /*1*/ /*fake_override*/ fun containsAll(/*0*/ elements: kotlin.collections.Collection<T>): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public abstract override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
public abstract override /*1*/ /*fake_override*/ fun iterator(): kotlin.collections.Iterator<T>
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,12 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
class ArraySortedChecker<A, T>(val array: A, val comparator: Comparator<in T>) {
fun <R> checkSorted(sorted: A.() -> R, sortedDescending: A.() -> R, iterator: R.() -> Iterator<T>) {}
}
fun <A, T: Comparable<T>> arrayData(vararg values: T, toArray: Array<out T>.() -> A) = ArraySortedChecker<A, T>(values.toArray(), naturalOrder())
fun main() {
with (arrayData("ac", "aD", "aba") { toList().toTypedArray() }) {}
}
@@ -0,0 +1,14 @@
package
public fun </*0*/ A, /*1*/ T : kotlin.Comparable<T>> arrayData(/*0*/ vararg values: T /*kotlin.Array<out T>*/, /*1*/ toArray: kotlin.Array<out T>.() -> A): ArraySortedChecker<A, T>
public fun main(): kotlin.Unit
public final class ArraySortedChecker</*0*/ A, /*1*/ T> {
public constructor ArraySortedChecker</*0*/ A, /*1*/ T>(/*0*/ array: A, /*1*/ comparator: kotlin.Comparator<in T> /* = java.util.Comparator<in T> */)
public final val array: A
public final val comparator: kotlin.Comparator<in T> /* = java.util.Comparator<in T> */
public final fun </*0*/ R> checkSorted(/*0*/ sorted: A.() -> R, /*1*/ sortedDescending: A.() -> R, /*2*/ iterator: R.() -> kotlin.collections.Iterator<T>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,27 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
class Wrapper<T> (val x: T)
inline fun <T, R> Wrapper<T>.unwrap(validator: (T) -> R): R = validator(x)
fun <T> select(x: T) {}
class Foo<W>(y: Wrapper<List<W>>) {
fun <T> MutableCollection<T>.foo(x: T) {}
fun <T> MutableCollection<T>.foo(x: Iterable<T>) {}
init {
/*
* Before the fix, `foo` can't be disambiguated because the lambda is alanyzed in full mode,
* not in partial as before the inroducing new posponed arguments analysis.
*
* It happens due to the lack of rerun stages after fixation variables
* (stage 5 see `fixVariablesOrReportNotEnoughInformation` in `KotlinConstraintSystemCompleter.kt`).
* Rerun is need as fixation of variables can be make lambda available for analysis.
*
* TODO: add tests with lambdas, which can't be analyzed in partial mode, but if can, the code will be successfully resolved.
*/
ArrayList<W>().foo(y.unwrap { it })
}
}
@@ -0,0 +1,21 @@
package
public fun </*0*/ T> select(/*0*/ x: T): kotlin.Unit
public inline fun </*0*/ T, /*1*/ R> Wrapper<T>.unwrap(/*0*/ validator: (T) -> R): R
public final class Foo</*0*/ W> {
public constructor Foo</*0*/ W>(/*0*/ y: Wrapper<kotlin.collections.List<W>>)
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final fun </*0*/ T> kotlin.collections.MutableCollection<T>.foo(/*0*/ x: T): kotlin.Unit
public final fun </*0*/ T> kotlin.collections.MutableCollection<T>.foo(/*0*/ x: kotlin.collections.Iterable<T>): kotlin.Unit
}
public final class Wrapper</*0*/ T> {
public constructor Wrapper</*0*/ T>(/*0*/ x: T)
public final val x: T
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,8 @@
Failures detected in FirBodyResolveTransformerAdapter, file: /suspendFunctions.fir.kt
Cause: java.lang.RuntimeException: While resolving call R?C|/takeSuspend|(R?C|/id|(<L> = id@fun <implicit>.<anonymous>(): <implicit> {
it#
}
), takeSuspend@fun <anonymous>(x: R|kotlin/Int|): R|kotlin/Unit| {
^ R|<local>/x|
}
)
@@ -0,0 +1,25 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
fun <T> select(vararg x: T) = x[0]
fun <K> id(x: K): K = x
fun <T: suspend (Int) -> Unit, K: T> takeSuspend(x: T, y: K) = x
fun <T: (Int) -> Unit, K: T> takeSimpleFunction(x: T, y: K) = x
fun main() {
select(suspend {}, <!DEBUG_INFO_EXPRESSION_TYPE("suspend () -> kotlin.Unit")!>{}<!>)
select(<!DEBUG_INFO_EXPRESSION_TYPE("suspend () -> kotlin.Unit")!>{}<!>, suspend {})
select(<!DEBUG_INFO_EXPRESSION_TYPE("suspend () -> kotlin.Unit")!>id {}<!>, suspend {})
select(<!DEBUG_INFO_EXPRESSION_TYPE("suspend () -> kotlin.Unit")!>id {}<!>, id(suspend {}))
select(<!DEBUG_INFO_EXPRESSION_TYPE("suspend () -> kotlin.Unit")!>id {}<!>, id<suspend () -> Unit> {})
takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>{ x -> x }<!>)
val x1: suspend (Int) -> Unit = takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>{ x -> x }<!>)
// Here, the error should be
val x2: (Int) -> Unit = <!TYPE_MISMATCH!>takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ it }<!><!>, <!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit"), TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ x -> x }<!>)<!>
val x3: suspend (Int) -> Unit = takeSimpleFunction(<!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ it }<!><!>, <!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit"), TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ x -> x }<!>)
val x4: (Int) -> Unit = <!TYPE_MISMATCH, TYPE_MISMATCH!>takeSimpleFunction(<!TYPE_MISMATCH!>id<suspend (Int) -> Unit> {}<!>, <!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit"), TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{}<!>)<!>
}
@@ -0,0 +1,25 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
fun <T> select(vararg x: T) = x[0]
fun <K> id(x: K): K = x
fun <T: suspend (Int) -> Unit, K: T> takeSuspend(x: T, y: K) = x
fun <T: (Int) -> Unit, K: T> takeSimpleFunction(x: T, y: K) = x
fun main() {
select(suspend {}, <!DEBUG_INFO_EXPRESSION_TYPE("suspend () -> kotlin.Unit")!>{}<!>)
select(<!DEBUG_INFO_EXPRESSION_TYPE("suspend () -> kotlin.Unit")!>{}<!>, suspend {})
select(<!DEBUG_INFO_EXPRESSION_TYPE("suspend () -> kotlin.Unit")!>id {}<!>, suspend {})
select(<!DEBUG_INFO_EXPRESSION_TYPE("suspend () -> kotlin.Unit")!>id {}<!>, id(suspend {}))
select(<!DEBUG_INFO_EXPRESSION_TYPE("suspend () -> kotlin.Unit")!>id {}<!>, id<suspend () -> Unit> {})
takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>{ x -> x }<!>)
val x1: suspend (Int) -> Unit = takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>id { it }<!>, <!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>{ x -> x }<!>)
// Here, the error should be
val x2: (Int) -> Unit = <!TYPE_MISMATCH!>takeSuspend(<!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ it }<!><!>, <!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit"), TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ x -> x }<!>)<!>
val x3: suspend (Int) -> Unit = takeSimpleFunction(<!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit")!>id <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ it }<!><!>, <!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit"), TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ x -> x }<!>)
val x4: (Int) -> Unit = <!TYPE_MISMATCH, TYPE_MISMATCH!>takeSimpleFunction(<!TYPE_MISMATCH!>id<suspend (Int) -> Unit> {}<!>, <!DEBUG_INFO_EXPRESSION_TYPE("suspend (kotlin.Int) -> kotlin.Unit"), TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{}<!>)<!>
}
@@ -0,0 +1,7 @@
package
public fun </*0*/ K> id(/*0*/ x: K): K
public fun main(): kotlin.Unit
public fun </*0*/ T> select(/*0*/ vararg x: T /*kotlin.Array<out T>*/): T
public fun </*0*/ T : (kotlin.Int) -> kotlin.Unit, /*1*/ K : T> takeSimpleFunction(/*0*/ x: T, /*1*/ y: K): T
public fun </*0*/ T : suspend (kotlin.Int) -> kotlin.Unit, /*1*/ K : T> takeSuspend(/*0*/ x: T, /*1*/ y: K): T
@@ -118,13 +118,12 @@ fun case_8(value_1: Int, value_2: Int) = when {
/*
* TESTCASE NUMBER: 9
* UNEXPECTED BEHAVIOUR
* ISSUES: KT-37249
*/
fun case_9(value_1: Int, value_2: String, value_3: String) = when {
value_1 == 1 -> try { 4 } catch (e: Exception) { 5 }
value_1 == 2 -> try { throw Exception() } catch (e: Exception) { value_2 }
else -> try { throw Exception() } catch (e: Exception) <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ {<!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>value_3<!>} }<!> finally { }
value_1 == 1 -> <!IMPLICIT_CAST_TO_ANY!>try { 4 } catch (e: Exception) { 5 }<!>
value_1 == 2 -> <!IMPLICIT_CAST_TO_ANY!>try { throw Exception() } catch (e: Exception) { value_2 }<!>
else -> <!IMPLICIT_CAST_TO_ANY!>try { throw Exception() } catch (e: Exception) { {value_3} } finally { }<!>
}
// TESTCASE NUMBER: 10
@@ -119,14 +119,13 @@ fun case_8(value_1: Int, value_2: Int) = when (value_1) {
/*
* TESTCASE NUMBER: 9
* UNEXPECTED BEHAVIOUR
* ISSUES: KT-37249
*/
fun case_9(value_1: Int, value_2: String, value_3: String): Any {
return when (value_1) {
1 -> try { 4 } catch (e: Exception) { 5 }
2 -> try { throw Exception() } catch (e: Exception) { value_2 }
else -> try { throw Exception() } catch (e: Exception) <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>{ {<!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>value_3<!>} }<!> finally { }
else -> try { throw Exception() } catch (e: Exception) { {value_3} } finally { }
}
}
@@ -10748,6 +10748,44 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
public void testWithExact() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/withExact.kt");
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PostponedArgumentsAnalysis extends AbstractDiagnosticsTestWithFirValidation {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPostponedArgumentsAnalysis() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("basic.kt")
public void testBasic() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.kt");
}
@TestMetadata("callableReferenceLambdaCombinationInsideCall.kt")
public void testCallableReferenceLambdaCombinationInsideCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/callableReferenceLambdaCombinationInsideCall.kt");
}
@TestMetadata("callableReferences.kt")
public void testCallableReferences() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/callableReferences.kt");
}
@TestMetadata("lackOfDeepIncorporation.kt")
public void testLackOfDeepIncorporation() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/lackOfDeepIncorporation.kt");
}
@TestMetadata("lambdasInTryCatch.kt")
public void testLambdasInTryCatch() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/lambdasInTryCatch.kt");
}
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/constraints")
@@ -3069,6 +3069,82 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/completion")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Completion extends AbstractDiagnosticsTestWithStdLib {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCompletion() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/inference/completion"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PostponedArgumentsAnalysis extends AbstractDiagnosticsTestWithStdLib {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPostponedArgumentsAnalysis() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("callableReferences.kt")
public void testCallableReferences() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/callableReferences.kt");
}
@TestMetadata("complexInterdependentInputOutputTypes.kt")
public void testComplexInterdependentInputOutputTypes() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/complexInterdependentInputOutputTypes.kt");
}
@TestMetadata("deepLambdas.kt")
public void testDeepLambdas() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/deepLambdas.kt");
}
@TestMetadata("fixIndependentVariables.kt")
public void testFixIndependentVariables() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/fixIndependentVariables.kt");
}
@TestMetadata("fixInputTypeToMoreSpecificType.kt")
public void testFixInputTypeToMoreSpecificType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/fixInputTypeToMoreSpecificType.kt");
}
@TestMetadata("fixReceiverToMoreSpecificType.kt")
public void testFixReceiverToMoreSpecificType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/fixReceiverToMoreSpecificType.kt");
}
@TestMetadata("moreSpecificOutputType.kt")
public void testMoreSpecificOutputType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/moreSpecificOutputType.kt");
}
@TestMetadata("rerunStagesAfterFixationInFullMode.kt")
public void testRerunStagesAfterFixationInFullMode() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/rerunStagesAfterFixationInFullMode.kt");
}
@TestMetadata("rerunStagesAfterFixationInPartialMode.kt")
public void testRerunStagesAfterFixationInPartialMode() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/rerunStagesAfterFixationInPartialMode.kt");
}
@TestMetadata("suspendFunctions.kt")
public void testSuspendFunctions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/suspendFunctions.kt");
}
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/delegates")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -3069,6 +3069,82 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/completion")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Completion extends AbstractDiagnosticsTestWithStdLibUsingJavac {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCompletion() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/inference/completion"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PostponedArgumentsAnalysis extends AbstractDiagnosticsTestWithStdLibUsingJavac {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPostponedArgumentsAnalysis() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("callableReferences.kt")
public void testCallableReferences() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/callableReferences.kt");
}
@TestMetadata("complexInterdependentInputOutputTypes.kt")
public void testComplexInterdependentInputOutputTypes() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/complexInterdependentInputOutputTypes.kt");
}
@TestMetadata("deepLambdas.kt")
public void testDeepLambdas() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/deepLambdas.kt");
}
@TestMetadata("fixIndependentVariables.kt")
public void testFixIndependentVariables() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/fixIndependentVariables.kt");
}
@TestMetadata("fixInputTypeToMoreSpecificType.kt")
public void testFixInputTypeToMoreSpecificType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/fixInputTypeToMoreSpecificType.kt");
}
@TestMetadata("fixReceiverToMoreSpecificType.kt")
public void testFixReceiverToMoreSpecificType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/fixReceiverToMoreSpecificType.kt");
}
@TestMetadata("moreSpecificOutputType.kt")
public void testMoreSpecificOutputType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/moreSpecificOutputType.kt");
}
@TestMetadata("rerunStagesAfterFixationInFullMode.kt")
public void testRerunStagesAfterFixationInFullMode() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/rerunStagesAfterFixationInFullMode.kt");
}
@TestMetadata("rerunStagesAfterFixationInPartialMode.kt")
public void testRerunStagesAfterFixationInPartialMode() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/rerunStagesAfterFixationInPartialMode.kt");
}
@TestMetadata("suspendFunctions.kt")
public void testSuspendFunctions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inference/completion/postponedArgumentsAnalysis/suspendFunctions.kt");
}
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/inference/delegates")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -10743,6 +10743,44 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
public void testWithExact() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/withExact.kt");
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PostponedArgumentsAnalysis extends AbstractDiagnosticsUsingJavacTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPostponedArgumentsAnalysis() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("basic.kt")
public void testBasic() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/basic.kt");
}
@TestMetadata("callableReferenceLambdaCombinationInsideCall.kt")
public void testCallableReferenceLambdaCombinationInsideCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/callableReferenceLambdaCombinationInsideCall.kt");
}
@TestMetadata("callableReferences.kt")
public void testCallableReferences() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/callableReferences.kt");
}
@TestMetadata("lackOfDeepIncorporation.kt")
public void testLackOfDeepIncorporation() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/lackOfDeepIncorporation.kt");
}
@TestMetadata("lambdasInTryCatch.kt")
public void testLambdasInTryCatch() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/completion/postponedArgumentsAnalysis/lambdasInTryCatch.kt");
}
}
}
@TestMetadata("compiler/testData/diagnostics/tests/inference/constraints")
@@ -442,6 +442,11 @@ public abstract class KotlinBuiltIns {
return "Function" + parameterCount;
}
@NotNull
private static FqNameUnsafe getKFunctionFqName(int parameterCount) {
return FqNames.reflect(FunctionClassDescriptor.Kind.KFunction.getClassNamePrefix() + parameterCount);
}
@NotNull
public static ClassId getFunctionClassId(int parameterCount) {
return new ClassId(BUILT_INS_PACKAGE_FQ_NAME, Name.identifier(getFunctionName(parameterCount)));
@@ -467,6 +472,17 @@ public abstract class KotlinBuiltIns {
return getBuiltInClassByFqName(COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier(getSuspendFunctionName(parameterCount))));
}
@NotNull
public ClassDescriptor getKFunction(int parameterCount) {
return getBuiltInClassByFqName(getKFunctionFqName(parameterCount).toSafe());
}
@NotNull
public ClassDescriptor getKSuspendFunction(int parameterCount) {
Name name = Name.identifier(FunctionClassDescriptor.Kind.KSuspendFunction.getClassNamePrefix() + parameterCount);
return getBuiltInClassByFqName(COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(name));
}
@NotNull
public ClassDescriptor getThrowable() {
return getBuiltInClassByName("Throwable");
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.BuiltInAnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
@@ -19,6 +20,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
@@ -67,6 +69,9 @@ val KotlinType.isKSuspendFunctionType: Boolean
val KotlinType.isFunctionOrSuspendFunctionType: Boolean
get() = isFunctionType || isSuspendFunctionType
val KotlinType.isFunctionOrKFunctionTypeWithAnySuspendability: Boolean
get() = isFunctionType || isSuspendFunctionType || isKFunctionType || isKSuspendFunctionType
val KotlinType.isBuiltinFunctionalType: Boolean
get() = constructor.declarationDescriptor?.isBuiltinFunctionalClassDescriptor == true
@@ -154,6 +159,16 @@ fun KotlinType.getValueParameterTypesFromCallableReflectionType(isCallableTypeWi
return arguments.subList(first, last)
}
fun KotlinType.extractFunctionalTypeFromSupertypes(): KotlinType {
assert(isBuiltinFunctionalTypeOrSubtype) { "Not a function type or subtype: $this" }
return if (isBuiltinFunctionalType) this else supertypes().first { it.isBuiltinFunctionalType }
}
fun KotlinType.getPureArgumentsForFunctionalTypeOrSubtype(): List<KotlinType> {
assert(isBuiltinFunctionalTypeOrSubtype) { "Not a function type or subtype: $this" }
return extractFunctionalTypeFromSupertypes().arguments.dropLast(1).map { it.type }
}
fun KotlinType.extractParameterNameFromFunctionTypeArgument(): Name? {
val annotation = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.parameterName) ?: return null
val name = (annotation.allValueArguments.values.singleOrNull() as? StringValue)
@@ -197,29 +212,38 @@ fun getFunctionTypeArgumentProjections(
@JvmOverloads
fun createFunctionType(
builtIns: KotlinBuiltIns,
annotations: Annotations,
receiverType: KotlinType?,
parameterTypes: List<KotlinType>,
parameterNames: List<Name>?,
returnType: KotlinType,
suspendFunction: Boolean = false
builtIns: KotlinBuiltIns,
annotations: Annotations,
receiverType: KotlinType?,
parameterTypes: List<KotlinType>,
parameterNames: List<Name>?,
returnType: KotlinType,
suspendFunction: Boolean = false
): SimpleType {
val arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, parameterNames, returnType, builtIns)
val size = parameterTypes.size
val parameterCount = if (receiverType == null) size else size + 1
val classDescriptor = if (suspendFunction) builtIns.getSuspendFunction(parameterCount) else builtIns.getFunction(parameterCount)
val parameterCount = if (receiverType == null) parameterTypes.size else parameterTypes.size + 1
val classDescriptor = getFunctionDescriptor(builtIns, parameterCount, suspendFunction)
// TODO: preserve laziness of given annotations
val typeAnnotations =
if (receiverType == null || annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType) != null) {
annotations
}
else {
Annotations.create(
annotations + BuiltInAnnotationDescriptor(builtIns, KotlinBuiltIns.FQ_NAMES.extensionFunctionType, emptyMap())
)
}
val typeAnnotations = if (receiverType != null) annotations.withExtensionFunctionAnnotation(builtIns) else annotations
return KotlinTypeFactory.simpleNotNullType(typeAnnotations, classDescriptor, arguments)
}
fun Annotations.hasExtensionFunctionAnnotation() = hasAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType)
fun Annotations.withoutExtensionFunctionAnnotation() =
FilteredAnnotations(this, true) { it != KotlinBuiltIns.FQ_NAMES.extensionFunctionType }
fun Annotations.withExtensionFunctionAnnotation(builtIns: KotlinBuiltIns) =
if (hasAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType)) {
this
} else {
Annotations.create(this + BuiltInAnnotationDescriptor(builtIns, KotlinBuiltIns.FQ_NAMES.extensionFunctionType, emptyMap()))
}
fun getFunctionDescriptor(builtIns: KotlinBuiltIns, parameterCount: Int, isSuspendFunction: Boolean) =
if (isSuspendFunction) builtIns.getSuspendFunction(parameterCount) else builtIns.getFunction(parameterCount)
fun getKFunctionDescriptor(builtIns: KotlinBuiltIns, parameterCount: Int, isSuspendFunction: Boolean) =
if (isSuspendFunction) builtIns.getKSuspendFunction(parameterCount) else builtIns.getKFunction(parameterCount)
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.types.checker
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -318,6 +319,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
return KotlinBuiltIns.isUnit(this)
}
override fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype(): Boolean {
require(this is UnwrappedType, this::errorMessage)
return isBuiltinFunctionalTypeOrSubtype
}
override fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker {
require(lowerBound is SimpleType, this::errorMessage)
require(upperBound is SimpleType, this::errorMessage)
@@ -132,6 +132,8 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
fun KotlinTypeMarker.isUnit(): Boolean
fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype(): Boolean
fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker