From f578d07b000f316a442f4c952877bd1e5b4c1a12 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Wed, 7 Jun 2017 12:34:21 +0300 Subject: [PATCH] [NI] Fix lambda return type when expected type is not functional type Introduce a fresh type variable for lambda return type. We can't set expected lambda return type to 'Any?', because we can't infer the actual type from return expressions in lambda in that case. --- .../components/CheckArgumentsResolutionPart.kt | 17 ++++++++++++++--- .../calls/inference/model/TypeVariable.kt | 7 +++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CheckArgumentsResolutionPart.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CheckArgumentsResolutionPart.kt index 0254f6bfb40..55975b80fb6 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CheckArgumentsResolutionPart.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CheckArgumentsResolutionPart.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.components.CreateDescriptorWithFreshTy import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition +import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.tower.isSuccess import org.jetbrains.kotlin.types.UnwrappedType @@ -82,7 +83,7 @@ internal object CheckArguments : ResolutionPart { } // if expected type isn't function type, then may be it is Function, Any or just `T` - fun processLambdaArgument( + private fun processLambdaArgument( kotlinCall: KotlinCall, csBuilder: ConstraintSystemBuilder, argument: LambdaKotlinCallArgument, @@ -117,7 +118,7 @@ internal object CheckArguments : ResolutionPart { parameters = argument.parametersTypes?.map { it ?: builtIns.nothingType } ?: emptyList() returnType = (argument as? FunctionExpression)?.returnType ?: expectedType.arguments.singleOrNull()?.type?.unwrap()?.takeIf { isFunctionSupertype } ?: - builtIns.nullableAnyType + createFreshTypeVariableForLambdaReturnType(csBuilder, argument, builtIns) // what about case where expected type is type variable? In old TY such cases was not supported. => do nothing for now. todo design } @@ -130,7 +131,17 @@ internal object CheckArguments : ResolutionPart { return null } - fun checkCallableExpectedType( + private fun createFreshTypeVariableForLambdaReturnType( + csBuilder: ConstraintSystemBuilder, + argument: LambdaKotlinCallArgument, + builtIns: KotlinBuiltIns + ): UnwrappedType { + val typeVariable = TypeVariableForLambdaReturnType(argument, builtIns, "_L") + csBuilder.registerVariable(typeVariable) + return typeVariable.defaultType + } + + private fun checkCallableExpectedType( csBuilder: ConstraintSystemBuilder, argument: CallableReferenceKotlinCallArgument, expectedType: UnwrappedType diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt index 68dab00c121..0b90785f4d7 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/TypeVariable.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.calls.model.KotlinCall +import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.* @@ -55,3 +56,9 @@ class TypeVariableFromCallableDescriptor( val originalTypeParameter: TypeParameterDescriptor, val call: KotlinCall? = null ) : NewTypeVariable(originalTypeParameter.builtIns, originalTypeParameter.name.identifier) + +class TypeVariableForLambdaReturnType( + val lambdaArgument: LambdaKotlinCallArgument, + builtIns: KotlinBuiltIns, + name: String +) : NewTypeVariable(builtIns, name) \ No newline at end of file