[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.
This commit is contained in:
Dmitry Petrov
2017-06-07 12:34:21 +03:00
committed by Mikhail Zarechenskiy
parent f637ebe9ff
commit f578d07b00
2 changed files with 21 additions and 3 deletions
@@ -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<R>, 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
@@ -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)