From 25a972cd80c28fb438d6dbb6c2b9fbf6c127dd81 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 28 Mar 2012 19:04:17 +0400 Subject: [PATCH] Removing the unnecessary class --- .../jet/lang/resolve/calls/CallResolver.java | 3 +- .../calls/inference/ConstraintSystemImpl.java | 605 ------------------ .../ConstraintSystemWithPriorities.java | 28 +- .../expressions/ExpressionTypingUtils.java | 2 +- 4 files changed, 27 insertions(+), 611 deletions(-) delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java 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 75cfc768414..2a7fe8aced5 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 @@ -463,7 +463,8 @@ public class CallResolver { constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences } - TypeSubstitutor substituteDontCare = ConstraintSystemImpl.makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE); + TypeSubstitutor substituteDontCare = ConstraintSystemWithPriorities + .makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE); // Value parameters for (Map.Entry entry : candidateCall.getValueArguments().entrySet()) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java deleted file mode 100644 index 47c900181a5..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright 2010-2012 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.annotations.Nullable; -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.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -/** - * @author abreslav - */ -public class ConstraintSystemImpl implements ConstraintSystem { - - 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 TypeSubstitutor.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() {} - } - - public static abstract class TypeValue { - private final Set mutableUpperBounds = Sets.newHashSet(); - private final Set upperBounds = Collections.unmodifiableSet(mutableUpperBounds); - - private final Set mutableLowerBounds = Sets.newHashSet(); - private final Set lowerBounds = Collections.unmodifiableSet(mutableLowerBounds); - - public void addUpperBound(@NotNull TypeValue bound) { - mutableUpperBounds.add(bound); - } - - public void addLowerBound(@NotNull TypeValue bound) { - mutableLowerBounds.add(bound); - } - - @NotNull - public Set getUpperBounds() { - return upperBounds; - } - - @NotNull - public Set getLowerBounds() { - return lowerBounds; - } - - @Nullable - public abstract KnownType getValue(); - - public abstract boolean equate(TypeValue other); - } - -//========================================================================================================================================================== - - private class UnknownType extends TypeValue { - - private final TypeParameterDescriptor typeParameterDescriptor; - private final Variance positionVariance; - private KnownType value; - private boolean beingComputed = false; - - private UnknownType(TypeParameterDescriptor typeParameterDescriptor, Variance positionVariance) { - this.typeParameterDescriptor = typeParameterDescriptor; - this.positionVariance = positionVariance; - } - - @Override - public void addUpperBound(@NotNull TypeValue bound) { - addBound(bound, getLowerBounds()); - super.addUpperBound(bound); - } - - @Override - public void addLowerBound(@NotNull TypeValue bound) { - addBound(bound, getUpperBounds()); - super.addLowerBound(bound); - } - - private void addBound(TypeValue bound, Set oppositeBounds) { - if (oppositeBounds.contains(bound)) { - this.equate(bound); - } - } - - @NotNull - public TypeParameterDescriptor getTypeParameterDescriptor() { - return typeParameterDescriptor; - } - - @Override - public KnownType getValue() { - if (beingComputed) { - throw new LoopInTypeVariableConstraintsException(); - } - if (value == null) { - beingComputed = true; - JetTypeChecker typeChecker = JetTypeChecker.INSTANCE; - try { - if (positionVariance == Variance.IN_VARIANCE) { - // maximal solution - throw new UnsupportedOperationException(); - } - else { - // minimal solution - - Set lowerBounds = getLowerBounds(); - if (!lowerBounds.isEmpty()) { - Set types = getTypes(lowerBounds); - - JetType commonSupertype = CommonSupertypes.commonSupertype(types); - for (TypeValue upperBound : getUpperBounds()) { - if (!typeChecker.isSubtypeOf(commonSupertype, upperBound.getValue().getType())) { - value = null; - } - } - - listener.log("minimal solution from lowerbounds for ", this, " is ", commonSupertype); - value = new KnownType(commonSupertype); - } - else { - Set upperBounds = getUpperBounds(); - Set types = getTypes(upperBounds); - JetType intersect = TypeUtils.intersect(typeChecker, types); - - value = new KnownType(intersect); - } - } - } - finally { - beingComputed = false; - } - } - - return value; - } - - @Override - public boolean equate(TypeValue other) { - if (other instanceof KnownType) { - KnownType knownType = (KnownType) other; - return setValue(knownType); - } - - assert other instanceof UnknownType; - mergeUnknowns((UnknownType) other, this); - return true; - } - - 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) { - types.add(lowerBound.getValue().getType()); - } - return types; - } - - @Override - public String toString() { - return "?" + typeParameterDescriptor; - } - - } - - private class KnownType extends TypeValue { - - private final JetType type; - - public KnownType(@NotNull JetType type) { - this.type = type; - } - - @NotNull - public JetType getType() { - return type; - } - - @Override - public KnownType getValue() { - return this; - } - - @Override - public String toString() { - return type.toString(); - } - - @Override - public boolean equate(TypeValue other) { - if (other instanceof KnownType) { - KnownType knownType = (KnownType) other; - return constraintExpander.equalTypes(type, knownType.getType()); - } - return other.equate(this); - } - } - - private final Map knownTypes = Maps.newHashMap(); - private final Map unknownTypes = Maps.newHashMap(); - private final JetTypeChecker typeChecker = JetTypeChecker.INSTANCE; - - 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; - } - } - - private final TypeCheckingProcedure constraintExpander; - private final ConstraintResolutionListener listener; - - public ConstraintSystemImpl(ConstraintResolutionListener listener) { - this.listener = listener; - this.constraintExpander = createConstraintExpander(); - } - - 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 aValue.equate(bValue); - } - - @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)) { - addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue); - } - return true; - } - - @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) { - addSubtypingConstraintOnTypeValues(subTypeValue, superTypeValue); - } - return someUnknown; - } - - private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) { - return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType; - } - - }, listener)); - } - - @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()) { - UnknownType unknownType = unknownTypes.get(typeParameterDescriptor); - if (unknownType != null) { - return unknownType; - } - } - } - - KnownType typeValue = knownTypes.get(type); - if (typeValue == null) { - typeValue = new KnownType(type); - knownTypes.put(type, typeValue); - } - return typeValue; - } - - @Override - public void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance) { - assert !unknownTypes.containsKey(typeParameterDescriptor); - UnknownType typeValue = new UnknownType(typeParameterDescriptor, positionVariance); - unknownTypes.put(typeParameterDescriptor, typeValue); - } - - @NotNull - private UnknownType getTypeVariable(TypeParameterDescriptor typeParameterDescriptor) { - UnknownType unknownType = unknownTypes.get(typeParameterDescriptor); - if (unknownType == null) { - throw new IllegalArgumentException("This type parameter is not an unknown in this constraint system: " + typeParameterDescriptor); - } - return unknownType; - } - - private void mergeUnknowns(@NotNull UnknownType a, @NotNull UnknownType b) { - listener.error("!!!mergeUnknowns() is not implemented!!!"); - } - - @Override - public void addSubtypingConstraint(@NotNull SubtypingConstraint constraint) { - TypeValue typeValueForLower = getTypeValueFor(constraint.getSubtype()); - TypeValue typeValueForUpper = getTypeValueFor(constraint.getSupertype()); - addSubtypingConstraintOnTypeValues(typeValueForLower, typeValueForUpper); - } - - private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) { - listener.log("Constraint added: ", typeValueForLower, " :< ", typeValueForUpper); - if (typeValueForLower != typeValueForUpper) { - typeValueForLower.addUpperBound(typeValueForUpper); - typeValueForUpper.addLowerBound(typeValueForLower); - } - } - - @Override - @NotNull - public ConstraintSystemSolution solve() { - // Expand custom bounds, e.g. List <: List - for (Map.Entry entry : Sets.newHashSet(knownTypes.entrySet())) { - JetType jetType = entry.getKey(); - KnownType typeValue = entry.getValue(); - - for (TypeValue upperBound : typeValue.getUpperBounds()) { - if (upperBound instanceof KnownType) { - KnownType knownBoundType = (KnownType) upperBound; - boolean ok = constraintExpander.isSubtypeOf(jetType, knownBoundType.getType()); - if (!ok) { - listener.error("Error while expanding '", jetType, " :< ", knownBoundType.getType(), "'"); - return new Solution().registerError("Mismatch while expanding constraints"); - } - } - } - - for (TypeValue lowerBound : typeValue.getLowerBounds()) { - if (lowerBound instanceof KnownType) { - KnownType knownBoundType = (KnownType) lowerBound; - boolean ok = constraintExpander.isSubtypeOf(knownBoundType.getType(), jetType); - if (!ok) { - listener.error("Error while expanding '" + knownBoundType.getType() + " :< " + jetType + "'"); - return new Solution().registerError("Mismatch while expanding constraints"); - } - } - } - } - - // Fill in upper bounds from type parameter bounds - for (Map.Entry entry : Sets.newHashSet(unknownTypes.entrySet())) { - TypeParameterDescriptor typeParameterDescriptor = entry.getKey(); - UnknownType typeValue = entry.getValue(); - for (JetType upperBound : typeParameterDescriptor.getUpperBounds()) { - addSubtypingConstraintOnTypeValues(typeValue, getTypeValueFor(upperBound)); - } - } - - // effective bounds for each node - Set visited = Sets.newHashSet(); - for (UnknownType unknownType : unknownTypes.values()) { - transitiveClosure(unknownType, visited); - } - - for (UnknownType unknownType : unknownTypes.values()) { -// listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType); - } - - for (KnownType knownType : knownTypes.values()) { -// listener.constraintsForKnownType(knownType.getType(), knownType); - } - - // Find inconsistencies - Solution solution = new Solution(); - - for (UnknownType unknownType : unknownTypes.values()) { - check(unknownType, solution); - } - for (KnownType knownType : knownTypes.values()) { - 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 - - listener.done(solution, unknownTypes.keySet()); - - return solution; - } - - private void check(TypeValue typeValue, Solution solution) { - try { - KnownType resultingValue = typeValue.getValue(); - JetType type = solution.getSubstitutor().substitute(resultingValue.getType(), Variance.INVARIANT); // TODO - for (TypeValue upperBound : typeValue.getUpperBounds()) { - JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().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.getValue().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 void transitiveClosure(TypeValue current, Set visited) { - if (!visited.add(current)) { - return; - } - - for (TypeValue upperBound : Sets.newHashSet(current.getUpperBounds())) { - if (upperBound instanceof KnownType) { - continue; - } - transitiveClosure(upperBound, visited); - Set upperBounds = upperBound.getUpperBounds(); - for (TypeValue transitiveBound : upperBounds) { - addSubtypingConstraintOnTypeValues(current, transitiveBound); - } - } - } - - 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 - public TypeProjection get(TypeConstructor key) { - DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor(); - if (declarationDescriptor instanceof TypeParameterDescriptor) { - TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor; - - if (!unknownTypes.containsKey(descriptor)) return null; - - TypeProjection typeProjection = new TypeProjection(getValue(descriptor)); - - listener.log(descriptor, " |-> ", typeProjection); - - return typeProjection; - } - return null; - } - - @Override - public boolean isEmpty() { - return false; - } - }); - - 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) { - KnownType value = getTypeVariable(typeParameterDescriptor).getValue(); - return value == null ? null : value.getType(); - } - - @NotNull - @Override - public TypeSubstitutor getSubstitutor() { - return typeSubstitutor; - } - - } - -} 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 index 075bc5371ef..f61be7f2a29 100644 --- 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 @@ -26,10 +26,7 @@ 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.Comparator; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.Set; +import java.util.*; import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.PARAMETER_BOUND; @@ -45,6 +42,29 @@ public class ConstraintSystemWithPriorities implements ConstraintSystem { } }; + 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 TypeSubstitutor.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() {} } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index 7839f8ff859..9e853dde7b2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -222,7 +222,7 @@ public class ExpressionTypingUtils { @NotNull JetType receiverType, @NotNull CallableDescriptor receiverArgument ) { - ConstraintSystem constraintSystem = new ConstraintSystemImpl(ConstraintResolutionListener.DO_NOTHING); + ConstraintSystem constraintSystem = new ConstraintSystemWithPriorities(ConstraintResolutionListener.DO_NOTHING); for (TypeParameterDescriptor typeParameterDescriptor : receiverArgument.getTypeParameters()) { constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); }