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 d2b6c54f282..29e6c107bc0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -49,8 +49,7 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils class GenericCandidateResolver( - private val argumentTypeResolver: ArgumentTypeResolver, - private val typeIntersector: TypeIntersector + private val argumentTypeResolver: ArgumentTypeResolver ) { fun inferTypeArguments(context: CallCandidateResolutionContext): ResolutionStatus { @@ -189,7 +188,7 @@ class GenericCandidateResolver( val possibleTypes = context.dataFlowInfo.getPossibleTypes(dataFlowValue) if (possibleTypes.isEmpty()) return type - return typeIntersector.intersect(JetTypeChecker.DEFAULT, possibleTypes) + return TypeIntersector.intersectTypes(JetTypeChecker.DEFAULT, possibleTypes) } public fun completeTypeInferenceDependentOnFunctionArgumentsForCall( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.java index 01b4565fb7a..e27fff01860 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.java @@ -22,17 +22,13 @@ 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; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver; import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext; -import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; -import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver; import org.jetbrains.kotlin.types.JetType; import org.jetbrains.kotlin.types.TypeIntersector; import org.jetbrains.kotlin.types.TypeUtils; @@ -47,9 +43,6 @@ import static org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST; public class SmartCastManager { - public SmartCastManager() { - } - @NotNull public List getSmartCastVariants( @NotNull ReceiverValue receiverToCast, @@ -146,7 +139,7 @@ public class SmartCastManager { } if (subTypes.isEmpty()) return null; - JetType intersection = TypeIntersector.intersectTypes(KotlinBuiltIns.getInstance(), JetTypeChecker.DEFAULT, subTypes); + JetType intersection = TypeIntersector.intersectTypes(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 12d6a0aa83f..0415bd2e13f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -1278,7 +1278,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetType rightType = facade.getTypeInfo(right, context).getType(); if (rightType != null) { - if (components.typeIntersector.isIntersectionEmpty(leftType, rightType)) { + if (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 a9d38199b49..d2c20806f13 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingComponents.java @@ -55,7 +55,6 @@ public class ExpressionTypingComponents { /*package*/ ModifiersChecker modifiersChecker; /*package*/ DataFlowAnalyzer dataFlowAnalyzer; /*package*/ Iterable callCheckers; - /*package*/ TypeIntersector typeIntersector; @Inject public void setGlobalContext(@NotNull GlobalContext globalContext) { @@ -171,9 +170,4 @@ 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 9f25717840f..8a25b0c67b2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.java @@ -347,7 +347,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { if (type == null) { return; } - if (components.typeIntersector.isIntersectionEmpty(type, subjectType)) { + if (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 a0416498e2c..db21d85a234 100644 --- a/compiler/tests/org/jetbrains/kotlin/types/JetTypeCheckerTest.java +++ b/compiler/tests/org/jetbrains/kotlin/types/JetTypeCheckerTest.java @@ -524,7 +524,7 @@ public class JetTypeCheckerTest extends JetLiteFixture { for (String type : types) { typesToIntersect.add(makeType(type)); } - JetType result = TypeIntersector.intersectTypes(KotlinBuiltIns.getInstance(), JetTypeChecker.DEFAULT, typesToIntersect); + JetType result = TypeIntersector.intersectTypes(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 169332bf382..66338ce7320 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 @@ -176,7 +176,10 @@ class LazyJavaTypeResolver( for (supertype in (classifier() as JavaTypeParameter).getUpperBounds()) { supertypesJet.add(transformJavaType(supertype, UPPER_BOUND.toAttributes())) } - return TypeIntersector.intersectTypes(KotlinBuiltIns.getInstance(), JetTypeChecker.DEFAULT, supertypesJet) + if (supertypesJet.isEmpty()) { + return c.module.builtIns.nullableAnyType + } + return TypeIntersector.intersectTypes(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 af37a261521..a16e40fb098 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeParameterDescriptor.java @@ -136,9 +136,8 @@ public abstract class AbstractTypeParameterDescriptor extends DeclarationDescrip private JetType computeUpperBoundsAsType() { Set upperBounds = getUpperBounds(); assert !upperBounds.isEmpty() : "Upper bound list is empty in " + getName(); - KotlinBuiltIns builtIns = getBuiltIns(this); - JetType upperBoundsAsType = TypeIntersector.intersectTypes(builtIns, JetTypeChecker.DEFAULT, upperBounds); - return upperBoundsAsType != null ? upperBoundsAsType : builtIns.getNothingType(); + JetType upperBoundsAsType = TypeIntersector.intersectTypes(JetTypeChecker.DEFAULT, upperBounds); + return upperBoundsAsType != null ? upperBoundsAsType : getBuiltIns(this).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 cfb1c0a2912..2f5f99f0db0 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 @@ -135,9 +135,9 @@ public class TypeBoundsImpl( } val upperBounds = filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND, values) - val intersectionOfUpperBounds = TypeIntersector(typeVariable.builtIns).intersect(JetTypeChecker.DEFAULT, upperBounds) - if (!upperBounds.isEmpty() && intersectionOfUpperBounds != null) { - if (tryPossibleAnswer(bounds, intersectionOfUpperBounds)) { + if (upperBounds.isNotEmpty()) { + val intersectionOfUpperBounds = TypeIntersector.intersectTypes(JetTypeChecker.DEFAULT, upperBounds) + if (intersectionOfUpperBounds != null && 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 7d878c0c1ab..4926cd9c1b9 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/CommonSupertypes.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/CommonSupertypes.java @@ -32,7 +32,6 @@ import org.jetbrains.kotlin.types.typeUtil.TypeUtilPackage; 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,6 +298,7 @@ public class CommonSupertypes { } if (outs != null) { + assert !outs.isEmpty() : "Out projections is empty for parameter " + parameterDescriptor + ", type projections " + typeProjections; Variance projectionKind = variance == OUT_VARIANCE ? Variance.INVARIANT : OUT_VARIANCE; JetType superType = findCommonSupertype(outs, recursionDepth + 1, maxDepth); for (JetType upperBound: parameterDescriptor.getUpperBounds()) { @@ -309,7 +309,8 @@ public class CommonSupertypes { return new TypeProjectionImpl(projectionKind, superType); } if (ins != null) { - JetType intersection = TypeIntersector.intersectTypes(getBuiltIns(parameterDescriptor), JetTypeChecker.DEFAULT, ins); + assert !ins.isEmpty() : "In projections is empty for parameter " + parameterDescriptor + ", type projections " + typeProjections; + JetType intersection = TypeIntersector.intersectTypes(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 584bd4f8db2..c134318a78c 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeIntersector.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeIntersector.java @@ -37,31 +37,16 @@ import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Co public class TypeIntersector { - private final KotlinBuiltIns builtIns; - - public TypeIntersector(@NotNull KotlinBuiltIns builtIns) { - this.builtIns = builtIns; + public static boolean isIntersectionEmpty(@NotNull JetType typeA, @NotNull JetType typeB) { + return intersectTypes(JetTypeChecker.DEFAULT, new LinkedHashSet(Arrays.asList(typeA, typeB))) == null; } - 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 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 builtIns.getNullableAnyType(); - } + assert (!types.isEmpty()) : "Attempting to intersect empty set of types, this case should be dealt with on the call site."; if (types.size() == 1) { return types.iterator().next(); @@ -69,19 +54,21 @@ public class TypeIntersector { // Intersection of T1..Tn is an intersection of their non-null versions, // made nullable is they all were nullable + JetType nothingOrNullableNothing = null; boolean allNullable = true; - boolean nothingTypePresent = false; List nullabilityStripped = new ArrayList(types.size()); for (JetType type : types) { if (type.isError()) continue; - nothingTypePresent |= KotlinBuiltIns.isNothingOrNullableNothing(type); + if (KotlinBuiltIns.isNothingOrNullableNothing(type)) { + nothingOrNullableNothing = type; + } allNullable &= type.isMarkedNullable(); nullabilityStripped.add(TypeUtils.makeNotNullable(type)); } - if (nothingTypePresent) { - return allNullable ? builtIns.getNullableNothingType() : builtIns.getNothingType(); + if (nothingOrNullableNothing != null) { + return TypeUtils.makeNullableAsSpecified(nothingOrNullableNothing, allNullable); } 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 9c1860cd800..38db56c846d 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 @@ -217,7 +217,7 @@ private fun JetNamedDeclaration.guessType(context: BindingContext): Array ErrorUtils.containsErrorType(expectedType) }) { return arrayOf() } - val theType = TypeIntersector.intersectTypes(KotlinBuiltIns.getInstance(), JetTypeChecker.DEFAULT, expectedTypes) + val theType = TypeIntersector.intersectTypes(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 6afdb11bf88..f250f3f7e40 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 @@ -531,7 +531,7 @@ private class MutableParameter( private val defaultType: JetType by lazy { writable = false if (defaultTypes.isNotEmpty()) { - TypeIntersector.intersectTypes(originalDescriptor.builtIns, JetTypeChecker.DEFAULT, defaultTypes)!! + TypeIntersector.intersectTypes(JetTypeChecker.DEFAULT, defaultTypes)!! } else originalType }