Added special type constructor for function/ extension function
that stores an information about declared argument types
This commit is contained in:
committed by
Alexander Udalov
parent
79ee91c048
commit
d9568ef88c
+25
-18
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
||||||
import org.jetbrains.kotlin.resolve.*;
|
import org.jetbrains.kotlin.resolve.*;
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
|
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
|
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
|
||||||
@@ -36,11 +37,11 @@ import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluat
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||||
|
import org.jetbrains.kotlin.types.ErrorUtils;
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker;
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
|
|
||||||
import org.jetbrains.kotlin.types.expressions.JetTypeInfo;
|
import org.jetbrains.kotlin.types.expressions.JetTypeInfo;
|
||||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryPackage;
|
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryPackage;
|
||||||
|
|
||||||
@@ -54,7 +55,9 @@ import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumen
|
|||||||
import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
|
import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.DEPENDENT;
|
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.DEPENDENT;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
|
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
|
||||||
import static org.jetbrains.kotlin.types.TypeUtils.*;
|
import static org.jetbrains.kotlin.resolve.calls.inference.InferencePackage.createCorrespondingFunctionTypeForFunctionPlaceholder;
|
||||||
|
import static org.jetbrains.kotlin.types.TypeUtils.DONT_CARE;
|
||||||
|
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||||
|
|
||||||
public class ArgumentTypeResolver {
|
public class ArgumentTypeResolver {
|
||||||
|
|
||||||
@@ -81,21 +84,21 @@ public class ArgumentTypeResolver {
|
|||||||
@NotNull JetType actualType,
|
@NotNull JetType actualType,
|
||||||
@NotNull JetType expectedType
|
@NotNull JetType expectedType
|
||||||
) {
|
) {
|
||||||
if (actualType == PLACEHOLDER_FUNCTION_TYPE) {
|
if (ErrorUtils.isFunctionPlaceholder(actualType)) {
|
||||||
return isFunctionOrErrorType(expectedType) || KotlinBuiltIns.isAnyOrNullableAny(expectedType); //todo function type extends
|
JetType functionType = createCorrespondingFunctionTypeForFunctionPlaceholder(actualType, expectedType);
|
||||||
|
return JetTypeChecker.DEFAULT.isSubtypeOf(functionType, expectedType);
|
||||||
}
|
}
|
||||||
return JetTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType);
|
return JetTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isFunctionOrErrorType(@NotNull JetType supertype) {
|
|
||||||
return KotlinBuiltIns.isFunctionOrExtensionFunctionType(supertype) || supertype.isError();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkTypesWithNoCallee(@NotNull CallResolutionContext<?> context) {
|
public void checkTypesWithNoCallee(@NotNull CallResolutionContext<?> context) {
|
||||||
checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
|
checkTypesWithNoCallee(context, SHAPE_FUNCTION_ARGUMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkTypesWithNoCallee(@NotNull CallResolutionContext<?> context, @NotNull ResolveArgumentsMode resolveFunctionArgumentBodies) {
|
public void checkTypesWithNoCallee(
|
||||||
|
@NotNull CallResolutionContext<?> context,
|
||||||
|
@NotNull ResolveArgumentsMode resolveFunctionArgumentBodies
|
||||||
|
) {
|
||||||
if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return;
|
if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return;
|
||||||
|
|
||||||
for (ValueArgument valueArgument : context.call.getValueArguments()) {
|
for (ValueArgument valueArgument : context.call.getValueArguments()) {
|
||||||
@@ -222,27 +225,31 @@ public class ArgumentTypeResolver {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JetType getShapeTypeOfFunctionLiteral(
|
public JetType getShapeTypeOfFunctionLiteral(
|
||||||
@NotNull JetFunction functionLiteral,
|
@NotNull JetFunction function,
|
||||||
@NotNull JetScope scope,
|
@NotNull JetScope scope,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
boolean expectedTypeIsUnknown
|
boolean expectedTypeIsUnknown
|
||||||
) {
|
) {
|
||||||
if (functionLiteral.getValueParameterList() == null) {
|
boolean isFunctionLiteral = function instanceof JetFunctionLiteral;
|
||||||
return expectedTypeIsUnknown ? PLACEHOLDER_FUNCTION_TYPE : builtIns.getFunctionType(
|
if (function.getValueParameterList() == null && isFunctionLiteral) {
|
||||||
Annotations.EMPTY, null, Collections.<JetType>emptyList(), DONT_CARE);
|
return expectedTypeIsUnknown
|
||||||
|
? ErrorUtils.createFunctionPlaceholderType(Collections.<JetType>emptyList())
|
||||||
|
: builtIns.getFunctionType(Annotations.EMPTY, null, Collections.<JetType>emptyList(), DONT_CARE);
|
||||||
}
|
}
|
||||||
List<JetParameter> valueParameters = functionLiteral.getValueParameters();
|
List<JetParameter> valueParameters = function.getValueParameters();
|
||||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(
|
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(
|
||||||
trace, "trace to resolve function literal parameter types");
|
trace, "trace to resolve function literal parameter types");
|
||||||
List<JetType> parameterTypes = Lists.newArrayList();
|
List<JetType> parameterTypes = Lists.newArrayList();
|
||||||
for (JetParameter parameter : valueParameters) {
|
for (JetParameter parameter : valueParameters) {
|
||||||
parameterTypes.add(resolveTypeRefWithDefault(parameter.getTypeReference(), scope, temporaryTrace, DONT_CARE));
|
parameterTypes.add(resolveTypeRefWithDefault(parameter.getTypeReference(), scope, temporaryTrace, DONT_CARE));
|
||||||
}
|
}
|
||||||
JetType returnType = resolveTypeRefWithDefault(functionLiteral.getTypeReference(), scope, temporaryTrace, DONT_CARE);
|
JetType returnType = resolveTypeRefWithDefault(function.getTypeReference(), scope, temporaryTrace, DONT_CARE);
|
||||||
assert returnType != null;
|
assert returnType != null;
|
||||||
JetType receiverType = resolveTypeRefWithDefault(functionLiteral.getReceiverTypeReference(), scope, temporaryTrace, null);
|
JetType receiverType = resolveTypeRefWithDefault(function.getReceiverTypeReference(), scope, temporaryTrace, null);
|
||||||
return builtIns.getFunctionType(Annotations.EMPTY, receiverType, parameterTypes,
|
|
||||||
returnType);
|
return expectedTypeIsUnknown && isFunctionLiteral
|
||||||
|
? ErrorUtils.createFunctionPlaceholderType(parameterTypes)
|
||||||
|
: builtIns.getFunctionType(Annotations.EMPTY, receiverType, parameterTypes, returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumen
|
|||||||
import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
|
import static org.jetbrains.kotlin.resolve.calls.CallResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.CallTransformer.CallForImplicitInvoke;
|
import static org.jetbrains.kotlin.resolve.calls.CallTransformer.CallForImplicitInvoke;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
|
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.inference.InferencePackage.createCorrespondingExtensionFunctionTypeIfNecessary;
|
|
||||||
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION;
|
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION;
|
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.*;
|
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.*;
|
||||||
@@ -534,18 +533,18 @@ public class CandidateResolver {
|
|||||||
|
|
||||||
ArgumentMatchStatus matchStatus = ArgumentMatchStatus.SUCCESS;
|
ArgumentMatchStatus matchStatus = ArgumentMatchStatus.SUCCESS;
|
||||||
JetType resultingType = type;
|
JetType resultingType = type;
|
||||||
if (type == null || (type.isError() && type != PLACEHOLDER_FUNCTION_TYPE)) {
|
if (type == null || (type.isError() && !ErrorUtils.isFunctionPlaceholder(type))) {
|
||||||
matchStatus = ArgumentMatchStatus.ARGUMENT_HAS_NO_TYPE;
|
matchStatus = ArgumentMatchStatus.ARGUMENT_HAS_NO_TYPE;
|
||||||
}
|
}
|
||||||
else if (!noExpectedType(expectedType)) {
|
else if (!noExpectedType(expectedType)) {
|
||||||
if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
|
if (!ArgumentTypeResolver.isSubtypeOfForArgumentType(type, expectedType)) {
|
||||||
JetType morePreciseType = makeMorePreciseType(type, expression, newContext);
|
JetType smartCast = smartCastValueArgumentTypeIfPossible(expression, newContext.expectedType, type, newContext);
|
||||||
if (morePreciseType == null) {
|
if (smartCast == null) {
|
||||||
resultStatus = OTHER_ERROR;
|
resultStatus = OTHER_ERROR;
|
||||||
matchStatus = ArgumentMatchStatus.TYPE_MISMATCH;
|
matchStatus = ArgumentMatchStatus.TYPE_MISMATCH;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resultingType = morePreciseType;
|
resultingType = smartCast;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ErrorUtils.containsUninferredParameter(expectedType)) {
|
else if (ErrorUtils.containsUninferredParameter(expectedType)) {
|
||||||
@@ -559,27 +558,6 @@ public class CandidateResolver {
|
|||||||
return new ValueArgumentsCheckingResult(resultStatus, argumentTypes);
|
return new ValueArgumentsCheckingResult(resultStatus, argumentTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static <C extends CallResolutionContext<C>> JetType makeMorePreciseType(
|
|
||||||
@NotNull JetType type,
|
|
||||||
@NotNull JetExpression expression,
|
|
||||||
@NotNull CallResolutionContext<C> context
|
|
||||||
) {
|
|
||||||
JetType smartCastType = smartCastValueArgumentTypeIfPossible(expression, context.expectedType, type, context);
|
|
||||||
if (smartCastType != null) {
|
|
||||||
return smartCastType;
|
|
||||||
}
|
|
||||||
// function literal without declaring receiver type { x -> ... }
|
|
||||||
// can be considered as extension function if one is expected
|
|
||||||
if (ArgumentTypeResolver.isFunctionLiteralArgument(expression, context)) {
|
|
||||||
JetType extensionFunctionType = createCorrespondingExtensionFunctionTypeIfNecessary(type, context.expectedType);
|
|
||||||
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(extensionFunctionType, context.expectedType)) {
|
|
||||||
return extensionFunctionType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static JetType smartCastValueArgumentTypeIfPossible(
|
private static JetType smartCastValueArgumentTypeIfPossible(
|
||||||
@NotNull JetExpression expression,
|
@NotNull JetExpression expression,
|
||||||
|
|||||||
@@ -382,8 +382,8 @@ public class JetTypeCheckerTest extends JetLiteFixture {
|
|||||||
public void testBlocks() throws Exception {
|
public void testBlocks() throws Exception {
|
||||||
assertType("if (1) {val a = 1; a} else {null}", "Int?");
|
assertType("if (1) {val a = 1; a} else {null}", "Int?");
|
||||||
assertType("if (1) {() -> val a = 1; a} else {() -> null}", "Function0<Int?>");
|
assertType("if (1) {() -> val a = 1; a} else {() -> null}", "Function0<Int?>");
|
||||||
assertType("if (1) {() -> val a = 1; a; var b : Boolean; b} else null", "Function0<Boolean>?");
|
assertType("if (1) (fun (): Boolean { val a = 1; a; var b : Boolean; return b }) else null", "Function0<Boolean>?");
|
||||||
assertType("if (1) {() -> val a = 1; a; var b = a; b} else null", "Function0<Int>?");
|
assertType("if (1) (fun (): Int { val a = 1; a; var b = a; return b }) else null", "Function0<Int>?");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNew() throws Exception {
|
public void testNew() throws Exception {
|
||||||
|
|||||||
+35
-42
@@ -24,8 +24,10 @@ import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
|||||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
|
import org.jetbrains.kotlin.types.ErrorUtils.FunctionPlaceholderTypeConstructor
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind
|
||||||
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
|
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
|
||||||
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedureCallbacks
|
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedureCallbacks
|
||||||
@@ -42,6 +44,7 @@ import org.jetbrains.kotlin.types.getCustomTypeVariable
|
|||||||
import org.jetbrains.kotlin.types.isFlexible
|
import org.jetbrains.kotlin.types.isFlexible
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
|
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitution
|
import org.jetbrains.kotlin.types.TypeSubstitution
|
||||||
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||||
|
|
||||||
public class ConstraintSystemImpl : ConstraintSystem {
|
public class ConstraintSystemImpl : ConstraintSystem {
|
||||||
|
|
||||||
@@ -234,7 +237,7 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == null || (type.isError() && type != TypeUtils.PLACEHOLDER_FUNCTION_TYPE)) {
|
if (type == null || (type.isError() && !ErrorUtils.isFunctionPlaceholder(type))) {
|
||||||
errors.add(ErrorInConstrainingType(constraintPosition))
|
errors.add(ErrorInConstrainingType(constraintPosition))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -251,30 +254,22 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
if (isErrorOrSpecialType(subType, constraintPosition) || isErrorOrSpecialType(superType, constraintPosition)) return
|
if (isErrorOrSpecialType(subType, constraintPosition) || isErrorOrSpecialType(superType, constraintPosition)) return
|
||||||
if (subType == null || superType == null) return
|
if (subType == null || superType == null) return
|
||||||
|
|
||||||
assert(superType != TypeUtils.PLACEHOLDER_FUNCTION_TYPE) {
|
assert(!ErrorUtils.isFunctionPlaceholder(superType)) {
|
||||||
"The type for " + constraintPosition + " shouldn't be a placeholder for function type"
|
"The type for " + constraintPosition + " shouldn't be a placeholder for function type"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subType == TypeUtils.PLACEHOLDER_FUNCTION_TYPE) {
|
// function literal { x -> ... } goes without declaring receiver type
|
||||||
if (!KotlinBuiltIns.isFunctionOrExtensionFunctionType(superType)) {
|
// and can be considered as extension function if one is expected
|
||||||
if (isMyTypeVariable(superType)) {
|
val newSubType = if (constraintKind == SUB_TYPE && ErrorUtils.isFunctionPlaceholder(subType)) {
|
||||||
// a constraint binds type parameter and any function type, so there is no new info and no error
|
if (isMyTypeVariable(superType)) {
|
||||||
return
|
// the constraint binds type parameter and a function type,
|
||||||
}
|
// we don't add it without knowing whether it's a function type or an extension function type
|
||||||
errors.add(TypeConstructorMismatch(constraintPosition))
|
return
|
||||||
}
|
}
|
||||||
return
|
createCorrespondingFunctionTypeForFunctionPlaceholder(subType, superType)
|
||||||
}
|
|
||||||
|
|
||||||
// todo temporary hack
|
|
||||||
// function literal without declaring receiver type { x -> ... }
|
|
||||||
// can be considered as extension function if one is expected
|
|
||||||
// (special type constructor for function/ extension function should be introduced like PLACEHOLDER_FUNCTION_TYPE)
|
|
||||||
val newSubType = if (constraintKind == SUB_TYPE) {
|
|
||||||
createCorrespondingExtensionFunctionTypeIfNecessary(subType, superType)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
subType : JetType
|
subType
|
||||||
}
|
}
|
||||||
|
|
||||||
fun simplifyConstraint(subType: JetType, superType: JetType) {
|
fun simplifyConstraint(subType: JetType, superType: JetType) {
|
||||||
@@ -422,31 +417,29 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
override fun getCurrentSubstitutor() = replaceUninferredBy(TypeUtils.DONT_CARE).setApproximateCapturedTypes()
|
override fun getCurrentSubstitutor() = replaceUninferredBy(TypeUtils.DONT_CARE).setApproximateCapturedTypes()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createCorrespondingExtensionFunctionTypeIfNecessary(functionType: JetType, expectedType: JetType): JetType {
|
fun createCorrespondingFunctionTypeForFunctionPlaceholder(
|
||||||
if (KotlinBuiltIns.isFunctionType(functionType) && KotlinBuiltIns.isExtensionFunctionType(expectedType)) {
|
functionPlaceholder: JetType,
|
||||||
return createCorrespondingExtensionFunctionType(functionType, DONT_CARE)
|
expectedType: JetType
|
||||||
|
): JetType {
|
||||||
|
assert(ErrorUtils.isFunctionPlaceholder(functionPlaceholder)) { "Function placeholder type expected: $functionPlaceholder" }
|
||||||
|
val functionPlaceholderTypeConstructor = functionPlaceholder.getConstructor() as FunctionPlaceholderTypeConstructor
|
||||||
|
val declaredArgumentTypes = functionPlaceholderTypeConstructor.getArgumentTypes()
|
||||||
|
|
||||||
|
val isExtension = KotlinBuiltIns.isExtensionFunctionType(expectedType)
|
||||||
|
val newArgumentTypes = if (declaredArgumentTypes.isEmpty()) {
|
||||||
|
val typeParamSize = expectedType.getConstructor().getParameters().size()
|
||||||
|
// the first parameter is receiver (if present), the last one is return type,
|
||||||
|
// the remaining are function arguments
|
||||||
|
val functionArgumentsSize = if (isExtension) typeParamSize - 2 else typeParamSize - 1
|
||||||
|
val result = arrayListOf<JetType>()
|
||||||
|
(1..functionArgumentsSize).forEach { result.add(DONT_CARE) }
|
||||||
|
result
|
||||||
}
|
}
|
||||||
return functionType
|
else {
|
||||||
}
|
declaredArgumentTypes
|
||||||
|
|
||||||
private fun createCorrespondingExtensionFunctionType(functionType: JetType, receiverType: JetType): JetType {
|
|
||||||
assert(KotlinBuiltIns.isFunctionType(functionType))
|
|
||||||
|
|
||||||
val typeArguments = functionType.getArguments()
|
|
||||||
assert(!typeArguments.isEmpty())
|
|
||||||
|
|
||||||
val arguments = ArrayList<JetType>()
|
|
||||||
// excluding the last type argument of the function type, which is the return type
|
|
||||||
var index = 0
|
|
||||||
val lastIndex = typeArguments.size() - 1
|
|
||||||
for (typeArgument in typeArguments) {
|
|
||||||
if (index < lastIndex) {
|
|
||||||
arguments.add(typeArgument.getType())
|
|
||||||
}
|
|
||||||
index++
|
|
||||||
}
|
}
|
||||||
val returnType = typeArguments.get(lastIndex).getType()
|
val receiverType = if (isExtension) DONT_CARE else null
|
||||||
return KotlinBuiltIns.getInstance().getFunctionType(functionType.getAnnotations(), receiverType, arguments, returnType)
|
return KotlinBuiltIns.getInstance().getFunctionType(Annotations.EMPTY, receiverType, newArgumentTypes, DONT_CARE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TypeSubstitutor.setApproximateCapturedTypes(): TypeSubstitutor {
|
private fun TypeSubstitutor.setApproximateCapturedTypes(): TypeSubstitutor {
|
||||||
|
|||||||
@@ -496,7 +496,7 @@ public class ErrorUtils {
|
|||||||
private final TypeParameterDescriptor typeParameterDescriptor;
|
private final TypeParameterDescriptor typeParameterDescriptor;
|
||||||
private final TypeConstructor errorTypeConstructor;
|
private final TypeConstructor errorTypeConstructor;
|
||||||
|
|
||||||
public UninferredParameterTypeConstructor(@NotNull TypeParameterDescriptor descriptor) {
|
private UninferredParameterTypeConstructor(@NotNull TypeParameterDescriptor descriptor) {
|
||||||
typeParameterDescriptor = descriptor;
|
typeParameterDescriptor = descriptor;
|
||||||
errorTypeConstructor = createErrorTypeConstructorWithCustomDebugName("CANT_INFER_TYPE_PARAMETER: " + descriptor.getName());
|
errorTypeConstructor = createErrorTypeConstructorWithCustomDebugName("CANT_INFER_TYPE_PARAMETER: " + descriptor.getName());
|
||||||
}
|
}
|
||||||
@@ -541,5 +541,70 @@ public class ErrorUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isFunctionPlaceholder(@Nullable JetType type) {
|
||||||
|
return type != null && type.getConstructor() instanceof FunctionPlaceholderTypeConstructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JetType createFunctionPlaceholderType(@NotNull List<JetType> argumentTypes) {
|
||||||
|
return new ErrorTypeImpl(
|
||||||
|
new FunctionPlaceholderTypeConstructor(argumentTypes),
|
||||||
|
createErrorScope("Scope for function placeholder type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FunctionPlaceholderTypeConstructor implements TypeConstructor {
|
||||||
|
private final TypeConstructor errorTypeConstructor;
|
||||||
|
private final List<JetType> argumentTypes;
|
||||||
|
|
||||||
|
private FunctionPlaceholderTypeConstructor(@NotNull List<JetType> argumentTypes) {
|
||||||
|
errorTypeConstructor = createErrorTypeConstructorWithCustomDebugName("PLACEHOLDER_FUNCTION_TYPE" + argumentTypes);
|
||||||
|
this.argumentTypes = argumentTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public List<JetType> getArgumentTypes() {
|
||||||
|
return argumentTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<TypeParameterDescriptor> getParameters() {
|
||||||
|
return errorTypeConstructor.getParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Collection<JetType> getSupertypes() {
|
||||||
|
return errorTypeConstructor.getSupertypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFinal() {
|
||||||
|
return errorTypeConstructor.isFinal();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDenotable() {
|
||||||
|
return errorTypeConstructor.isDenotable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ClassifierDescriptor getDeclarationDescriptor() {
|
||||||
|
return errorTypeConstructor.getDeclarationDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Annotations getAnnotations() {
|
||||||
|
return errorTypeConstructor.getAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return errorTypeConstructor.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ErrorUtils() {}
|
private ErrorUtils() {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user