From da025475a8f3cdee3b56131ca91185afdfdc2921 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Mon, 27 Jul 2015 20:03:04 +0300 Subject: [PATCH] Make TypeIntersector a component and inject it into some points of usage --- .../resolve/calls/GenericCandidateResolver.kt | 5 ++-- .../calls/smartcasts/SmartCastUtils.java | 3 ++- .../BasicExpressionTypingVisitor.java | 2 +- .../ExpressionTypingComponents.java | 9 ++++++- .../PatternMatchingTypingVisitor.java | 5 ++-- .../kotlin/types/JetTypeCheckerTest.java | 2 +- .../java/lazy/types/LazyJavaTypeResolver.kt | 2 +- .../impl/AbstractTypeParameterDescriptor.java | 6 +++-- .../resolve/calls/inference/TypeBoundsImpl.kt | 3 ++- .../kotlin/types/CommonSupertypes.java | 3 ++- .../kotlin/types/TypeIntersector.java | 25 ++++++++++++++++--- .../callableBuilder/typeUtils.kt | 2 +- .../extractableAnalysisUtil.kt | 3 ++- 13 files changed, 50 insertions(+), 20 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt index a653c72cd17..949605e2f6e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -49,7 +49,8 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils class GenericCandidateResolver( - val argumentTypeResolver: ArgumentTypeResolver + private val argumentTypeResolver: ArgumentTypeResolver, + private val typeIntersector: TypeIntersector ) { fun inferTypeArguments(context: CallCandidateResolutionContext): ResolutionStatus { @@ -188,7 +189,7 @@ class GenericCandidateResolver( val possibleTypes = context.dataFlowInfo.getPossibleTypes(dataFlowValue) if (possibleTypes.isEmpty()) return type - return TypeIntersector.intersect(JetTypeChecker.DEFAULT, possibleTypes) + return typeIntersector.intersect(JetTypeChecker.DEFAULT, possibleTypes) } public fun completeTypeInferenceDependentOnFunctionArgumentsForCall( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastUtils.java index d8e7d48fc04..253940c7540 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastUtils.java @@ -22,6 +22,7 @@ import kotlin.KotlinPackage; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor; import org.jetbrains.kotlin.psi.JetExpression; @@ -152,7 +153,7 @@ public class SmartCastUtils { } if (subTypes.isEmpty()) return null; - JetType intersection = TypeIntersector.intersect(JetTypeChecker.DEFAULT, subTypes); + JetType intersection = TypeIntersector.intersectTypes(KotlinBuiltIns.getInstance(), JetTypeChecker.DEFAULT, subTypes); if (intersection == null || !intersection.getConstructor().isDenotable()) { return receiverParameterType; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index a6d6fd64a0c..a79e1d78ff5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -1251,7 +1251,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetType rightType = facade.getTypeInfo(right, context).getType(); if (rightType != null) { - if (TypeIntersector.isIntersectionEmpty(leftType, rightType)) { + if (components.typeIntersector.isIntersectionEmpty(leftType, rightType)) { context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType)); } SenselessComparisonChecker.checkSenselessComparisonWithNull( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java index ba2453cb2f4..a9d38199b49 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.types.expressions; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; +import org.jetbrains.kotlin.builtins.ReflectionTypes; import org.jetbrains.kotlin.context.GlobalContext; import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap; import org.jetbrains.kotlin.resolve.*; @@ -27,7 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker; import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator; import org.jetbrains.kotlin.types.DynamicTypesSettings; -import org.jetbrains.kotlin.builtins.ReflectionTypes; +import org.jetbrains.kotlin.types.TypeIntersector; import javax.inject.Inject; @@ -54,6 +55,7 @@ public class ExpressionTypingComponents { /*package*/ ModifiersChecker modifiersChecker; /*package*/ DataFlowAnalyzer dataFlowAnalyzer; /*package*/ Iterable callCheckers; + /*package*/ TypeIntersector typeIntersector; @Inject public void setGlobalContext(@NotNull GlobalContext globalContext) { @@ -169,4 +171,9 @@ public class ExpressionTypingComponents { public void setCallCheckers(@NotNull Iterable callCheckers) { this.callCheckers = callCheckers; } + + @Inject + public void setTypeIntersector(@NotNull TypeIntersector typeIntersector) { + this.typeIntersector = typeIntersector; + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.java index 25b25b3bb86..9951e217adb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.java @@ -44,7 +44,6 @@ import java.util.Set; import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean; import static org.jetbrains.kotlin.diagnostics.Errors.*; import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT; -import static org.jetbrains.kotlin.types.TypeIntersector.isIntersectionEmpty; import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE; import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.newWritableScopeImpl; @@ -338,7 +337,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { /* * (a: SubjectType) is Type */ - private static void checkTypeCompatibility( + private void checkTypeCompatibility( @NotNull ExpressionTypingContext context, @Nullable JetType type, @NotNull JetType subjectType, @@ -348,7 +347,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { if (type == null) { return; } - if (isIntersectionEmpty(type, subjectType)) { + if (components.typeIntersector.isIntersectionEmpty(type, subjectType)) { context.trace.report(INCOMPATIBLE_TYPES.on(reportErrorOn, type, subjectType)); return; } diff --git a/compiler/tests/org/jetbrains/kotlin/types/JetTypeCheckerTest.java b/compiler/tests/org/jetbrains/kotlin/types/JetTypeCheckerTest.java index 24795fc0851..de5074f22e0 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/JetTypeCheckerTest.java +++ b/compiler/tests/org/jetbrains/kotlin/types/JetTypeCheckerTest.java @@ -523,7 +523,7 @@ public class JetTypeCheckerTest extends JetLiteFixture { for (String type : types) { typesToIntersect.add(makeType(type)); } - JetType result = TypeIntersector.intersect(JetTypeChecker.DEFAULT, typesToIntersect); + JetType result = TypeIntersector.intersectTypes(KotlinBuiltIns.getInstance(), JetTypeChecker.DEFAULT, typesToIntersect); // assertNotNull("Intersection is null for " + typesToIntersect, result); assertEquals(makeType(expected), result); } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt index 4620242d6fb..d5495cf2c55 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt @@ -178,7 +178,7 @@ class LazyJavaTypeResolver( for (supertype in (classifier() as JavaTypeParameter).getUpperBounds()) { supertypesJet.add(transformJavaType(supertype, UPPER_BOUND.toAttributes())) } - return TypeIntersector.intersect(JetTypeChecker.DEFAULT, supertypesJet) + return TypeIntersector.intersectTypes(KotlinBuiltIns.getInstance(), JetTypeChecker.DEFAULT, supertypesJet) ?: ErrorUtils.createErrorType("Can't intersect upper bounds of " + javaType.getPresentableText()) } 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 9aeadf80d93..af37a261521 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.descriptors.impl; import kotlin.jvm.functions.Function0; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.ReadOnly; +import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptorVisitor; import org.jetbrains.kotlin.descriptors.SourceElement; @@ -135,8 +136,9 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip private JetType computeUpperBoundsAsType() { Set upperBounds = getUpperBounds(); assert !upperBounds.isEmpty() : "Upper bound list is empty in " + getName(); - JetType upperBoundsAsType = TypeIntersector.intersect(JetTypeChecker.DEFAULT, upperBounds); - return upperBoundsAsType != null ? upperBoundsAsType : getBuiltIns(this).getNothingType(); + KotlinBuiltIns builtIns = getBuiltIns(this); + JetType upperBoundsAsType = TypeIntersector.intersectTypes(builtIns, JetTypeChecker.DEFAULT, upperBounds); + return upperBoundsAsType != null ? upperBoundsAsType : builtIns.getNothingType(); } @NotNull diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/TypeBoundsImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/TypeBoundsImpl.kt index b69d0e3673d..cfb1c0a2912 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/TypeBoundsImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/TypeBoundsImpl.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_B import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.JetTypeChecker import org.jetbrains.kotlin.utils.addIfNotNull @@ -134,7 +135,7 @@ public class TypeBoundsImpl( } val upperBounds = filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND, values) - val intersectionOfUpperBounds = TypeIntersector.intersect(JetTypeChecker.DEFAULT, upperBounds) + val intersectionOfUpperBounds = TypeIntersector(typeVariable.builtIns).intersect(JetTypeChecker.DEFAULT, upperBounds) if (!upperBounds.isEmpty() && intersectionOfUpperBounds != null) { if (tryPossibleAnswer(bounds, intersectionOfUpperBounds)) { return setOf(intersectionOfUpperBounds) diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/CommonSupertypes.java b/core/descriptors/src/org/jetbrains/kotlin/types/CommonSupertypes.java index f16ee694333..696e72be1fe 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/CommonSupertypes.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/CommonSupertypes.java @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.types.checker.JetTypeChecker; import java.util.*; +import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns; import static org.jetbrains.kotlin.types.TypeUtils.topologicallySortSuperclassesAndRecordAllInstances; import static org.jetbrains.kotlin.types.Variance.IN_VARIANCE; import static org.jetbrains.kotlin.types.Variance.OUT_VARIANCE; @@ -299,7 +300,7 @@ public class CommonSupertypes { return new TypeProjectionImpl(projectionKind, findCommonSupertype(outs, recursionDepth + 1, maxDepth)); } if (ins != null) { - JetType intersection = TypeIntersector.intersect(JetTypeChecker.DEFAULT, ins); + JetType intersection = TypeIntersector.intersectTypes(getBuiltIns(parameterDescriptor), JetTypeChecker.DEFAULT, ins); if (intersection == null) { return new TypeProjectionImpl(OUT_VARIANCE, findCommonSupertype(parameterDescriptor.getUpperBounds(), recursionDepth + 1, maxDepth)); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeIntersector.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeIntersector.java index 4867aa1b520..584bd4f8db2 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeIntersector.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeIntersector.java @@ -36,14 +36,31 @@ import static org.jetbrains.kotlin.resolve.calls.inference.InferencePackage.regi import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.SPECIAL; public class TypeIntersector { - public static boolean isIntersectionEmpty(@NotNull JetType typeA, @NotNull JetType typeB) { + + private final KotlinBuiltIns builtIns; + + public TypeIntersector(@NotNull KotlinBuiltIns builtIns) { + this.builtIns = builtIns; + } + + public boolean isIntersectionEmpty(@NotNull JetType typeA, @NotNull JetType typeB) { return intersect(JetTypeChecker.DEFAULT, new LinkedHashSet(Arrays.asList(typeA, typeB))) == null; } + //TODO: usages of this method should be removed @Nullable - public static JetType intersect(@NotNull JetTypeChecker typeChecker, @NotNull Set types) { + public static JetType intersectTypes( + @NotNull KotlinBuiltIns builtIns, + @NotNull JetTypeChecker typeChecker, + @NotNull Set types + ) { + return new TypeIntersector(builtIns).intersect(typeChecker, types); + } + + @Nullable + public JetType intersect(@NotNull JetTypeChecker typeChecker, @NotNull Set types) { if (types.isEmpty()) { - return KotlinBuiltIns.getInstance().getNullableAnyType(); + return builtIns.getNullableAnyType(); } if (types.size() == 1) { @@ -64,7 +81,7 @@ public class TypeIntersector { } if (nothingTypePresent) { - return allNullable ? KotlinBuiltIns.getInstance().getNullableNothingType() : KotlinBuiltIns.getInstance().getNothingType(); + return allNullable ? builtIns.getNullableNothingType() : builtIns.getNothingType(); } if (nullabilityStripped.isEmpty()) { diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt index 15fc202b339..f212d60c8cc 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt @@ -196,7 +196,7 @@ private fun JetNamedDeclaration.guessType(context: BindingContext): Array ErrorUtils.containsErrorType(expectedType) }) { return arrayOf() } - val theType = TypeIntersector.intersect(JetTypeChecker.DEFAULT, expectedTypes) + val theType = TypeIntersector.intersectTypes(KotlinBuiltIns.getInstance(), JetTypeChecker.DEFAULT, expectedTypes) if (theType != null) { return arrayOf(theType) } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt index d1dd9aebb02..bd1ab52dd9c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractableAnalysisUtil.kt @@ -70,6 +70,7 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.tasks.isSynthesizedInvoke +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue @@ -519,7 +520,7 @@ private class MutableParameter( private val defaultType: JetType by lazy { writable = false - TypeIntersector.intersect(JetTypeChecker.DEFAULT, defaultTypes)!! + TypeIntersector.intersectTypes(originalDescriptor.builtIns, JetTypeChecker.DEFAULT, defaultTypes)!! } private val parameterTypeCandidates: List by lazy {