From a4bb47a73ff1be2fc696710a262f73e44a7eda6e Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Fri, 20 Jul 2012 16:27:47 +0400 Subject: [PATCH] type inference with functional literal params changed if there are function literals without declared parameter types, try adding constraint with current substituted result first (known type parameters), if there is error, try adding constraint with 'dont_care' substitution --- .../jet/lang/resolve/calls/CallResolver.java | 14 ++++++++++++-- .../calls/inference/ConstraintSystem.java | 7 +++++++ .../calls/inference/ConstraintSystemImpl.java | 19 ++++++++++++++++--- .../inference/inferInFunctionLiterals.kt | 12 ++++++++++++ 4 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/inferInFunctionLiterals.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index baa2e099bc0..75fc8857b2f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -347,6 +347,9 @@ public class CallResolver { constraintSystem.addSubtypingConstraint(descriptor.getReturnType(), context.expectedType, ConstraintPosition.EXPECTED_TYPE_POSITION); + TypeSubstitutor substituteDontCare = ConstraintSystemWithPriorities + .makeConstantSubstitutor(resolvedCall.getCandidateDescriptor().getTypeParameters(), ConstraintSystemImpl.DONT_CARE); + // constraints for function literals // Value parameters for (Map.Entry entry : resolvedCall.getValueArguments().entrySet()) { @@ -356,8 +359,15 @@ public class CallResolver { for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) { if (!JetPsiUtil.isFunctionLiteralWithoutDeclaredParameterTypes(valueArgument.getArgumentExpression())) continue; + ConstraintSystem systemWithCurrentSubstitution = constraintSystem.copy(); addConstraintForValueArgument(valueArgument, valueParameterDescriptor, constraintSystem.getCurrentSubstitutor(), - constraintSystem, context); + systemWithCurrentSubstitution, context); + if (systemWithCurrentSubstitution.hasContradiction() || systemWithCurrentSubstitution.hasErrorInConstrainingTypes()) { + addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintSystem, context); + } + else { + constraintSystem = systemWithCurrentSubstitution; + } } } @@ -753,7 +763,7 @@ public class CallResolver { // Solution - if (!constraintsSystem.hasTypeConstructorMismatch() && !constraintsSystem.hasConflictingConstraints()) { //no contradiction + if (!constraintsSystem.hasContradiction()) { candidateCall.setHasUnknownTypeParameters(true); return SUCCESS; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java index e369e975945..c18be884f4e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java @@ -64,6 +64,11 @@ public interface ConstraintSystem { */ boolean isSuccessful(); + /** + * Return true if constraint system has no contradiction (it can be not successful because of the lack of information for a type variable). + */ + boolean hasContradiction(); + /** * Returns true if type constraints for some type variable are contradicting.

* @@ -133,4 +138,6 @@ public interface ConstraintSystem { */ @NotNull TypeSubstitutor getCurrentSubstitutor(); + + ConstraintSystem copy(); } 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 0151e20b868..3ca82d3d353 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 @@ -105,6 +105,16 @@ public class ConstraintSystemImpl implements ConstraintSystem { typeParameterConstraints.put(typeVariable, new TypeConstraintsImpl(positionVariance)); } + @Override + @NotNull + public ConstraintSystem copy() { + ConstraintSystemImpl newConstraintSystem = new ConstraintSystemImpl(); + newConstraintSystem.typeParameterConstraints.putAll(typeParameterConstraints); + newConstraintSystem.errorConstraintPositions.addAll(errorConstraintPositions); + newConstraintSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes; + return newConstraintSystem; + } + @NotNull public ConstraintSystem replaceTypeVariables(@NotNull Function typeVariablesMap) { ConstraintSystemImpl newConstraintSystem = new ConstraintSystemImpl(); @@ -116,9 +126,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { assert newTypeParameter != null; newConstraintSystem.typeParameterConstraints.put(newTypeParameter, typeConstraints); } - for (ConstraintPosition constraintPosition : errorConstraintPositions) { - newConstraintSystem.errorConstraintPositions.add(constraintPosition); - } + newConstraintSystem.errorConstraintPositions.addAll(errorConstraintPositions); newConstraintSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes; return newConstraintSystem; } @@ -221,6 +229,11 @@ public class ConstraintSystemImpl implements ConstraintSystem { return !hasTypeConstructorMismatch() && !hasUnknownParameters() && !hasConflictingConstraints(); } + @Override + public boolean hasContradiction() { + return hasTypeConstructorMismatch() || hasConflictingConstraints(); + } + @Override public boolean hasConflictingConstraints() { for (TypeParameterDescriptor typeParameter : typeParameterConstraints.keySet()) { diff --git a/compiler/testData/diagnostics/tests/inference/inferInFunctionLiterals.kt b/compiler/testData/diagnostics/tests/inference/inferInFunctionLiterals.kt new file mode 100644 index 00000000000..a677ec097c3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/inferInFunctionLiterals.kt @@ -0,0 +1,12 @@ +package n + +//+JDK +import java.util.* + +fun expected(t: T, f: () -> T) : T = t + +fun test(arrayList: ArrayList, list: List) { + val t = expected(arrayList, { list.reverse() }) +} + +fun List.reverse() : List = this \ No newline at end of file