diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBounds.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBounds.java deleted file mode 100644 index ac460f43026..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBounds.java +++ /dev/null @@ -1,79 +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.Sets; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.Variance; - -import java.util.Set; - -/** - * @author svtk - */ -public class TypeBounds { - private final Variance variance; - private final Set upperBounds = Sets.newLinkedHashSet(); - private final Set lowerBounds = Sets.newLinkedHashSet(); - private final Set exactValues = Sets.newLinkedHashSet(); - - public TypeBounds(Variance variance) { - this.variance = variance; - } - - public Variance getVariance() { - return variance; - } - - public void addUpperBound(JetType upperBound) { - upperBounds.add(upperBound); - } - - public void addLowerBound(JetType lowerBound) { - lowerBounds.add(lowerBound); - } - - public Set getUpperBounds() { - return upperBounds; - } - - public Set getLowerBounds() { - return lowerBounds; - } - - public void setExactValue(JetType exactType) { - exactValues.add(exactType); - } - - public Set getExactValues() { - return exactValues; - } - - public boolean isEmpty() { - return lowerBounds.isEmpty() && upperBounds.isEmpty() && exactValues.isEmpty(); - } - - @Override - public String toString() { - return "TypeBounds{" + - "upperBounds=" + upperBounds + - ", lowerBounds=" + lowerBounds + - ", exactValues=" + exactValues + - '}'; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeConstraintsImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeConstraintsImpl.java new file mode 100644 index 00000000000..62430383547 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeConstraintsImpl.java @@ -0,0 +1,175 @@ +/* + * 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.Lists; +import com.google.common.collect.Sets; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.types.CommonSupertypes; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.Variance; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; + +import java.util.Collections; +import java.util.Set; + +/** + * @author svtk + */ +public class TypeConstraintsImpl implements TypeConstraints { + private static final TypeConstraintsData EMPTY_CONSTRAINTS_DATA = new TypeConstraintsData(null, null, Collections.emptySet()); + private static class TypeConstraintsData { + private final JetType lowerConstraint; + private final JetType upperConstraint; + private final Set conflicts; + + private TypeConstraintsData(JetType lowerConstraint, JetType upperConstraint, Set conflicts) { + this.lowerConstraint = lowerConstraint; + this.upperConstraint = upperConstraint; + this.conflicts = conflicts; + } + + public JetType getLowerConstraint() { + return lowerConstraint; + } + + public JetType getUpperConstraint() { + return upperConstraint; + } + + public Set getConflicts() { + return conflicts; + } + } + + private final Variance variance; + private TypeConstraintsData typeConstraintsData = EMPTY_CONSTRAINTS_DATA; + + private final Set upperConstraints = Sets.newLinkedHashSet(); + private final Set lowerConstraints = Sets.newLinkedHashSet(); + private final Set equalConstraints = Sets.newLinkedHashSet(); + + private boolean changed = false; + + public TypeConstraintsImpl(Variance variance) { + this.variance = variance; + } + + @NotNull + @Override + public Variance getVariance() { + return variance; + } + + public void addUpperConstraint(@NotNull JetType constraint) { + upperConstraints.add(constraint); + changed = true; + } + + public void addLowerConstraint(@NotNull JetType constraint) { + lowerConstraints.add(constraint); + changed = true; + } + + public void addEqualConstraint(@NotNull JetType constraint) { + equalConstraints.add(constraint); + changed = true; + } + + private void updateResult() { + if (!changed) { + return; + } + JetType lowerConstraint = null; + JetType upperConstraint = null; + Set conflicts = Sets.newLinkedHashSet(); + if (!lowerConstraints.isEmpty()) { + lowerConstraint = CommonSupertypes.commonSupertype(lowerConstraints); + } + if (!upperConstraints.isEmpty()) { + //todo + upperConstraint = upperConstraints.iterator().next(); + } + + if (lowerConstraint != null && upperConstraint != null && !JetTypeChecker.INSTANCE.isSubtypeOf(lowerConstraint, upperConstraint)) { + conflicts.add(lowerConstraint); + conflicts.add(upperConstraint); + } + + if (equalConstraints.size() > 1) { + conflicts.addAll(equalConstraints); + } + else if (equalConstraints.size() == 1) { + JetType value = equalConstraints.iterator().next(); + if (lowerConstraint != null && !JetTypeChecker.INSTANCE.isSubtypeOf(lowerConstraint, value)) { + conflicts.add(lowerConstraint); + conflicts.add(value); + } + if (upperConstraint != null && !JetTypeChecker.INSTANCE.isSubtypeOf(value, upperConstraint)) { + conflicts.add(upperConstraint); + conflicts.add(value); + } + lowerConstraint = value; + upperConstraint = value; + } + typeConstraintsData = new TypeConstraintsData(lowerConstraint, upperConstraint, conflicts); + } + + @Override + public boolean isSuccessful() { + updateResult(); + return typeConstraintsData.getConflicts().isEmpty(); + } + + @Nullable + @Override + public JetType getLowerConstraint() { + updateResult(); + return typeConstraintsData.getLowerConstraint(); + } + + @Nullable + @Override + public JetType getUpperConstraint() { + updateResult(); + return typeConstraintsData.getUpperConstraint(); + } + + @NotNull + @Override + public Set getConflicts() { + updateResult(); + return typeConstraintsData.getConflicts(); + } + + @Override + public boolean isEmpty() { + updateResult(); + return typeConstraintsData.getLowerConstraint() == null && typeConstraintsData.getUpperConstraint() == null && typeConstraintsData.getConflicts().isEmpty(); + } + + @Override + public String toString() { + return "TypeConstraints{" + + "upper=" + getUpperConstraint() + + ", lower=" + getLowerConstraint() + + ", conflicts=" + getConflicts() + + '}'; + } +}