From 2d65186574cf8adb2d6895a25a2ecbc69c088977 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Tue, 17 Sep 2013 15:51:33 +0400 Subject: [PATCH] refactoring: moved 'getValue', 'getValues' methods to TypeConstraints --- .../lang/diagnostics/rendering/Renderers.java | 3 +- .../lang/resolve/calls/CallResolverUtil.java | 3 +- .../calls/inference/ConstraintSystem.java | 2 +- .../calls/inference/ConstraintSystemImpl.java | 16 +- .../calls/inference/ConstraintsUtil.java | 149 +----------------- .../calls/inference/TypeConstraints.java | 6 + .../calls/inference/TypeConstraintsImpl.java | 149 +++++++++++++++++- 7 files changed, 170 insertions(+), 158 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java index b78fa46334d..85d04cee461 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java @@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil; import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData; +import org.jetbrains.jet.lang.resolve.calls.inference.TypeConstraints; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeSubstitutor; @@ -277,7 +278,7 @@ public class Renderers { .table(newTable(). descriptor(inferenceErrorData.descriptor)); - JetType inferredValueForTypeParameter = ConstraintsUtil.getValue(inferenceErrorData.constraintSystem.getTypeConstraints(typeParameterDescriptor)); + JetType inferredValueForTypeParameter = inferenceErrorData.constraintSystem.getTypeConstraints(typeParameterDescriptor).getValue(); assert inferredValueForTypeParameter != null; JetType upperBound = typeParameterDescriptor.getUpperBoundsAsType(); JetType upperBoundWithSubstitutedInferredTypes = inferenceErrorData.constraintSystem.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverUtil.java index 4667445bc59..bf429775a96 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverUtil.java @@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext; import org.jetbrains.jet.lang.resolve.calls.context.CallResolutionContext; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil; +import org.jetbrains.jet.lang.resolve.calls.inference.TypeConstraints; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallImpl; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; @@ -115,7 +116,7 @@ public class CallResolverUtil { if (returnType == null) return false; for (TypeParameterDescriptor typeVariable : constraintSystem.getTypeVariables()) { - JetType inferredValueForTypeVariable = ConstraintsUtil.getValue(constraintSystem.getTypeConstraints(typeVariable)); + JetType inferredValueForTypeVariable = constraintSystem.getTypeConstraints(typeVariable).getValue(); if (inferredValueForTypeVariable == null) { if (TypeUtils.dependsOnTypeParameters(returnType, Collections.singleton(typeVariable))) { return true; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java index f9637517a43..0244a0ea5ff 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java @@ -64,7 +64,7 @@ public interface ConstraintSystem { * Returns the resulting type constraints of solving the constraint system for specific type variable.

* Returns null if the type variable was not registered. */ - @Nullable + @NotNull TypeConstraints getTypeConstraints(@NotNull TypeParameterDescriptor typeVariable); /** 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 index db547b436a3..1a10a87a46d 100644 --- 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 @@ -72,7 +72,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { public boolean hasConflictingConstraints() { for (TypeParameterDescriptor typeParameter : typeParameterConstraints.keySet()) { TypeConstraints typeConstraints = getTypeConstraints(typeParameter); - if (typeConstraints != null && ConstraintsUtil.getValues(typeConstraints).size() > 1) return true; + if (typeConstraints.getValues().size() > 1) return true; } return false; } @@ -133,11 +133,11 @@ public class ConstraintSystemImpl implements ConstraintSystem { if (declarationDescriptor instanceof TypeParameterDescriptor) { TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor; - JetType value = ConstraintsUtil.getValue(getTypeConstraints(descriptor)); - if (value != null && !TypeUtils.equalsOrContainsAsArgument(value, DONT_CARE)) { - return new TypeProjection(value); - } if (typeParameterConstraints.containsKey(descriptor)) { + JetType value = getTypeConstraints(descriptor).getValue(); + if (value != null && !TypeUtils.equalsOrContainsAsArgument(value, DONT_CARE)) { + return new TypeProjection(value); + } return defaultTypeProjection; } } @@ -363,9 +363,11 @@ public class ConstraintSystemImpl implements ConstraintSystem { } @Override - @Nullable + @NotNull public TypeConstraints getTypeConstraints(@NotNull TypeParameterDescriptor typeVariable) { - return typeParameterConstraints.get(typeVariable); + TypeConstraintsImpl typeConstraints = typeParameterConstraints.get(typeVariable); + assert typeConstraints != null : "TypeParameterDescriptor is not a type variable for constraint system: " + typeVariable; + return typeConstraints; } @Nullable 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 3c715347b4f..88cb8a09fb6 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 @@ -19,8 +19,6 @@ package org.jetbrains.jet.lang.resolve.calls.inference; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.intellij.openapi.util.Pair; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; @@ -30,147 +28,11 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import java.util.*; public class ConstraintsUtil { - - @NotNull - public static Set getValues(@Nullable TypeConstraints typeConstraints) { - Set values = Sets.newLinkedHashSet(); - if (typeConstraints == null || typeConstraints.isEmpty()) { - return values; - } - TypeConstraints typeConstraintsWithoutErrorTypes = filterNotContainingErrorType(typeConstraints, values); - Collection exactBounds = typeConstraintsWithoutErrorTypes.getExactBounds(); - if (exactBounds.size() == 1) { - JetType exactBound = exactBounds.iterator().next(); - if (trySuggestion(exactBound, typeConstraints)) { - return Collections.singleton(exactBound); - } - } - values.addAll(exactBounds); - - Pair, Collection> pair = - TypeUtils.filterNumberTypes(typeConstraintsWithoutErrorTypes.getLowerBounds()); - Collection generalLowerBounds = pair.getFirst(); - Collection numberLowerBounds = pair.getSecond(); - - JetType superTypeOfLowerBounds = commonSupertype(generalLowerBounds); - if (trySuggestion(superTypeOfLowerBounds, typeConstraints)) { - return Collections.singleton(superTypeOfLowerBounds); - } - ContainerUtil.addIfNotNull(superTypeOfLowerBounds, values); - - Collection upperBounds = typeConstraintsWithoutErrorTypes.getUpperBounds(); - for (JetType upperBound : upperBounds) { - if (trySuggestion(upperBound, typeConstraints)) { - return Collections.singleton(upperBound); - } - } - //todo - //fun foo(t: T, consumer: Consumer): T - //foo(1, c: Consumer) - infer Int, not Any here - - values.addAll(typeConstraintsWithoutErrorTypes.getUpperBounds()); - - JetType superTypeOfNumberLowerBounds = commonSupertypeForNumberTypes(numberLowerBounds); - if (trySuggestion(superTypeOfNumberLowerBounds, typeConstraints)) { - return Collections.singleton(superTypeOfNumberLowerBounds); - } - ContainerUtil.addIfNotNull(superTypeOfNumberLowerBounds, values); - - if (superTypeOfLowerBounds != null && superTypeOfNumberLowerBounds != null) { - JetType superTypeOfAllLowerBounds = commonSupertype(Lists.newArrayList(superTypeOfLowerBounds, superTypeOfNumberLowerBounds)); - if (trySuggestion(superTypeOfAllLowerBounds, typeConstraints)) { - return Collections.singleton(superTypeOfAllLowerBounds); - } - } - return values; - } - - @Nullable - private static JetType commonSupertype(@NotNull Collection lowerBounds) { - if (lowerBounds.isEmpty()) return null; - if (lowerBounds.size() == 1) { - JetType type = lowerBounds.iterator().next(); - if (type.getConstructor() instanceof IntersectionTypeConstructor) { - return commonSupertype(type.getConstructor().getSupertypes()); - } - } - return CommonSupertypes.commonSupertype(lowerBounds); - } - - @Nullable - private static JetType commonSupertypeForNumberTypes(@NotNull Collection numberLowerBounds) { - if (numberLowerBounds.isEmpty()) return null; - return TypeUtils.commonSupertypeForNumberTypes(numberLowerBounds); - } - - private static boolean trySuggestion( - @Nullable JetType suggestion, - @NotNull TypeConstraints typeConstraints - ) { - if (suggestion == null) return false; - if (!suggestion.getConstructor().isDenotable()) return false; - if (typeConstraints.getExactBounds().size() > 1) return false; - - for (JetType exactBound : typeConstraints.getExactBounds()) { - if (!JetTypeChecker.INSTANCE.equalTypes(exactBound, suggestion)) { - return false; - } - } - for (JetType lowerBound : typeConstraints.getLowerBounds()) { - if (!JetTypeChecker.INSTANCE.isSubtypeOf(lowerBound, suggestion)) { - return false; - } - } - for (JetType upperBound : typeConstraints.getUpperBounds()) { - if (!JetTypeChecker.INSTANCE.isSubtypeOf(suggestion, upperBound)) { - return false; - } - } - return true; - } - - @NotNull - private static TypeConstraints filterNotContainingErrorType( - @NotNull TypeConstraints typeConstraints, - @NotNull Collection values - ) { - TypeConstraintsImpl typeConstraintsWithoutErrorType = new TypeConstraintsImpl(typeConstraints.getVarianceOfPosition()); - Collection> allBounds = ((TypeConstraintsImpl) typeConstraints).getAllBounds(); - for (Pair pair : allBounds) { - TypeConstraintsImpl.BoundKind boundKind = pair.getFirst(); - JetType type = pair.getSecond(); - if (ErrorUtils.containsErrorType(type)) { - values.add(type); - } - else if (type != null) { - typeConstraintsWithoutErrorType.addBound(boundKind, type); - } - } - return typeConstraintsWithoutErrorType; - } - - @Nullable - public static JetType getValue(@Nullable TypeConstraints typeConstraints) { - //todo all checks - //todo variance dependance - if (typeConstraints == null) { - //todo assert typeConstraints != null; - return null; - } - Set values = getValues(typeConstraints); - if (values.size() == 1) { - return values.iterator().next(); - } - return null; - } - - - @Nullable public static TypeParameterDescriptor getFirstConflictingParameter(@NotNull ConstraintSystem constraintSystem) { for (TypeParameterDescriptor typeParameter : constraintSystem.getTypeVariables()) { TypeConstraints constraints = constraintSystem.getTypeConstraints(typeParameter); - if (getValues(constraints).size() > 1) { + if (constraints.getValues().size() > 1) { return typeParameter; } } @@ -182,7 +44,7 @@ public class ConstraintsUtil { TypeParameterDescriptor firstConflictingParameter = getFirstConflictingParameter(constraintSystem); if (firstConflictingParameter == null) return Collections.emptyList(); - Collection conflictingTypes = getValues(constraintSystem.getTypeConstraints(firstConflictingParameter)); + Collection conflictingTypes = constraintSystem.getTypeConstraints(firstConflictingParameter).getValues(); ArrayList> substitutionContexts = Lists.newArrayList(); for (JetType type : conflictingTypes) { @@ -209,8 +71,7 @@ public class ConstraintsUtil { @NotNull public static JetType getSafeValue(@NotNull ConstraintSystem constraintSystem, @NotNull TypeParameterDescriptor typeParameter) { - TypeConstraints constraints = constraintSystem.getTypeConstraints(typeParameter); - JetType type = getValue(constraints); + JetType type = constraintSystem.getTypeConstraints(typeParameter).getValue(); if (type != null) { return type; } @@ -223,9 +84,7 @@ public class ConstraintsUtil { @NotNull TypeParameterDescriptor typeParameter, boolean substituteOtherTypeParametersInBound ) { - TypeConstraints typeConstraints = constraintSystem.getTypeConstraints(typeParameter); - assert typeConstraints != null; - JetType type = getValue(typeConstraints); + JetType type = constraintSystem.getTypeConstraints(typeParameter).getValue(); if (type == null) return true; for (JetType upperBound : typeParameter.getUpperBounds()) { if (!substituteOtherTypeParametersInBound && TypeUtils.dependsOnTypeParameters(upperBound, constraintSystem.getTypeVariables())) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeConstraints.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeConstraints.java index d1aa3560aa7..5a9bbff7000 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeConstraints.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeConstraints.java @@ -38,4 +38,10 @@ public interface TypeConstraints { Variance getVarianceOfPosition(); boolean isEmpty(); + + @Nullable + JetType getValue(); + + @NotNull + Collection getValues(); } 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 index be1071fc754..f51272550da 100644 --- 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 @@ -19,11 +19,15 @@ package org.jetbrains.jet.lang.resolve.calls.inference; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.intellij.openapi.util.Pair; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Predicate; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.Variance; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import java.util.Collection; +import java.util.Collections; import java.util.Set; public class TypeConstraintsImpl implements TypeConstraints { @@ -32,6 +36,8 @@ public class TypeConstraintsImpl implements TypeConstraints { private final Set lowerBounds = Sets.newLinkedHashSet(); private final Set exactBounds = Sets.newLinkedHashSet(); + private Collection resultValues; + public TypeConstraintsImpl(Variance varianceOfPosition) { this.varianceOfPosition = varianceOfPosition; } @@ -43,6 +49,7 @@ public class TypeConstraintsImpl implements TypeConstraints { } public void addBound(@NotNull BoundKind boundKind, @NotNull JetType type) { + resultValues = null; switch (boundKind) { case LOWER_BOUND: lowerBounds.add(type); @@ -83,6 +90,7 @@ public class TypeConstraintsImpl implements TypeConstraints { typeConstraints.upperBounds.addAll(upperBounds); typeConstraints.lowerBounds.addAll(lowerBounds); typeConstraints.exactBounds.addAll(exactBounds); + typeConstraints.resultValues = resultValues; return typeConstraints; } @@ -90,7 +98,7 @@ public class TypeConstraintsImpl implements TypeConstraints { LOWER_BOUND, UPPER_BOUND, EXACT_BOUND } - public Collection> getAllBounds() { + private Collection> getAllBounds() { Collection> result = Lists.newArrayList(); for (JetType exactBound : exactBounds) { result.add(Pair.create(BoundKind.EXACT_BOUND, exactBound)); @@ -103,4 +111,139 @@ public class TypeConstraintsImpl implements TypeConstraints { } return result; } + + @Nullable + @Override + public JetType getValue() { + Collection values = getValues(); + if (values.size() == 1) { + return values.iterator().next(); + } + return null; + + } + + @NotNull + @Override + public Collection getValues() { + if (resultValues == null) { + resultValues = computeValues(); + } + return resultValues; + } + + private Collection computeValues() { + Set values = Sets.newLinkedHashSet(); + if (isEmpty()) { + return values; + } + TypeConstraints withoutErrorTypes = filterNotContainingErrorType(values); + Collection exactBounds = withoutErrorTypes.getExactBounds(); + if (exactBounds.size() == 1) { + JetType exactBound = exactBounds.iterator().next(); + if (trySuggestion(exactBound)) { + return Collections.singleton(exactBound); + } + } + values.addAll(exactBounds); + + Pair, Collection> pair = + TypeUtils.filterNumberTypes(withoutErrorTypes.getLowerBounds()); + Collection generalLowerBounds = pair.getFirst(); + Collection numberLowerBounds = pair.getSecond(); + + JetType superTypeOfLowerBounds = commonSupertype(generalLowerBounds); + if (trySuggestion(superTypeOfLowerBounds)) { + return Collections.singleton(superTypeOfLowerBounds); + } + ContainerUtil.addIfNotNull(superTypeOfLowerBounds, values); + + Collection upperBounds = withoutErrorTypes.getUpperBounds(); + for (JetType upperBound : upperBounds) { + if (trySuggestion(upperBound)) { + return Collections.singleton(upperBound); + } + } + //todo + //fun foo(t: T, consumer: Consumer): T + //foo(1, c: Consumer) - infer Int, not Any here + + values.addAll(withoutErrorTypes.getUpperBounds()); + + JetType superTypeOfNumberLowerBounds = commonSupertypeForNumberTypes(numberLowerBounds); + if (trySuggestion(superTypeOfNumberLowerBounds)) { + return Collections.singleton(superTypeOfNumberLowerBounds); + } + ContainerUtil.addIfNotNull(superTypeOfNumberLowerBounds, values); + + if (superTypeOfLowerBounds != null && superTypeOfNumberLowerBounds != null) { + JetType superTypeOfAllLowerBounds = commonSupertype(Lists.newArrayList(superTypeOfLowerBounds, superTypeOfNumberLowerBounds)); + if (trySuggestion(superTypeOfAllLowerBounds)) { + return Collections.singleton(superTypeOfAllLowerBounds); + } + } + return values; + } + + private boolean trySuggestion( + @Nullable JetType suggestion + ) { + if (suggestion == null) return false; + if (!suggestion.getConstructor().isDenotable()) return false; + if (getExactBounds().size() > 1) return false; + + for (JetType exactBound : getExactBounds()) { + if (!JetTypeChecker.INSTANCE.equalTypes(exactBound, suggestion)) { + return false; + } + } + for (JetType lowerBound : getLowerBounds()) { + if (!JetTypeChecker.INSTANCE.isSubtypeOf(lowerBound, suggestion)) { + return false; + } + } + for (JetType upperBound : getUpperBounds()) { + if (!JetTypeChecker.INSTANCE.isSubtypeOf(suggestion, upperBound)) { + return false; + } + } + return true; + } + + @NotNull + private TypeConstraints filterNotContainingErrorType( + @NotNull Collection values + ) { + TypeConstraintsImpl typeConstraintsWithoutErrorType = new TypeConstraintsImpl(getVarianceOfPosition()); + Collection> allBounds = getAllBounds(); + for (Pair pair : allBounds) { + TypeConstraintsImpl.BoundKind boundKind = pair.getFirst(); + JetType type = pair.getSecond(); + if (ErrorUtils.containsErrorType(type)) { + values.add(type); + } + else if (type != null) { + typeConstraintsWithoutErrorType.addBound(boundKind, type); + } + } + return typeConstraintsWithoutErrorType; + } + + @Nullable + private static JetType commonSupertype(@NotNull Collection lowerBounds) { + if (lowerBounds.isEmpty()) return null; + if (lowerBounds.size() == 1) { + JetType type = lowerBounds.iterator().next(); + if (type.getConstructor() instanceof IntersectionTypeConstructor) { + return commonSupertype(type.getConstructor().getSupertypes()); + } + } + return CommonSupertypes.commonSupertype(lowerBounds); + } + + @Nullable + private static JetType commonSupertypeForNumberTypes(@NotNull Collection numberLowerBounds) { + if (numberLowerBounds.isEmpty()) return null; + return TypeUtils.commonSupertypeForNumberTypes(numberLowerBounds); + } }