Get rid of passing typeChecker from the call hierarchy

This commit is contained in:
Mikhail Zarechenskiy
2017-09-01 14:15:30 +03:00
parent e7449a3584
commit 0dc29d6d7e
11 changed files with 27 additions and 33 deletions
@@ -51,7 +51,6 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.ResolveConstruct
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
@@ -255,7 +254,7 @@ class GenericCandidateResolver(
val possibleTypes = context.dataFlowInfo.getCollectedTypes(dataFlowValue)
if (possibleTypes.isEmpty()) return type
return TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, possibleTypes + type)
return TypeIntersector.intersectTypes(possibleTypes + type)
}
fun <D : CallableDescriptor> completeTypeInferenceDependentOnFunctionArgumentsForCall(context: CallCandidateResolutionContext<D>) {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -124,7 +124,7 @@ class TypeBoundsImpl(override val typeVariable: TypeVariable) : TypeBounds {
val upperBounds = filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND, values)
if (upperBounds.isNotEmpty()) {
val intersectionOfUpperBounds = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, upperBounds)
val intersectionOfUpperBounds = TypeIntersector.intersectTypes(upperBounds)
if (intersectionOfUpperBounds != null && tryPossibleAnswer(bounds, intersectionOfUpperBounds)) {
return setOf(intersectionOfUpperBounds)
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -21,9 +21,9 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.Errors.SMARTCAST_IMPOSSIBLE
import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.*
import org.jetbrains.kotlin.resolve.BindingContext.IMPLICIT_RECEIVER_SMARTCAST
import org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeIntersector
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import java.util.*
class SmartCastManager {
@@ -100,7 +99,7 @@ class SmartCastManager {
.distinct()
if (subTypes.isEmpty()) return null
val intersection = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, subTypes)
val intersection = TypeIntersector.intersectTypes(subTypes)
if (intersection == null || !intersection.constructor.isDenotable) {
return receiverParameterType
}
@@ -203,28 +203,26 @@ object CastDiagnosticsUtil {
expression: KtBinaryExpressionWithTypeRHS,
context: ExpressionTypingContext,
targetType: KotlinType,
actualType: KotlinType,
typeChecker: KotlinTypeChecker
actualType: KotlinType
): Boolean {
// Here: x as? Type <=> x as Type?
val refinedTargetType = if (KtPsiUtil.isSafeCast(expression)) TypeUtils.makeNullable(targetType) else targetType
val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(expression.left, actualType, context)
return isRefinementUseless(possibleTypes, refinedTargetType, typeChecker, shouldCheckForExactType(expression, context.expectedType))
return isRefinementUseless(possibleTypes, refinedTargetType, shouldCheckForExactType(expression, context.expectedType))
}
// It is a warning "useless cast" for `as` and a warning "redundant is" for `is`
fun isRefinementUseless(
possibleTypes: Collection<KotlinType>,
targetType: KotlinType,
typeChecker: KotlinTypeChecker,
shouldCheckForExactType: Boolean
): Boolean {
val intersectedType = TypeIntersector.intersectTypes(typeChecker, possibleTypes.map { it.upperIfFlexible() }) ?: return false
val intersectedType = TypeIntersector.intersectTypes(possibleTypes.map { it.upperIfFlexible() }) ?: return false
return if (shouldCheckForExactType)
isExactTypeCast(intersectedType, targetType)
else
isUpcast(intersectedType, targetType, typeChecker)
isUpcast(intersectedType, targetType)
}
private fun shouldCheckForExactType(expression: KtBinaryExpressionWithTypeRHS, expectedType: KotlinType): Boolean {
@@ -241,8 +239,8 @@ object CastDiagnosticsUtil {
return candidateType == targetType && candidateType.isExtensionFunctionType == targetType.isExtensionFunctionType
}
private fun isUpcast(candidateType: KotlinType, targetType: KotlinType, typeChecker: KotlinTypeChecker): Boolean {
if (!typeChecker.isSubtypeOf(candidateType, targetType)) return false
private fun isUpcast(candidateType: KotlinType, targetType: KotlinType): Boolean {
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(candidateType, targetType)) return false
if (candidateType.isFunctionType && targetType.isFunctionType) {
return candidateType.isExtensionFunctionType == targetType.isExtensionFunctionType
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
import org.jetbrains.kotlin.utils.DFS;
@@ -305,7 +304,7 @@ public class CommonSupertypes {
}
if (ins != null) {
assert !ins.isEmpty() : "In projections is empty for parameter " + parameterDescriptor + ", type projections " + typeProjections;
KotlinType intersection = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, ins);
KotlinType intersection = TypeIntersector.intersectTypes(ins);
if (intersection == null) {
return TypeUtils.makeStarProjection(parameterDescriptor);
}
@@ -37,11 +37,11 @@ import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getB
public class TypeIntersector {
public static boolean isIntersectionEmpty(@NotNull KotlinType typeA, @NotNull KotlinType typeB) {
return intersectTypes(KotlinTypeChecker.DEFAULT, new LinkedHashSet<>(Arrays.asList(typeA, typeB))) == null;
return intersectTypes(new LinkedHashSet<>(Arrays.asList(typeA, typeB))) == null;
}
@Nullable
public static KotlinType intersectTypes(@NotNull KotlinTypeChecker typeChecker, @NotNull Collection<KotlinType> types) {
public static KotlinType intersectTypes(@NotNull Collection<KotlinType> types) {
assert !types.isEmpty() : "Attempting to intersect empty collection of types, this case should be dealt with on the call site.";
if (types.size() == 1) {
@@ -72,6 +72,7 @@ public class TypeIntersector {
return ErrorUtils.createErrorType("Intersection of error types: " + types);
}
KotlinTypeChecker typeChecker = KotlinTypeChecker.DEFAULT;
// Now we remove types that have subtypes in the list
List<KotlinType> resultingTypes = new ArrayList<>();
outer:
@@ -151,7 +152,7 @@ public class TypeIntersector {
public static KotlinType getUpperBoundsAsType(@NotNull TypeParameterDescriptor descriptor) {
List<KotlinType> upperBounds = descriptor.getUpperBounds();
assert !upperBounds.isEmpty() : "Upper bound list is empty: " + descriptor;
KotlinType upperBoundsAsType = intersectTypes(KotlinTypeChecker.DEFAULT, upperBounds);
KotlinType upperBoundsAsType = intersectTypes(upperBounds);
return upperBoundsAsType != null ? upperBoundsAsType : getBuiltIns(descriptor).getNothingType();
}
@@ -378,13 +378,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return;
}
KotlinTypeChecker typeChecker = KotlinTypeChecker.DEFAULT;
if (CastDiagnosticsUtil.INSTANCE.castIsUseless(expression, context, targetType, actualType, typeChecker)) {
if (CastDiagnosticsUtil.INSTANCE.castIsUseless(expression, context, targetType, actualType)) {
context.trace.report(USELESS_CAST.on(expression));
return;
}
if (CastDiagnosticsUtil.isCastErased(actualType, targetType, typeChecker)) {
if (CastDiagnosticsUtil.isCastErased(actualType, targetType, KotlinTypeChecker.DEFAULT)) {
context.trace.report(UNCHECKED_CAST.on(expression, actualType, targetType));
}
}
@@ -462,7 +462,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
if (subjectType.containsError() || targetType.containsError()) return
val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(subjectType, context, subjectDataFlowValue)
if (CastDiagnosticsUtil.isRefinementUseless(possibleTypes, targetType, KotlinTypeChecker.DEFAULT, false)) {
if (CastDiagnosticsUtil.isRefinementUseless(possibleTypes, targetType, false)) {
context.trace.report(Errors.USELESS_IS_CHECK.on(isCheck, !negated))
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -509,7 +509,7 @@ public class KotlinTypeCheckerTest extends KotlinTestWithEnvironment {
for (String type : types) {
typesToIntersect.add(makeType(type));
}
KotlinType result = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, typesToIntersect);
KotlinType result = TypeIntersector.intersectTypes(typesToIntersect);
// assertNotNull("Intersection is null for " + typesToIntersect, result);
assertEquals(makeType(expected), result);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
* Copyright 2010-2017 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.
@@ -255,7 +255,7 @@ private fun KtNamedDeclaration.guessType(context: BindingContext): Array<KotlinT
if (expectedTypes.isEmpty() || expectedTypes.any { expectedType -> ErrorUtils.containsErrorType(expectedType) }) {
return arrayOf()
}
val theType = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, expectedTypes)
val theType = TypeIntersector.intersectTypes(expectedTypes)
return if (theType != null) {
arrayOf(theType)
}
@@ -66,7 +66,6 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.DFS.*
@@ -514,7 +513,7 @@ internal class MutableParameter(
private val defaultType: KotlinType by lazy {
writable = false
if (defaultTypes.isNotEmpty()) {
TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, defaultTypes)!!
TypeIntersector.intersectTypes(defaultTypes)!!
}
else originalType
}