Get rid of passing typeChecker from the call hierarchy
This commit is contained in:
+1
-2
@@ -51,7 +51,6 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
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.ControlStructureTypingUtils.ResolveConstruct
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||||
|
|
||||||
@@ -255,7 +254,7 @@ class GenericCandidateResolver(
|
|||||||
val possibleTypes = context.dataFlowInfo.getCollectedTypes(dataFlowValue)
|
val possibleTypes = context.dataFlowInfo.getCollectedTypes(dataFlowValue)
|
||||||
if (possibleTypes.isEmpty()) return type
|
if (possibleTypes.isEmpty()) return type
|
||||||
|
|
||||||
return TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, possibleTypes + type)
|
return TypeIntersector.intersectTypes(possibleTypes + type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <D : CallableDescriptor> completeTypeInferenceDependentOnFunctionArgumentsForCall(context: CallCandidateResolutionContext<D>) {
|
fun <D : CallableDescriptor> completeTypeInferenceDependentOnFunctionArgumentsForCall(context: CallCandidateResolutionContext<D>) {
|
||||||
|
|||||||
+2
-2
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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)
|
val upperBounds = filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND, values)
|
||||||
if (upperBounds.isNotEmpty()) {
|
if (upperBounds.isNotEmpty()) {
|
||||||
val intersectionOfUpperBounds = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, upperBounds)
|
val intersectionOfUpperBounds = TypeIntersector.intersectTypes(upperBounds)
|
||||||
if (intersectionOfUpperBounds != null && tryPossibleAnswer(bounds, intersectionOfUpperBounds)) {
|
if (intersectionOfUpperBounds != null && tryPossibleAnswer(bounds, intersectionOfUpperBounds)) {
|
||||||
return setOf(intersectionOfUpperBounds)
|
return setOf(intersectionOfUpperBounds)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-5
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.diagnostics.Errors.SMARTCAST_IMPOSSIBLE
|
||||||
import org.jetbrains.kotlin.psi.Call
|
import org.jetbrains.kotlin.psi.Call
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
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.*
|
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.BindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeIntersector
|
import org.jetbrains.kotlin.types.TypeIntersector
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class SmartCastManager {
|
class SmartCastManager {
|
||||||
@@ -100,7 +99,7 @@ class SmartCastManager {
|
|||||||
.distinct()
|
.distinct()
|
||||||
if (subTypes.isEmpty()) return null
|
if (subTypes.isEmpty()) return null
|
||||||
|
|
||||||
val intersection = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, subTypes)
|
val intersection = TypeIntersector.intersectTypes(subTypes)
|
||||||
if (intersection == null || !intersection.constructor.isDenotable) {
|
if (intersection == null || !intersection.constructor.isDenotable) {
|
||||||
return receiverParameterType
|
return receiverParameterType
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -203,28 +203,26 @@ object CastDiagnosticsUtil {
|
|||||||
expression: KtBinaryExpressionWithTypeRHS,
|
expression: KtBinaryExpressionWithTypeRHS,
|
||||||
context: ExpressionTypingContext,
|
context: ExpressionTypingContext,
|
||||||
targetType: KotlinType,
|
targetType: KotlinType,
|
||||||
actualType: KotlinType,
|
actualType: KotlinType
|
||||||
typeChecker: KotlinTypeChecker
|
|
||||||
): Boolean {
|
): Boolean {
|
||||||
// Here: x as? Type <=> x as Type?
|
// Here: x as? Type <=> x as Type?
|
||||||
val refinedTargetType = if (KtPsiUtil.isSafeCast(expression)) TypeUtils.makeNullable(targetType) else targetType
|
val refinedTargetType = if (KtPsiUtil.isSafeCast(expression)) TypeUtils.makeNullable(targetType) else targetType
|
||||||
val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(expression.left, actualType, context)
|
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`
|
// It is a warning "useless cast" for `as` and a warning "redundant is" for `is`
|
||||||
fun isRefinementUseless(
|
fun isRefinementUseless(
|
||||||
possibleTypes: Collection<KotlinType>,
|
possibleTypes: Collection<KotlinType>,
|
||||||
targetType: KotlinType,
|
targetType: KotlinType,
|
||||||
typeChecker: KotlinTypeChecker,
|
|
||||||
shouldCheckForExactType: Boolean
|
shouldCheckForExactType: Boolean
|
||||||
): 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)
|
return if (shouldCheckForExactType)
|
||||||
isExactTypeCast(intersectedType, targetType)
|
isExactTypeCast(intersectedType, targetType)
|
||||||
else
|
else
|
||||||
isUpcast(intersectedType, targetType, typeChecker)
|
isUpcast(intersectedType, targetType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldCheckForExactType(expression: KtBinaryExpressionWithTypeRHS, expectedType: KotlinType): Boolean {
|
private fun shouldCheckForExactType(expression: KtBinaryExpressionWithTypeRHS, expectedType: KotlinType): Boolean {
|
||||||
@@ -241,8 +239,8 @@ object CastDiagnosticsUtil {
|
|||||||
return candidateType == targetType && candidateType.isExtensionFunctionType == targetType.isExtensionFunctionType
|
return candidateType == targetType && candidateType.isExtensionFunctionType == targetType.isExtensionFunctionType
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isUpcast(candidateType: KotlinType, targetType: KotlinType, typeChecker: KotlinTypeChecker): Boolean {
|
private fun isUpcast(candidateType: KotlinType, targetType: KotlinType): Boolean {
|
||||||
if (!typeChecker.isSubtypeOf(candidateType, targetType)) return false
|
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(candidateType, targetType)) return false
|
||||||
|
|
||||||
if (candidateType.isFunctionType && targetType.isFunctionType) {
|
if (candidateType.isFunctionType && targetType.isFunctionType) {
|
||||||
return candidateType.isExtensionFunctionType == targetType.isExtensionFunctionType
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.TypeParameterDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
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.types.typeUtil.TypeUtilsKt;
|
||||||
import org.jetbrains.kotlin.utils.DFS;
|
import org.jetbrains.kotlin.utils.DFS;
|
||||||
|
|
||||||
@@ -305,7 +304,7 @@ public class CommonSupertypes {
|
|||||||
}
|
}
|
||||||
if (ins != null) {
|
if (ins != null) {
|
||||||
assert !ins.isEmpty() : "In projections is empty for parameter " + parameterDescriptor + ", type projections " + typeProjections;
|
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) {
|
if (intersection == null) {
|
||||||
return TypeUtils.makeStarProjection(parameterDescriptor);
|
return TypeUtils.makeStarProjection(parameterDescriptor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getB
|
|||||||
public class TypeIntersector {
|
public class TypeIntersector {
|
||||||
|
|
||||||
public static boolean isIntersectionEmpty(@NotNull KotlinType typeA, @NotNull KotlinType typeB) {
|
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
|
@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.";
|
assert !types.isEmpty() : "Attempting to intersect empty collection of types, this case should be dealt with on the call site.";
|
||||||
|
|
||||||
if (types.size() == 1) {
|
if (types.size() == 1) {
|
||||||
@@ -72,6 +72,7 @@ public class TypeIntersector {
|
|||||||
return ErrorUtils.createErrorType("Intersection of error types: " + types);
|
return ErrorUtils.createErrorType("Intersection of error types: " + types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KotlinTypeChecker typeChecker = KotlinTypeChecker.DEFAULT;
|
||||||
// Now we remove types that have subtypes in the list
|
// Now we remove types that have subtypes in the list
|
||||||
List<KotlinType> resultingTypes = new ArrayList<>();
|
List<KotlinType> resultingTypes = new ArrayList<>();
|
||||||
outer:
|
outer:
|
||||||
@@ -151,7 +152,7 @@ public class TypeIntersector {
|
|||||||
public static KotlinType getUpperBoundsAsType(@NotNull TypeParameterDescriptor descriptor) {
|
public static KotlinType getUpperBoundsAsType(@NotNull TypeParameterDescriptor descriptor) {
|
||||||
List<KotlinType> upperBounds = descriptor.getUpperBounds();
|
List<KotlinType> upperBounds = descriptor.getUpperBounds();
|
||||||
assert !upperBounds.isEmpty() : "Upper bound list is empty: " + descriptor;
|
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();
|
return upperBoundsAsType != null ? upperBoundsAsType : getBuiltIns(descriptor).getNothingType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -378,13 +378,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotlinTypeChecker typeChecker = KotlinTypeChecker.DEFAULT;
|
if (CastDiagnosticsUtil.INSTANCE.castIsUseless(expression, context, targetType, actualType)) {
|
||||||
if (CastDiagnosticsUtil.INSTANCE.castIsUseless(expression, context, targetType, actualType, typeChecker)) {
|
|
||||||
context.trace.report(USELESS_CAST.on(expression));
|
context.trace.report(USELESS_CAST.on(expression));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CastDiagnosticsUtil.isCastErased(actualType, targetType, typeChecker)) {
|
if (CastDiagnosticsUtil.isCastErased(actualType, targetType, KotlinTypeChecker.DEFAULT)) {
|
||||||
context.trace.report(UNCHECKED_CAST.on(expression, actualType, targetType));
|
context.trace.report(UNCHECKED_CAST.on(expression, actualType, targetType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -462,7 +462,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
|||||||
if (subjectType.containsError() || targetType.containsError()) return
|
if (subjectType.containsError() || targetType.containsError()) return
|
||||||
|
|
||||||
val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(subjectType, context, subjectDataFlowValue)
|
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))
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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) {
|
for (String type : types) {
|
||||||
typesToIntersect.add(makeType(type));
|
typesToIntersect.add(makeType(type));
|
||||||
}
|
}
|
||||||
KotlinType result = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, typesToIntersect);
|
KotlinType result = TypeIntersector.intersectTypes(typesToIntersect);
|
||||||
// assertNotNull("Intersection is null for " + typesToIntersect, result);
|
// assertNotNull("Intersection is null for " + typesToIntersect, result);
|
||||||
assertEquals(makeType(expected), result);
|
assertEquals(makeType(expected), result);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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) }) {
|
if (expectedTypes.isEmpty() || expectedTypes.any { expectedType -> ErrorUtils.containsErrorType(expectedType) }) {
|
||||||
return arrayOf()
|
return arrayOf()
|
||||||
}
|
}
|
||||||
val theType = TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, expectedTypes)
|
val theType = TypeIntersector.intersectTypes(expectedTypes)
|
||||||
return if (theType != null) {
|
return if (theType != null) {
|
||||||
arrayOf(theType)
|
arrayOf(theType)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -66,7 +66,6 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
|
|||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
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 {
|
private val defaultType: KotlinType by lazy {
|
||||||
writable = false
|
writable = false
|
||||||
if (defaultTypes.isNotEmpty()) {
|
if (defaultTypes.isNotEmpty()) {
|
||||||
TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, defaultTypes)!!
|
TypeIntersector.intersectTypes(defaultTypes)!!
|
||||||
}
|
}
|
||||||
else originalType
|
else originalType
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user