diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 6047be04453..e6db420488d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -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); 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 30f28d9ffa7..43cc85b9f99 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 @@ -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 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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemSolution.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemSolution.java index 9a78a00adda..40a2cbbb90e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemSolution.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemSolution.java @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/SolutionStatus.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/SolutionStatus.java new file mode 100644 index 00000000000..0fd5cd02517 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/SolutionStatus.java @@ -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(); +} diff --git a/compiler/testData/checkerWithErrorTypes/full/regression/kt385.109.441.jet b/compiler/testData/checkerWithErrorTypes/full/regression/kt385.109.441.jet new file mode 100644 index 00000000000..8af621372fd --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/full/regression/kt385.109.441.jet @@ -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 Iterator.foreach(operation: fun(element: T) : Unit) : Unit = while(hasNext) operation(next()) + +fun Iterator.foreach(operation: fun(index: Int, element: T) : Unit) : Unit { + var k = 0 + while(hasNext) + operation(k++, next()) +} + +fun Iterable.foreach(operation: fun(element: T) : Unit) : Unit = iterator() foreach operation + +fun Iterable.foreach(operation: fun(index: Int, element: T) : Unit) : Unit = iterator() foreach operation + +fun box() : String { + return generic_invoker( { () : String => "OK"} ) +} + +fun 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(body : fun() : T) : T = body() + +fun main(args : Array) { + + println(run { 1 }) +} \ No newline at end of file