Move inference parameter type in FunctionDescriptorResolver

This commit is contained in:
Stanislav Erokhin
2015-03-05 12:56:50 +03:00
parent 0c74675e6e
commit d9882a6d0b
13 changed files with 294 additions and 267 deletions
@@ -171,8 +171,7 @@ public class DefaultErrorMessages {
MAP.put(CONFLICTING_IMPORT, "Conflicting import, imported name ''{0}'' is ambiguous", STRING);
MAP.put(PLATFORM_CLASS_MAPPED_TO_KOTLIN, "This class shouldn''t be used in Kotlin. Use {0} instead.", CLASSES_OR_SEPARATED);
MAP.put(CANNOT_INFER_PARAMETER_TYPE,
"Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) -> ...} notation");
MAP.put(CANNOT_INFER_PARAMETER_TYPE, "Cannot infer a type for this parameter. Please specify it explicitly.");
MAP.put(NO_BACKING_FIELD_ABSTRACT_PROPERTY, "This property doesn't have a backing field, because it's abstract");
MAP.put(NO_BACKING_FIELD_CUSTOM_ACCESSORS,
@@ -17,13 +17,15 @@
package org.jetbrains.kotlin.resolve
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.ModifiersChecker.*
@@ -37,7 +39,10 @@ import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.JetTypeChecker
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import java.util.ArrayList
class FunctionDescriptorResolver(
@@ -65,7 +70,7 @@ class FunctionDescriptorResolver(
CallableMemberDescriptor.Kind.DECLARATION,
function.toSourceElement()
)
initializeFunctionDescriptorAndExplicitReturnType(containingDescriptor, scope, function, functionDescriptor, trace)
initializeFunctionDescriptorAndExplicitReturnType(containingDescriptor, scope, function, functionDescriptor, trace, null)
initializeFunctionReturnTypeBasedOnFunctionBody(scope, function, functionDescriptor, trace, dataFlowInfo)
BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor)
return functionDescriptor
@@ -85,7 +90,7 @@ class FunctionDescriptorResolver(
CallableMemberDescriptor.Kind.DECLARATION,
function.toSourceElement()
)
initializeFunctionDescriptorAndExplicitReturnType(containingDescriptor, scope, function, functionDescriptor, trace)
initializeFunctionDescriptorAndExplicitReturnType(containingDescriptor, scope, function, functionDescriptor, trace, null)
initializeFunctionReturnTypeBasedOnFunctionBody(scope, function, functionDescriptor, trace, dataFlowInfo)
BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor)
return functionDescriptor
@@ -117,12 +122,13 @@ class FunctionDescriptorResolver(
functionDescriptor.setReturnType(returnType)
}
private fun initializeFunctionDescriptorAndExplicitReturnType(
fun initializeFunctionDescriptorAndExplicitReturnType(
containingDescriptor: DeclarationDescriptor,
scope: JetScope,
function: JetFunction,
functionDescriptor: SimpleFunctionDescriptorImpl,
trace: BindingTrace
trace: BindingTrace,
expectedFunctionType: JetType?
) {
val innerScope = WritableScopeImpl(scope, functionDescriptor, TraceBasedRedeclarationHandler(trace), "Function descriptor header scope")
innerScope.addLabeledDeclaration(functionDescriptor)
@@ -133,18 +139,18 @@ class FunctionDescriptorResolver(
descriptorResolver.resolveGenericBounds(function, functionDescriptor, innerScope, typeParameterDescriptors, trace)
val receiverTypeRef = function.getReceiverTypeReference()
val receiverType = if (receiverTypeRef != null) {
typeResolver.resolveType(innerScope, receiverTypeRef, trace, true)
} else null
val receiverType =
if (receiverTypeRef != null)
typeResolver.resolveType(innerScope, receiverTypeRef, trace, true)
else
expectedFunctionType.getReceiverType()
val valueParameterDescriptors = resolveValueParameters(functionDescriptor, innerScope, function.getValueParameters(), trace)
val valueParameterDescriptors = createValueParameterDescriptors(function, functionDescriptor, innerScope, trace, expectedFunctionType)
innerScope.changeLockLevel(WritableScope.LockLevel.READING)
val returnTypeRef = function.getTypeReference()
val returnType = if (returnTypeRef != null) {
typeResolver.resolveType(innerScope, returnTypeRef, trace, true)
} else null
val returnType = function.getTypeReference()?.let { typeResolver.resolveType(innerScope, it, trace, true) }
val modality = resolveModalityFromModifiers(function, getDefaultModality(containingDescriptor, function.hasBody()))
val visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, containingDescriptor))
@@ -159,6 +165,45 @@ class FunctionDescriptorResolver(
)
}
private fun createValueParameterDescriptors(
function: JetFunction,
functionDescriptor: SimpleFunctionDescriptorImpl,
innerScope: WritableScopeImpl,
trace: BindingTrace,
expectedFunctionType: JetType?
): List<ValueParameterDescriptor> {
val expectedValueParameters = expectedFunctionType.getValueParameters(functionDescriptor)
if (expectedValueParameters != null) {
if (expectedValueParameters.size() == 1 && function is JetFunctionLiteral && function.getValueParameterList() == null) {
// it parameter for lambda
val valueParameterDescriptor = expectedValueParameters.first()
val it = ValueParameterDescriptorImpl(functionDescriptor, null, 0, Annotations.EMPTY, Name.identifier("it"),
valueParameterDescriptor.getType(), valueParameterDescriptor.hasDefaultValue(),
valueParameterDescriptor.getVarargElementType(), SourceElement.NO_SOURCE)
trace.record(BindingContext.AUTO_CREATED_IT, it)
return listOf(it)
}
if (function.getValueParameters().size() != expectedValueParameters.size()) {
val expectedParameterTypes = ExpressionTypingUtils.getValueParametersTypes(expectedValueParameters)
trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(function, expectedParameterTypes.size(), expectedParameterTypes))
}
}
return resolveValueParameters(
functionDescriptor,
innerScope,
function.getValueParameters(),
trace,
expectedValueParameters
)
}
private fun JetType.functionTypeExpected() = !TypeUtils.noExpectedType(this) && KotlinBuiltIns.isFunctionOrExtensionFunctionType(this)
private fun JetType?.getReceiverType(): JetType? =
if (this != null && functionTypeExpected()) getReceiverType(this) else null
private fun JetType?.getValueParameters(owner: FunctionDescriptor): List<ValueParameterDescriptor>? =
if (this != null && functionTypeExpected()) getValueParameters(owner, this) else null
public fun resolvePrimaryConstructorDescriptor(
scope: JetScope,
classDescriptor: ClassDescriptor,
@@ -222,7 +267,7 @@ class FunctionDescriptorResolver(
parameterScope.changeLockLevel(WritableScope.LockLevel.BOTH)
val constructor = constructorDescriptor.initialize(
typeParameters,
resolveValueParameters(constructorDescriptor, parameterScope, valueParameters, trace),
resolveValueParameters(constructorDescriptor, parameterScope, valueParameters, trace, null),
resolveVisibilityFromModifiers(
modifierList,
DescriptorUtils.getDefaultConstructorVisibility(classDescriptor)
@@ -238,20 +283,43 @@ class FunctionDescriptorResolver(
functionDescriptor: FunctionDescriptor,
parameterScope: WritableScope,
valueParameters: List<JetParameter>,
trace: BindingTrace
trace: BindingTrace,
expectedValueParameters: List<ValueParameterDescriptor>?
): List<ValueParameterDescriptor> {
val result = ArrayList<ValueParameterDescriptor>()
for (i in valueParameters.indices) {
val valueParameter = valueParameters.get(i)
val typeReference = valueParameter.getTypeReference()
val expectedType = expectedValueParameters?.let { if (i < it.size()) it[i].getType() else null }
val type: JetType
if (typeReference == null) {
trace.report(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION.on(valueParameter))
type = ErrorUtils.createErrorType("Type annotation was missing")
if (typeReference != null) {
type = typeResolver.resolveType(parameterScope, typeReference, trace, true)
if (expectedType != null) {
if (!JetTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) {
trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(valueParameter, expectedType))
}
}
}
else {
type = typeResolver.resolveType(parameterScope, typeReference, trace, true)
if (isFunctionLiteral(functionDescriptor) || isFunctionExpression(functionDescriptor)) {
val containsUninferredParameter = TypeUtils.containsSpecialType(expectedType) {
TypeUtils.isDontCarePlaceholder(it) || ErrorUtils.isUninferredParameter(it)
}
if (expectedType == null || containsUninferredParameter) {
trace.report(CANNOT_INFER_PARAMETER_TYPE.on(valueParameter))
}
if (expectedType != null) {
type = expectedType
}
else {
type = TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE
}
} else {
trace.report(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION.on(valueParameter))
type = ErrorUtils.createErrorType("Type annotation was missing for parameter ${valueParameter.getNameAsSafeName()}")
}
}
if (functionDescriptor !is ConstructorDescriptor) {
@@ -262,7 +330,7 @@ class FunctionDescriptorResolver(
checkConstructorParameterHasNoModifier(trace, valueParameter)
}
val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptor(parameterScope, functionDescriptor,
val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptorWithAnnotationArguments(parameterScope, functionDescriptor,
valueParameter, i, type, trace)
parameterScope.addVariableDescriptor(valueParameterDescriptor)
result.add(valueParameterDescriptor)
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.scopes.WritableScope
import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_LAMBDA_PARAM_TYPE
import org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
import org.jetbrains.kotlin.types.checker.JetTypeChecker
@@ -127,12 +127,12 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
val expectedType = context.expectedType
val functionTypeExpected = !noExpectedType(expectedType) && KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType)
val functionDescriptor = createFunctionDescriptor(expression, context, functionTypeExpected)
val functionDescriptor = createFunctionDescriptor(expression, context)
val safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected)
functionDescriptor.setReturnType(safeReturnType)
val resultType = createFunctionType(functionDescriptor)!!
if (!noExpectedType(expectedType) && KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType)) {
if (functionTypeExpected) {
// all checks were done before
return JetTypeInfo.create(resultType, context.dataFlowInfo)
}
@@ -142,115 +142,18 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
private fun createFunctionDescriptor(
expression: JetFunctionLiteralExpression,
context: ExpressionTypingContext,
functionTypeExpected: Boolean
context: ExpressionTypingContext
): AnonymousFunctionDescriptor {
val functionLiteral = expression.getFunctionLiteral()
val receiverTypeRef = functionLiteral.getReceiverTypeReference()
val functionDescriptor = AnonymousFunctionDescriptor(context.scope.getContainingDeclaration(), Annotations.EMPTY,
CallableMemberDescriptor.Kind.DECLARATION, functionLiteral.toSourceElement())
val valueParameterDescriptors = createValueParameterDescriptors(context, functionLiteral, functionDescriptor, functionTypeExpected)
val effectiveReceiverType: JetType?
if (receiverTypeRef == null) {
if (functionTypeExpected) {
effectiveReceiverType = KotlinBuiltIns.getReceiverType(context.expectedType)
}
else {
effectiveReceiverType = null
}
}
else {
effectiveReceiverType = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, receiverTypeRef,
context.trace, true)
}
functionDescriptor.initialize(effectiveReceiverType, ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER, listOf(),
valueParameterDescriptors, /*unsubstitutedReturnType = */ null, Modality.FINAL, Visibilities.LOCAL)
components.expressionTypingServices.getFunctionDescriptorResolver().
initializeFunctionDescriptorAndExplicitReturnType(context.scope.getContainingDeclaration(), context.scope, functionLiteral,
functionDescriptor, context.trace, context.expectedType)
BindingContextUtils.recordFunctionDeclarationToDescriptor(context.trace, functionLiteral, functionDescriptor)
return functionDescriptor
}
private fun createValueParameterDescriptors(
context: ExpressionTypingContext,
functionLiteral: JetFunctionLiteral,
functionDescriptor: FunctionDescriptorImpl,
functionTypeExpected: Boolean
): List<ValueParameterDescriptor> {
val valueParameterDescriptors = Lists.newArrayList<ValueParameterDescriptor>()
val declaredValueParameters = functionLiteral.getValueParameters()
val expectedValueParameters = if (functionTypeExpected) KotlinBuiltIns.getValueParameters(functionDescriptor, context.expectedType)
else null
val valueParameterList = functionLiteral.getValueParameterList()
val hasDeclaredValueParameters = valueParameterList != null
if (functionTypeExpected && !hasDeclaredValueParameters && expectedValueParameters!!.size() == 1) {
val valueParameterDescriptor = expectedValueParameters!!.get(0)
val it = ValueParameterDescriptorImpl(functionDescriptor, null, 0, Annotations.EMPTY, Name.identifier("it"),
valueParameterDescriptor.getType(), valueParameterDescriptor.hasDefaultValue(),
valueParameterDescriptor.getVarargElementType(), SourceElement.NO_SOURCE)
valueParameterDescriptors.add(it)
context.trace.record<ValueParameterDescriptor>(AUTO_CREATED_IT, it)
}
else {
if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) {
val expectedParameterTypes = ExpressionTypingUtils.getValueParametersTypes(expectedValueParameters)
context.trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(functionLiteral, expectedParameterTypes.size(), expectedParameterTypes))
}
for (i in declaredValueParameters.indices) {
val valueParameterDescriptor = createValueParameterDescriptor(context, functionDescriptor, declaredValueParameters, expectedValueParameters, i)
valueParameterDescriptors.add(valueParameterDescriptor)
}
}
return valueParameterDescriptors
}
private fun createValueParameterDescriptor(
context: ExpressionTypingContext,
functionDescriptor: FunctionDescriptorImpl,
declaredValueParameters: List<JetParameter>,
expectedValueParameters: List<ValueParameterDescriptor>?,
index: Int
): ValueParameterDescriptor {
val declaredParameter = declaredValueParameters.get(index)
val typeReference = declaredParameter.getTypeReference()
val expectedType: JetType?
if (expectedValueParameters != null && index < expectedValueParameters.size()) {
expectedType = expectedValueParameters.get(index).getType()
}
else {
expectedType = null
}
val type: JetType
if (typeReference != null) {
type = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true)
if (expectedType != null) {
if (!JetTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) {
context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType))
}
}
}
else {
val containsUninferredParameter = TypeUtils.containsSpecialType(expectedType) {
TypeUtils.isDontCarePlaceholder(it) || ErrorUtils.isUninferredParameter(it)
}
if (expectedType == null || containsUninferredParameter) {
context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter))
}
if (expectedType != null) {
type = expectedType
}
else {
type = CANT_INFER_LAMBDA_PARAM_TYPE
}
}
return components.expressionTypingServices.getDescriptorResolver()
.resolveValueParameterDescriptorWithAnnotationArguments(context.scope, functionDescriptor, declaredParameter,
index, type, context.trace)
}
private fun computeReturnType(
expression: JetFunctionLiteralExpression,
context: ExpressionTypingContext,
@@ -265,10 +168,9 @@ public class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Express
return components.builtIns.getUnitType()
}
}
return returnType ?: CANT_INFER_LAMBDA_PARAM_TYPE
return returnType ?: CANT_INFER_FUNCTION_PARAM_TYPE
}
private fun computeUnsafeReturnType(
expression: JetFunctionLiteralExpression,
context: ExpressionTypingContext,