Fix anonymous function literals handling in type checker

- [NI] Create type info directly if the expected type is functional.
- Properly handle suspended function expected type.
This commit is contained in:
Dmitry Petrov
2017-06-07 13:06:45 +03:00
committed by Mikhail Zarechenskiy
parent 6facdcb7ea
commit 26cc08be65
3 changed files with 32 additions and 7 deletions
@@ -123,7 +123,17 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
createTypeInfo(components.dataFlowAnalyzer.checkStatementType(function, context), context)
}
else {
components.dataFlowAnalyzer.createCheckedTypeInfo(functionDescriptor.createFunctionType(), context, function)
val expectedType = context.expectedType
val functionalTypeExpected = expectedType.isBuiltinFunctionalType()
val suspendFunctionTypeExpected = expectedType.isSuspendFunctionType()
val resultType = functionDescriptor.createFunctionType(suspendFunctionTypeExpected)
if (functionalTypeExpected)
createTypeInfo(resultType, context)
else
components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, function)
}
}
@@ -144,8 +154,8 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
if (!expression.functionLiteral.hasBody()) return null
val expectedType = context.expectedType
val functionTypeExpected = !noExpectedType(expectedType) && expectedType.isBuiltinFunctionalType
val suspendFunctionTypeExpected = !noExpectedType(expectedType) && expectedType.isSuspendFunctionType
val functionTypeExpected = expectedType.isBuiltinFunctionalType()
val suspendFunctionTypeExpected = expectedType.isSuspendFunctionType()
val functionDescriptor = createFunctionLiteralDescriptor(expression, context)
expression.valueParameters.forEach {
@@ -174,10 +184,10 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
): AnonymousFunctionDescriptor {
val functionLiteral = expression.functionLiteral
val functionDescriptor = AnonymousFunctionDescriptor(
context.scope.ownerDescriptor,
components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace),
CallableMemberDescriptor.Kind.DECLARATION, functionLiteral.toSourceElement(),
!noExpectedType(context.expectedType) && context.expectedType.isSuspendFunctionType
context.scope.ownerDescriptor,
components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace),
CallableMemberDescriptor.Kind.DECLARATION, functionLiteral.toSourceElement(),
context.expectedType.isSuspendFunctionType()
)
components.functionDescriptorResolver.
initializeFunctionDescriptorAndExplicitReturnType(context.scope.ownerDescriptor, context.scope, functionLiteral,
@@ -189,6 +199,12 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
return functionDescriptor
}
private fun KotlinType.isBuiltinFunctionalType() =
!noExpectedType(this) && isBuiltinFunctionalType
private fun KotlinType.isSuspendFunctionType() =
!noExpectedType(this) && isSuspendFunctionType
private fun computeReturnType(
expression: KtLambdaExpression,
context: ExpressionTypingContext,
@@ -4,3 +4,8 @@ val test1: suspend () -> Unit = {}
val test2: suspend Any.() -> Unit = {}
val test3: suspend Any.(Int) -> Int = { k: Int -> k + 1 }
val test4: SuspendFn = {}
val test1f: suspend () -> Unit = fun () {}
val test2f: suspend Any.() -> Unit = fun Any.() {}
val test3f: suspend Any.(Int) -> Int = fun (k: Int) = k + 1
val test4f: SuspendFn = fun Any.() {}
@@ -1,7 +1,11 @@
package
public val test1: suspend () -> kotlin.Unit
public val test1f: suspend () -> kotlin.Unit
public val test2: suspend kotlin.Any.() -> kotlin.Unit
public val test2f: suspend kotlin.Any.() -> kotlin.Unit
public val test3: suspend kotlin.Any.(kotlin.Int) -> kotlin.Int
public val test3f: suspend kotlin.Any.(kotlin.Int) -> kotlin.Int
public val test4: SuspendFn /* = suspend () -> kotlin.Unit */
public val test4f: SuspendFn /* = suspend () -> kotlin.Unit */
public typealias SuspendFn = suspend () -> kotlin.Unit