Simplistic type inference:

KT-258 Support equality constraints in type inference
KT-399 Type argument inference not implemented for CALL_EXPRESSION
This commit is contained in:
Andrey Breslav
2011-11-09 19:52:05 +03:00
parent 787d3aa450
commit a24e448973
4 changed files with 80 additions and 3 deletions
@@ -115,6 +115,16 @@ public class ConstraintSystemImpl implements ConstraintSystem {
return value;
}
public boolean setValue(@NotNull KnownType value) {
if (this.value != null) {
// If we have already assigned a value to this unknown,
// it is a conflict to assign another one, unless this new one is equal to the previous
return TypeUtils.equalTypes(this.value.getType(), value.getType());
}
this.value = value;
return true;
}
private Set<JetType> getTypes(Set<TypeValue> lowerBounds) {
Set<JetType> types = Sets.newHashSet();
for (TypeValue lowerBound : lowerBounds) {
@@ -161,7 +171,28 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private final JetTypeChecker.TypeCheckingProcedure constraintExpander = new JetTypeChecker.TypeCheckingProcedure(new JetTypeChecker.TypingConstraintBuilder() {
@Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b) {
return TypeUtils.equalTypes(a, b);
TypeValue aValue = getTypeValueFor(a);
TypeValue bValue = getTypeValueFor(b);
if (aValue instanceof UnknownType) {
UnknownType aUnknown = (UnknownType) aValue;
if (bValue instanceof UnknownType) {
UnknownType bUnknown = (UnknownType) bValue;
mergeUnknowns(aUnknown, bUnknown);
}
else {
if (!aUnknown.setValue((KnownType) bValue)) return false;
}
}
else if (bValue instanceof UnknownType) {
UnknownType bUnknown = (UnknownType) bValue;
if (!bUnknown.setValue((KnownType) aValue)) return false;
}
else {
return TypeUtils.equalTypes(a, b);
}
return true;
}
@Override
@@ -188,8 +219,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
});
public ConstraintSystemImpl() {
}
public ConstraintSystemImpl() {}
@NotNull
private TypeValue getTypeValueFor(@NotNull JetType type) {
@@ -226,6 +256,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
return unknownType;
}
private void mergeUnknowns(@NotNull UnknownType a, @NotNull UnknownType b) {
}
@Override
public void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper) {
TypeValue typeValueForLower = getTypeValueFor(lower);
@@ -289,6 +323,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
check(knownType, solution);
}
// TODO : check that all bounds are respected by solutions:
// we have set some of them from equality constraints with known types
// and thus the bounds may be violated if some of the constraints conflict
return solution;
}
@@ -0,0 +1,10 @@
// KT-258 Support equality constraints in type inference
import java.util.*
fun test() {
val attributes : HashMap<String, String> = HashMap()
attributes["href"] = "1" // inference fails, but it shouldn't
}
fun <K, V> java.util.Map<K, V>.set(key : K, value : V) {}//= this.put(key, value)
@@ -0,0 +1,18 @@
class C<T>() {
fun foo() : T <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>{}<!>
}
fun foo(c: C<Int>) {}
fun bar<T>() : C<T> <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>{}<!>
fun main(args : Array<String>) {
val a : C<Int> = C();
val x : C<in String> = C()
val y : C<out String> = C()
val z : C<*> = C()
val ba : C<Int> = bar();
val bx : C<in String> = bar()
val by : C<out String> = bar()
val bz : C<*> = bar()
}
@@ -0,0 +1,11 @@
// KT-399 Type argument inference not implemented for CALL_EXPRESSION
fun <T> getSameTypeChecker(obj: T) : Function1<Any,Boolean> {
return { (a : Any) => a is T }
}
fun box() : String {
if(getSameTypeChecker<String>("lala")(10)) return "fail"
if(!getSameTypeChecker<String>("mama")("lala")) return "fail"
return "OK"
}