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,
ConstraintPosition.EXPECTED_TYPE_POSITION);
TypeSubstitutor substituteDontCare = ConstraintSystemWithPriorities
.makeConstantSubstitutor(resolvedCall.getCandidateDescriptor().getTypeParameters(), ConstraintSystemImpl.DONT_CARE);
// constraints for function literals
// Value parameters
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> 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;
}
@@ -64,6 +64,11 @@ public interface ConstraintSystem {
*/
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/>
*
@@ -133,4 +138,6 @@ public interface ConstraintSystem {
*/
@NotNull
TypeSubstitutor getCurrentSubstitutor();
ConstraintSystem copy();
}
@@ -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<TypeParameterDescriptor, TypeParameterDescriptor> 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()) {
@@ -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