From ce399df305cca62a75a0fcd226d0cb6c5e4176c5 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Tue, 17 Sep 2013 13:14:18 +0400 Subject: [PATCH] removed ConstraintSystemWIthPriorities --- .../lang/resolve/calls/CandidateResolver.java | 4 +- .../calls/inference/ConstraintPosition.java | 1 + .../ConstraintResolutionListener.java | 54 -- .../inference/ConstraintSystemSolution.java | 34 - .../ConstraintSystemWithPriorities.java | 590 ------------------ .../calls/inference/ConstraintsUtil.java | 23 + .../DebugConstraintResolutionListener.java | 98 --- .../PrintingConstraintResolutionListener.java | 72 --- .../calls/inference/SolutionStatus.java | 33 - .../calls/results/ResolutionDebugInfo.java | 3 - .../jetbrains/jet/lang/types/TypeUtils.java | 12 +- 11 files changed, 29 insertions(+), 895 deletions(-) delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemSolution.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SolutionStatus.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index 690a1047d33..41ea9453088 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -40,8 +40,6 @@ import org.jetbrains.jet.lang.resolve.calls.results.ResolutionStatus; import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask; import org.jetbrains.jet.lang.resolve.calls.tasks.TaskPrioritizer; import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor; -import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; -import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.*; @@ -537,7 +535,7 @@ public class CandidateResolver { constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences } - TypeSubstitutor substituteDontCare = ConstraintSystemWithPriorities + TypeSubstitutor substituteDontCare = ConstraintsUtil .makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE); // Value parameters diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.java index d2343cb0e7b..e36aa2d30b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.java @@ -25,6 +25,7 @@ public class ConstraintPosition { public static final ConstraintPosition EXPECTED_TYPE_POSITION = new ConstraintPosition("EXPECTED_TYPE_POSITION"); public static final ConstraintPosition BOUND_CONSTRAINT_POSITION = new ConstraintPosition("BOUND_CONSTRAINT_POSITION"); public static final ConstraintPosition FROM_COMPLETER = new ConstraintPosition("FROM_COMPLETER"); + public static final ConstraintPosition SPECIAL = new ConstraintPosition("SPECIAL"); private static final Map valueParameterPositions = Maps.newHashMap(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java deleted file mode 100644 index e74f7a0f3c9..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.resolve.calls.inference; - -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.types.JetType; - -import java.util.Set; - -public interface ConstraintResolutionListener { - - public static final ConstraintResolutionListener DO_NOTHING = new ConstraintResolutionListener() { - @Override - public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue) { - } - - @Override - public void constraintsForKnownType(JetType type, BoundsOwner typeValue) { - } - - @Override - public void done(ConstraintSystemSolution solution, Set typeParameterDescriptors) { - } - - @Override - public void log(Object... messageFragments) { - } - - @Override - public void error(Object... messageFragments) { - } - }; - - void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue); - void constraintsForKnownType(JetType type, BoundsOwner typeValue); - void done(ConstraintSystemSolution solution, Set typeParameterDescriptors); - - void log(Object... messageFragments); - void error(Object... messageFragments); -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemSolution.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemSolution.java deleted file mode 100644 index 3e452971dbd..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemSolution.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.resolve.calls.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; -import org.jetbrains.jet.lang.types.TypeSubstitutor; - -public interface ConstraintSystemSolution { - @NotNull - SolutionStatus getStatus(); - - @NotNull - TypeSubstitutor getSubstitutor(); - - @Nullable - JetType getValue(TypeParameterDescriptor typeParameterDescriptor); -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java deleted file mode 100644 index 60ac29135a8..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.resolve.calls.inference; - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.types.*; -import org.jetbrains.jet.lang.types.checker.JetTypeChecker; -import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure; -import org.jetbrains.jet.lang.types.checker.TypingConstraints; - -import java.util.*; - -import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.PARAMETER_BOUND; - -public class ConstraintSystemWithPriorities { - - public static final Comparator SUBTYPING_CONSTRAINT_ORDER = new Comparator() { - @Override - public int compare(SubtypingConstraint o1, SubtypingConstraint o2) { - return o1.getType().compareTo(o2.getType()); - } - }; - - public static TypeSubstitutor makeConstantSubstitutor(Collection typeParameterDescriptors, JetType type) { - final Set constructors = Sets.newHashSet(); - for (TypeParameterDescriptor typeParameterDescriptor : typeParameterDescriptors) { - constructors.add(typeParameterDescriptor.getTypeConstructor()); - } - final TypeProjection projection = new TypeProjection(type); - - return TypeSubstitutor.create(new TypeSubstitution() { - @Override - public TypeProjection get(TypeConstructor key) { - if (constructors.contains(key)) { - return projection; - } - return null; - } - - @Override - public boolean isEmpty() { - return false; - } - }); - } - - private static class LoopInTypeVariableConstraintsException extends RuntimeException { - public LoopInTypeVariableConstraintsException() {} - } - - //========================================================================================================================================================== - - private final Map knownTypes = Maps.newLinkedHashMap(); // linked - for easier debugging - private final Map unknownTypes = Maps.newLinkedHashMap(); // linked - for easier debugging - private final Set unsolvedUnknowns = Sets.newLinkedHashSet(); // linked - for easier debugging - private final PriorityQueue constraintQueue = new PriorityQueue(10, SUBTYPING_CONSTRAINT_ORDER); - - private final JetTypeChecker typeChecker = JetTypeChecker.INSTANCE; - private final TypeCheckingProcedure constraintExpander; - private final ConstraintResolutionListener listener; - - public ConstraintSystemWithPriorities(ConstraintResolutionListener listener) { - this.listener = listener; - this.constraintExpander = createConstraintExpander(); - } - - @NotNull - private TypeValue getTypeValueFor(@NotNull JetType type) { - DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); - if (declarationDescriptor instanceof TypeParameterDescriptor) { - TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor; - // Checking that this is not a T?, but exactly T - if (typeParameterDescriptor.getDefaultType().isNullable() == type.isNullable()) { - TypeValue unknownType = unknownTypes.get(typeParameterDescriptor); - if (unknownType != null) { - return unknownType; - } - } - } - - TypeValue typeValue = knownTypes.get(type); - if (typeValue == null) { - typeValue = new TypeValue(type); - knownTypes.put(type, typeValue); - } - return typeValue; - } - - public void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance) { - assert !unknownTypes.containsKey(typeParameterDescriptor); - TypeValue typeValue = new TypeValue(typeParameterDescriptor, positionVariance); - unknownTypes.put(typeParameterDescriptor, typeValue); - unsolvedUnknowns.add(typeValue); - } - - @NotNull - private TypeValue getTypeVariable(TypeParameterDescriptor typeParameterDescriptor) { - TypeValue unknownType = unknownTypes.get(typeParameterDescriptor); - if (unknownType == null) { - throw new IllegalArgumentException("This type parameter is not an unknown in this constraint system: " + typeParameterDescriptor); - } - return unknownType; - } - - public void addSubtypingConstraint(@NotNull SubtypingConstraint constraint) { - constraintQueue.add(constraint); - } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Constraint expansion - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - private TypeCheckingProcedure createConstraintExpander() { - return new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() { - @Override - public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) { - TypeValue aValue = getTypeValueFor(a); - TypeValue bValue = getTypeValueFor(b); - - return expandEqualityConstraint(aValue, bValue); - } - - @SuppressWarnings("SuspiciousMethodCalls") @Override - public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) { - return a.equals(b) - || unknownTypes.containsKey(a.getDeclarationDescriptor()) - || unknownTypes.containsKey(b.getDeclarationDescriptor()); - } - - @Override - public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) { - TypeValue subtypeValue = getTypeValueFor(subtype); - TypeValue supertypeValue = getTypeValueFor(supertype); - - if (someUnknown(subtypeValue, supertypeValue)) { - expandSubtypingConstraint(subtypeValue, supertypeValue); - } - return true; // For known types further expansion happens automatically - } - - @Override - public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) { - // If some of the types is an unknown, the constraint must be generated, and we should carry on - // otherwise there can be no solution, and we should fail - TypeValue subTypeValue = getTypeValueFor(subtype); - TypeValue superTypeValue = getTypeValueFor(supertype); - boolean someUnknown = someUnknown(subTypeValue, superTypeValue); - if (someUnknown) { - expandSubtypingConstraint(subTypeValue, superTypeValue); - } - return someUnknown; - } - - private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) { - return !subtypeValue.isKnown() || !supertypeValue.isKnown(); - } - - }, listener)); - } - - private boolean assignValueTo(TypeValue unknown, JetType value) { - if (unknown.hasValue()) { - // 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(unknown.getType(), value); - } - unsolvedUnknowns.remove(unknown); - unknown.setValue(value); - return true; - } - - private boolean mergeUnknowns(@NotNull TypeValue a, @NotNull TypeValue b) { - assert !a.isKnown() && !b.isKnown(); - listener.error("!!!mergeUnknowns() is not implemented!!!"); - return false; - } - - public boolean expandEqualityConstraint(TypeValue a, TypeValue b) { - if (a.isKnown() && b.isKnown()) { - return constraintExpander.equalTypes(a.getType(), b.getType()); - } - - // At least one of them is unknown - if (a.isKnown()) { - TypeValue tmp = a; - a = b; - b = tmp; - } - - // Now a is definitely unknown - if (b.isKnown()) { - return assignValueTo(a, b.getType()); - } - - // They are both unknown - return mergeUnknowns(a, b); - } - - private boolean expandSubtypingConstraint(TypeValue lower, TypeValue upper) { - listener.log("Constraint added: ", lower, " :< ", upper); - - if (lower == upper) return true; - - // Remember for a later check - lower.addUpperBound(upper); - upper.addLowerBound(lower); - - if (lower.isKnown() && upper.isKnown()) { - // Two known types: expand constraints - return constraintExpander.isSubtypeOf(lower.getType(), upper.getType()); - } - else if (!lower.isKnown() && !upper.isKnown()) { - // Two unknown types: merge them into one variable - return mergeUnknowns(lower, upper); - } - else { - // One unknown and one known - if (upper.isKnown()) { - if (!TypeUtils.canHaveSubtypes(typeChecker, upper.getType())) { - // Upper bound is final -> we have to equate the lower bounds to it - return expandEqualityConstraint(lower, upper); - } - if (lower.getLowerBounds().contains(upper)) { - // upper :< lower :< upper - return expandEqualityConstraint(lower, upper); - } - } - else { - if (upper.getUpperBounds().contains(lower)) { - // lower :< upper :< lower - return expandEqualityConstraint(lower, upper); - } - } - } - return true; - } - - @NotNull - public ConstraintSystemSolution solve() { - Solution solution = new Solution(); - // At this point we only have type values, no bounds added for them, no values computed for unknown types - - // After the parameters are inferred we will make sure the initial constraints are satisfied - PriorityQueue constraintsToEnsureAfterInference = new PriorityQueue(constraintQueue); - - // Expand and solve constraints - while (!constraintQueue.isEmpty()) { - SubtypingConstraint constraint = constraintQueue.poll(); - - // Apply constraint - TypeValue lower = getTypeValueFor(constraint.getSubtype()); - TypeValue upper = getTypeValueFor(constraint.getSupertype()); - boolean success = expandSubtypingConstraint(lower, upper); - if (!success) { - solution.registerError(constraint.getErrorMessage()); -// break; - } - - // (???) Propagate info - - // Any unknowns left? - if (unsolvedUnknowns.isEmpty()) break; - } - - - // effective bounds for each node -// Set visited = Sets.newHashSet(); -// for (TypeValue unknownType : unknownTypes.values()) { -// transitiveClosure(unknownType, visited); -// } - - assert constraintQueue.isEmpty() || unsolvedUnknowns.isEmpty() : constraintQueue + " " + unsolvedUnknowns; - - for (TypeValue unknown : Sets.newLinkedHashSet(unsolvedUnknowns)) { - if (!computeValueFor(unknown)) { - listener.error("Not enough data to compute value for ", unknown); - solution.registerError("Not enough data to compute value for " + unknown + ". Please, specify type arguments explicitly"); - } - } - - // Logging - for (TypeValue unknownType : unknownTypes.values()) { - listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType); - } - for (TypeValue knownType : knownTypes.values()) { - listener.constraintsForKnownType(knownType.getType(), knownType); - } - - // Now, let's check the rest of the constraints and re-check the initial ones - - // Add constraints for the declared bounds for parameters - // Maybe these bounds could reconcile some resolution earlier? Then, move them up - for (Map.Entry entry : Sets.newHashSet(unknownTypes.entrySet())) { - TypeParameterDescriptor typeParameterDescriptor = entry.getKey(); - TypeValue unknown = entry.getValue(); - for (JetType upperBound : typeParameterDescriptor.getUpperBounds()) { - constraintsToEnsureAfterInference.add(PARAMETER_BOUND.assertSubtyping(unknown.getOriginalType(), getTypeValueFor(upperBound).getOriginalType())); -// unknown.addUpperBound(new TypeValue(upperBound)); - } - for (JetType lowerBound : typeParameterDescriptor.getLowerBounds()) { - constraintsToEnsureAfterInference.add(PARAMETER_BOUND.assertSubtyping(getTypeValueFor(lowerBound).getOriginalType(), unknown.getOriginalType())); -// unknown.addLowerBound(new TypeValue(lowerBound)); - } - } - - - // Find inconsistencies - - // 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 - - - for (SubtypingConstraint constraint : constraintsToEnsureAfterInference) { - JetType substitutedSubtype = solution.getSubstitutor().substitute(constraint.getSubtype(), Variance.INVARIANT); // TODO - if (substitutedSubtype == null) continue; - JetType substitutedSupertype = solution.getSubstitutor().substitute(constraint.getSupertype(), Variance.INVARIANT); // TODO - if (substitutedSupertype == null) continue; - - if (!typeChecker.isSubtypeOf(substitutedSubtype, substitutedSupertype)) { - solution.registerError(constraint.getErrorMessage()); - listener.error("Constraint violation: ", substitutedSubtype, " :< ", substitutedSupertype, " message: ", constraint.getErrorMessage()); - } - } - - -// for (TypeValue unknownType : unknownTypes.values()) { -// check(unknownType, solution); -// } -// -// for (TypeValue knownType : knownTypes.values()) { -// check(knownType, solution); -// } - - - listener.done(solution, unknownTypes.keySet()); - - return solution; - } - - private final Set beingComputed = Sets.newHashSet(); - - public boolean computeValueFor(TypeValue unknown) { - assert !unknown.isKnown(); - if (beingComputed.contains(unknown)) { - throw new LoopInTypeVariableConstraintsException(); - } - if (!unknown.hasValue()) { - beingComputed.add(unknown); - try { - if (unknown.getPositionVariance() == Variance.IN_VARIANCE) { - // maximal solution - throw new UnsupportedOperationException(); - } - else { - // minimal solution - - Set lowerBounds = unknown.getLowerBounds(); - Set upperBounds = unknown.getUpperBounds(); - if (!lowerBounds.isEmpty()) { - Set types = getTypes(lowerBounds); - - JetType commonSupertype = CommonSupertypes.commonSupertype(types); - for (TypeValue upperBound : upperBounds) { - if (!typeChecker.isSubtypeOf(commonSupertype, upperBound.getType())) { - return false; - } - } - - listener.log("minimal solution from lower bounds for ", this, " is ", commonSupertype); - assignValueTo(unknown, commonSupertype); - } - else if (!upperBounds.isEmpty()) { - Set types = getTypes(upperBounds); - JetType intersect = TypeUtils.intersect(typeChecker, types); - - if (intersect == null) return false; - - assignValueTo(unknown, intersect); - } - else { - return false; // No bounds to compute the value from - } - } - } finally { - beingComputed.remove(unknown); - } - } - return true; - } - - private static Set getTypes(Set lowerBounds) { - Set types = Sets.newHashSet(); - for (TypeValue lowerBound : lowerBounds) { - types.add(lowerBound.getType()); - } - return types; - } - - private void transitiveClosure(TypeValue current, Set visited) { - if (!visited.add(current)) { - return; - } - - for (TypeValue upperBound : Sets.newHashSet(current.getUpperBounds())) { - if (upperBound.isKnown()) { - continue; - } - transitiveClosure(upperBound, visited); - Set upperBounds = upperBound.getUpperBounds(); - for (TypeValue transitiveBound : upperBounds) { - expandSubtypingConstraint(current, transitiveBound); - } - } - } - - private void check(TypeValue typeValue, Solution solution) { - if (!typeValue.hasValue()) return; - try { - JetType resultingType = typeValue.getType(); - JetType type = solution.getSubstitutor().substitute(resultingType, Variance.INVARIANT); // TODO - for (TypeValue upperBound : typeValue.getUpperBounds()) { - JetType boundingType = solution.getSubstitutor().substitute(upperBound.getType(), Variance.INVARIANT); - if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO - solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType); - listener.error("Constraint violation: ", type, " :< ", boundingType); - } - } - for (TypeValue lowerBound : typeValue.getLowerBounds()) { - JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getType(), Variance.INVARIANT); - if (!typeChecker.isSubtypeOf(boundingType, type)) { - solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type); - listener.error("Constraint violation: ", boundingType, " :< ", type); - } - } - } - catch (LoopInTypeVariableConstraintsException e) { - listener.error("Loop detected"); - solution.registerError("[TODO] Loop in constraints"); - } - } - - 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 TypeSubstitution() { - @Override - public TypeProjection get(TypeConstructor key) { - DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor(); - if (declarationDescriptor instanceof TypeParameterDescriptor) { - TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor; - - if (!unknownTypes.containsKey(descriptor)) return null; - - JetType value = getValue(descriptor); - if (value == null) { - return null; - } - TypeProjection typeProjection = new TypeProjection(value); - - listener.log(descriptor, " |-> ", typeProjection); - - return typeProjection; - } - return null; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public String toString() { - return unknownTypes.toString(); - } - }); - - private SolutionStatus status; - - public Solution() { - this.status = SolutionStatus.SUCCESS; - } - - private Solution registerError(String message) { - status = new Error(message); - return this; - } - - @NotNull - @Override - public SolutionStatus getStatus() { - return status; - } - - @Override - public JetType getValue(TypeParameterDescriptor typeParameterDescriptor) { - TypeValue typeVariable = getTypeVariable(typeParameterDescriptor); - return typeVariable.hasValue() ? typeVariable.getType() : null; - } - - @NotNull - @Override - public TypeSubstitutor getSubstitutor() { - return typeSubstitutor; - } - - } - private static final class TypeConstraintBuilderAdapter implements TypingConstraints { - private final TypingConstraints delegate; - private final ConstraintResolutionListener listener; - - private TypeConstraintBuilderAdapter(TypingConstraints delegate, ConstraintResolutionListener listener) { - this.delegate = delegate; - this.listener = listener; - } - - @Override - public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) { - boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure); - if (!result) { - listener.error("-- Failed to equate ", a, " and ", b); - } - return result; - } - - @Override - public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) { - boolean result = delegate.assertEqualTypeConstructors(a, b); - if (!result) { - listener.error("-- Type constructors are not equal: ", a, " and ", b); - } - return result; - } - - @Override - public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) { - boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure); - if (!result) { - listener.error("-- " + subtype + " can't be a subtype of " + supertype); - } - return result; - } - - @Override - public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) { - boolean result = delegate.noCorrespondingSupertype(subtype, supertype); - if (!result) { - listener.error("-- " + subtype + " has no supertype corresponding to " + supertype); - } - return result; - } - } - -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java index d4404efb976..3c715347b4f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java @@ -252,4 +252,27 @@ public class ConstraintsUtil { } return true; } + + public static TypeSubstitutor makeConstantSubstitutor(Collection typeParameterDescriptors, JetType type) { + final Set constructors = Sets.newHashSet(); + for (TypeParameterDescriptor typeParameterDescriptor : typeParameterDescriptors) { + constructors.add(typeParameterDescriptor.getTypeConstructor()); + } + final TypeProjection projection = new TypeProjection(type); + + return TypeSubstitutor.create(new TypeSubstitution() { + @Override + public TypeProjection get(TypeConstructor key) { + if (constructors.contains(key)) { + return projection; + } + return null; + } + + @Override + public boolean isEmpty() { + return false; + } + }); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java deleted file mode 100644 index bebcd7e24bb..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.resolve.calls.inference; - -import com.google.common.collect.Maps; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.resolve.calls.results.ResolutionDebugInfo; -import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; -import org.jetbrains.jet.lang.types.JetType; - -import java.util.Map; -import java.util.Set; - -import static org.jetbrains.jet.lang.resolve.calls.results.ResolutionDebugInfo.*; - -public class DebugConstraintResolutionListener implements ConstraintResolutionListener { - - private final ResolutionDebugInfo.Data debugInfo; - private final ResolvedCall candidateCall; - - public DebugConstraintResolutionListener(@NotNull ResolvedCall candidateCall, @NotNull ResolutionDebugInfo.Data debugInfo) { - this.debugInfo = debugInfo; - this.candidateCall = candidateCall; - } - - @Override - public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue) { - if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return; - Map map = debugInfo.getByKey(BOUNDS_FOR_UNKNOWNS, candidateCall); - if (map == null) { - map = Maps.newLinkedHashMap(); - debugInfo.putByKey(BOUNDS_FOR_UNKNOWNS, candidateCall, map); - } - map.put(typeParameterDescriptor, typeValue); - } - - @Override - public void constraintsForKnownType(JetType type, BoundsOwner typeValue) { - if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return; - Map map = debugInfo.getByKey(BOUNDS_FOR_KNOWNS, candidateCall); - if (map == null) { - map = Maps.newLinkedHashMap(); - debugInfo.putByKey(BOUNDS_FOR_KNOWNS, candidateCall, map); - } - map.put(type, typeValue); - } - - @Override - public void done(ConstraintSystemSolution solution, Set typeParameterDescriptors) { - if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return; - debugInfo.putByKey(SOLUTION, candidateCall, solution); - debugInfo.putByKey(UNKNOWNS, candidateCall, typeParameterDescriptors); - } - - @Override - public void log(Object... messageFragments) { - if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return; - StringBuilder stringBuilder = debugInfo.getByKey(LOG, candidateCall); - if (stringBuilder == null) { - stringBuilder = new StringBuilder(); - debugInfo.putByKey(LOG, candidateCall, stringBuilder); - } - for (Object m : messageFragments) { - stringBuilder.append(m); - } - stringBuilder.append("\n"); - } - - @Override - public void error(Object... messageFragments) { - if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return; - StringBuilder stringBuilder = debugInfo.getByKey(ERRORS, candidateCall); - if (stringBuilder == null) { - stringBuilder = new StringBuilder(); - debugInfo.putByKey(ERRORS, candidateCall, stringBuilder); - } - for (Object m : messageFragments) { - stringBuilder.append(m); - } - stringBuilder.append("\n"); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java deleted file mode 100644 index 2b3fc6c430f..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.resolve.calls.inference; - -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.resolve.calls.results.ResolutionDebugInfo; -import org.jetbrains.jet.lang.types.JetType; - -import java.util.Set; - -public class PrintingConstraintResolutionListener implements ConstraintResolutionListener { - - @Override - public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue) { - println("Constraints for " + typeParameterDescriptor); - printTypeValue(typeValue); - } - - @Override - public void constraintsForKnownType(JetType type, BoundsOwner typeValue) { - println("Constraints for " + type); - printTypeValue(typeValue); - } - - @Override - public void done(ConstraintSystemSolution solution, Set typeParameterDescriptors) { - println("=================================================="); - println(""); - println(""); - } - - @Override - public void log(Object... messageFragments) { - for (Object fragment : messageFragments) { - println(fragment); - } - } - - @Override - public void error(Object... messageFragments) { - for (Object fragment : messageFragments) { - println(fragment); - } - } - - private void printTypeValue(BoundsOwner typeValue) { - for (BoundsOwner bound : typeValue.getUpperBounds()) { - println(" :< " + bound); - } - for (BoundsOwner bound : typeValue.getLowerBounds()) { - println(" :> " + bound); - } - } - - private static void println(Object message) { - ResolutionDebugInfo.println(message); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SolutionStatus.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SolutionStatus.java deleted file mode 100644 index df79e99d9ed..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SolutionStatus.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.resolve.calls.inference; - -public interface SolutionStatus { - SolutionStatus SUCCESS = new SolutionStatus() { - @Override - public boolean isSuccessful() { - return true; - } - - @Override - public String toString() { - return "SUCCESS"; - } - }; - - boolean isSuccessful(); -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/ResolutionDebugInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/ResolutionDebugInfo.java index 1bfa6560bfc..4a30b835ad4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/ResolutionDebugInfo.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/ResolutionDebugInfo.java @@ -22,7 +22,6 @@ import com.intellij.psi.PsiElement; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.resolve.calls.inference.BoundsOwner; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask; import org.jetbrains.jet.lang.types.JetType; @@ -40,8 +39,6 @@ public class ResolutionDebugInfo { public static final WritableSlice, StringBuilder> LOG = Slices.createSimpleSlice(); public static final WritableSlice, Map> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice(); public static final WritableSlice, Map> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice(); - public static final WritableSlice, ConstraintSystemSolution> SOLUTION = Slices.createSimpleSlice(); - public static final WritableSlice, Collection> UNKNOWNS = Slices.createSimpleSlice(); public static boolean RESOLUTION_DEBUG_INFO_ENABLED = false; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java index 30859c6bb8d..6cc6560ecb7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -28,10 +28,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintResolutionListener; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemWithPriorities; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType; +import org.jetbrains.jet.lang.resolve.calls.inference.*; import org.jetbrains.jet.lang.resolve.constants.NumberValueTypeConstructor; import org.jetbrains.jet.lang.resolve.scopes.ChainedScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -231,7 +228,6 @@ public class TypeUtils { } private static boolean unify(JetType withParameters, JetType expected) { - ConstraintSystemWithPriorities constraintSystem = new ConstraintSystemWithPriorities(ConstraintResolutionListener.DO_NOTHING); // T -> how T is used final Map parameters = Maps.newHashMap(); Processor processor = new Processor() { @@ -248,13 +244,13 @@ public class TypeUtils { }; processAllTypeParameters(withParameters, Variance.INVARIANT, processor); processAllTypeParameters(expected, Variance.INVARIANT, processor); + ConstraintSystemImpl constraintSystem = new ConstraintSystemImpl(); for (Map.Entry entry : parameters.entrySet()) { constraintSystem.registerTypeVariable(entry.getKey(), entry.getValue()); } - constraintSystem.addSubtypingConstraint(ConstraintType.VALUE_ARGUMENT.assertSubtyping(withParameters, expected)); + constraintSystem.addSubtypeConstraint(withParameters, expected, ConstraintPosition.SPECIAL); - ConstraintSystemSolution solution = constraintSystem.solve(); - return solution.getStatus().isSuccessful(); + return constraintSystem.isSuccessful(); } private static void processAllTypeParameters(JetType type, Variance howThiTypeIsUsed, Processor result) {