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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-3
@@ -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
|
||||||
Reference in New Issue
Block a user