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:
+41
-3
@@ -115,6 +115,16 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
return value;
|
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) {
|
private Set<JetType> getTypes(Set<TypeValue> lowerBounds) {
|
||||||
Set<JetType> types = Sets.newHashSet();
|
Set<JetType> types = Sets.newHashSet();
|
||||||
for (TypeValue lowerBound : lowerBounds) {
|
for (TypeValue lowerBound : lowerBounds) {
|
||||||
@@ -161,7 +171,28 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
private final JetTypeChecker.TypeCheckingProcedure constraintExpander = new JetTypeChecker.TypeCheckingProcedure(new JetTypeChecker.TypingConstraintBuilder() {
|
private final JetTypeChecker.TypeCheckingProcedure constraintExpander = new JetTypeChecker.TypeCheckingProcedure(new JetTypeChecker.TypingConstraintBuilder() {
|
||||||
@Override
|
@Override
|
||||||
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b) {
|
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
|
@Override
|
||||||
@@ -188,8 +219,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
public ConstraintSystemImpl() {
|
public ConstraintSystemImpl() {}
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private TypeValue getTypeValueFor(@NotNull JetType type) {
|
private TypeValue getTypeValueFor(@NotNull JetType type) {
|
||||||
@@ -226,6 +256,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void mergeUnknowns(@NotNull UnknownType a, @NotNull UnknownType b) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper) {
|
public void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper) {
|
||||||
TypeValue typeValueForLower = getTypeValueFor(lower);
|
TypeValue typeValueForLower = getTypeValueFor(lower);
|
||||||
@@ -289,6 +323,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
|||||||
check(knownType, solution);
|
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;
|
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"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user