[NI] Use definitely not-null types for smartcasts
This commit is contained in:
@@ -3389,7 +3389,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
}
|
||||
|
||||
private TypeAndNullability calcTypeForIEEE754ArithmeticIfNeeded(@Nullable KtExpression expression) {
|
||||
return CodegenUtilKt.calcTypeForIEEE754ArithmeticIfNeeded(expression, bindingContext, context.getFunctionDescriptor());
|
||||
return CodegenUtilKt.calcTypeForIEEE754ArithmeticIfNeeded(
|
||||
expression, bindingContext, context.getFunctionDescriptor(), state.getLanguageVersionSettings());
|
||||
}
|
||||
|
||||
private StackValue generateAssignmentExpression(KtBinaryExpression expression) {
|
||||
|
||||
@@ -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.
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
@@ -277,7 +278,12 @@ fun Collection<VariableDescriptor>.filterOutDescriptorsWithSpecialNames() = filt
|
||||
|
||||
class TypeAndNullability(@JvmField val type: Type, @JvmField val isNullable: Boolean)
|
||||
|
||||
fun calcTypeForIEEE754ArithmeticIfNeeded(expression: KtExpression?, bindingContext: BindingContext, descriptor: DeclarationDescriptor): TypeAndNullability? {
|
||||
fun calcTypeForIEEE754ArithmeticIfNeeded(
|
||||
expression: KtExpression?,
|
||||
bindingContext: BindingContext,
|
||||
descriptor: DeclarationDescriptor,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): TypeAndNullability? {
|
||||
val ktType = expression.kotlinType(bindingContext) ?: return null
|
||||
|
||||
if (KotlinBuiltIns.isDoubleOrNullableDouble(ktType)) {
|
||||
@@ -289,7 +295,7 @@ fun calcTypeForIEEE754ArithmeticIfNeeded(expression: KtExpression?, bindingConte
|
||||
}
|
||||
|
||||
val dataFlow = DataFlowValueFactory.createDataFlowValue(expression!!, ktType, bindingContext, descriptor)
|
||||
val stableTypes = bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow)
|
||||
val stableTypes = bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow, languageVersionSettings)
|
||||
return stableTypes.firstNotNullResult {
|
||||
when {
|
||||
KotlinBuiltIns.isDoubleOrNullableDouble(it) -> TypeAndNullability(Type.DOUBLE_TYPE, TypeUtils.isNullableType(it))
|
||||
|
||||
+3
-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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -49,7 +49,8 @@ object ProtectedSyntheticExtensionCallChecker : CallChecker {
|
||||
|
||||
val receiverValue = resolvedCall.extensionReceiver as ReceiverValue
|
||||
val receiverTypes = listOf(receiverValue.type) + context.dataFlowInfo.getStableTypes(
|
||||
DataFlowValueFactory.createDataFlowValue(receiverValue, context.trace.bindingContext, context.scope.ownerDescriptor)
|
||||
DataFlowValueFactory.createDataFlowValue(receiverValue, context.trace.bindingContext, context.scope.ownerDescriptor),
|
||||
context.languageVersionSettings
|
||||
)
|
||||
|
||||
if (receiverTypes.none { Visibilities.isVisible(getReceiverValueWithSmartCast(null, it), sourceFunction, from) }) {
|
||||
|
||||
+1
-1
@@ -331,7 +331,7 @@ class GenericCandidateResolver(
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(deparenthesizedArgument, type, context)
|
||||
if (!dataFlowValue.isStable) return type
|
||||
|
||||
val possibleTypes = context.dataFlowInfo.getCollectedTypes(dataFlowValue)
|
||||
val possibleTypes = context.dataFlowInfo.getCollectedTypes(dataFlowValue, context.languageVersionSettings)
|
||||
if (possibleTypes.isEmpty()) return type
|
||||
|
||||
return TypeIntersector.intersectTypes(possibleTypes + type)
|
||||
|
||||
@@ -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.
|
||||
@@ -48,7 +48,7 @@ interface DataFlowInfo {
|
||||
* are NOT included. So it's quite possible to get an empty set here.
|
||||
* Also, type order in the result set MAKES SENSE so keep it stable and do not change without reason
|
||||
*/
|
||||
fun getCollectedTypes(key: DataFlowValue): Set<KotlinType>
|
||||
fun getCollectedTypes(key: DataFlowValue, languageVersionSettings: LanguageVersionSettings): Set<KotlinType>
|
||||
|
||||
/**
|
||||
* Returns possible types for the given value if it's stable.
|
||||
@@ -58,7 +58,7 @@ interface DataFlowInfo {
|
||||
* are NOT included. So it's quite possible to get an empty set here.
|
||||
* Also, type order in the result set MAKES SENSE so keep it stable and do not change without reason
|
||||
*/
|
||||
fun getStableTypes(key: DataFlowValue): Set<KotlinType>
|
||||
fun getStableTypes(key: DataFlowValue, languageVersionSettings: LanguageVersionSettings): Set<KotlinType>
|
||||
|
||||
/**
|
||||
* Call this function to clear all data flow information about
|
||||
|
||||
+39
-23
@@ -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.
|
||||
@@ -16,20 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.smartcasts
|
||||
|
||||
import com.google.common.collect.SetMultimap
|
||||
import com.google.common.collect.LinkedHashMultimap
|
||||
import com.google.common.collect.SetMultimap
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
import org.jetbrains.kotlin.types.isFlexible
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.utils.newLinkedHashSetWithExpectedSize
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.utils.newLinkedHashSetWithExpectedSize
|
||||
import java.util.*
|
||||
|
||||
internal class DelegatingDataFlowInfo private constructor(
|
||||
@@ -141,10 +138,15 @@ internal class DelegatingDataFlowInfo private constructor(
|
||||
return nullability != getCollectedNullability(value)
|
||||
}
|
||||
|
||||
override fun getCollectedTypes(key: DataFlowValue) = getCollectedTypes(key, true)
|
||||
override fun getCollectedTypes(key: DataFlowValue, languageVersionSettings: LanguageVersionSettings) =
|
||||
getCollectedTypes(key, true, languageVersionSettings)
|
||||
|
||||
private fun getCollectedTypes(key: DataFlowValue, enrichWithNotNull: Boolean): Set<KotlinType> {
|
||||
val types = collectTypesFromMeAndParents(key)
|
||||
private fun getCollectedTypes(
|
||||
key: DataFlowValue,
|
||||
enrichWithNotNull: Boolean,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): Set<KotlinType> {
|
||||
val types = collectTypesFromMeAndParents(key, languageVersionSettings)
|
||||
if (!enrichWithNotNull || getCollectedNullability(key).canBeNull()) {
|
||||
return types
|
||||
}
|
||||
@@ -152,20 +154,34 @@ internal class DelegatingDataFlowInfo private constructor(
|
||||
val enrichedTypes = newLinkedHashSetWithExpectedSize<KotlinType>(types.size + 1)
|
||||
val originalType = key.type
|
||||
for (type in types) {
|
||||
enrichedTypes.add(TypeUtils.makeNotNullable(type))
|
||||
enrichedTypes.add(type.makeReallyNotNullIfNeeded(languageVersionSettings))
|
||||
}
|
||||
if (originalType.isMarkedNullable) {
|
||||
enrichedTypes.add(TypeUtils.makeNotNullable(originalType))
|
||||
if (originalType.canBeDefinitelyNotNullOrNotNull(languageVersionSettings)) {
|
||||
enrichedTypes.add(originalType.makeReallyNotNullIfNeeded(languageVersionSettings))
|
||||
}
|
||||
|
||||
return enrichedTypes
|
||||
}
|
||||
|
||||
override fun getStableTypes(key: DataFlowValue) = getStableTypes(key, true)
|
||||
override fun getStableTypes(key: DataFlowValue, languageVersionSettings: LanguageVersionSettings) =
|
||||
getStableTypes(key, true, languageVersionSettings)
|
||||
|
||||
private fun getStableTypes(key: DataFlowValue, enrichWithNotNull: Boolean) =
|
||||
if (!key.isStable) LinkedHashSet() else getCollectedTypes(key, enrichWithNotNull)
|
||||
private fun getStableTypes(key: DataFlowValue, enrichWithNotNull: Boolean, languageVersionSettings: LanguageVersionSettings) =
|
||||
if (!key.isStable) LinkedHashSet() else getCollectedTypes(key, enrichWithNotNull, languageVersionSettings)
|
||||
|
||||
private fun KotlinType.canBeDefinitelyNotNullOrNotNull(settings: LanguageVersionSettings): Boolean {
|
||||
return if (settings.supportsFeature(LanguageFeature.NewInference))
|
||||
this.isMarkedNullable || DefinitelyNotNullType.makesSenseToBeDefinitelyNotNull(this.unwrap())
|
||||
else
|
||||
this.isMarkedNullable
|
||||
}
|
||||
|
||||
private fun KotlinType.makeReallyNotNullIfNeeded(settings: LanguageVersionSettings): KotlinType {
|
||||
return if (settings.supportsFeature(LanguageFeature.NewInference))
|
||||
this.unwrap().makeDefinitelyNotNullOrNotNull()
|
||||
else
|
||||
TypeUtils.makeNotNullable(this)
|
||||
}
|
||||
/**
|
||||
* Call this function to clear all data flow information about
|
||||
* the given data flow value.
|
||||
@@ -184,7 +200,7 @@ internal class DelegatingDataFlowInfo private constructor(
|
||||
putNullabilityAndTypeInfo(nullability, a, nullabilityOfB, languageVersionSettings, affectReceiver = false)
|
||||
|
||||
val newTypeInfo = newTypeInfo()
|
||||
var typesForB = getStableTypes(b)
|
||||
var typesForB = getStableTypes(b, languageVersionSettings)
|
||||
// Own type of B must be recorded separately, e.g. for a constant
|
||||
// But if its type is the same as A, there is no reason to do it
|
||||
// because own type is not saved in this set
|
||||
@@ -211,8 +227,8 @@ internal class DelegatingDataFlowInfo private constructor(
|
||||
|
||||
// NB: == has no guarantees of type equality, see KT-11280 for the example
|
||||
if (identityEquals || !nullabilityOfA.canBeNonNull() || !nullabilityOfB.canBeNonNull()) {
|
||||
newTypeInfo.putAll(a, getStableTypes(b, false))
|
||||
newTypeInfo.putAll(b, getStableTypes(a, false))
|
||||
newTypeInfo.putAll(a, getStableTypes(b, false, languageVersionSettings))
|
||||
newTypeInfo.putAll(b, getStableTypes(a, false, languageVersionSettings))
|
||||
if (a.type != b.type) {
|
||||
// To avoid recording base types of own type
|
||||
if (!a.type.isSubtypeOf(b.type)) {
|
||||
@@ -228,7 +244,7 @@ internal class DelegatingDataFlowInfo private constructor(
|
||||
return if (changed) create(this, resultNullabilityInfo, if (newTypeInfo.isEmpty) EMPTY_TYPE_INFO else newTypeInfo) else this
|
||||
}
|
||||
|
||||
private fun collectTypesFromMeAndParents(value: DataFlowValue): Set<KotlinType> {
|
||||
private fun collectTypesFromMeAndParents(value: DataFlowValue, languageVersionSettings: LanguageVersionSettings): Set<KotlinType> {
|
||||
val types = LinkedHashSet<KotlinType>()
|
||||
|
||||
var current: DataFlowInfo? = this
|
||||
@@ -238,7 +254,7 @@ internal class DelegatingDataFlowInfo private constructor(
|
||||
current = if (value == current.valueWithGivenTypeInfo) null else current.parent
|
||||
}
|
||||
else {
|
||||
types.addAll(current.getCollectedTypes(value))
|
||||
types.addAll(current.getCollectedTypes(value, languageVersionSettings))
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -266,7 +282,7 @@ internal class DelegatingDataFlowInfo private constructor(
|
||||
value: DataFlowValue, type: KotlinType, languageVersionSettings: LanguageVersionSettings
|
||||
): DataFlowInfo {
|
||||
if (value.type == type) return this
|
||||
if (getCollectedTypes(value).contains(type)) return this
|
||||
if (getCollectedTypes(value, languageVersionSettings).contains(type)) return this
|
||||
if (!value.type.isFlexible() && value.type.isSubtypeOf(type)) return this
|
||||
val newTypeInfo = newTypeInfo()
|
||||
newTypeInfo.put(value, type)
|
||||
|
||||
+11
-6
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.smartcasts
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.SMARTCAST_IMPOSSIBLE
|
||||
import org.jetbrains.kotlin.psi.Call
|
||||
@@ -39,9 +40,11 @@ class SmartCastManager {
|
||||
receiverToCast: ReceiverValue,
|
||||
bindingContext: BindingContext,
|
||||
containingDeclarationOrModule: DeclarationDescriptor,
|
||||
dataFlowInfo: DataFlowInfo
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): List<KotlinType> {
|
||||
val variants = getSmartCastVariantsExcludingReceiver(bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast)
|
||||
val variants = getSmartCastVariantsExcludingReceiver(
|
||||
bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings)
|
||||
val result = ArrayList<KotlinType>(variants.size + 1)
|
||||
result.add(receiverToCast.type)
|
||||
result.addAll(variants)
|
||||
@@ -58,7 +61,8 @@ class SmartCastManager {
|
||||
return getSmartCastVariantsExcludingReceiver(context.trace.bindingContext,
|
||||
context.scope.ownerDescriptor,
|
||||
context.dataFlowInfo,
|
||||
receiverToCast)
|
||||
receiverToCast,
|
||||
context.languageVersionSettings)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,10 +72,11 @@ class SmartCastManager {
|
||||
bindingContext: BindingContext,
|
||||
containingDeclarationOrModule: DeclarationDescriptor,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
receiverToCast: ReceiverValue
|
||||
receiverToCast: ReceiverValue,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): Collection<KotlinType> {
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverToCast, bindingContext, containingDeclarationOrModule)
|
||||
return dataFlowInfo.getCollectedTypes(dataFlowValue)
|
||||
return dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings)
|
||||
}
|
||||
|
||||
fun getSmartCastReceiverResult(
|
||||
@@ -163,7 +168,7 @@ class SmartCastManager {
|
||||
recordExpressionType: Boolean
|
||||
): SmartCastResult? {
|
||||
val calleeExpression = call?.calleeExpression
|
||||
for (possibleType in c.dataFlowInfo.getCollectedTypes(dataFlowValue)) {
|
||||
for (possibleType in c.dataFlowInfo.getCollectedTypes(dataFlowValue, c.languageVersionSettings)) {
|
||||
if (ArgumentTypeResolver.isSubtypeOfForArgumentType(possibleType, expectedType) && (additionalPredicate == null || additionalPredicate(possibleType))) {
|
||||
if (expression != null) {
|
||||
recordCastOrError(expression, possibleType, c.trace, dataFlowValue, call, recordExpressionType)
|
||||
|
||||
+3
-2
@@ -79,7 +79,7 @@ class KotlinResolutionCallbacksImpl(
|
||||
|
||||
fun createCallArgument(ktExpression: KtExpression, typeInfo: KotlinTypeInfo) =
|
||||
createSimplePSICallArgument(trace.bindingContext, outerCallContext.statementFilter, outerCallContext.scope.ownerDescriptor,
|
||||
CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo)
|
||||
CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo, languageVersionSettings)
|
||||
|
||||
val lambdaInfo = LambdaInfo(expectedReturnType ?: TypeUtils.NO_EXPECTED_TYPE,
|
||||
if (expectedReturnType == null) ContextDependency.DEPENDENT else ContextDependency.INDEPENDENT)
|
||||
@@ -156,7 +156,8 @@ class KotlinResolutionCallbacksImpl(
|
||||
resolvedAtom.candidateDescriptor,
|
||||
trace.bindingContext,
|
||||
psiKotlinCall.resultDataFlowInfo,
|
||||
ExpressionReceiver.create(expression, returnType, trace.bindingContext)
|
||||
ExpressionReceiver.create(expression, returnType, trace.bindingContext),
|
||||
languageVersionSettings
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -199,7 +200,8 @@ internal fun createSimplePSICallArgument(
|
||||
typeInfoForArgument: KotlinTypeInfo
|
||||
) = createSimplePSICallArgument(contextForArgument.trace.bindingContext, contextForArgument.statementFilter,
|
||||
contextForArgument.scope.ownerDescriptor, valueArgument,
|
||||
contextForArgument.dataFlowInfo, typeInfoForArgument)
|
||||
contextForArgument.dataFlowInfo, typeInfoForArgument,
|
||||
contextForArgument.languageVersionSettings)
|
||||
|
||||
internal fun createSimplePSICallArgument(
|
||||
bindingContext: BindingContext,
|
||||
@@ -207,7 +209,8 @@ internal fun createSimplePSICallArgument(
|
||||
ownerDescriptor: DeclarationDescriptor,
|
||||
valueArgument: ValueArgument,
|
||||
dataFlowInfoBeforeThisArgument: DataFlowInfo,
|
||||
typeInfoForArgument: KotlinTypeInfo
|
||||
typeInfoForArgument: KotlinTypeInfo,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): SimplePSIKotlinCallArgument? {
|
||||
|
||||
val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null
|
||||
@@ -223,7 +226,8 @@ internal fun createSimplePSICallArgument(
|
||||
val receiverToCast = transformToReceiverWithSmartCastInfo(
|
||||
ownerDescriptor, bindingContext,
|
||||
typeInfoForArgument.dataFlowInfo, // dataFlowInfoBeforeThisArgument cannot be used here, because of if() { if (x != null) return; x }
|
||||
ExpressionReceiver.create(ktExpression, baseType, bindingContext)
|
||||
ExpressionReceiver.create(ktExpression, baseType, bindingContext),
|
||||
languageVersionSettings
|
||||
).let {
|
||||
if (onlyResolvedCall == null) it.prepareReceiverRegardingCaptureTypes() else it
|
||||
}
|
||||
|
||||
+8
-3
@@ -491,16 +491,21 @@ class NewResolutionOldInference(
|
||||
}
|
||||
|
||||
fun ResolutionContext<*>.transformToReceiverWithSmartCastInfo(receiver: ReceiverValue) =
|
||||
transformToReceiverWithSmartCastInfo(scope.ownerDescriptor, trace.bindingContext, dataFlowInfo, receiver)
|
||||
transformToReceiverWithSmartCastInfo(scope.ownerDescriptor, trace.bindingContext, dataFlowInfo, receiver, languageVersionSettings)
|
||||
|
||||
fun transformToReceiverWithSmartCastInfo(
|
||||
containingDescriptor: DeclarationDescriptor,
|
||||
bindingContext: BindingContext,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
receiver: ReceiverValue
|
||||
receiver: ReceiverValue,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): ReceiverValueWithSmartCastInfo {
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver, bindingContext, containingDescriptor)
|
||||
return ReceiverValueWithSmartCastInfo(receiver, dataFlowInfo.getCollectedTypes(dataFlowValue), dataFlowValue.isStable)
|
||||
return ReceiverValueWithSmartCastInfo(
|
||||
receiver,
|
||||
dataFlowInfo.getCollectedTypes(dataFlowValue, languageVersionSettings),
|
||||
dataFlowValue.isStable
|
||||
)
|
||||
}
|
||||
|
||||
@Deprecated("Temporary error")
|
||||
|
||||
@@ -372,7 +372,11 @@ class PSICallResolver(
|
||||
|
||||
temporaryTrace.record(BindingContext.REFERENCE_TARGET, calleeExpression, variable.resolvedCall.candidateDescriptor)
|
||||
val dataFlowValue = DataFlowValueFactory.createDataFlowValue(variableReceiver, temporaryTrace.bindingContext, context.scope.ownerDescriptor)
|
||||
return ReceiverValueWithSmartCastInfo(variableReceiver, context.dataFlowInfo.getCollectedTypes(dataFlowValue), dataFlowValue.isStable)
|
||||
return ReceiverValueWithSmartCastInfo(
|
||||
variableReceiver,
|
||||
context.dataFlowInfo.getCollectedTypes(dataFlowValue, context.languageVersionSettings),
|
||||
dataFlowValue.isStable
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -381,17 +381,18 @@ public class DataFlowAnalyzer {
|
||||
@NotNull ResolutionContext c
|
||||
) {
|
||||
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, c);
|
||||
return getAllPossibleTypes(type, c, dataFlowValue);
|
||||
return getAllPossibleTypes(type, c, dataFlowValue, c.languageVersionSettings);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<KotlinType> getAllPossibleTypes(
|
||||
@NotNull KotlinType type,
|
||||
@NotNull ResolutionContext c,
|
||||
@NotNull DataFlowValue dataFlowValue
|
||||
@NotNull DataFlowValue dataFlowValue,
|
||||
@NotNull LanguageVersionSettings languageVersionSettings
|
||||
) {
|
||||
Collection<KotlinType> possibleTypes = Sets.newHashSet(type);
|
||||
possibleTypes.addAll(c.dataFlowInfo.getStableTypes(dataFlowValue));
|
||||
possibleTypes.addAll(c.dataFlowInfo.getStableTypes(dataFlowValue, languageVersionSettings));
|
||||
return possibleTypes;
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -102,7 +102,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
||||
DataFlowValueFactory.createDataFlowValue(it, subjectType, contextAfterSubject)
|
||||
} ?: DataFlowValue.nullValue(components.builtIns)
|
||||
|
||||
val possibleTypesForSubject = subjectTypeInfo?.dataFlowInfo?.getStableTypes(subjectDataFlowValue) ?: emptySet()
|
||||
val possibleTypesForSubject = subjectTypeInfo?.dataFlowInfo?.getStableTypes(
|
||||
subjectDataFlowValue, components.languageVersionSettings) ?: emptySet()
|
||||
checkSmartCastsInSubjectIfRequired(expression, contextBeforeSubject, subjectType, possibleTypesForSubject)
|
||||
|
||||
val dataFlowInfoForEntries = analyzeConditionsInWhenEntries(expression, contextAfterSubject, subjectDataFlowValue, subjectType)
|
||||
@@ -463,7 +464,7 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
||||
) {
|
||||
if (subjectType.containsError() || targetType.containsError()) return
|
||||
|
||||
val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(subjectType, context, subjectDataFlowValue)
|
||||
val possibleTypes = DataFlowAnalyzer.getAllPossibleTypes(subjectType, context, subjectDataFlowValue, context.languageVersionSettings)
|
||||
if (CastDiagnosticsUtil.isRefinementUseless(possibleTypes, targetType, false)) {
|
||||
context.trace.report(Errors.USELESS_IS_CHECK.on(isCheck, !negated))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user