Move inference parameter type in FunctionDescriptorResolver
This commit is contained in:
+1
-2
@@ -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)
|
||||
|
||||
+8
-106
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user