KT-385 type inference does not work properly

KT-109 Good code is red: type arguments are not inferred
KT-441 Exception in type inference when multiple overloads accepting an integer literal are accessible
This commit is contained in:
Andrey Breslav
2011-11-10 20:55:12 +03:00
parent 1e3f2889a4
commit 839d986f44
5 changed files with 106 additions and 16 deletions
@@ -442,7 +442,7 @@ public class CallResolver {
}
ConstraintSystemSolution solution = constraintSystem.solve();
if (solution.isSuccessful()) {
if (solution.getStatus().isSuccessful()) {
D substitute = (D) candidate.substitute(solution.getSubstitutor());
assert substitute != null;
replaceValueParametersWithSubstitutedOnes(candidateCall, substitute);
@@ -269,8 +269,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) {
println(typeValueForLower + " :< " + typeValueForUpper);
typeValueForLower.getUpperBounds().add(typeValueForUpper);
typeValueForUpper.getLowerBounds().add(typeValueForLower);
if (typeValueForLower != typeValueForUpper) {
typeValueForLower.getUpperBounds().add(typeValueForUpper);
typeValueForUpper.getLowerBounds().add(typeValueForLower);
}
}
@Override
@@ -286,7 +288,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
KnownType knownBoundType = (KnownType) upperBound;
boolean ok = constraintExpander.run(jetType, knownBoundType.getType());
if (!ok) {
return new Solution(true);
return new Solution().registerError("Mismatch while expanding constraints");
}
}
}
@@ -314,7 +316,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
// Find inconsistencies
Solution solution = new Solution(false);
Solution solution = new Solution();
for (UnknownType unknownType : unknownTypes.values()) {
check(unknownType, solution);
@@ -337,20 +339,33 @@ public class ConstraintSystemImpl implements ConstraintSystem {
for (TypeValue upperBound : typeValue.getUpperBounds()) {
JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO
solution.registerError();
solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType);
println("Constraint violation: " + type + " :< " + boundingType);
}
}
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getValue().getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(boundingType, type)) {
solution.registerError();
solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type);
println("Constraint violation: " + boundingType + " :< " + type);
}
}
}
catch (LoopInTypeVariableConstraintsException e) {
solution.registerError();
println("-------------------------------------------------------------------");
for (Map.Entry<TypeParameterDescriptor, UnknownType> entry : unknownTypes.entrySet()) {
println("Unknown: " + entry.getKey());
UnknownType unknownType = entry.getValue();
println("Lower bounds: ");
for (TypeValue lowerBound : unknownType.getLowerBounds()) {
println(" " + lowerBound);
}
println("Upper bounds: ");
for (TypeValue lowerBound : unknownType.getUpperBounds()) {
println(" " + lowerBound);
}
}
solution.registerError("[TODO] Loop in constraints");
e.printStackTrace();
}
}
@@ -369,6 +384,25 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
}
private static class Error implements SolutionStatus {
private final String message;
private Error(String message) {
this.message = message;
}
@Override
public boolean isSuccessful() {
return false;
}
@Override
public String toString() {
return message;
}
}
public class Solution implements ConstraintSystemSolution {
private final TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(new TypeSubstitutor.TypeSubstitution() {
@Override
@@ -388,19 +422,22 @@ public class ConstraintSystemImpl implements ConstraintSystem {
return false;
}
});
private boolean failed;
public Solution(boolean failed) {
this.failed = failed;
private SolutionStatus status;
public Solution() {
this.status = SolutionStatus.SUCCESS;
}
private void registerError() {
failed = true;
private Solution registerError(String message) {
status = new Error(message);
return this;
}
@NotNull
@Override
public boolean isSuccessful() {
return !failed;
public SolutionStatus getStatus() {
return status;
}
@Override
@@ -409,6 +446,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
return value == null ? null : value.getType();
}
@NotNull
@Override
public TypeSubstitutor getSubstitutor() {
return typeSubstitutor;
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang.types.inference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.JetType;
@@ -9,8 +10,10 @@ import org.jetbrains.jet.lang.types.TypeSubstitutor;
* @author abreslav
*/
public interface ConstraintSystemSolution {
boolean isSuccessful();
@NotNull
SolutionStatus getStatus();
@NotNull
TypeSubstitutor getSubstitutor();
@Nullable
@@ -0,0 +1,15 @@
package org.jetbrains.jet.lang.types.inference;
/**
* @author abreslav
*/
public interface SolutionStatus {
SolutionStatus SUCCESS = new SolutionStatus() {
@Override
public boolean isSuccessful() {
return true;
}
};
boolean isSuccessful();
}
@@ -0,0 +1,34 @@
// KT-385 type inference does not work properly`
// KT-109 Good code is red: type arguments are not inferred
// KT-441 Exception in type inference when multiple overloads accepting an integer literal are accessible
import java.util.*
fun <T> Iterator<T>.foreach(operation: fun(element: T) : Unit) : Unit = while(hasNext) operation(next())
fun <T> Iterator<T>.foreach(operation: fun(index: Int, element: T) : Unit) : Unit {
var k = 0
while(hasNext)
operation(k++, next())
}
fun <T> Iterable<T>.foreach(operation: fun(element: T) : Unit) : Unit = iterator() foreach operation
fun <T> Iterable<T>.foreach(operation: fun(index: Int, element: T) : Unit) : Unit = iterator() foreach operation
fun box() : String {
return generic_invoker( { () : String => "OK"} )
}
fun <T> generic_invoker(gen : fun () : T) : T {
return gen()
}
fun println(message : Int) { System.out?.println(message) }
fun println(message : Long) { System.out?.println(message) }
inline fun run<T>(body : fun() : T) : T = body()
fun main(args : Array<String>) {
println(run { 1 })
}