[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:
Pavel Kirpichenkov
2020-09-30 16:07:03 +03:00
parent 5eae6f2f4e
commit 712a2ce1ab
35 changed files with 614 additions and 368 deletions
@@ -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");
@@ -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)
}
}
@@ -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) {
@@ -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)
}
@@ -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 --------------------------
@@ -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)
@@ -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")
}
}
@@ -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
}
@@ -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,
@@ -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 {
@@ -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
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
class Host(var value: String) {
@@ -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<!>
}
@@ -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()))
}
@@ -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<!> })<!>
}
@@ -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,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_ANONYMOUS_PARAMETER
fun <T> id(x: T) = x
@@ -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
@@ -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,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -DEPRECATION -EXPERIMENTAL_IS_NOT_ENABLED -UNUSED_VARIABLE
// WITH_RUNTIME
@@ -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,3 +1,4 @@
// FIR_IDENTICAL
// !WITH_NEW_INFERENCE
//If this test hangs, it means something is broken.
package a
@@ -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");
@@ -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
}
@@ -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 {