From a24e448973bacbe63d07dd41a854c014f9f01a3e Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 9 Nov 2011 19:52:05 +0300 Subject: [PATCH] Simplistic type inference: KT-258 Support equality constraints in type inference KT-399 Type argument inference not implemented for CALL_EXPRESSION --- .../types/inference/ConstraintSystemImpl.java | 44 +++++++++++++++++-- .../full/regression/kt258.jet | 10 +++++ .../quick/TypeInference.jet | 18 ++++++++ .../quick/regressions/kt399.jet | 11 +++++ 4 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/checkerWithErrorTypes/full/regression/kt258.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/TypeInference.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/regressions/kt399.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java index fc7e403dd5b..a569a0beb1f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java @@ -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 getTypes(Set lowerBounds) { Set 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; } diff --git a/compiler/testData/checkerWithErrorTypes/full/regression/kt258.jet b/compiler/testData/checkerWithErrorTypes/full/regression/kt258.jet new file mode 100644 index 00000000000..257dfb12378 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/full/regression/kt258.jet @@ -0,0 +1,10 @@ +// KT-258 Support equality constraints in type inference + +import java.util.* + +fun test() { + val attributes : HashMap = HashMap() + attributes["href"] = "1" // inference fails, but it shouldn't +} + +fun java.util.Map.set(key : K, value : V) {}//= this.put(key, value) diff --git a/compiler/testData/checkerWithErrorTypes/quick/TypeInference.jet b/compiler/testData/checkerWithErrorTypes/quick/TypeInference.jet new file mode 100644 index 00000000000..ed8093219b0 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/TypeInference.jet @@ -0,0 +1,18 @@ +class C() { + fun foo() : T {} +} + +fun foo(c: C) {} +fun bar() : C {} + +fun main(args : Array) { + val a : C = C(); + val x : C = C() + val y : C = C() + val z : C<*> = C() + + val ba : C = bar(); + val bx : C = bar() + val by : C = bar() + val bz : C<*> = bar() +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/regressions/kt399.jet b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt399.jet new file mode 100644 index 00000000000..9fd7e71c393 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt399.jet @@ -0,0 +1,11 @@ +// KT-399 Type argument inference not implemented for CALL_EXPRESSION + +fun getSameTypeChecker(obj: T) : Function1 { + return { (a : Any) => a is T } +} + +fun box() : String { + if(getSameTypeChecker("lala")(10)) return "fail" + if(!getSameTypeChecker("mama")("lala")) return "fail" + return "OK" +} \ No newline at end of file