[FIR] Improved lambda completion: initial implementation
Repeat the logic of KotlinConstraintSystemCompleter in ConstraintSystemCompleter. Implement additional context operations required for updated lambda completion algorithm.
This commit is contained in:
+5
@@ -10447,6 +10447,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/inference/lambdaInValInitializerWithAnonymousFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaParameterTypeInElvis.kt")
|
||||
public void testLambdaParameterTypeInElvis() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/lambdaParameterTypeInElvis.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("listConstructor.kt")
|
||||
public void testListConstructor() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/listConstructor.kt");
|
||||
|
||||
+55
-41
@@ -5,14 +5,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.inference
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeFixVariableConstraintPosition
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemUtilContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.PostponedArgumentInputTypesResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.FixVariableConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.model.LambdaWithTypeVariableAsExpectedTypeMarker
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedAtomWithRevisableExpectedType
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
|
||||
object ConeConstraintSystemUtilContext : ConstraintSystemUtilContext {
|
||||
@@ -41,67 +45,77 @@ object ConeConstraintSystemUtilContext : ConstraintSystemUtilContext {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isFunctionOrKFunctionTypeWithAnySuspendability(): Boolean {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isSuspendFunctionTypeOrSubtype(): Boolean {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun extractFunctionalTypeFromSupertypes(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.extractArgumentsForFunctionalTypeOrSubtype(): List<KotlinTypeMarker> {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun <T> createArgumentConstraintPosition(argument: T): ArgumentConstraintPosition<T> {
|
||||
TODO()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return ConeArgumentConstraintPosition() as ArgumentConstraintPosition<T>
|
||||
}
|
||||
|
||||
override fun <T> createFixVariableConstraintPosition(variable: TypeVariableMarker, atom: T): FixVariableConstraintPosition<T> {
|
||||
TODO()
|
||||
require(atom == null)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return ConeFixVariableConstraintPosition(variable) as FixVariableConstraintPosition<T>
|
||||
}
|
||||
|
||||
override fun extractParameterTypesFromDeclaration(declaration: PostponedAtomWithRevisableExpectedType): List<ConeKotlinType?>? {
|
||||
TODO()
|
||||
require(declaration is PostponedResolvedAtom)
|
||||
return when (declaration) {
|
||||
is LambdaWithTypeVariableAsExpectedTypeAtom -> {
|
||||
val atom = declaration.atom
|
||||
return if (atom.isLambda) { // lambda - must return null in case of absent parameters
|
||||
if (atom.valueParameters.isNotEmpty())
|
||||
atom.collectDeclaredValueParameterTypes()
|
||||
else null
|
||||
} else { // function expression - all types are explicit, shouldn't return null
|
||||
mutableListOf<ConeKotlinType?>().apply {
|
||||
atom.receiverTypeRef?.coneType?.let { add(it) }
|
||||
addAll(atom.collectDeclaredValueParameterTypes())
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isExtensionFunctionType(): Boolean {
|
||||
TODO()
|
||||
}
|
||||
private fun FirAnonymousFunction.collectDeclaredValueParameterTypes(): List<ConeKotlinType?> =
|
||||
valueParameters.map {
|
||||
if (it.returnTypeRef !is FirImplicitTypeRef)
|
||||
it.returnTypeRef.coneType
|
||||
else null
|
||||
}
|
||||
|
||||
override fun getFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun getKFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun isAnonymousFunction(argument: PostponedAtomWithRevisableExpectedType): Boolean {
|
||||
TODO()
|
||||
override fun PostponedAtomWithRevisableExpectedType.isAnonymousFunction(): Boolean {
|
||||
require(this is PostponedResolvedAtom)
|
||||
return this is LambdaWithTypeVariableAsExpectedTypeAtom && !this.atom.isLambda
|
||||
}
|
||||
|
||||
override fun PostponedAtomWithRevisableExpectedType.isFunctionExpressionWithReceiver(): Boolean {
|
||||
TODO()
|
||||
require(this is PostponedResolvedAtom)
|
||||
return this is LambdaWithTypeVariableAsExpectedTypeAtom && !this.atom.isLambda && this.atom.receiverTypeRef?.coneType != null
|
||||
}
|
||||
|
||||
override fun createTypeVariableForLambdaReturnType(): TypeVariableMarker {
|
||||
TODO()
|
||||
return ConeTypeVariableForPostponedAtom(PostponedArgumentInputTypesResolver.TYPE_VARIABLE_NAME_FOR_LAMBDA_RETURN_TYPE)
|
||||
}
|
||||
|
||||
override fun createTypeVariableForLambdaParameterType(argument: PostponedAtomWithRevisableExpectedType, index: Int): TypeVariableMarker {
|
||||
TODO()
|
||||
override fun createTypeVariableForLambdaParameterType(
|
||||
argument: PostponedAtomWithRevisableExpectedType,
|
||||
index: Int
|
||||
): TypeVariableMarker {
|
||||
return ConeTypeVariableForPostponedAtom(
|
||||
"${PostponedArgumentInputTypesResolver.TYPE_VARIABLE_NAME_PREFIX_FOR_LAMBDA_PARAMETER_TYPE}$index"
|
||||
)
|
||||
}
|
||||
|
||||
override fun createTypeVariableForCallableReferenceParameterType(argument: PostponedAtomWithRevisableExpectedType, index: Int): TypeVariableMarker {
|
||||
TODO()
|
||||
override fun createTypeVariableForCallableReferenceParameterType(
|
||||
argument: PostponedAtomWithRevisableExpectedType,
|
||||
index: Int
|
||||
): TypeVariableMarker {
|
||||
return ConeTypeVariableForPostponedAtom(
|
||||
"${PostponedArgumentInputTypesResolver.TYPE_VARIABLE_NAME_PREFIX_FOR_CR_PARAMETER_TYPE}$index"
|
||||
)
|
||||
}
|
||||
|
||||
override fun createTypeVariableForCallableReferenceReturnType(): TypeVariableMarker {
|
||||
TODO()
|
||||
return ConeTypeVariableForPostponedAtom(PostponedArgumentInputTypesResolver.TYPE_VARIABLE_NAME_FOR_LAMBDA_RETURN_TYPE)
|
||||
}
|
||||
}
|
||||
|
||||
+212
-134
@@ -13,25 +13,19 @@ import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeFixVariableConstraintPosition
|
||||
import org.jetbrains.kotlin.fir.returnExpressions
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.TypeVariableDirectionCalculator
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.VariableFixationFinder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
||||
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.resolve.calls.model.PostponedAtomWithRevisableExpectedType
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.typeConstructor
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
||||
private val inferenceComponents = components.session.inferenceComponents
|
||||
val variableFixationFinder = inferenceComponents.variableFixationFinder
|
||||
private val postponedArgumentsInputTypesResolver = inferenceComponents.postponedArgumentInputTypesResolver
|
||||
|
||||
fun complete(
|
||||
c: ConstraintSystemCompletionContext,
|
||||
@@ -41,133 +35,219 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
||||
context: ResolutionContext,
|
||||
collectVariablesFromContext: Boolean = false,
|
||||
analyze: (PostponedResolvedAtom) -> Unit
|
||||
) {
|
||||
) = with(c) {
|
||||
|
||||
while (true) {
|
||||
if (analyzePostponeArgumentIfPossible(c, topLevelAtoms, analyze)) continue
|
||||
completion@ while (true) {
|
||||
val postponedArguments = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
|
||||
|
||||
val allTypeVariables = getOrderedAllTypeVariables(c, topLevelAtoms, collectVariablesFromContext)
|
||||
val postponedAtoms = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
|
||||
val variableForFixation =
|
||||
variableFixationFinder.findFirstVariableForFixation(
|
||||
c, allTypeVariables, postponedAtoms, completionMode, candidateReturnType
|
||||
) ?: break
|
||||
if (completionMode == ConstraintSystemCompletionMode.UNTIL_FIRST_LAMBDA && hasLambdaToAnalyze(postponedArguments)) return
|
||||
|
||||
if (
|
||||
completionMode == ConstraintSystemCompletionMode.FULL &&
|
||||
resolveLambdaOrCallableReferenceWithTypeVariableAsExpectedType(c, variableForFixation, postponedAtoms, context, analyze)
|
||||
) {
|
||||
// Stage 1
|
||||
if (analyzeArgumentWithFixedParameterTypes(postponedArguments, analyze))
|
||||
continue
|
||||
|
||||
val someVariableIsReadyForFixation = isAnyVariableReadyForFixation(
|
||||
completionMode, topLevelAtoms, candidateReturnType, collectVariablesFromContext, postponedArguments
|
||||
)
|
||||
|
||||
if (postponedArguments.isEmpty() && !someVariableIsReadyForFixation)
|
||||
break
|
||||
|
||||
val postponedArgumentsWithRevisableType = postponedArguments
|
||||
.filterIsInstance<PostponedAtomWithRevisableExpectedType>()
|
||||
.filter { it.revisedExpectedType == null }
|
||||
val dependencyProvider =
|
||||
TypeVariableDependencyInformationProvider(notFixedTypeVariables, postponedArguments, candidateReturnType, this)
|
||||
|
||||
// Stage 2
|
||||
val newExpectedTypeWasBuilt = postponedArgumentsInputTypesResolver.collectParameterTypesAndBuildNewExpectedTypes(
|
||||
asConstraintSystemCompletionContext(), postponedArgumentsWithRevisableType, completionMode, dependencyProvider
|
||||
)
|
||||
|
||||
if (newExpectedTypeWasBuilt)
|
||||
continue
|
||||
|
||||
if (completionMode == ConstraintSystemCompletionMode.FULL) {
|
||||
// Stage 3
|
||||
for (argument in postponedArguments) {
|
||||
val variableWasFixed = postponedArgumentsInputTypesResolver.fixNextReadyVariableForParameterTypeIfNeeded(
|
||||
asConstraintSystemCompletionContext(),
|
||||
argument,
|
||||
postponedArguments,
|
||||
candidateReturnType,
|
||||
dependencyProvider,
|
||||
) { // atom provided here is used only inside constraint positions, omitting right now
|
||||
null
|
||||
}
|
||||
|
||||
if (variableWasFixed)
|
||||
continue@completion
|
||||
}
|
||||
|
||||
// Stage 4
|
||||
for (argument in postponedArgumentsWithRevisableType) {
|
||||
val argumentWasTransformed =
|
||||
transformToAtomWithNewFunctionalExpectedType(asConstraintSystemCompletionContext(), context, argument)
|
||||
|
||||
if (argumentWasTransformed)
|
||||
continue@completion
|
||||
}
|
||||
}
|
||||
|
||||
if (variableForFixation.hasProperConstraint || completionMode == ConstraintSystemCompletionMode.FULL) {
|
||||
val variableWithConstraints = c.notFixedTypeVariables.getValue(variableForFixation.variable)
|
||||
|
||||
fixVariable(c, candidateReturnType, variableWithConstraints, emptyList())
|
||||
|
||||
// if (!variableForFixation.hasProperConstraint) {
|
||||
// c.addError(NotEnoughInformationForTypeParameter(variableWithConstraints.typeVariable))
|
||||
// }
|
||||
// Stage 5: analyze the next ready postponed argument
|
||||
if (analyzeNextReadyPostponedArgument(postponedArguments, completionMode, analyze))
|
||||
continue
|
||||
|
||||
// Stage 6: fix type variables – fix if possible or report not enough information (if completion mode is full)
|
||||
val variableWasFixed = fixVariablesOrReportNotEnoughInformation(
|
||||
completionMode, topLevelAtoms, candidateReturnType, collectVariablesFromContext, postponedArguments
|
||||
)
|
||||
if (variableWasFixed)
|
||||
continue
|
||||
|
||||
// Stage 7: force analysis of remaining not analyzed postponed arguments and rerun stages if there are
|
||||
if (completionMode == ConstraintSystemCompletionMode.FULL) {
|
||||
if (analyzeRemainingNotAnalyzedPostponedArgument(postponedArguments, analyze))
|
||||
continue
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
if (completionMode == ConstraintSystemCompletionMode.FULL) {
|
||||
// force resolution for all not-analyzed argument's
|
||||
getOrderedNotAnalyzedPostponedArguments(topLevelAtoms).forEach(analyze)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveLambdaOrCallableReferenceWithTypeVariableAsExpectedType(
|
||||
c: ConstraintSystemCompletionContext,
|
||||
variableForFixation: VariableFixationFinder.VariableForFixation,
|
||||
postponedAtoms: List<PostponedResolvedAtom>,
|
||||
context: ResolutionContext,
|
||||
private fun ConstraintSystemCompletionContext.analyzeArgumentWithFixedParameterTypes(
|
||||
postponedArguments: List<PostponedResolvedAtom>,
|
||||
analyze: (PostponedResolvedAtom) -> Unit
|
||||
): Boolean {
|
||||
val variable = variableForFixation.variable as ConeTypeVariableTypeConstructor
|
||||
val hasProperAtom = postponedAtoms.any {
|
||||
when (it) {
|
||||
is LambdaWithTypeVariableAsExpectedTypeAtom/*, is PostponedCallableReferenceAtom*/
|
||||
-> it.expectedType.typeConstructor(c) == variable // TODO
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
if (
|
||||
!hasProperAtom &&
|
||||
variableForFixation.hasProperConstraint &&
|
||||
!variableForFixation.hasOnlyTrivialProperConstraint
|
||||
) return false
|
||||
val argumentWithFixedOrPostponedInputTypes = findPostponedArgumentWithFixedOrPostponedInputTypes(postponedArguments)
|
||||
|
||||
val postponedAtom = postponedAtoms.firstOrNull() ?: return false
|
||||
val csBuilder = (c as NewConstraintSystemImpl).getBuilder()
|
||||
val expectedTypeVariableConstructor = postponedAtom.expectedType?.typeConstructor(c)?.takeIf { it in c.allTypeVariables } as? ConeTypeVariableTypeConstructor ?: variable
|
||||
val expectedTypeVariable = csBuilder.currentStorage().allTypeVariables[expectedTypeVariableConstructor] as ConeTypeVariable? ?: return false
|
||||
|
||||
val atomToAnalyze = when (postponedAtom) {
|
||||
is LambdaWithTypeVariableAsExpectedTypeAtom -> {
|
||||
postponedAtom.preparePostponedAtomWithTypeVariableAsExpectedType(
|
||||
c, csBuilder, expectedTypeVariable,
|
||||
parameterTypes = null,
|
||||
isSuitable = { isBuiltinFunctionalType(components.session) },
|
||||
typeVariableCreator = { ConeTypeVariableForLambdaReturnType(postponedAtom.atom, "_R") },
|
||||
newAtomCreator = { returnTypeVariable, expectedType ->
|
||||
postponedAtom.transformToResolvedLambda(csBuilder, context, expectedType, returnTypeVariable)
|
||||
}
|
||||
)
|
||||
}
|
||||
// is PostponedCallableReferenceAtom -> TODO()
|
||||
else -> return false
|
||||
if (argumentWithFixedOrPostponedInputTypes != null) {
|
||||
analyze(argumentWithFixedOrPostponedInputTypes)
|
||||
return true
|
||||
}
|
||||
analyze(atomToAnalyze)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun ConstraintSystemCompletionContext.findPostponedArgumentWithFixedOrPostponedInputTypes(postponedArguments: List<PostponedResolvedAtom>) =
|
||||
postponedArguments.firstOrNull { argument -> argument.inputTypes.all { containsOnlyFixedOrPostponedVariables(it) } }
|
||||
|
||||
private fun ConstraintSystemCompletionContext.isAnyVariableReadyForFixation(
|
||||
completionMode: ConstraintSystemCompletionMode,
|
||||
topLevelAtoms: List<FirStatement>,
|
||||
topLevelType: ConeKotlinType,
|
||||
collectVariablesFromContext: Boolean,
|
||||
postponedArguments: List<PostponedResolvedAtom>,
|
||||
): Boolean {
|
||||
return variableFixationFinder.findFirstVariableForFixation(
|
||||
this,
|
||||
getOrderedAllTypeVariables(this, topLevelAtoms, collectVariablesFromContext),
|
||||
postponedArguments,
|
||||
completionMode,
|
||||
topLevelType
|
||||
) != null
|
||||
}
|
||||
|
||||
private fun transformToAtomWithNewFunctionalExpectedType(
|
||||
c: ConstraintSystemCompletionContext,
|
||||
resolutionContext: ResolutionContext,
|
||||
argument: PostponedAtomWithRevisableExpectedType,
|
||||
): Boolean = with(c) {
|
||||
val revisedExpectedType: ConeKotlinType =
|
||||
argument.revisedExpectedType?.takeIf { it.isFunctionOrKFunctionWithAnySuspendability() }?.cast() ?: return false
|
||||
|
||||
when (argument) {
|
||||
is ResolvedCallableReferenceAtom -> {
|
||||
argument.reviseExpectedType(revisedExpectedType)
|
||||
}
|
||||
|
||||
is LambdaWithTypeVariableAsExpectedTypeAtom ->
|
||||
argument.transformToResolvedLambda(c.getBuilder(), resolutionContext, revisedExpectedType, null /*TODO()*/)
|
||||
else -> throw IllegalStateException("Unsupported postponed argument type of $argument")
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private inline fun <T : PostponedResolvedAtom, V : ConeTypeVariable> T.preparePostponedAtomWithTypeVariableAsExpectedType(
|
||||
c: ConstraintSystemCompletionContext,
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
variable: ConeTypeVariable,
|
||||
parameterTypes: Array<out ConeKotlinType?>?,
|
||||
isSuitable: ConeKotlinType.() -> Boolean,
|
||||
typeVariableCreator: () -> V,
|
||||
newAtomCreator: (V, ConeKotlinType) -> PostponedResolvedAtom
|
||||
): PostponedResolvedAtom {
|
||||
val functionalType = (inferenceComponents.resultTypeResolver.findResultType(
|
||||
c,
|
||||
c.notFixedTypeVariables.getValue(variable.typeConstructor),
|
||||
TypeVariableDirectionCalculator.ResolveDirection.TO_SUPERTYPE
|
||||
) as ConeKotlinType).lowerBoundIfFlexible()
|
||||
val isExtensionWithoutParameters = functionalType.isExtensionFunctionType && functionalType.typeArguments.size == 2 && parameterTypes?.isEmpty() == true
|
||||
if (parameterTypes?.all { type -> type != null } == true && !isExtensionWithoutParameters) return this
|
||||
if (!functionalType.isSuitable()) return this
|
||||
require(functionalType is ConeClassLikeType)
|
||||
val returnVariable = typeVariableCreator()
|
||||
csBuilder.registerVariable(returnVariable)
|
||||
private fun ConstraintSystemCompletionContext.analyzeNextReadyPostponedArgument(
|
||||
postponedArguments: List<PostponedResolvedAtom>,
|
||||
completionMode: ConstraintSystemCompletionMode,
|
||||
analyze: (PostponedResolvedAtom) -> Unit,
|
||||
): Boolean {
|
||||
if (completionMode == ConstraintSystemCompletionMode.FULL) {
|
||||
val argumentWithTypeVariableAsExpectedType = findPostponedArgumentWithRevisableExpectedType(postponedArguments)
|
||||
|
||||
val expectedType = ConeClassLikeTypeImpl(
|
||||
lookupTag = functionalType.lookupTag,
|
||||
typeArguments = (functionalType.typeArguments.dropLast(1) + returnVariable.defaultType).toTypedArray(),
|
||||
isNullable = functionalType.isNullable,
|
||||
attributes = functionalType.attributes
|
||||
)
|
||||
if (argumentWithTypeVariableAsExpectedType != null) {
|
||||
analyze(argumentWithTypeVariableAsExpectedType)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
csBuilder.addSubtypeConstraint(
|
||||
expectedType,
|
||||
variable.defaultType,
|
||||
SimpleConstraintSystemConstraintPosition
|
||||
// ArgumentConstraintPosition(atom as KotlinCallArgument)
|
||||
)
|
||||
return newAtomCreator(returnVariable, expectedType)
|
||||
return analyzeArgumentWithFixedParameterTypes(postponedArguments, analyze)
|
||||
}
|
||||
|
||||
// Avoiding smart cast from filterIsInstanceOrNull looks dirty
|
||||
private fun findPostponedArgumentWithRevisableExpectedType(postponedArguments: List<PostponedResolvedAtom>) =
|
||||
postponedArguments.firstOrNull { argument -> argument is PostponedAtomWithRevisableExpectedType }
|
||||
|
||||
private fun ConstraintSystemCompletionContext.fixVariablesOrReportNotEnoughInformation(
|
||||
completionMode: ConstraintSystemCompletionMode,
|
||||
topLevelAtoms: List<FirStatement>,
|
||||
topLevelType: ConeKotlinType,
|
||||
collectVariablesFromContext: Boolean,
|
||||
postponedArguments: List<PostponedResolvedAtom>,
|
||||
): Boolean {
|
||||
while (true) {
|
||||
val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
|
||||
this,
|
||||
getOrderedAllTypeVariables(asConstraintSystemCompletionContext(), topLevelAtoms, collectVariablesFromContext),
|
||||
postponedArguments,
|
||||
completionMode,
|
||||
topLevelType
|
||||
) ?: break
|
||||
|
||||
if (!variableForFixation.hasProperConstraint && completionMode == ConstraintSystemCompletionMode.PARTIAL)
|
||||
break
|
||||
|
||||
val variableWithConstraints = notFixedTypeVariables.getValue(variableForFixation.variable)
|
||||
|
||||
if (variableForFixation.hasProperConstraint) {
|
||||
fixVariable(asConstraintSystemCompletionContext(), variableWithConstraints)
|
||||
return true
|
||||
} else {
|
||||
// TODO("Not enough information for parameter")
|
||||
fixVariable(asConstraintSystemCompletionContext(), variableWithConstraints) // means Nothing/Any instead of Error type
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
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 ConstraintSystemCompletionContext.hasLambdaToAnalyze(
|
||||
postponedArguments: List<PostponedResolvedAtom>
|
||||
): Boolean {
|
||||
return analyzeArgumentWithFixedParameterTypes(postponedArguments) {}
|
||||
}
|
||||
|
||||
private fun getOrderedAllTypeVariables(
|
||||
c: ConstraintSystemCompletionContext,
|
||||
topLevelAtoms: List<FirStatement>,
|
||||
collectVariablesFromContext: Boolean
|
||||
): List<TypeConstructorMarker> {
|
||||
): List<TypeConstructorMarker> = with(c) {
|
||||
if (collectVariablesFromContext) {
|
||||
return c.notFixedTypeVariables.keys.toList()
|
||||
}
|
||||
@@ -175,15 +255,31 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
||||
fun ConeTypeVariable?.toTypeConstructor(): TypeConstructorMarker? =
|
||||
this?.typeConstructor?.takeIf { it in c.notFixedTypeVariables.keys }
|
||||
|
||||
// TODO: non-top-level variables?
|
||||
fun PostponedAtomWithRevisableExpectedType.collectNotFixedVariables() {
|
||||
revisedExpectedType?.getArguments()?.map { it.getType().typeConstructor() }
|
||||
?.filterIsInstance<ConeTypeVariableTypeConstructor>().orEmpty()
|
||||
.mapNotNullTo(result) { it.takeIf { it in notFixedTypeVariables } }
|
||||
}
|
||||
|
||||
fun FirStatement.collectAllTypeVariables() {
|
||||
this.processAllContainingCallCandidates(processBlocks = true) { candidate ->
|
||||
candidate.freshVariables.mapNotNullTo(result) { typeVariable ->
|
||||
typeVariable.toTypeConstructor()
|
||||
}
|
||||
|
||||
for (lambdaAtom in candidate.postponedAtoms) {
|
||||
if (lambdaAtom is ResolvedLambdaAtom) {
|
||||
result.addIfNotNull(lambdaAtom.typeVariableForLambdaReturnType.toTypeConstructor())
|
||||
for (postponedAtom in candidate.postponedAtoms) {
|
||||
when {
|
||||
postponedAtom is ResolvedLambdaAtom -> {
|
||||
result.addIfNotNull(postponedAtom.typeVariableForLambdaReturnType.toTypeConstructor())
|
||||
}
|
||||
postponedAtom is LambdaWithTypeVariableAsExpectedTypeAtom -> {
|
||||
postponedAtom.collectNotFixedVariables()
|
||||
}
|
||||
postponedAtom is ResolvedCallableReferenceAtom -> {
|
||||
if (postponedAtom.postponed)
|
||||
postponedAtom.collectNotFixedVariables()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,30 +299,17 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
||||
|
||||
private fun fixVariable(
|
||||
c: ConstraintSystemCompletionContext,
|
||||
topLevelType: KotlinTypeMarker,
|
||||
variableWithConstraints: VariableWithConstraints,
|
||||
postponedResolveKtPrimitives: List<PostponedResolvedAtom>
|
||||
) {
|
||||
val direction = TypeVariableDirectionCalculator(c, postponedResolveKtPrimitives, topLevelType).getDirection(variableWithConstraints)
|
||||
val resultType = inferenceComponents.resultTypeResolver.findResultType(c, variableWithConstraints, direction)
|
||||
val resultType = inferenceComponents.resultTypeResolver.findResultType(
|
||||
c,
|
||||
variableWithConstraints,
|
||||
TypeVariableDirectionCalculator.ResolveDirection.UNKNOWN
|
||||
)
|
||||
val variable = variableWithConstraints.typeVariable
|
||||
c.fixVariable(variable, resultType, ConeFixVariableConstraintPosition(variable)) // TODO: obtain atom for diagnostics
|
||||
}
|
||||
|
||||
private fun analyzePostponeArgumentIfPossible(
|
||||
c: ConstraintSystemCompletionContext,
|
||||
topLevelAtoms: List<FirStatement>,
|
||||
analyze: (PostponedResolvedAtom) -> Unit
|
||||
): Boolean {
|
||||
for (argument in getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)) {
|
||||
if (canWeAnalyzeIt(c, argument)) {
|
||||
analyze(argument)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getOrderedNotAnalyzedPostponedArguments(topLevelAtoms: List<FirStatement>): List<PostponedResolvedAtom> {
|
||||
val notAnalyzedArguments = arrayListOf<PostponedResolvedAtom>()
|
||||
for (primitive in topLevelAtoms) {
|
||||
@@ -243,11 +326,6 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) {
|
||||
|
||||
return notAnalyzedArguments
|
||||
}
|
||||
|
||||
private fun canWeAnalyzeIt(c: ConstraintSystemCompletionContext, argument: PostponedResolvedAtomMarker): Boolean {
|
||||
if (argument.analyzed) return false
|
||||
return argument.inputTypes.all { c.containsOnlyFixedOrPostponedVariables(it) }
|
||||
}
|
||||
}
|
||||
|
||||
fun FirStatement.processAllContainingCallCandidates(processBlocks: Boolean, processor: (Candidate) -> Unit) {
|
||||
|
||||
+3
-2
@@ -25,11 +25,12 @@ class InferenceComponents(val session: FirSession) : FirSessionComponent {
|
||||
session.languageVersionSettings,
|
||||
)
|
||||
val resultTypeResolver = ResultTypeResolver(approximator, trivialConstraintTypeInferenceOracle)
|
||||
val variableFixationFinder = VariableFixationFinder(trivialConstraintTypeInferenceOracle, session.languageVersionSettings)
|
||||
val postponedArgumentInputTypesResolver =
|
||||
PostponedArgumentInputTypesResolver(resultTypeResolver, variableFixationFinder, ConeConstraintSystemUtilContext)
|
||||
|
||||
val constraintSystemFactory = ConstraintSystemFactory()
|
||||
|
||||
val variableFixationFinder = VariableFixationFinder(trivialConstraintTypeInferenceOracle, session.languageVersionSettings)
|
||||
|
||||
fun createConstraintSystem(): NewConstraintSystemImpl {
|
||||
return NewConstraintSystemImpl(injector, ctx)
|
||||
}
|
||||
|
||||
+38
-7
@@ -17,7 +17,8 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeVariable
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedAtomWithRevisableExpectedType
|
||||
import org.jetbrains.kotlin.resolve.calls.model.LambdaWithTypeVariableAsExpectedTypeMarker
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedCallableReferenceMarker
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
// --------------------------- Variables ---------------------------
|
||||
|
||||
class ConeTypeVariableForLambdaReturnType(val argument: FirAnonymousFunction, name: String) : ConeTypeVariable(name)
|
||||
class ConeTypeVariableForPostponedAtom(name: String) : ConeTypeVariable(name)
|
||||
|
||||
// -------------------------- Atoms --------------------------
|
||||
|
||||
@@ -61,15 +63,27 @@ class ResolvedLambdaAtom(
|
||||
|
||||
class LambdaWithTypeVariableAsExpectedTypeAtom(
|
||||
val atom: FirAnonymousFunction,
|
||||
override val expectedType: ConeKotlinType,
|
||||
private val initialExpectedTypeType: ConeKotlinType,
|
||||
val expectedTypeRef: FirTypeRef,
|
||||
val candidateOfOuterCall: Candidate
|
||||
) : PostponedResolvedAtom(), PostponedAtomWithRevisableExpectedType {
|
||||
val candidateOfOuterCall: Candidate,
|
||||
) : PostponedResolvedAtom(), LambdaWithTypeVariableAsExpectedTypeMarker {
|
||||
init {
|
||||
candidateOfOuterCall.postponedAtoms += this
|
||||
}
|
||||
|
||||
override val inputTypes: Collection<ConeKotlinType> get() = listOf(expectedType)
|
||||
override var parameterTypesFromDeclaration: List<ConeKotlinType?>? = null
|
||||
private set
|
||||
|
||||
override fun updateParameterTypesFromDeclaration(types: List<KotlinTypeMarker?>?) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
types as List<ConeKotlinType?>?
|
||||
parameterTypesFromDeclaration = types
|
||||
}
|
||||
|
||||
override val expectedType: ConeKotlinType
|
||||
get() = revisedExpectedType ?: initialExpectedTypeType
|
||||
|
||||
override val inputTypes: Collection<ConeKotlinType> get() = listOf(initialExpectedTypeType)
|
||||
override val outputType: ConeKotlinType? get() = null
|
||||
override var revisedExpectedType: ConeKotlinType? = null
|
||||
private set
|
||||
@@ -84,10 +98,11 @@ class LambdaWithTypeVariableAsExpectedTypeAtom(
|
||||
|
||||
class ResolvedCallableReferenceAtom(
|
||||
val reference: FirCallableReferenceAccess,
|
||||
override val expectedType: ConeKotlinType?,
|
||||
private val initialExpectedType: ConeKotlinType?,
|
||||
val lhs: DoubleColonLHS?,
|
||||
private val session: FirSession
|
||||
) : PostponedResolvedAtom() {
|
||||
) : PostponedResolvedAtom(), PostponedCallableReferenceMarker {
|
||||
// TODO: in several places atoms are filtered by the marker interface - potential overhead/errors
|
||||
var postponed: Boolean = false
|
||||
|
||||
var resultingCandidate: Pair<Candidate, CandidateApplicability>? = null
|
||||
@@ -103,6 +118,22 @@ class ResolvedCallableReferenceAtom(
|
||||
if (!postponed) return null
|
||||
return extractInputOutputTypesFromCallableReferenceExpectedType(expectedType, session)?.outputType
|
||||
}
|
||||
|
||||
override val expectedType: ConeKotlinType?
|
||||
get() = if (!postponed)
|
||||
initialExpectedType
|
||||
else
|
||||
revisedExpectedType ?: initialExpectedType
|
||||
|
||||
override var revisedExpectedType: ConeKotlinType? = null
|
||||
get() = if (postponed) field else expectedType
|
||||
private set
|
||||
|
||||
override fun reviseExpectedType(expectedType: KotlinTypeMarker) {
|
||||
if (!postponed) return
|
||||
require(expectedType is ConeKotlinType)
|
||||
revisedExpectedType = expectedType
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------- Utils --------------------------
|
||||
|
||||
+3
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.inference.model
|
||||
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.DeclaredUpperBoundConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.FixVariableConstraintPosition
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
@@ -12,3 +13,5 @@ import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
class ConeDeclaredUpperBoundConstraintPosition : DeclaredUpperBoundConstraintPosition<Nothing?>(null)
|
||||
|
||||
class ConeFixVariableConstraintPosition(variable: TypeVariableMarker) : FixVariableConstraintPosition<Nothing?>(variable, null)
|
||||
|
||||
class ConeArgumentConstraintPosition : ArgumentConstraintPosition<Nothing?>(null)
|
||||
+1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.FirTargetElement
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
|
||||
import org.jetbrains.kotlin.fir.isPrimitiveNumberOrUnsignedNumberType
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.NoSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
@@ -20,7 +23,9 @@ import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeContext {
|
||||
|
||||
@@ -49,19 +54,22 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
||||
return coneFlexibleOrSimpleType(this, lowerBound, upperBound)
|
||||
}
|
||||
|
||||
// TODO: implement taking into account `isExtensionFunction`
|
||||
override fun createSimpleType(
|
||||
constructor: TypeConstructorMarker,
|
||||
arguments: List<TypeArgumentMarker>,
|
||||
nullable: Boolean,
|
||||
isExtensionFunction: Boolean
|
||||
): SimpleTypeMarker {
|
||||
val attributes = if (isExtensionFunction) // TODO: assert correct type constructor
|
||||
ConeAttributes.create(listOf(CompilerConeAttributes.ExtensionFunctionType))
|
||||
else ConeAttributes.Empty
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return when (constructor) {
|
||||
is ConeClassLikeLookupTag -> ConeClassLikeTypeImpl(
|
||||
constructor,
|
||||
(arguments as List<ConeTypeProjection>).toTypedArray(),
|
||||
nullable
|
||||
nullable,
|
||||
attributes,
|
||||
)
|
||||
is ConeTypeParameterLookupTag -> ConeTypeParameterTypeImpl(
|
||||
constructor,
|
||||
@@ -203,7 +211,14 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
||||
return this.typeConstructor().isUnitTypeConstructor() && !this.isNullable
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype() = TODO()
|
||||
override fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype(): Boolean {
|
||||
require(this is ConeKotlinType)
|
||||
return this.isTypeOrSubtypeOf {
|
||||
it.lowerBoundIfFlexible().safeAs<ConeKotlinType>()?.isBuiltinFunctionalType(session)
|
||||
?: error("Unexpected lower bound for type: ${it.render()}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker {
|
||||
require(this is ConeKotlinType)
|
||||
@@ -376,4 +391,97 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
||||
if (this !is ConeClassLikeType) return false
|
||||
return isPrimitiveNumberOrUnsignedNumberType()
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isFunctionOrKFunctionWithAnySuspendability(): Boolean {
|
||||
require(this is ConeKotlinType)
|
||||
return this.isBuiltinFunctionalType(session)
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.isTypeOrSubtypeOf(predicate: (ConeKotlinType) -> Boolean): Boolean {
|
||||
return predicate(this) || DFS.dfsFromNode(
|
||||
this,
|
||||
{
|
||||
// FIXME supertypes of type constructor contain unsubstituted arguments
|
||||
it.typeConstructor().supertypes().cast<Collection<ConeKotlinType>>()
|
||||
},
|
||||
DFS.VisitedWithSet(),
|
||||
object : DFS.AbstractNodeHandler<ConeKotlinType, Boolean>() {
|
||||
private var result = false
|
||||
|
||||
override fun beforeChildren(current: ConeKotlinType): Boolean {
|
||||
if (predicate(current)) {
|
||||
result = true
|
||||
}
|
||||
return !result
|
||||
}
|
||||
|
||||
override fun result() = result
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isSuspendFunctionTypeOrSubtype(): Boolean {
|
||||
require(this is ConeKotlinType)
|
||||
return isTypeOrSubtypeOf {
|
||||
it.lowerBoundIfFlexible().safeAs<ConeKotlinType>()?.isSuspendFunctionType(session)
|
||||
?: error("Unexpected lower bound for type: ${it.render()}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isExtensionFunctionType(): Boolean {
|
||||
require(this is ConeKotlinType)
|
||||
return this.lowerBoundIfFlexible().safeAs<ConeKotlinType>()?.isExtensionFunctionType(session) == true
|
||||
}
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
override fun KotlinTypeMarker.extractArgumentsForFunctionalTypeOrSubtype(): List<KotlinTypeMarker> {
|
||||
val builtInFunctionalType = getFunctionalTypeFromSupertypes().cast<ConeKotlinType>()
|
||||
return buildList {
|
||||
// excluding return type
|
||||
for (index in 0 until builtInFunctionalType.argumentsCount() - 1) {
|
||||
add(builtInFunctionalType.getArgument(index).getType())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.getFunctionalTypeFromSupertypes(): KotlinTypeMarker {
|
||||
require(this is ConeKotlinType)
|
||||
assert(this.isBuiltinFunctionalTypeOrSubtype()) {
|
||||
"Not a function type or subtype: ${this.render()}"
|
||||
}
|
||||
|
||||
return fullyExpandedType(session).let {
|
||||
val simpleType = it.lowerBoundIfFlexible()
|
||||
if (simpleType.safeAs<ConeKotlinType>()?.isBuiltinFunctionalType(session) == true)
|
||||
this
|
||||
else {
|
||||
var functionalSupertype: KotlinTypeMarker? = null
|
||||
simpleType.anySuperTypeConstructor { typeConstructor ->
|
||||
simpleType.fastCorrespondingSupertypes(typeConstructor)?.any { superType ->
|
||||
val isFunctional = superType.cast<ConeKotlinType>().isBuiltinFunctionalType(session)
|
||||
if (isFunctional)
|
||||
functionalSupertype = superType
|
||||
isFunctional
|
||||
} ?: false
|
||||
}
|
||||
functionalSupertype ?: error("Failed to find functional supertype for $simpleType")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
|
||||
val classId = if (isSuspend)
|
||||
StandardNames.getSuspendFunctionClassId(parametersNumber)
|
||||
else StandardNames.getFunctionClassId(parametersNumber)
|
||||
return session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.toLookupTag()
|
||||
?: error("Can't find Function type")
|
||||
}
|
||||
|
||||
override fun getKFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
|
||||
val classId = if (isSuspend)
|
||||
StandardNames.getKSuspendFunctionClassId(parametersNumber)
|
||||
else StandardNames.getKFunctionClassId(parametersNumber)
|
||||
return session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.toLookupTag()
|
||||
?: error("Can't find KFunction type")
|
||||
}
|
||||
}
|
||||
|
||||
+2
-9
@@ -25,23 +25,16 @@ interface ConstraintSystemUtilContext {
|
||||
fun KotlinTypeMarker.refineType(): KotlinTypeMarker
|
||||
|
||||
// PostponedArgumentInputTypesResolver
|
||||
fun extractFunctionalTypeFromSupertypes(type: KotlinTypeMarker): KotlinTypeMarker
|
||||
fun KotlinTypeMarker.extractArgumentsForFunctionalTypeOrSubtype(): List<KotlinTypeMarker>
|
||||
fun KotlinTypeMarker.isFunctionOrKFunctionTypeWithAnySuspendability(): Boolean
|
||||
fun KotlinTypeMarker.isSuspendFunctionTypeOrSubtype(): Boolean
|
||||
fun <T> createArgumentConstraintPosition(argument: T): ArgumentConstraintPosition<T>
|
||||
fun <T> createFixVariableConstraintPosition(variable: TypeVariableMarker, atom: T): FixVariableConstraintPosition<T>
|
||||
fun extractParameterTypesFromDeclaration(declaration: PostponedAtomWithRevisableExpectedType): List<KotlinTypeMarker?>?
|
||||
fun KotlinTypeMarker.isExtensionFunctionType(): Boolean
|
||||
fun getFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker
|
||||
fun getKFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker
|
||||
fun isAnonymousFunction(argument: PostponedAtomWithRevisableExpectedType): Boolean
|
||||
fun PostponedAtomWithRevisableExpectedType.isAnonymousFunction(): Boolean
|
||||
fun PostponedAtomWithRevisableExpectedType.isFunctionExpressionWithReceiver(): Boolean
|
||||
fun createTypeVariableForLambdaReturnType(): TypeVariableMarker
|
||||
fun createTypeVariableForLambdaParameterType(argument: PostponedAtomWithRevisableExpectedType, index: Int): TypeVariableMarker
|
||||
fun createTypeVariableForCallableReferenceReturnType(): TypeVariableMarker
|
||||
fun createTypeVariableForCallableReferenceParameterType(
|
||||
argument: PostponedAtomWithRevisableExpectedType,
|
||||
index: Int
|
||||
): TypeVariableMarker
|
||||
fun createTypeVariableForCallableReferenceReturnType(): TypeVariableMarker
|
||||
}
|
||||
|
||||
+7
-8
@@ -38,7 +38,7 @@ class PostponedArgumentInputTypesResolver(
|
||||
variableDependencyProvider: TypeVariableDependencyInformationProvider
|
||||
): List<TypeWithKind>? {
|
||||
fun List<Constraint>.extractFunctionalTypes() = mapNotNull { constraint ->
|
||||
TypeWithKind(resolutionTypeSystemContext.extractFunctionalTypeFromSupertypes(constraint.type), constraint.kind)
|
||||
TypeWithKind(constraint.type.getFunctionalTypeFromSupertypes(), constraint.kind)
|
||||
}
|
||||
|
||||
val typeVariableTypeConstructor = variable.typeVariable.freshTypeConstructor()
|
||||
@@ -216,7 +216,7 @@ class PostponedArgumentInputTypesResolver(
|
||||
parametersNumber: Int,
|
||||
isSuspend: Boolean,
|
||||
resultTypeResolver: ResultTypeResolver
|
||||
): TypeConstructorMarker = with(resolutionTypeSystemContext) {
|
||||
): TypeConstructorMarker {
|
||||
val expectedType = argument.expectedType
|
||||
?: throw IllegalStateException("Postponed argument's expected type must not be null")
|
||||
|
||||
@@ -263,7 +263,7 @@ class PostponedArgumentInputTypesResolver(
|
||||
*
|
||||
* TODO: regarding anonymous functions: see info about need for analysis in partial mode in `collectParameterTypesAndBuildNewExpectedTypes`
|
||||
*/
|
||||
if (areAllParameterTypesSpecified && !isExtensionFunction && !isAnonymousFunction(argument))
|
||||
if (areAllParameterTypesSpecified && !isExtensionFunction && !argument.isAnonymousFunction())
|
||||
return null
|
||||
|
||||
val allParameterTypes =
|
||||
@@ -283,7 +283,6 @@ class PostponedArgumentInputTypesResolver(
|
||||
resultTypeResolver
|
||||
)
|
||||
|
||||
val isExtensionFunctionType = parameterTypesInfo.isExtensionFunction
|
||||
val areParametersNumberInDeclarationAndConstraintsEqual =
|
||||
!parametersFromDeclaration.isNullOrEmpty() && !parametersFromConstraints.isNullOrEmpty()
|
||||
&& parametersFromDeclaration.size == parametersFromConstraints.first().size
|
||||
@@ -295,7 +294,7 @@ class PostponedArgumentInputTypesResolver(
|
||||
* Example: `val x: String.() -> Int = id { x: String -> 42 }`
|
||||
*/
|
||||
val shouldDiscriminateExtensionFunctionAnnotation =
|
||||
isExtensionFunctionType && areAllParameterTypesSpecified && areParametersNumberInDeclarationAndConstraintsEqual
|
||||
isExtensionFunction && areAllParameterTypesSpecified && areParametersNumberInDeclarationAndConstraintsEqual
|
||||
|
||||
/*
|
||||
* We need to add an extension function annotation for anonymous functions with an explicitly specified receiver
|
||||
@@ -344,7 +343,7 @@ class PostponedArgumentInputTypesResolver(
|
||||
*
|
||||
* TODO: investigate why we can't do it for anonymous functions in full mode always (see `diagnostics/tests/resolve/resolveWithSpecifiedFunctionLiteralWithId.kt`)
|
||||
*/
|
||||
if (completionMode == ConstraintSystemCompletionMode.PARTIAL && !isAnonymousFunction(argument))
|
||||
if (completionMode == ConstraintSystemCompletionMode.PARTIAL && !argument.isAnonymousFunction())
|
||||
return@any false
|
||||
if (argument.revisedExpectedType != null) return@any false
|
||||
val parameterTypesInfo =
|
||||
@@ -402,10 +401,10 @@ class PostponedArgumentInputTypesResolver(
|
||||
topLevelType: KotlinTypeMarker,
|
||||
dependencyProvider: TypeVariableDependencyInformationProvider,
|
||||
resolvedAtomProvider: ResolvedAtomProvider
|
||||
): Boolean = with(resolutionTypeSystemContext) {
|
||||
): Boolean = with(c) {
|
||||
val expectedType = argument.run { safeAs<PostponedAtomWithRevisableExpectedType>()?.revisedExpectedType ?: expectedType }
|
||||
|
||||
if (expectedType != null && expectedType.isFunctionOrKFunctionTypeWithAnySuspendability()) {
|
||||
if (expectedType != null && expectedType.isFunctionOrKFunctionWithAnySuspendability()) {
|
||||
val wasFixedSomeVariable = c.fixNextReadyVariableForParameterType(
|
||||
expectedType,
|
||||
postponedArguments,
|
||||
|
||||
+3
-36
@@ -51,26 +51,6 @@ class ClassicConstraintSystemUtilContext(
|
||||
return kotlinTypeRefiner.refineType(this)
|
||||
}
|
||||
|
||||
override fun extractFunctionalTypeFromSupertypes(type: KotlinTypeMarker): KotlinTypeMarker {
|
||||
require(type is KotlinType)
|
||||
return type.extractFunctionalTypeFromSupertypes()
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.extractArgumentsForFunctionalTypeOrSubtype(): List<KotlinTypeMarker> {
|
||||
require(this is KotlinType)
|
||||
return this.getPureArgumentsForFunctionalTypeOrSubtype()
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isFunctionOrKFunctionTypeWithAnySuspendability(): Boolean {
|
||||
require(this is KotlinType)
|
||||
return this.isFunctionOrKFunctionTypeWithAnySuspendability
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isSuspendFunctionTypeOrSubtype(): Boolean {
|
||||
require(this is KotlinType)
|
||||
return this.isSuspendFunctionTypeOrSubtype
|
||||
}
|
||||
|
||||
override fun <T> createArgumentConstraintPosition(argument: T): ArgumentConstraintPosition<T> {
|
||||
require(argument is ResolvedAtom)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -95,22 +75,9 @@ class ClassicConstraintSystemUtilContext(
|
||||
}
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isExtensionFunctionType(): Boolean {
|
||||
require(this is KotlinType)
|
||||
return this.isExtensionFunctionType
|
||||
}
|
||||
|
||||
override fun getFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
|
||||
return getFunctionDescriptor(builtIns, parametersNumber, isSuspend).typeConstructor
|
||||
}
|
||||
|
||||
override fun getKFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
|
||||
return getKFunctionDescriptor(builtIns, parametersNumber, isSuspend).typeConstructor
|
||||
}
|
||||
|
||||
override fun isAnonymousFunction(argument: PostponedAtomWithRevisableExpectedType): Boolean {
|
||||
require(argument is ResolvedAtom)
|
||||
return argument.atom is FunctionExpression
|
||||
override fun PostponedAtomWithRevisableExpectedType.isAnonymousFunction(): Boolean {
|
||||
require(this is ResolvedAtom)
|
||||
return this.atom is FunctionExpression
|
||||
}
|
||||
|
||||
override fun PostponedAtomWithRevisableExpectedType.isFunctionExpressionWithReceiver(): Boolean {
|
||||
|
||||
+2
-2
@@ -150,9 +150,9 @@ class KotlinConstraintSystemCompleter(
|
||||
c: ConstraintSystemCompletionContext,
|
||||
argument: PostponedAtomWithRevisableExpectedType,
|
||||
diagnosticsHolder: KotlinDiagnosticsHolder
|
||||
): Boolean = with(ctx) {
|
||||
): Boolean = with(c) {
|
||||
val revisedExpectedType: UnwrappedType =
|
||||
argument.revisedExpectedType?.takeIf { it.isFunctionOrKFunctionTypeWithAnySuspendability() }?.cast() ?: return false
|
||||
argument.revisedExpectedType?.takeIf { it.isFunctionOrKFunctionWithAnySuspendability() }?.cast() ?: return false
|
||||
|
||||
when (argument) {
|
||||
is PostponedCallableReferenceAtom ->
|
||||
|
||||
@@ -212,8 +212,7 @@ class CallableReferenceWithRevisedExpectedTypeAtom(
|
||||
class PostponedCallableReferenceAtom(
|
||||
eagerCallableReferenceAtom: EagerCallableReferenceAtom
|
||||
) : AbstractPostponedCallableReferenceAtom(eagerCallableReferenceAtom.atom, eagerCallableReferenceAtom.expectedType),
|
||||
PostponedCallableReferenceMarker,
|
||||
PostponedAtomWithRevisableExpectedType
|
||||
PostponedCallableReferenceMarker
|
||||
{
|
||||
override var revisedExpectedType: UnwrappedType? = null
|
||||
private set
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
class Host(var value: String) {
|
||||
|
||||
Vendored
+1
-1
@@ -5,5 +5,5 @@ fun foo(x: Any, y: Int) = y
|
||||
fun main() {
|
||||
<!UNRESOLVED_REFERENCE!>::foo<!>
|
||||
|
||||
val fooRef: (Int, Any) -> Unit = ::foo
|
||||
val fooRef: (Int, Any) -> Unit = <!UNRESOLVED_REFERENCE!>::foo<!>
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,6 +19,6 @@ fun testFunctions() {
|
||||
|
||||
fun testNestedCalls() {
|
||||
id<String>(inferFromLambda { materialize() })
|
||||
id<String>(inferFromLambda(fun() = materialize()))
|
||||
id<String>(inferFromLambda2(fun() = materialize()))
|
||||
<!INAPPLICABLE_CANDIDATE!>id<!><String>(inferFromLambda(fun() = materialize()))
|
||||
<!INAPPLICABLE_CANDIDATE!>id<!><String>(inferFromLambda2(fun() = materialize()))
|
||||
}
|
||||
|
||||
Vendored
+47
-47
@@ -64,14 +64,14 @@ class A5<K, Q>: Function2<K, Q, Float> {
|
||||
|
||||
fun main() {
|
||||
// Inferring lambda parameter types by other lambda explicit parameters; expected type is type variable
|
||||
select(id1 { x -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>x<!>.<!UNRESOLVED_REFERENCE!>inv<!>() }, id2 { x: Int -> })
|
||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!>.<!UNRESOLVED_REFERENCE!>inv<!>() }, id2 { x: Int -> })
|
||||
selectWithInv(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!>.<!UNRESOLVED_REFERENCE!>inv<!>() }, id2(Inv { x: Int -> }))
|
||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!>.<!UNRESOLVED_REFERENCE!>inv<!>() }, id1 { x: Number -> TODO() }, id1(id2 { x: Int -> x }))
|
||||
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("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!>.<!UNRESOLVED_REFERENCE!>x<!>.<!UNRESOLVED_REFERENCE!>inv<!>() }, id1 { x: Inv<Int> -> TODO() })
|
||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
|
||||
select(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!>.<!UNRESOLVED_REFERENCE!>inv<!>() }), id(id { x: Int -> x }))
|
||||
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<kotlin.Number> & Inv<kotlin.Int>")!>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)))<!>
|
||||
@@ -90,7 +90,7 @@ fun main() {
|
||||
takeDependentLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>it<!>; 10 }, { })
|
||||
|
||||
// Inferring lambda parameter types by anonymous function parameters
|
||||
select({ <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!> }, fun(x: Int) = 1)
|
||||
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 })
|
||||
@@ -110,8 +110,8 @@ fun main() {
|
||||
val x7: (Int) -> Unit = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<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("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!> })
|
||||
val x11: (B) -> Unit = selectC(id { }, id { x -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>x<!> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!> })
|
||||
val x10: (Int) -> Unit = selectFloat(id { }, id { x -> }, id { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number & kotlin.Comparable<*>")!>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)
|
||||
/*
|
||||
@@ -121,7 +121,7 @@ fun main() {
|
||||
*/
|
||||
val x12 = <!INAPPLICABLE_CANDIDATE!>selectC<!>(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, id { x: B -> })
|
||||
val x13 = <!INAPPLICABLE_CANDIDATE!>selectA<!>(id { <!DEBUG_INFO_EXPRESSION_TYPE("A")!>it<!> }, id { x: C -> })
|
||||
val x14 = selectC(id { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!> }, id { x: A -> }, { x -> x })
|
||||
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
|
||||
@@ -130,7 +130,7 @@ fun main() {
|
||||
* K >: (A) -> TypeVariable(_R) -> TypeVariable(_RP1) <: A
|
||||
* K == intersect(CST(C, B), A) == A
|
||||
*/
|
||||
val x16: (C) -> Unit = selectB(id { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!> }, { x -> }, id { x: A -> x })
|
||||
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
|
||||
/*
|
||||
@@ -138,7 +138,7 @@ fun main() {
|
||||
* K <: (C) -> Unit -> TypeVariable(_RP1) >: C
|
||||
* K == (B) -> Unit -> TypeVariable(_RP1) == B
|
||||
*/
|
||||
val x17: (C) -> Unit = selectB(id { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!> }, id { <!UNRESOLVED_REFERENCE!>it<!> }, id<(B) -> Unit> { x -> x })
|
||||
val x17: (C) -> Unit = selectB(id { <!DEBUG_INFO_EXPRESSION_TYPE("B")!>it<!> }, id { it }, id<(B) -> Unit> { x -> x })
|
||||
val x18: (C) -> Unit = select(id { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("C")!>it<!> }, id<(B) -> Unit> { x -> x })
|
||||
|
||||
// Resolution of extension/non-extension functions combination
|
||||
@@ -147,8 +147,8 @@ fun main() {
|
||||
val x21: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>)
|
||||
select(id<String.() -> Unit>(fun(x: String) {}), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>)
|
||||
select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.String, kotlin.String, kotlin.Unit>")!>id(fun String.(x: String) {})<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<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("ERROR CLASS: 'this' is not defined in this context"), DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing"), NO_THIS!>this<!> })
|
||||
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), { x -> <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: 'this' is not defined in this context"), DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing"), NO_THIS!>this<!> })
|
||||
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), { x: String -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing"), 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.Nothing"), 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) { }), { x, y -> x })
|
||||
@@ -159,9 +159,9 @@ fun main() {
|
||||
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.<!UNRESOLVED_REFERENCE!>inv<!>() + y.<!UNRESOLVED_REFERENCE!>toByte<!>() }, { x: Int, y -> y.<!UNRESOLVED_REFERENCE!>toByte<!>() }, { x, y: Number -> x.inv() })
|
||||
select(id { x, y -> x.<!UNRESOLVED_REFERENCE!>inv<!>() + y.<!UNRESOLVED_REFERENCE!>toByte<!>() }, id { x: Int, y -> y.<!UNRESOLVED_REFERENCE!>toByte<!>() }, id { x, y: Number -> x.<!UNRESOLVED_REFERENCE!>inv<!>() })
|
||||
select({ x, y -> x.<!UNRESOLVED_REFERENCE!>inv<!>() + y.<!UNRESOLVED_REFERENCE!>toByte<!>() }, id { x: Int, y -> y.<!UNRESOLVED_REFERENCE!>toByte<!>() }, id { x, y: Number -> x.<!UNRESOLVED_REFERENCE!>inv<!>() })
|
||||
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 })
|
||||
@@ -180,56 +180,56 @@ fun main() {
|
||||
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.Function3<kotlin.Nothing, kotlin.Nothing, kotlin.Nothing, kotlin.Float>")!>select(A2(), { a, b, c -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>b<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>c<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any?>")!>select(A3(), { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!> }, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>a<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function3<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.Nothing")!>c<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<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.reflect.KFunction<kotlin.Any?>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>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<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> })<!>
|
||||
// It's OK because `A3::foo2` is from companion of `A3`
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction1<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.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<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.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Comparable<*> & java.io.Serializable>")!>select(A4(), { x: Number -> "" })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.Int, kotlin.Int, kotlin.Comparable<*> & java.io.Serializable>")!>select(A5<Int, Int>(), { x: Number, y: Int -> "" })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("A2")!>select(A2(), id { a, b, c -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>b<!>; <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>c<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Any?>")!>select(id(A3()), { <!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Unresolved name: it"), UNRESOLVED_REFERENCE!>it<!> }, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>a<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function3<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.Nothing")!>c<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<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.reflect.KFunction<kotlin.Any?>")!>select(A3(), <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>, id { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> })<!>
|
||||
<!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<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, id { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction<kotlin.Any?>")!>select(id(A3()), id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>), { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>it<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction<kotlin.Any?>")!>select(id(A3()), id(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.reflect.KFunction2<A3, kotlin.Int, kotlin.Unit>")!>A3::foo1<!>), { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, id { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>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<!>, id { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>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<!>, { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, id { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>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<!>), { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>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<!>), { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> }, id { it -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>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.reflect.KFunction<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.reflect.KFunction<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("A4")!>select(A4(), id { x: Number -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("A5<kotlin.Int, kotlin.Int>")!>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("A5<kotlin.Int, kotlin.Int>")!>select(id(A5<Int, Int>()), id { x, y -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>y<!> })<!>
|
||||
<!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.Function1<kotlin.Int, kotlin.Number>")!>select(A4(), id { x: Number -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>x<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.Int, kotlin.Int, kotlin.Number & kotlin.Comparable<*>>")!>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.Function2<kotlin.Int, kotlin.Int, kotlin.Number & kotlin.Comparable<*>>")!>select(id(A5<Int, Int>()), id { x, y -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>y<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function2<kotlin.Number, kotlin.Int, kotlin.Number & kotlin.Comparable<*>>")!>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.Nothing")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>y<!>; 1f })
|
||||
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.Int, kotlin.Unit>")!>select({ x: Int -> }, { x: String -> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Unit>")!>select({ x: Int -> }, { x: Int, y: Number -> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>select(id { x: Int -> }, { x: String -> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Unit>")!>select({ x: Int -> }, id { x: Int, y: Number -> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Unit>")!>select(id { x: Int -> }, id { x: String -> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Unit>")!>select(id { x: Int -> }, id { x: Int, y: Number -> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Comparable<*> & java.io.Serializable>")!>select({ x: Int -> 1 }, { x: String -> "" })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Int, kotlin.Number & kotlin.Comparable<*>>")!>select({ x: Int -> 1 }, { x: Int, y: Number -> 1f })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, Inv<kotlin.String>>")!>select(id { x: Int -> Inv(10) }, { x: String -> Inv("") })<!>
|
||||
<!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<*, kotlin.Comparable<*> & java.io.Serializable>")!>select({ x: Int -> 1 }, { x: String -> "" })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function<kotlin.Number & kotlin.Comparable<*>>")!>select({ x: Int -> 1 }, { x: Int, y: Number -> 1f })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<*, Inv<out kotlin.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.Function1<kotlin.Int, kotlin.Int>")!>select(id { x: Int -> 10 }, id { x: Int, y: Number -> TODO() })<!>
|
||||
<!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()" })
|
||||
|
||||
// Anonymous functions
|
||||
val x69: (C) -> Unit = selectB({ <!UNRESOLVED_REFERENCE!>it<!> }, { }, id(fun (x) { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>x<!> }))
|
||||
val x69: (C) -> Unit = selectB({ it }, { }, id(fun (x) { <!DEBUG_INFO_EXPRESSION_TYPE("A")!>x<!> }))
|
||||
select(id1(fun(it) { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id1 { x: Number -> TODO() }, id1(id2(::takeInt)))
|
||||
select(id(fun (it) { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }), id(id<(Int) -> Unit> { x: Number -> Unit }))
|
||||
select(id(fun (it) { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id<(Int) -> Unit> { })
|
||||
val x70: (Int) -> Unit = selectNumber(id(fun (it) { }), id {}, id {})
|
||||
val x71: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun String.() { })<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>)
|
||||
val x72: String.() -> Unit = select(fun String.() { }, fun(x: String) {}) // must be error
|
||||
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), fun (x, y) { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>y<!> })
|
||||
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), fun (x, y) { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>y<!> })
|
||||
select(id<Int.(String) -> Unit>(fun (x, y) {}), { x: Int, y: String -> x }) // receiver of anonymous function must be specified explicitly
|
||||
select(id<Int.(String) -> Unit>(fun Int.(y) {}), { x: Int, y: String -> x })
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.String>")!>select(A3(), fun (x) = "", { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> })<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Number, java.io.Serializable>")!>select(A3(), fun (x) = "", { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>a<!> })<!>
|
||||
}
|
||||
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_ANONYMOUS_PARAMETER
|
||||
|
||||
fun <T> id(x: T) = x
|
||||
fun <T> select(vararg x: T) = x[0]
|
||||
|
||||
val x1 = select(id { <!NO_THIS!>this<!> }, fun Int.() = this)
|
||||
val x2 = select(id { <!NO_THIS!>this<!> + <!UNRESOLVED_REFERENCE!>it<!>.<!UNRESOLVED_REFERENCE!>inv<!>() }, fun Int.(x: Int) = this)
|
||||
val x3 = select(id { <!NO_THIS!>this<!>.<!UNRESOLVED_REFERENCE!>length<!> + <!UNRESOLVED_REFERENCE!>it<!>.<!UNRESOLVED_REFERENCE!>inv<!>() }, fun String.(x: Int) = length)
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_ANONYMOUS_PARAMETER
|
||||
|
||||
fun <T> id(x: T) = x
|
||||
|
||||
+2
-1
@@ -7,7 +7,8 @@ fun <T> foo() = foo() as T
|
||||
|
||||
fun <T> foo2(): T = TODO()
|
||||
|
||||
val test = foo2().plus("") as String
|
||||
// TODO: "not enough information" should be reported on foo2() instead
|
||||
val test = foo2().<!UNRESOLVED_REFERENCE!>plus<!>("") as String
|
||||
|
||||
fun <T> T.bar() = this
|
||||
val barTest = "".bar() as Number
|
||||
@@ -22,6 +22,6 @@ fun test_1() {
|
||||
fun test_2() {
|
||||
select(
|
||||
A::toB,
|
||||
<!UNRESOLVED_REFERENCE!>A::toC<!>
|
||||
A::toC
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNREACHABLE_CODE
|
||||
|
||||
interface Some {
|
||||
fun method(): Unit
|
||||
}
|
||||
|
||||
fun <S> elvis(nullable: S?, notNullable: S): S = TODO()
|
||||
|
||||
fun <R : Some> Some.doWithPredicate(predicate: (R) -> Unit): R? = TODO()
|
||||
|
||||
fun test(derived: Some) {
|
||||
val expected: Some = derived.doWithPredicate { it.method() } ?: TODO()
|
||||
val expected2: Some = elvis(derived.doWithPredicate { it.method() }, TODO())
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ S> elvis(/*0*/ nullable: S?, /*1*/ notNullable: S): S
|
||||
public fun test(/*0*/ derived: Some): kotlin.Unit
|
||||
public fun </*0*/ R : Some> Some.doWithPredicate(/*0*/ predicate: (R) -> kotlin.Unit): R?
|
||||
|
||||
public interface Some {
|
||||
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 fun method(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
|
||||
// !LANGUAGE: +InferenceCompatibility
|
||||
|
||||
fun <T, VR : T> foo(x: T, fn: (VR?, T) -> Unit) {}
|
||||
|
||||
fun takeInt(x: Int) {}
|
||||
|
||||
fun main(x: Int) {
|
||||
foo(x) { prev: Int?, new -> <!INAPPLICABLE_CANDIDATE!>takeInt<!>(new) } // `new` is `Int` in OI, `Int?` in NI
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_ANONYMOUS_PARAMETER
|
||||
// !LANGUAGE: +InferenceCompatibility
|
||||
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -DEPRECATION -EXPERIMENTAL_IS_NOT_ENABLED -UNUSED_VARIABLE
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.experimental.ExperimentalTypeInference
|
||||
|
||||
@UseExperimental(ExperimentalTypeInference::class)
|
||||
fun <R> combined(
|
||||
check: () -> Unit,
|
||||
@BuilderInference block: TestInterface<R>.() -> Unit
|
||||
): R = TODO()
|
||||
|
||||
interface TestInterface<R> {
|
||||
fun emit(r: R)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
val ret = combined({ }) {
|
||||
<!INAPPLICABLE_CANDIDATE!>emit<!>(1)
|
||||
}
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -DEPRECATION -EXPERIMENTAL_IS_NOT_ENABLED -UNUSED_VARIABLE
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
Vendored
-36
@@ -1,36 +0,0 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
//If this test hangs, it means something is broken.
|
||||
package a
|
||||
|
||||
object A {
|
||||
val iii = 42
|
||||
}
|
||||
|
||||
//inappropriate but participating in resolve functions
|
||||
fun foo(s: String, a: Any) = s + a
|
||||
fun foo(a: Any, s: String) = s + a
|
||||
fun foo(i: Int, j: Int) = i + j
|
||||
fun foo(a: Any, i: Int) = "$a$i"
|
||||
fun foo(f: (Int) -> Int, i: Int) = f(i)
|
||||
fun foo(f: (String) -> Int, s: String) = f(s)
|
||||
fun foo(f: (Any) -> Int, a: Any) = f(a)
|
||||
fun foo(s: String, f: (String) -> Int) = f(s)
|
||||
fun foo(a: Any, f: (Any) -> Int) = f(a)
|
||||
//appropriate function
|
||||
fun foo(i: Int, f: (Int) -> Int) = f(i)
|
||||
|
||||
fun <T> id(t: T) = t
|
||||
|
||||
fun test() {
|
||||
<!AMBIGUITY!>foo<!>(1, id(fun(x1: Int) =
|
||||
<!AMBIGUITY!>foo<!>(2, id(fun(x2: Int) =
|
||||
<!AMBIGUITY!>foo<!>(3, id(fun(x3: Int) =
|
||||
<!AMBIGUITY!>foo<!>(4, id(fun(x4: Int) =
|
||||
<!AMBIGUITY!>foo<!>(5, id(fun(x5: Int) =
|
||||
x1 + x2 + x3 + x4 + x5 + A.iii
|
||||
))
|
||||
))
|
||||
))
|
||||
))
|
||||
))
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !WITH_NEW_INFERENCE
|
||||
//If this test hangs, it means something is broken.
|
||||
package a
|
||||
|
||||
+1
-1
@@ -4,5 +4,5 @@
|
||||
fun <T: Any> foo(f: (T) -> Unit): T? = null // T is used only as return type
|
||||
fun test() {
|
||||
val x = foo { it checkType { _<String>() }} ?: "" // foo() is inferred as foo<String>, which isn't very good
|
||||
val y: Any = foo { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>it<!> checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Any>() } } ?: "" // but for now it's fixed by specifying expected type
|
||||
val y: Any = foo { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>it<!> checkType { _<Any>() } } ?: "" // but for now it's fixed by specifying expected type
|
||||
}
|
||||
@@ -10454,6 +10454,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
||||
runTest("compiler/testData/diagnostics/tests/inference/lambdaInValInitializerWithAnonymousFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaParameterTypeInElvis.kt")
|
||||
public void testLambdaParameterTypeInElvis() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/lambdaParameterTypeInElvis.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("listConstructor.kt")
|
||||
public void testListConstructor() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/listConstructor.kt");
|
||||
|
||||
Generated
+5
@@ -10449,6 +10449,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inference/lambdaInValInitializerWithAnonymousFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaParameterTypeInElvis.kt")
|
||||
public void testLambdaParameterTypeInElvis() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/lambdaParameterTypeInElvis.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("listConstructor.kt")
|
||||
public void testListConstructor() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/listConstructor.kt");
|
||||
|
||||
@@ -208,14 +208,20 @@ object StandardNames {
|
||||
return "Function$parameterCount"
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getFunctionClassId(parameterCount: Int): ClassId {
|
||||
return ClassId(BUILT_INS_PACKAGE_FQ_NAME, Name.identifier(getFunctionName(parameterCount)))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getKFunctionFqName(parameterCount: Int): FqNameUnsafe {
|
||||
return reflect(FunctionClassKind.KFunction.classNamePrefix + parameterCount)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getFunctionClassId(parameterCount: Int): ClassId {
|
||||
return ClassId(BUILT_INS_PACKAGE_FQ_NAME, Name.identifier(getFunctionName(parameterCount)))
|
||||
fun getKFunctionClassId(parameterCount: Int): ClassId {
|
||||
val fqName = getKFunctionFqName(parameterCount)
|
||||
return ClassId(fqName.parent().toSafe(), fqName.shortName())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@@ -228,6 +234,17 @@ object StandardNames {
|
||||
return ClassId(COROUTINES_PACKAGE_FQ_NAME_RELEASE, Name.identifier(getSuspendFunctionName(parameterCount)))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getKSuspendFunctionName(parameterCount: Int): FqNameUnsafe {
|
||||
return reflect(FunctionClassKind.KSuspendFunction.classNamePrefix + parameterCount)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getKSuspendFunctionClassId(parameterCount: Int): ClassId {
|
||||
val fqName = getKSuspendFunctionName(parameterCount)
|
||||
return ClassId(fqName.parent().toSafe(), fqName.shortName())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isPrimitiveArray(arrayFqName: FqNameUnsafe): Boolean {
|
||||
return FqNames.arrayClassFqNameToPrimitiveType.get(arrayFqName) != null
|
||||
|
||||
@@ -193,6 +193,20 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
||||
fun TypeVariableTypeConstructorMarker.isContainedInInvariantOrContravariantPositions(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.isSignedOrUnsignedNumberType(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.isFunctionOrKFunctionWithAnySuspendability(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.isSuspendFunctionTypeOrSubtype(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.isExtensionFunctionType(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.extractArgumentsForFunctionalTypeOrSubtype(): List<KotlinTypeMarker>
|
||||
|
||||
fun KotlinTypeMarker.getFunctionalTypeFromSupertypes(): KotlinTypeMarker
|
||||
|
||||
fun getFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker
|
||||
|
||||
fun getKFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker
|
||||
}
|
||||
|
||||
|
||||
|
||||
+34
-3
@@ -5,10 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.types.checker
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.builtins.StandardNames.FqNames
|
||||
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
|
||||
@@ -674,6 +672,39 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
||||
|
||||
} ?: error("Expected intersection type, found $firstCandidate")
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isFunctionOrKFunctionWithAnySuspendability(): Boolean {
|
||||
require(this is KotlinType, this::errorMessage)
|
||||
return this.isFunctionOrKFunctionTypeWithAnySuspendability
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isSuspendFunctionTypeOrSubtype(): Boolean {
|
||||
require(this is KotlinType, this::errorMessage)
|
||||
return this.isSuspendFunctionTypeOrSubtype
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isExtensionFunctionType(): Boolean {
|
||||
require(this is KotlinType, this::errorMessage)
|
||||
return this.isExtensionFunctionType
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.extractArgumentsForFunctionalTypeOrSubtype(): List<KotlinTypeMarker> {
|
||||
require(this is KotlinType, this::errorMessage)
|
||||
return this.getPureArgumentsForFunctionalTypeOrSubtype()
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.getFunctionalTypeFromSupertypes(): KotlinTypeMarker {
|
||||
require(this is KotlinType)
|
||||
return this.extractFunctionalTypeFromSupertypes()
|
||||
}
|
||||
|
||||
override fun getFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
|
||||
return getFunctionDescriptor(builtIns, parametersNumber, isSuspend).typeConstructor
|
||||
}
|
||||
|
||||
override fun getKFunctionTypeConstructor(parametersNumber: Int, isSuspend: Boolean): TypeConstructorMarker {
|
||||
return getKFunctionDescriptor(builtIns, parametersNumber, isSuspend).typeConstructor
|
||||
}
|
||||
}
|
||||
|
||||
fun TypeVariance.convertVariance(): Variance {
|
||||
|
||||
Reference in New Issue
Block a user