From 86bc21da301dd0ad78e8c7627401d748d726c2f2 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 23 Oct 2015 20:05:14 +0300 Subject: [PATCH] Make getUpperBoundsAsType an utility, remove from TypeParameterDescriptor --- .../AlternativeMethodSignatureData.java | 18 ++++++++------- .../TypeTransformingVisitor.java | 2 +- .../kotlin/diagnostics/rendering/Renderers.kt | 3 ++- .../kotlin/resolve/DescriptorResolver.java | 5 +++-- .../jetbrains/kotlin/resolve/OverloadUtil.kt | 3 ++- .../jetbrains/kotlin/resolve/TypeResolver.kt | 14 +++++------- .../kotlin/resolve/calls/CallResolverUtil.kt | 6 ++--- .../calls/inference/ConstraintsUtil.java | 2 +- .../LazyTypeParameterDescriptor.java | 1 - .../kotlin/types/BoundsSubstitutor.java | 2 +- .../descriptors/TypeParameterDescriptor.java | 3 --- .../impl/AbstractTypeParameterDescriptor.java | 22 ------------------- .../kotlin/types/TypeIntersector.java | 16 +++++++++++++- .../jetbrains/kotlin/idea/util/FuzzyType.kt | 2 +- .../refactoring/pullUp/KotlinPullUpData.kt | 11 ++++------ 15 files changed, 48 insertions(+), 62 deletions(-) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/AlternativeMethodSignatureData.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/AlternativeMethodSignatureData.java index 4d46a256cb9..acaece7435b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/AlternativeMethodSignatureData.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/AlternativeMethodSignatureData.java @@ -32,14 +32,13 @@ import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt; import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils; -import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.TypeSubstitutor; -import org.jetbrains.kotlin.types.TypeUtils; -import org.jetbrains.kotlin.types.Variance; +import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import static org.jetbrains.kotlin.load.java.components.TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT; import static org.jetbrains.kotlin.load.java.components.TypeUsage.UPPER_BOUND; @@ -140,13 +139,16 @@ public class AlternativeMethodSignatureData extends ElementAlternativeSignatureD for (TypeParameterDescriptor parameter : methodTypeParameters) { int index = parameter.getIndex(); - KotlinType substituted = substitutor.substitute(parameter.getUpperBoundsAsType(), Variance.INVARIANT); + KotlinType upperBoundsAsType = TypeIntersector.getUpperBoundsAsType(parameter); + KotlinType substituted = substitutor.substitute(upperBoundsAsType, Variance.INVARIANT); assert substituted != null; - if (!TypeUtils.equalTypes(substituted, altTypeParameters.get(index).getUpperBoundsAsType())) { + KotlinType altUpperBoundsAsType = TypeIntersector.getUpperBoundsAsType(altTypeParameters.get(index)); + if (!TypeUtils.equalTypes(substituted, altUpperBoundsAsType)) { throw new AlternativeSignatureMismatchException( "Type parameter's upper bound changed for method which overrides another: " - + altTypeParameters.get(index).getUpperBoundsAsType() + ", was: " + parameter.getUpperBoundsAsType()); + + altUpperBoundsAsType + ", was: " + upperBoundsAsType + ); } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/TypeTransformingVisitor.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/TypeTransformingVisitor.java index f33b381e31f..f2bba364853 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/TypeTransformingVisitor.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/TypeTransformingVisitor.java @@ -150,7 +150,7 @@ public class TypeTransformingVisitor extends KtVisitor { KtScope memberScope; if (typeConstructorClassifier instanceof TypeParameterDescriptor) { - memberScope = ((TypeParameterDescriptor) typeConstructorClassifier).getUpperBoundsAsType().getMemberScope(); + memberScope = typeConstructorClassifier.getDefaultType().getMemberScope(); } else if (typeConstructorClassifier instanceof ClassDescriptor) { memberScope = ((ClassDescriptor) typeConstructorClassifier).getMemberScope(altArguments); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt index a6812e862c1..17216aeb71a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt @@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeIntersector import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.checker.KotlinTypeChecker @@ -324,7 +325,7 @@ public object Renderers { } val explanation: String - val upperBound = typeParameterWithCapturedConstraint.getUpperBoundsAsType() + val upperBound = TypeIntersector.getUpperBoundsAsType(typeParameterWithCapturedConstraint) if (!KotlinBuiltIns.isNullableAny(upperBound) && capturedTypeConstructor.typeProjection.getProjectionKind() == Variance.IN_VARIANCE) { explanation = "Type parameter has an upper bound '" + result.getTypeRenderer().render(upperBound) + "'" + " that cannot be satisfied capturing 'in' projection" diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 6a14ac581e5..fd342ec7fc3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -62,7 +62,8 @@ import java.util.*; import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*; import static org.jetbrains.kotlin.diagnostics.Errors.*; import static org.jetbrains.kotlin.lexer.KtTokens.*; -import static org.jetbrains.kotlin.resolve.BindingContext.*; +import static org.jetbrains.kotlin.resolve.BindingContext.CONSTRUCTOR; +import static org.jetbrains.kotlin.resolve.BindingContext.PACKAGE_TO_FILES; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; import static org.jetbrains.kotlin.resolve.ModifiersChecker.resolveModalityFromModifiers; import static org.jetbrains.kotlin.resolve.ModifiersChecker.resolveVisibilityFromModifiers; @@ -539,7 +540,7 @@ public class DescriptorResolver { @NotNull TypeParameterDescriptor parameter, @NotNull KtTypeParameter typeParameter ) { - if (KotlinBuiltIns.isNothing(parameter.getUpperBoundsAsType())) { + if (KotlinBuiltIns.isNothing(TypeIntersector.getUpperBoundsAsType(parameter))) { trace.report(CONFLICTING_UPPER_BOUNDS.on(typeParameter, parameter)); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadUtil.kt index 5bd58d5f5fe..74335011c08 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OverloadUtil.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.INCOMPATIBLE import org.jetbrains.kotlin.resolve.scopes.KtScope import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeIntersector import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.oneMoreSpecificThanAnother @@ -74,7 +75,7 @@ object OverloadUtil { val classifier = constructor.declarationDescriptor return when (classifier) { is ClassDescriptor -> this - is TypeParameterDescriptor -> classifier.upperBoundsAsType + is TypeParameterDescriptor -> TypeIntersector.getUpperBoundsAsType(classifier) else -> error("Unknown type constructor: $this") } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index 8346df66c23..eb145b7f21f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -40,9 +40,7 @@ import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.Variance.INVARIANT -import org.jetbrains.kotlin.types.Variance.IN_VARIANCE -import org.jetbrains.kotlin.types.Variance.OUT_VARIANCE +import org.jetbrains.kotlin.types.Variance.* public class TypeResolver( private val annotationResolver: AnnotationResolver, @@ -323,12 +321,10 @@ public class TypeResolver( } private fun getScopeForTypeParameter(c: TypeResolutionContext, typeParameterDescriptor: TypeParameterDescriptor): KtScope { - if (c.checkBounds) { - return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope() - } - else { - return LazyScopeAdapter(LockBasedStorageManager.NO_LOCKS.createLazyValue { - typeParameterDescriptor.getUpperBoundsAsType().getMemberScope() + return when { + c.checkBounds -> TypeIntersector.getUpperBoundsAsType(typeParameterDescriptor).memberScope + else -> LazyScopeAdapter(LockBasedStorageManager.NO_LOCKS.createLazyValue { + TypeIntersector.getUpperBoundsAsType(typeParameterDescriptor).memberScope }) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt index 30f81fa92ee..3e5494b79dc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt @@ -88,9 +88,9 @@ public fun CallableDescriptor.hasInferredReturnType(constraintSystem: Constraint public fun getErasedReceiverType(receiverParameterDescriptor: ReceiverParameterDescriptor, descriptor: CallableDescriptor): KotlinType { var receiverType = receiverParameterDescriptor.getType() - for (typeParameter in descriptor.getTypeParameters()) { - if (typeParameter.getTypeConstructor() == receiverType.getConstructor()) { - receiverType = typeParameter.getUpperBoundsAsType() + for (typeParameter in descriptor.typeParameters) { + if (typeParameter.typeConstructor == receiverType.constructor) { + receiverType = TypeIntersector.getUpperBoundsAsType(typeParameter) } } val fakeTypeArguments = ContainerUtil.newSmartList() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintsUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintsUtil.java index 5d47c8b30e4..e0925f7c5a8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintsUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintsUtil.java @@ -77,7 +77,7 @@ public class ConstraintsUtil { return type; } //todo may be error type - return typeParameter.getUpperBoundsAsType(); + return TypeIntersector.getUpperBoundsAsType(typeParameter); } public static boolean checkUpperBoundIsSatisfied( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyTypeParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyTypeParameterDescriptor.java index 98cf6595de9..c17df1ea455 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyTypeParameterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyTypeParameterDescriptor.java @@ -119,7 +119,6 @@ public class LazyTypeParameterDescriptor extends AbstractLazyTypeParameterDescri getOriginal(); ForceResolveUtil.forceResolveAllContents(getTypeConstructor()); ForceResolveUtil.forceResolveAllContents(getUpperBounds()); - getUpperBoundsAsType(); getVariance(); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/BoundsSubstitutor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/BoundsSubstitutor.java index fbf047e1ffa..2c892662c5d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/BoundsSubstitutor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/BoundsSubstitutor.java @@ -60,7 +60,7 @@ public class BoundsSubstitutor { // todo assert: no loops for (TypeParameterDescriptor descriptor : topologicallySortTypeParameters(typeParameters)) { - KotlinType upperBoundsAsType = descriptor.getUpperBoundsAsType(); + KotlinType upperBoundsAsType = TypeIntersector.getUpperBoundsAsType(descriptor); KotlinType substitutedUpperBoundsAsType = substitutor.substitute(upperBoundsAsType, Variance.INVARIANT); mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjectionImpl(substitutedUpperBoundsAsType)); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java index c0b29e7433f..28b4fea57b7 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/TypeParameterDescriptor.java @@ -33,9 +33,6 @@ public interface TypeParameterDescriptor extends ClassifierDescriptor { @NotNull List getUpperBounds(); - @NotNull - KotlinType getUpperBoundsAsType(); - @NotNull List getLowerBounds(); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java index c3f636c9ad2..d74de66daf3 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java @@ -31,7 +31,6 @@ import org.jetbrains.kotlin.resolve.scopes.LazyScopeAdapter; import org.jetbrains.kotlin.storage.NotNullLazyValue; import org.jetbrains.kotlin.storage.StorageManager; import org.jetbrains.kotlin.types.*; -import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; import java.util.ArrayList; import java.util.Collections; @@ -50,7 +49,6 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip private final NotNullLazyValue typeConstructor; private final NotNullLazyValue defaultType; private final NotNullLazyValue> upperBounds; - private final NotNullLazyValue upperBoundsAsType; protected AbstractTypeParameterDescriptor( @NotNull final StorageManager storageManager, @@ -104,12 +102,6 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip return resolveUpperBounds(); } }, FALLBACK_UPPER_BOUNDS_ON_RECURSION); - this.upperBoundsAsType = storageManager.createLazyValue(new Function0() { - @Override - public KotlinType invoke() { - return computeUpperBoundsAsType(); - } - }); } @NotNull @@ -140,20 +132,6 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip return upperBounds.invoke(); } - @NotNull - @Override - public KotlinType getUpperBoundsAsType() { - return upperBoundsAsType.invoke(); - } - - @NotNull - private KotlinType computeUpperBoundsAsType() { - List upperBounds = getUpperBounds(); - assert !upperBounds.isEmpty() : "Upper bound list is empty in " + getName(); - KotlinType upperBoundsAsType = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, upperBounds); - return upperBoundsAsType != null ? upperBoundsAsType : getBuiltIns(this).getNothingType(); - } - @NotNull @Override public TypeConstructor getTypeConstructor() { diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeIntersector.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeIntersector.java index 49e9abacab1..7ea3f5ea278 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeIntersector.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeIntersector.java @@ -34,6 +34,7 @@ import java.util.*; import static org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImplKt.registerTypeVariables; import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.SPECIAL; +import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns; public class TypeIntersector { @@ -139,7 +140,20 @@ public class TypeIntersector { ); } - // TODO : check intersectibility, don't use a chanied scope + /** + * Note: this method was used in overload and override bindings to approximate type parameters with several bounds, + * but as it turned out at some point, that logic was inconsistent with Java rules, so it was simplified. + * Most of the other usages of this method are left untouched but probably should be investigated closely if they're still valid. + */ + @NotNull + public static KotlinType getUpperBoundsAsType(@NotNull TypeParameterDescriptor descriptor) { + List upperBounds = descriptor.getUpperBounds(); + assert !upperBounds.isEmpty() : "Upper bound list is empty: " + descriptor; + KotlinType upperBoundsAsType = intersectTypes(KotlinTypeChecker.DEFAULT, upperBounds); + return upperBoundsAsType != null ? upperBoundsAsType : getBuiltIns(descriptor).getNothingType(); + } + + // TODO: check intersectability, don't use a chained scope private static class IntersectionScope extends ChainedScope { public IntersectionScope(@NotNull TypeConstructor constructor, @NotNull KtScope[] scopes) { super(null, "member scope for intersection type " + constructor, scopes); diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/FuzzyType.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/FuzzyType.kt index 44f52817fdd..25938f7f186 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/FuzzyType.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/FuzzyType.kt @@ -47,7 +47,7 @@ fun FuzzyType.isAlmostEverything(): Boolean { if (freeParameters.isEmpty()) return false val typeParameter = type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return false if (typeParameter !in freeParameters) return false - return typeParameter.upperBoundsAsType.isAnyOrNullableAny() + return typeParameter.upperBounds.singleOrNull()?.isAnyOrNullableAny() ?: false } class FuzzyType( diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/KotlinPullUpData.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/KotlinPullUpData.kt index bf26f1104de..b208ec12113 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/KotlinPullUpData.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/KotlinPullUpData.kt @@ -21,17 +21,14 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade -import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.idea.refactoring.memberInfo.getClassDescriptorIfAny +import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtNamedDeclaration import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.utils.collectDescriptorsFiltered -import org.jetbrains.kotlin.types.TypeConstructor -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.TypeProjectionImpl -import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.substitutions.getTypeSubstitution import org.jetbrains.kotlin.utils.keysToMap import java.util.* @@ -60,7 +57,7 @@ class KotlinPullUpData(val sourceClass: KtClassOrObject, val substitution = LinkedHashMap() typeParametersInSourceClassContext.forEach { - substitution[it.typeConstructor] = TypeProjectionImpl(it.upperBoundsAsType) + substitution[it.typeConstructor] = TypeProjectionImpl(TypeIntersector.getUpperBoundsAsType(it)) } val superClassSubstitution = getTypeSubstitution(targetClassDescriptor.defaultType, sourceClassDescriptor.defaultType) @@ -77,4 +74,4 @@ class KotlinPullUpData(val sourceClass: KtClassOrObject, } val isInterfaceTarget: Boolean = targetClassDescriptor.kind == ClassKind.INTERFACE -} \ No newline at end of file +}