Generic type arguments inference for lambdas as suspend functions.
This commit is contained in:
committed by
Stanislav Erokhin
parent
bf987cff5f
commit
6d73e13798
@@ -17,10 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.resolve
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.*
|
||||||
import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
|
|
||||||
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
|
||||||
@@ -239,7 +236,7 @@ class FunctionDescriptorResolver(
|
|||||||
return replaceAnnotations(AnnotationsImpl(annotations.filter { it != parameterNameAnnotation }))
|
return replaceAnnotations(AnnotationsImpl(annotations.filter { it != parameterNameAnnotation }))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.functionTypeExpected() = !TypeUtils.noExpectedType(this) && isFunctionType
|
private fun KotlinType.functionTypeExpected() = !TypeUtils.noExpectedType(this) && isBuiltinFunctionalType
|
||||||
private fun KotlinType.getReceiverType(): KotlinType? =
|
private fun KotlinType.getReceiverType(): KotlinType? =
|
||||||
if (functionTypeExpected()) this.getReceiverTypeFromFunctionType() else null
|
if (functionTypeExpected()) this.getReceiverTypeFromFunctionType() else null
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.callResolverUtil
|
|||||||
import com.google.common.collect.Lists
|
import com.google.common.collect.Lists
|
||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||||
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl
|
||||||
import org.jetbrains.kotlin.lexer.KtToken
|
import org.jetbrains.kotlin.lexer.KtToken
|
||||||
@@ -50,19 +51,19 @@ enum class ResolveArgumentsMode {
|
|||||||
|
|
||||||
|
|
||||||
fun hasUnknownFunctionParameter(type: KotlinType): Boolean {
|
fun hasUnknownFunctionParameter(type: KotlinType): Boolean {
|
||||||
assert(ReflectionTypes.isCallableType(type)) { "type $type is not a function or property" }
|
assert(ReflectionTypes.isCallableType(type) || type.isSuspendFunctionType) { "type $type is not a function or property" }
|
||||||
return getParameterArgumentsOfCallableType(type).any {
|
return getParameterArgumentsOfCallableType(type).any {
|
||||||
it.type.contains { TypeUtils.isDontCarePlaceholder(it) } || ErrorUtils.containsUninferredParameter(it.type)
|
it.type.contains { TypeUtils.isDontCarePlaceholder(it) } || ErrorUtils.containsUninferredParameter(it.type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasUnknownReturnType(type: KotlinType): Boolean {
|
fun hasUnknownReturnType(type: KotlinType): Boolean {
|
||||||
assert(ReflectionTypes.isCallableType(type)) { "type $type is not a function or property" }
|
assert(ReflectionTypes.isCallableType(type) || type.isSuspendFunctionType) { "type $type is not a function or property" }
|
||||||
return ErrorUtils.containsErrorType(getReturnTypeForCallable(type))
|
return ErrorUtils.containsErrorType(getReturnTypeForCallable(type))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun replaceReturnTypeForCallable(type: KotlinType, given: KotlinType): KotlinType {
|
fun replaceReturnTypeForCallable(type: KotlinType, given: KotlinType): KotlinType {
|
||||||
assert(ReflectionTypes.isCallableType(type)) { "type $type is not a function or property" }
|
assert(ReflectionTypes.isCallableType(type) || type.isSuspendFunctionType) { "type $type is not a function or property" }
|
||||||
val newArguments = Lists.newArrayList<TypeProjection>()
|
val newArguments = Lists.newArrayList<TypeProjection>()
|
||||||
newArguments.addAll(getParameterArgumentsOfCallableType(type))
|
newArguments.addAll(getParameterArgumentsOfCallableType(type))
|
||||||
newArguments.add(TypeProjectionImpl(Variance.INVARIANT, given))
|
newArguments.add(TypeProjectionImpl(Variance.INVARIANT, given))
|
||||||
|
|||||||
+2
-1
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||||
|
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
@@ -308,7 +309,7 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
|||||||
if (expectedType == null || TypeUtils.isDontCarePlaceholder(expectedType)) {
|
if (expectedType == null || TypeUtils.isDontCarePlaceholder(expectedType)) {
|
||||||
expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, false)
|
expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, false)
|
||||||
}
|
}
|
||||||
if (expectedType == null || !expectedType.isFunctionTypeOrSubtype || hasUnknownFunctionParameter(expectedType)) {
|
if (expectedType == null || !expectedType.isBuiltinFunctionalTypeOrSubtype || hasUnknownFunctionParameter(expectedType)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val dataFlowInfoForArguments = context.candidateCall.dataFlowInfoForArguments
|
val dataFlowInfoForArguments = context.candidateCall.dataFlowInfoForArguments
|
||||||
|
|||||||
+3
-1
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.inference
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.createFunctionType
|
import org.jetbrains.kotlin.builtins.createFunctionType
|
||||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||||
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl.ConstraintKind.EQUAL
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl.ConstraintKind.EQUAL
|
||||||
@@ -448,5 +449,6 @@ internal fun createTypeForFunctionPlaceholder(
|
|||||||
functionPlaceholderTypeConstructor.argumentTypes
|
functionPlaceholderTypeConstructor.argumentTypes
|
||||||
}
|
}
|
||||||
val receiverType = if (isExtension) DONT_CARE else null
|
val receiverType = if (isExtension) DONT_CARE else null
|
||||||
return createFunctionType(functionPlaceholder.builtIns, Annotations.EMPTY, receiverType, newArgumentTypes, null, DONT_CARE)
|
return createFunctionType(functionPlaceholder.builtIns, Annotations.EMPTY, receiverType, newArgumentTypes, null, DONT_CARE,
|
||||||
|
suspendFunction = expectedType.isSuspendFunctionType)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -14,4 +14,4 @@ fun test4(): suspend () -> Unit = useSuspendFn {}
|
|||||||
|
|
||||||
fun test5(sfn: suspend () -> Unit) = ambiguous(sfn)
|
fun test5(sfn: suspend () -> Unit) = ambiguous(sfn)
|
||||||
fun test6(fn: () -> Unit) = ambiguous(fn)
|
fun test6(fn: () -> Unit) = ambiguous(fn)
|
||||||
fun test7(): () -> Unit = ambiguous {}
|
fun test7(): () -> Unit = <!OVERLOAD_RESOLUTION_AMBIGUITY!>ambiguous<!> {}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
fun <T> withS(x: T, sfn: suspend (T) -> Unit) = x
|
||||||
|
|
||||||
|
val test1 = withS(100) {}
|
||||||
|
|
||||||
|
fun <TT> test2(x: TT) = withS(x) {}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val test1: kotlin.Int
|
||||||
|
public fun </*0*/ TT> test2(/*0*/ x: TT): TT
|
||||||
|
public fun </*0*/ T> withS(/*0*/ x: T, /*1*/ sfn: suspend (T) -> kotlin.Unit): T
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
fun <T1, T2> withS2(x: T1, sfn1: suspend (T1) -> T2, sfn2: suspend (T2) -> Unit): T2 = null!!
|
||||||
|
|
||||||
|
val test1 = withS2(100, { "" }, { })
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val test1: kotlin.String
|
||||||
|
public fun </*0*/ T1, /*1*/ T2> withS2(/*0*/ x: T1, /*1*/ sfn1: suspend (T1) -> T2, /*2*/ sfn2: suspend (T2) -> kotlin.Unit): T2
|
||||||
@@ -41,24 +41,31 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
|||||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
val KotlinType.isFunctionTypeOrSubtype: Boolean
|
private fun KotlinType.isTypeOrSubtypeOf(predicate: (KotlinType) -> Boolean): Boolean =
|
||||||
get() = isFunctionType || DFS.dfsFromNode(
|
predicate(this) ||
|
||||||
this,
|
DFS.dfsFromNode(
|
||||||
DFS.Neighbors { it.constructor.supertypes },
|
this,
|
||||||
DFS.VisitedWithSet(),
|
DFS.Neighbors { it.constructor.supertypes },
|
||||||
object : DFS.AbstractNodeHandler<KotlinType, Boolean>() {
|
DFS.VisitedWithSet(),
|
||||||
private var result = false
|
object : DFS.AbstractNodeHandler<KotlinType, Boolean>() {
|
||||||
|
private var result = false
|
||||||
|
|
||||||
override fun beforeChildren(current: KotlinType): Boolean {
|
override fun beforeChildren(current: KotlinType): Boolean {
|
||||||
if (current.isFunctionType) {
|
if (predicate(current)) {
|
||||||
result = true
|
result = true
|
||||||
|
}
|
||||||
|
return !result
|
||||||
}
|
}
|
||||||
return !result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun result() = result
|
override fun result() = result
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val KotlinType.isFunctionTypeOrSubtype: Boolean
|
||||||
|
get() = isTypeOrSubtypeOf { it.isFunctionType }
|
||||||
|
|
||||||
|
val KotlinType.isBuiltinFunctionalTypeOrSubtype: Boolean
|
||||||
|
get() = isTypeOrSubtypeOf { it.isBuiltinFunctionalType }
|
||||||
|
|
||||||
val KotlinType.isFunctionType: Boolean
|
val KotlinType.isFunctionType: Boolean
|
||||||
get() = constructor.declarationDescriptor?.getFunctionalClassKind() == FunctionClassDescriptor.Kind.Function
|
get() = constructor.declarationDescriptor?.getFunctionalClassKind() == FunctionClassDescriptor.Kind.Function
|
||||||
|
|||||||
Reference in New Issue
Block a user