Introduce 'SuspendFunction$n<...>' types.
This commit is contained in:
committed by
Stanislav Erokhin
parent
a15d423db4
commit
6e1340da82
@@ -134,7 +134,7 @@ class TypeResolver(
|
||||
|
||||
val typeElement = typeReference.typeElement
|
||||
|
||||
val type = resolveTypeElement(c, annotations, typeElement)
|
||||
val type = resolveTypeElement(c, annotations, typeReference.modifierList, typeElement)
|
||||
c.trace.recordScope(c.scope, typeReference)
|
||||
|
||||
if (!type.isBare) {
|
||||
@@ -175,8 +175,14 @@ class TypeResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveTypeElement(c: TypeResolutionContext, annotations: Annotations, typeElement: KtTypeElement?): PossiblyBareType {
|
||||
private fun resolveTypeElement(c: TypeResolutionContext, annotations: Annotations, modifiers: KtModifierList?, typeElement: KtTypeElement?): PossiblyBareType {
|
||||
var result: PossiblyBareType? = null
|
||||
|
||||
val hasSuspendModifier = modifiers?.hasModifier(KtTokens.SUSPEND_KEYWORD) ?: false
|
||||
if (hasSuspendModifier && typeElement !is KtFunctionType) {
|
||||
c.trace.report(Errors.WRONG_MODIFIER_TARGET.on(modifiers!!.getModifier(KtTokens.SUSPEND_KEYWORD)!!, KtTokens.SUSPEND_KEYWORD, "non-functional type"))
|
||||
}
|
||||
|
||||
typeElement?.accept(object : KtVisitorVoid() {
|
||||
override fun visitUserType(type: KtUserType) {
|
||||
val qualifierResolutionResult = resolveDescriptorForType(c.scope, type, c.trace, c.isDebuggerContext)
|
||||
@@ -198,7 +204,7 @@ class TypeResolver(
|
||||
|
||||
override fun visitNullableType(nullableType: KtNullableType) {
|
||||
val innerType = nullableType.getInnerType()
|
||||
val baseType = resolveTypeElement(c, annotations, innerType)
|
||||
val baseType = resolveTypeElement(c, annotations, modifiers, innerType)
|
||||
if (baseType.isNullable || innerType is KtNullableType || innerType is KtDynamicType) {
|
||||
c.trace.report(REDUNDANT_NULLABLE.on(nullableType))
|
||||
}
|
||||
@@ -219,7 +225,8 @@ class TypeResolver(
|
||||
moduleDescriptor.builtIns, annotations, receiverType,
|
||||
parameterDescriptors.map { it.type },
|
||||
parameterDescriptors.map { it.name },
|
||||
returnType
|
||||
returnType,
|
||||
suspendFunction = hasSuspendModifier
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
typealias Action = () -> Unit
|
||||
|
||||
interface SAM {
|
||||
fun run()
|
||||
}
|
||||
|
||||
typealias Test1 = suspend () -> Unit
|
||||
typealias Test2 = suspend Int.(String) -> Unit
|
||||
typealias Test3 = <!WRONG_MODIFIER_TARGET!>suspend<!> Function0<Unit>
|
||||
typealias Test4 = <!WRONG_MODIFIER_TARGET!>suspend<!> Action
|
||||
typealias Test5 = List<suspend () -> Unit>
|
||||
typealias Test6 = <!WRONG_MODIFIER_TARGET!>suspend<!> List<() -> Unit>
|
||||
typealias Test7 = <!WRONG_MODIFIER_TARGET!>suspend<!> SAM
|
||||
typealias Test8 = SuspendFunction0<Unit>
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
package
|
||||
|
||||
public interface SAM {
|
||||
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 run(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
public typealias Action = () -> kotlin.Unit
|
||||
public typealias Test1 = suspend () -> kotlin.Unit
|
||||
public typealias Test2 = suspend kotlin.Int.(kotlin.String) -> kotlin.Unit
|
||||
public typealias Test3 = () -> kotlin.Unit
|
||||
public typealias Test4 = Action
|
||||
public typealias Test5 = kotlin.collections.List<suspend () -> kotlin.Unit>
|
||||
public typealias Test6 = kotlin.collections.List<() -> kotlin.Unit>
|
||||
public typealias Test7 = SAM
|
||||
public typealias Test8 = suspend () -> kotlin.Unit
|
||||
@@ -523,6 +523,11 @@ public abstract class KotlinBuiltIns {
|
||||
return "Function" + parameterCount;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getSuspendFunctionName(int parameterCount) {
|
||||
return "SuspendFunction" + parameterCount;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassId getFunctionClassId(int parameterCount) {
|
||||
return new ClassId(BUILT_INS_PACKAGE_FQ_NAME, Name.identifier(getFunctionName(parameterCount)));
|
||||
@@ -533,6 +538,11 @@ public abstract class KotlinBuiltIns {
|
||||
return getBuiltInClassByName(getFunctionName(parameterCount));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassDescriptor getSuspendFunction(int parameterCount) {
|
||||
return getBuiltInClassByName(getSuspendFunctionName(parameterCount));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassDescriptor getThrowable() {
|
||||
return getBuiltInClassByName("Throwable");
|
||||
|
||||
@@ -18,6 +18,9 @@ package org.jetbrains.kotlin.builtins
|
||||
|
||||
import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
|
||||
@@ -57,16 +60,23 @@ val KotlinType.isFunctionTypeOrSubtype: Boolean
|
||||
)
|
||||
|
||||
val KotlinType.isFunctionType: Boolean
|
||||
get() = constructor.declarationDescriptor?.getFunctionalClassKind() == FunctionClassDescriptor.Kind.Function
|
||||
|
||||
val KotlinType.isSuspendFunctionType: Boolean
|
||||
get() = constructor.declarationDescriptor?.getFunctionalClassKind() == FunctionClassDescriptor.Kind.SuspendFunction
|
||||
|
||||
val KotlinType.isBuiltinFunctionalType: Boolean
|
||||
get() {
|
||||
val descriptor = constructor.declarationDescriptor
|
||||
return descriptor != null && isNumberedFunctionClassFqName(descriptor.fqNameUnsafe)
|
||||
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
|
||||
return kind == FunctionClassDescriptor.Kind.Function ||
|
||||
kind == FunctionClassDescriptor.Kind.SuspendFunction
|
||||
}
|
||||
|
||||
val KotlinType.isNonExtensionFunctionType: Boolean
|
||||
get() = isFunctionType && !isTypeAnnotatedWithExtensionFunctionType
|
||||
get() = isBuiltinFunctionalType && !isTypeAnnotatedWithExtensionFunctionType
|
||||
|
||||
val KotlinType.isExtensionFunctionType: Boolean
|
||||
get() = isFunctionType && isTypeAnnotatedWithExtensionFunctionType
|
||||
get() = isBuiltinFunctionalType && isTypeAnnotatedWithExtensionFunctionType
|
||||
|
||||
private val KotlinType.isTypeAnnotatedWithExtensionFunctionType: Boolean
|
||||
get() = annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType) != null
|
||||
@@ -85,18 +95,29 @@ fun isNumberedFunctionClassFqName(fqName: FqNameUnsafe): Boolean {
|
||||
return BuiltInFictitiousFunctionClassFactory.isFunctionClassName(shortName, KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME)
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.getFunctionalClassKind(): FunctionClassDescriptor.Kind? {
|
||||
if (this !is ClassDescriptor) return null
|
||||
|
||||
val fqNameUnsafe = this.fqNameUnsafe
|
||||
if (!fqNameUnsafe.isSafe || fqNameUnsafe.isRoot) return null
|
||||
val fqName = fqNameUnsafe.toSafe()
|
||||
|
||||
return BuiltInFictitiousFunctionClassFactory.getFunctionalClassKind(fqName.shortName().asString(), fqName.parent())
|
||||
}
|
||||
|
||||
|
||||
fun KotlinType.getReceiverTypeFromFunctionType(): KotlinType? {
|
||||
assert(isFunctionType) { "Not a function type: ${this}" }
|
||||
assert(isBuiltinFunctionalType) { "Not a function type: ${this}" }
|
||||
return if (isTypeAnnotatedWithExtensionFunctionType) arguments.first().type else null
|
||||
}
|
||||
|
||||
fun KotlinType.getReturnTypeFromFunctionType(): KotlinType {
|
||||
assert(isFunctionType) { "Not a function type: ${this}" }
|
||||
assert(isBuiltinFunctionalType) { "Not a function type: ${this}" }
|
||||
return arguments.last().type
|
||||
}
|
||||
|
||||
fun KotlinType.getValueParameterTypesFromFunctionType(): List<TypeProjection> {
|
||||
assert(isFunctionType) { "Not a function type: ${this}" }
|
||||
assert(isBuiltinFunctionalType) { "Not a function type: ${this}" }
|
||||
val arguments = arguments
|
||||
val first = if (isExtensionFunctionType) 1 else 0
|
||||
val last = arguments.size - 1
|
||||
@@ -147,17 +168,20 @@ fun getFunctionTypeArgumentProjections(
|
||||
return arguments
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun createFunctionType(
|
||||
builtIns: KotlinBuiltIns,
|
||||
annotations: Annotations,
|
||||
receiverType: KotlinType?,
|
||||
parameterTypes: List<KotlinType>,
|
||||
parameterNames: List<Name>?,
|
||||
returnType: KotlinType
|
||||
returnType: KotlinType,
|
||||
suspendFunction: Boolean = false
|
||||
): SimpleType {
|
||||
val arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, parameterNames, returnType, builtIns)
|
||||
val size = parameterTypes.size
|
||||
val classDescriptor = builtIns.getFunction(if (receiverType == null) size else size + 1)
|
||||
val parameterCount = if (receiverType == null) size else size + 1
|
||||
val classDescriptor = if (suspendFunction) builtIns.getSuspendFunction(parameterCount) else builtIns.getFunction(parameterCount)
|
||||
|
||||
val typeAnnotations =
|
||||
if (receiverType == null || annotations.findAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType) != null) {
|
||||
|
||||
+9
-4
@@ -38,10 +38,9 @@ class BuiltInFictitiousFunctionClassFactory(
|
||||
|
||||
companion object {
|
||||
private fun parseClassName(className: String, packageFqName: FqName): KindWithArity? {
|
||||
val kind = FunctionClassDescriptor.Kind.byPackage(packageFqName) ?: return null
|
||||
val kind = FunctionClassDescriptor.Kind.byClassNamePrefix(packageFqName, className) ?: return null
|
||||
|
||||
val prefix = kind.classNamePrefix
|
||||
if (!className.startsWith(prefix)) return null
|
||||
|
||||
val arity = toInt(className.substring(prefix.length)) ?: return null
|
||||
|
||||
@@ -49,8 +48,14 @@ class BuiltInFictitiousFunctionClassFactory(
|
||||
return KindWithArity(kind, arity)
|
||||
}
|
||||
|
||||
@JvmStatic fun getFunctionalClassKind(className: String, packageFqName: FqName) =
|
||||
parseClassName(className, packageFqName)?.kind
|
||||
|
||||
@JvmStatic fun isFunctionClassName(className: String, packageFqName: FqName) =
|
||||
parseClassName(className, packageFqName) != null
|
||||
getFunctionalClassKind(className, packageFqName) == Kind.Function
|
||||
|
||||
@JvmStatic fun isSuspendFunctionClassName(className: String, packageFqName: FqName) =
|
||||
getFunctionalClassKind(className, packageFqName) == Kind.SuspendFunction
|
||||
|
||||
private fun toInt(s: String): Int? {
|
||||
if (s.isEmpty()) return null
|
||||
@@ -67,7 +72,7 @@ class BuiltInFictitiousFunctionClassFactory(
|
||||
|
||||
override fun shouldCreateClass(packageFqName: FqName, name: Name): Boolean {
|
||||
val string = name.asString()
|
||||
return (string.startsWith("Function") || string.startsWith("KFunction")) // an optimization
|
||||
return (string.startsWith("Function") || string.startsWith("KFunction") || string.startsWith("SuspendFunction")) // an optimization
|
||||
&& parseClassName(string, packageFqName) != null
|
||||
}
|
||||
|
||||
|
||||
+14
-2
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
@@ -49,6 +50,7 @@ class FunctionClassDescriptor(
|
||||
|
||||
enum class Kind(val packageFqName: FqName, val classNamePrefix: String) {
|
||||
Function(BUILT_INS_PACKAGE_FQ_NAME, "Function"),
|
||||
SuspendFunction(BUILT_INS_PACKAGE_FQ_NAME, "SuspendFunction"),
|
||||
KFunction(KOTLIN_REFLECT_FQ_NAME, "KFunction");
|
||||
|
||||
fun numberedClassName(arity: Int) = Name.identifier("$classNamePrefix$arity")
|
||||
@@ -59,6 +61,9 @@ class FunctionClassDescriptor(
|
||||
KOTLIN_REFLECT_FQ_NAME -> KFunction
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun byClassNamePrefix(packageFqName: FqName, className: String) =
|
||||
Kind.values().firstOrNull { it.packageFqName == packageFqName && className.startsWith(it.classNamePrefix) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,8 +133,15 @@ class FunctionClassDescriptor(
|
||||
result.add(KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, descriptor, arguments))
|
||||
}
|
||||
|
||||
// Add unnumbered base class, e.g. Function for Function{n}, KFunction for KFunction{n}
|
||||
add(containingDeclaration, Name.identifier(functionKind.classNamePrefix))
|
||||
|
||||
if (functionKind == Kind.SuspendFunction) {
|
||||
// SuspendFunction$N<...> <: Any
|
||||
result.add(containingDeclaration.builtIns.anyType)
|
||||
}
|
||||
else {
|
||||
// Add unnumbered base class, e.g. Function for Function{n}, KFunction for KFunction{n}
|
||||
add(containingDeclaration, Name.identifier(functionKind.classNamePrefix))
|
||||
}
|
||||
|
||||
// For KFunction{n}, add corresponding numbered Function{n} class, e.g. Function2 for KFunction2
|
||||
if (functionKind == Kind.KFunction) {
|
||||
|
||||
@@ -196,7 +196,7 @@ internal class DescriptorRendererImpl(
|
||||
}
|
||||
|
||||
private fun shouldRenderAsPrettyFunctionType(type: KotlinType): Boolean {
|
||||
return type.isFunctionType && type.arguments.none { it.isStarProjection }
|
||||
return type.isBuiltinFunctionalType && type.arguments.none { it.isStarProjection }
|
||||
}
|
||||
|
||||
override fun renderFlexibleType(lowerRendered: String, upperRendered: String, builtIns: KotlinBuiltIns): String {
|
||||
@@ -322,6 +322,10 @@ internal class DescriptorRendererImpl(
|
||||
|
||||
if (needParenthesis) append("(")
|
||||
|
||||
if (type.isSuspendFunctionType) {
|
||||
append("suspend ") // anything special about modifier?
|
||||
}
|
||||
|
||||
if (receiverType != null) {
|
||||
val surroundReceiver = shouldRenderAsPrettyFunctionType(receiverType) && !receiverType.isMarkedNullable
|
||||
if (surroundReceiver) {
|
||||
|
||||
Reference in New Issue
Block a user