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
This commit is contained in:
Svetlana Isakova
2012-07-20 16:27:47 +04:00
parent a54b162e36
commit a4bb47a73f
4 changed files with 47 additions and 5 deletions
@@ -347,6 +347,9 @@ public class CallResolver {
constraintSystem.addSubtypingConstraint(descriptor.getReturnType(), context.expectedType, constraintSystem.addSubtypingConstraint(descriptor.getReturnType(), context.expectedType,
ConstraintPosition.EXPECTED_TYPE_POSITION); ConstraintPosition.EXPECTED_TYPE_POSITION);
TypeSubstitutor substituteDontCare = ConstraintSystemWithPriorities
.makeConstantSubstitutor(resolvedCall.getCandidateDescriptor().getTypeParameters(), ConstraintSystemImpl.DONT_CARE);
// constraints for function literals // constraints for function literals
// Value parameters // Value parameters
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) { for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
@@ -356,8 +359,15 @@ public class CallResolver {
for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) { for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
if (!JetPsiUtil.isFunctionLiteralWithoutDeclaredParameterTypes(valueArgument.getArgumentExpression())) continue; if (!JetPsiUtil.isFunctionLiteralWithoutDeclaredParameterTypes(valueArgument.getArgumentExpression())) continue;
ConstraintSystem systemWithCurrentSubstitution = constraintSystem.copy();
addConstraintForValueArgument(valueArgument, valueParameterDescriptor, constraintSystem.getCurrentSubstitutor(), 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 // Solution
if (!constraintsSystem.hasTypeConstructorMismatch() && !constraintsSystem.hasConflictingConstraints()) { //no contradiction if (!constraintsSystem.hasContradiction()) {
candidateCall.setHasUnknownTypeParameters(true); candidateCall.setHasUnknownTypeParameters(true);
return SUCCESS; return SUCCESS;
} }
@@ -64,6 +64,11 @@ public interface ConstraintSystem {
*/ */
boolean isSuccessful(); boolean isSuccessful();
/**
* Return <tt>true</tt> if constraint system has no contradiction (it can be not successful because of the lack of information for a type variable).
*/
boolean hasContradiction();
/** /**
* Returns <tt>true</tt> if type constraints for some type variable are contradicting. <p/> * Returns <tt>true</tt> if type constraints for some type variable are contradicting. <p/>
* *
@@ -133,4 +138,6 @@ public interface ConstraintSystem {
*/ */
@NotNull @NotNull
TypeSubstitutor getCurrentSubstitutor(); TypeSubstitutor getCurrentSubstitutor();
ConstraintSystem copy();
} }
@@ -105,6 +105,16 @@ public class ConstraintSystemImpl implements ConstraintSystem {
typeParameterConstraints.put(typeVariable, new TypeConstraintsImpl(positionVariance)); 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 @NotNull
public ConstraintSystem replaceTypeVariables(@NotNull Function<TypeParameterDescriptor, TypeParameterDescriptor> typeVariablesMap) { public ConstraintSystem replaceTypeVariables(@NotNull Function<TypeParameterDescriptor, TypeParameterDescriptor> typeVariablesMap) {
ConstraintSystemImpl newConstraintSystem = new ConstraintSystemImpl(); ConstraintSystemImpl newConstraintSystem = new ConstraintSystemImpl();
@@ -116,9 +126,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
assert newTypeParameter != null; assert newTypeParameter != null;
newConstraintSystem.typeParameterConstraints.put(newTypeParameter, typeConstraints); newConstraintSystem.typeParameterConstraints.put(newTypeParameter, typeConstraints);
} }
for (ConstraintPosition constraintPosition : errorConstraintPositions) { newConstraintSystem.errorConstraintPositions.addAll(errorConstraintPositions);
newConstraintSystem.errorConstraintPositions.add(constraintPosition);
}
newConstraintSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes; newConstraintSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes;
return newConstraintSystem; return newConstraintSystem;
} }
@@ -221,6 +229,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
return !hasTypeConstructorMismatch() && !hasUnknownParameters() && !hasConflictingConstraints(); return !hasTypeConstructorMismatch() && !hasUnknownParameters() && !hasConflictingConstraints();
} }
@Override
public boolean hasContradiction() {
return hasTypeConstructorMismatch() || hasConflictingConstraints();
}
@Override @Override
public boolean hasConflictingConstraints() { public boolean hasConflictingConstraints() {
for (TypeParameterDescriptor typeParameter : typeParameterConstraints.keySet()) { for (TypeParameterDescriptor typeParameter : typeParameterConstraints.keySet()) {
@@ -0,0 +1,12 @@
package n
//+JDK
import java.util.*
fun expected<T>(t: T, <!UNUSED_PARAMETER!>f<!>: () -> T) : T = t
fun test(arrayList: ArrayList<Int>, list: List<Int>) {
val <!UNUSED_VARIABLE!>t<!> = expected(arrayList, { list.reverse() })
}
fun <T> List<T>.reverse() : List<T> = this