NI: Improve postponed arguments analysis
Introduce seven stages: 1) Analyze postponed arguments with fixed parameter types 2) Collect parameter types from constraints and lambda parameters' declaration 3) Fix not postponed variables for parameter types of all postponed arguments 4) Create atoms with revised expected types if needed 5) Analyze the first ready postponed argument and rerun stages if it has been analyzed 6) Force fixation remaining type variables: fix if possible or report not enough information 7) Force analysis remaining not analyzed postponed arguments and rerun stages if there are ^KT-37952 Fixed ^KT-32156 Fixed ^KT-37249 Fixed ^KT-37341 Fixed
This commit is contained in:
@@ -442,6 +442,11 @@ public abstract class KotlinBuiltIns {
|
||||
return "Function" + parameterCount;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static FqNameUnsafe getKFunctionFqName(int parameterCount) {
|
||||
return FqNames.reflect(FunctionClassDescriptor.Kind.KFunction.getClassNamePrefix() + parameterCount);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassId getFunctionClassId(int parameterCount) {
|
||||
return new ClassId(BUILT_INS_PACKAGE_FQ_NAME, Name.identifier(getFunctionName(parameterCount)));
|
||||
@@ -467,6 +472,17 @@ public abstract class KotlinBuiltIns {
|
||||
return getBuiltInClassByFqName(COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier(getSuspendFunctionName(parameterCount))));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassDescriptor getKFunction(int parameterCount) {
|
||||
return getBuiltInClassByFqName(getKFunctionFqName(parameterCount).toSafe());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassDescriptor getKSuspendFunction(int parameterCount) {
|
||||
Name name = Name.identifier(FunctionClassDescriptor.Kind.KSuspendFunction.getClassNamePrefix() + parameterCount);
|
||||
return getBuiltInClassByFqName(COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(name));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassDescriptor getThrowable() {
|
||||
return getBuiltInClassByName("Throwable");
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.annotations.BuiltInAnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -19,6 +20,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
@@ -67,6 +69,9 @@ val KotlinType.isKSuspendFunctionType: Boolean
|
||||
val KotlinType.isFunctionOrSuspendFunctionType: Boolean
|
||||
get() = isFunctionType || isSuspendFunctionType
|
||||
|
||||
val KotlinType.isFunctionOrKFunctionTypeWithAnySuspendability: Boolean
|
||||
get() = isFunctionType || isSuspendFunctionType || isKFunctionType || isKSuspendFunctionType
|
||||
|
||||
val KotlinType.isBuiltinFunctionalType: Boolean
|
||||
get() = constructor.declarationDescriptor?.isBuiltinFunctionalClassDescriptor == true
|
||||
|
||||
@@ -154,6 +159,16 @@ fun KotlinType.getValueParameterTypesFromCallableReflectionType(isCallableTypeWi
|
||||
return arguments.subList(first, last)
|
||||
}
|
||||
|
||||
fun KotlinType.extractFunctionalTypeFromSupertypes(): KotlinType {
|
||||
assert(isBuiltinFunctionalTypeOrSubtype) { "Not a function type or subtype: $this" }
|
||||
return if (isBuiltinFunctionalType) this else supertypes().first { it.isBuiltinFunctionalType }
|
||||
}
|
||||
|
||||
fun KotlinType.getPureArgumentsForFunctionalTypeOrSubtype(): List<KotlinType> {
|
||||
assert(isBuiltinFunctionalTypeOrSubtype) { "Not a function type or subtype: $this" }
|
||||
return extractFunctionalTypeFromSupertypes().arguments.dropLast(1).map { it.type }
|
||||
}
|
||||
|
||||
fun KotlinType.extractParameterNameFromFunctionTypeArgument(): Name? {
|
||||
val annotation = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.parameterName) ?: return null
|
||||
val name = (annotation.allValueArguments.values.singleOrNull() as? StringValue)
|
||||
@@ -197,29 +212,38 @@ fun getFunctionTypeArgumentProjections(
|
||||
|
||||
@JvmOverloads
|
||||
fun createFunctionType(
|
||||
builtIns: KotlinBuiltIns,
|
||||
annotations: Annotations,
|
||||
receiverType: KotlinType?,
|
||||
parameterTypes: List<KotlinType>,
|
||||
parameterNames: List<Name>?,
|
||||
returnType: KotlinType,
|
||||
suspendFunction: Boolean = false
|
||||
builtIns: KotlinBuiltIns,
|
||||
annotations: Annotations,
|
||||
receiverType: KotlinType?,
|
||||
parameterTypes: List<KotlinType>,
|
||||
parameterNames: List<Name>?,
|
||||
returnType: KotlinType,
|
||||
suspendFunction: Boolean = false
|
||||
): SimpleType {
|
||||
val arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, parameterNames, returnType, builtIns)
|
||||
val size = parameterTypes.size
|
||||
val parameterCount = if (receiverType == null) size else size + 1
|
||||
val classDescriptor = if (suspendFunction) builtIns.getSuspendFunction(parameterCount) else builtIns.getFunction(parameterCount)
|
||||
val parameterCount = if (receiverType == null) parameterTypes.size else parameterTypes.size + 1
|
||||
val classDescriptor = getFunctionDescriptor(builtIns, parameterCount, suspendFunction)
|
||||
|
||||
// TODO: preserve laziness of given annotations
|
||||
val typeAnnotations =
|
||||
if (receiverType == null || annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType) != null) {
|
||||
annotations
|
||||
}
|
||||
else {
|
||||
Annotations.create(
|
||||
annotations + BuiltInAnnotationDescriptor(builtIns, KotlinBuiltIns.FQ_NAMES.extensionFunctionType, emptyMap())
|
||||
)
|
||||
}
|
||||
val typeAnnotations = if (receiverType != null) annotations.withExtensionFunctionAnnotation(builtIns) else annotations
|
||||
|
||||
return KotlinTypeFactory.simpleNotNullType(typeAnnotations, classDescriptor, arguments)
|
||||
}
|
||||
|
||||
fun Annotations.hasExtensionFunctionAnnotation() = hasAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType)
|
||||
|
||||
fun Annotations.withoutExtensionFunctionAnnotation() =
|
||||
FilteredAnnotations(this, true) { it != KotlinBuiltIns.FQ_NAMES.extensionFunctionType }
|
||||
|
||||
fun Annotations.withExtensionFunctionAnnotation(builtIns: KotlinBuiltIns) =
|
||||
if (hasAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType)) {
|
||||
this
|
||||
} else {
|
||||
Annotations.create(this + BuiltInAnnotationDescriptor(builtIns, KotlinBuiltIns.FQ_NAMES.extensionFunctionType, emptyMap()))
|
||||
}
|
||||
|
||||
fun getFunctionDescriptor(builtIns: KotlinBuiltIns, parameterCount: Int, isSuspendFunction: Boolean) =
|
||||
if (isSuspendFunction) builtIns.getSuspendFunction(parameterCount) else builtIns.getFunction(parameterCount)
|
||||
|
||||
fun getKFunctionDescriptor(builtIns: KotlinBuiltIns, parameterCount: Int, isSuspendFunction: Boolean) =
|
||||
if (isSuspendFunction) builtIns.getKSuspendFunction(parameterCount) else builtIns.getKFunction(parameterCount)
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.types.checker
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -318,6 +319,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
||||
return KotlinBuiltIns.isUnit(this)
|
||||
}
|
||||
|
||||
override fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype(): Boolean {
|
||||
require(this is UnwrappedType, this::errorMessage)
|
||||
return isBuiltinFunctionalTypeOrSubtype
|
||||
}
|
||||
|
||||
override fun createFlexibleType(lowerBound: SimpleTypeMarker, upperBound: SimpleTypeMarker): KotlinTypeMarker {
|
||||
require(lowerBound is SimpleType, this::errorMessage)
|
||||
require(upperBound is SimpleType, this::errorMessage)
|
||||
|
||||
@@ -132,6 +132,8 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
|
||||
|
||||
fun KotlinTypeMarker.isUnit(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype(): Boolean
|
||||
|
||||
fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user