diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java index 83b108e4f0b..3c0833fd099 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.lang.resolve.calls.inference; import com.google.common.base.Function; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; @@ -177,15 +178,29 @@ public class ConstraintSystemImpl implements ConstraintSystem { assert subjectType != TypeUtils.NO_EXPECTED_TYPE : "Subject type shouldn't be NO_EXPECTED_TYPE (in position " + constraintPosition + " )"; if (ErrorUtils.isErrorType(subjectType)) return; + DeclarationDescriptor subjectTypeDescriptor = subjectType.getConstructor().getDeclarationDescriptor(); + + KotlinBuiltIns kotlinBuiltIns = KotlinBuiltIns.getInstance(); if (constrainingType == PLACEHOLDER_FUNCTION_TYPE) { - if (!KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(subjectType)) { + if (!kotlinBuiltIns.isFunctionOrExtensionFunctionType(subjectType)) { + if (subjectTypeDescriptor instanceof TypeParameterDescriptor && typeParameterConstraints.get(subjectTypeDescriptor) != null) { + // a constraint binds type parameter and any function type, so there is no new info and no error + return; + } errorConstraintPositions.add(constraintPosition); } return; } + // 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) + if (constraintKind == SUB_TYPE && kotlinBuiltIns.isFunctionType(constrainingType) && kotlinBuiltIns.isExtensionFunctionType(subjectType)) { + constrainingType = createCorrespondingExtensionFunctionType(constrainingType, DONT_CARE); + } + DeclarationDescriptor constrainingTypeDescriptor = constrainingType.getConstructor().getDeclarationDescriptor(); - DeclarationDescriptor subjectTypeDescriptor = subjectType.getConstructor().getDeclarationDescriptor(); if (subjectTypeDescriptor instanceof TypeParameterDescriptor) { TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) subjectTypeDescriptor; @@ -204,7 +219,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { if (constrainingTypeDescriptor instanceof TypeParameterDescriptor) { assert typeParameterConstraints.get(constrainingTypeDescriptor) == null : "Constraining type contains type variable " + constrainingTypeDescriptor.getName(); } - if (constraintKind == SUB_TYPE && KotlinBuiltIns.getInstance().isNothingOrNullableNothing(constrainingType)) { + if (constraintKind == SUB_TYPE && kotlinBuiltIns.isNothingOrNullableNothing(constrainingType)) { // following constraints are always true: // 'Nothing' is a subtype of any type if (!constrainingType.isNullable()) return; @@ -217,7 +232,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { } switch (constraintKind) { case SUB_TYPE: { - if (KotlinBuiltIns.getInstance().isNothingOrNullableNothing(constrainingType)) break; + if (kotlinBuiltIns.isNothingOrNullableNothing(constrainingType)) break; JetType correspondingSupertype = TypeCheckingProcedure.findCorrespondingSupertype(constrainingType, subjectType); if (correspondingSupertype != null) { constrainingType = correspondingSupertype; @@ -225,7 +240,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { break; } case SUPER_TYPE: { - if (KotlinBuiltIns.getInstance().isNothingOrNullableNothing(subjectType)) break; + if (kotlinBuiltIns.isNothingOrNullableNothing(subjectType)) break; JetType correspondingSupertype = TypeCheckingProcedure.findCorrespondingSupertype(subjectType, constrainingType); if (correspondingSupertype != null) { subjectType = correspondingSupertype; @@ -388,4 +403,25 @@ public class ConstraintSystemImpl implements ConstraintSystem { public TypeSubstitutor getCurrentSubstitutor() { return currentSubstitutor; } + + @NotNull + public static JetType createCorrespondingExtensionFunctionType(@NotNull JetType functionType, @NotNull JetType receiverType) { + assert KotlinBuiltIns.getInstance().isFunctionType(functionType); + + List typeArguments = functionType.getArguments(); + assert !typeArguments.isEmpty(); + + List arguments = Lists.newArrayList(); + // excluding the last type argument of the function type, which is the return type + int index = 0; + int lastIndex = typeArguments.size() - 1; + for (TypeProjection typeArgument : typeArguments) { + if (index < lastIndex) { + arguments.add(typeArgument.getType()); + } + index++; + } + JetType returnType = typeArguments.get(lastIndex).getType(); + return KotlinBuiltIns.getInstance().getFunctionType(functionType.getAnnotations(), receiverType, arguments, returnType); + } } diff --git a/compiler/testData/diagnostics/tests/inference/kt3184.kt b/compiler/testData/diagnostics/tests/inference/kt3184.kt new file mode 100644 index 00000000000..3c801f7d6b8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/kt3184.kt @@ -0,0 +1,26 @@ +//KT-3184 Type inference seems partially broken +package a + +import java.util.HashMap + +private fun test(value: T, extf: String.(value: T)->Unit) { + "".extf(value) +} + +fun main(args: Array) { + test(1, {(value) -> println(value)}) +} + +fun tests() { + val dict = HashMap Unit>() + dict["0"] = { str -> println(str) } + dict["1"] = { println(it) } + + dict.set("1", { println(it) }) + dict["1"] = { r -> println(r) } +} + +// from standard library +fun MutableMap.set(key : K, value : V) : V? = this.put(key, value) + +fun println(message : Any?) = System.out.println(message) \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index ec43d4b1b34..8fa2ff57d6e 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -2036,6 +2036,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/inference/kt1293.kt"); } + @TestMetadata("kt3184.kt") + public void testKt3184() throws Exception { + doTest("compiler/testData/diagnostics/tests/inference/kt3184.kt"); + } + @TestMetadata("kt619.kt") public void testKt619() throws Exception { doTest("compiler/testData/diagnostics/tests/inference/kt619.kt");