From 7f0cca52caac1ad0c7a7fed9ae6d84865d039bd7 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 28 Nov 2017 16:16:59 +0300 Subject: [PATCH] [NI] Use definitely not-null types for smartcasts --- .../kotlin/codegen/ExpressionCodegen.java | 3 +- .../jetbrains/kotlin/codegen/codegenUtil.kt | 12 +++- .../ProtectedSyntheticExtensionCallChecker.kt | 5 +- .../resolve/calls/GenericCandidateResolver.kt | 2 +- .../resolve/calls/smartcasts/DataFlowInfo.kt | 6 +- .../smartcasts/DelegatingDataFlowInfo.kt | 62 ++++++++++++------- .../calls/smartcasts/SmartCastManager.kt | 17 +++-- .../tower/KotlinResolutionCallbacksImpl.kt | 5 +- .../resolve/calls/tower/NewCallArguments.kt | 10 ++- .../calls/tower/NewResolutionOldInference.kt | 11 +++- .../resolve/calls/tower/PSICallResolver.kt | 6 +- .../types/expressions/DataFlowAnalyzer.java | 7 ++- .../PatternMatchingTypingVisitor.kt | 5 +- .../codeInsight/ReferenceVariantsHelper.kt | 9 ++- .../jetbrains/kotlin/idea/util/CallType.kt | 21 +++++-- .../org/jetbrains/kotlin/idea/util/Utils.kt | 8 ++- .../kotlin/idea/util/extensionsUtils.kt | 41 +----------- .../KotlinExpressionTypeProvider.kt | 5 +- .../callableBuilder/typeUtils.kt | 4 +- .../extractionEngine/ExtractionData.kt | 10 +-- .../extractionEngine/inferParameterInfo.kt | 9 ++- .../js/translate/expression/WhenTranslator.kt | 5 +- .../intrinsic/operation/EqualsBOIF.kt | 4 +- 23 files changed, 154 insertions(+), 113 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 691828d8607..fdcf73fd988 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -3389,7 +3389,8 @@ public class ExpressionCodegen extends KtVisitor 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) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt index 3769e04e2b7..5df37e36c4f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt @@ -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.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)) diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt index 9dabfce44b6..1eb98ebf7c5 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/ProtectedSyntheticExtensionCallChecker.kt @@ -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) }) { 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 9646e101df9..0b050e581a2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/GenericCandidateResolver.kt @@ -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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowInfo.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowInfo.kt index f2d96b12735..9436db538b3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowInfo.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DataFlowInfo.kt @@ -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 + fun getCollectedTypes(key: DataFlowValue, languageVersionSettings: LanguageVersionSettings): Set /** * 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 + fun getStableTypes(key: DataFlowValue, languageVersionSettings: LanguageVersionSettings): Set /** * Call this function to clear all data flow information about diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DelegatingDataFlowInfo.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DelegatingDataFlowInfo.kt index 4e9cdb27a69..b3a8abf8387 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DelegatingDataFlowInfo.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/DelegatingDataFlowInfo.kt @@ -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 { - val types = collectTypesFromMeAndParents(key) + private fun getCollectedTypes( + key: DataFlowValue, + enrichWithNotNull: Boolean, + languageVersionSettings: LanguageVersionSettings + ): Set { + val types = collectTypesFromMeAndParents(key, languageVersionSettings) if (!enrichWithNotNull || getCollectedNullability(key).canBeNull()) { return types } @@ -152,20 +154,34 @@ internal class DelegatingDataFlowInfo private constructor( val enrichedTypes = newLinkedHashSetWithExpectedSize(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 { + private fun collectTypesFromMeAndParents(value: DataFlowValue, languageVersionSettings: LanguageVersionSettings): Set { val types = LinkedHashSet() 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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt index 34e82ce88e1..95858594b2b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt @@ -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 { - val variants = getSmartCastVariantsExcludingReceiver(bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast) + val variants = getSmartCastVariantsExcludingReceiver( + bindingContext, containingDeclarationOrModule, dataFlowInfo, receiverToCast, languageVersionSettings) val result = ArrayList(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 { 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) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt index f14664501f8..df032ca8d1e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt @@ -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 ) } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt index d713b3e0ed2..704ab001f62 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt @@ -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 } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt index e452e8fcee5..39918b21ad8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewResolutionOldInference.kt @@ -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") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index b4e086d9bd1..d465277eaed 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -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 + ) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java index c4f8947f841..fbc90f23362 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DataFlowAnalyzer.java @@ -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 getAllPossibleTypes( @NotNull KotlinType type, @NotNull ResolutionContext c, - @NotNull DataFlowValue dataFlowValue + @NotNull DataFlowValue dataFlowValue, + @NotNull LanguageVersionSettings languageVersionSettings ) { Collection possibleTypes = Sets.newHashSet(type); - possibleTypes.addAll(c.dataFlowInfo.getStableTypes(dataFlowValue)); + possibleTypes.addAll(c.dataFlowInfo.getStableTypes(dataFlowValue, languageVersionSettings)); return possibleTypes; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt index 7ea9da30366..cb9e4b7184f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt @@ -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)) } diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt index 1725f2564a2..2cc56d348e7 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.idea.codeInsight import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.frontendService @@ -176,7 +177,13 @@ class ReferenceVariantsHelper( val smartCastManager = resolutionFacade.frontendService() val implicitReceiverTypes = resolutionScope.getImplicitReceiversWithInstance().flatMap { - smartCastManager.getSmartCastVariantsWithLessSpecificExcluded(it.value, bindingContext, containingDeclaration, dataFlowInfo) + smartCastManager.getSmartCastVariantsWithLessSpecificExcluded( + it.value, + bindingContext, + containingDeclaration, + dataFlowInfo, + resolutionFacade.frontendService() + ) }.toSet() val descriptors = LinkedHashSet() diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt index 9369b25dd27..9f43fc0ef85 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt @@ -17,8 +17,10 @@ package org.jetbrains.kotlin.idea.util import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.idea.resolve.frontendService import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* @@ -43,7 +45,6 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.expressions.DoubleColonLHS import org.jetbrains.kotlin.util.supertypesWithAny import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull -import java.lang.RuntimeException import java.util.* sealed class CallType(val descriptorKindFilter: DescriptorKindFilter) { @@ -232,6 +233,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex( stableSmartCastsOnly: Boolean, withImplicitReceiversWhenExplicitPresent: Boolean = false ): Collection? { + val languageVersionSettings = resolutionFacade.frontendService() + val receiverExpression: KtExpression? when (this) { is CallTypeAndReceiver.CALLABLE_REFERENCE -> { @@ -242,7 +245,8 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex( is DoubleColonLHS.Expression -> { val receiverValue = ExpressionReceiver.create(receiver, lhs.type, bindingContext) - return receiverValueTypes(receiverValue, lhs.dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly) + return receiverValueTypes(receiverValue, lhs.dataFlowInfo, bindingContext, + moduleDescriptor, stableSmartCastsOnly, languageVersionSettings) .map { ReceiverType(it, 0) } } } @@ -300,7 +304,7 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex( var receiverIndex = 0 fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) { - val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly) + val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings) types.mapTo(result) { ReceiverType(it, receiverIndex, implicit) } receiverIndex++ } @@ -318,11 +322,18 @@ private fun receiverValueTypes( dataFlowInfo: DataFlowInfo, bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor, - stableSmartCastsOnly: Boolean + stableSmartCastsOnly: Boolean, + languageVersionSettings: LanguageVersionSettings ): List { val dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiverValue, bindingContext, moduleDescriptor) return if (dataFlowValue.isStable || !stableSmartCastsOnly) { // we don't include smart cast receiver types for "unstable" receiver value to mark members grayed - SmartCastManager().getSmartCastVariantsWithLessSpecificExcluded(receiverValue, bindingContext, moduleDescriptor, dataFlowInfo) + SmartCastManager().getSmartCastVariantsWithLessSpecificExcluded( + receiverValue, + bindingContext, + moduleDescriptor, + dataFlowInfo, + languageVersionSettings + ) } else { listOf(receiverValue.type) diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt index bef88eac4ed..f804278e9dc 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/Utils.kt @@ -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. @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.util +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* @@ -57,9 +58,10 @@ fun SmartCastManager.getSmartCastVariantsWithLessSpecificExcluded( receiverToCast: ReceiverValue, bindingContext: BindingContext, containingDeclarationOrModule: DeclarationDescriptor, - dataFlowInfo: DataFlowInfo + dataFlowInfo: DataFlowInfo, + languageVersionSettings: LanguageVersionSettings ): List { - val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo) + val variants = getSmartCastVariants(receiverToCast, bindingContext, containingDeclarationOrModule, dataFlowInfo, languageVersionSettings) return variants.filter { type -> variants.all { another -> another === type || chooseMoreSpecific(type, another).let { it == null || it === type } } } diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/extensionsUtils.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/extensionsUtils.kt index 41a4c32021d..8f694ebf7d1 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/extensionsUtils.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/extensionsUtils.kt @@ -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. @@ -24,9 +24,6 @@ import org.jetbrains.kotlin.psi.KtPsiUtil import org.jetbrains.kotlin.psi.KtReferenceExpression import org.jetbrains.kotlin.psi.KtThisExpression import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo -import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager -import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue @@ -35,42 +32,6 @@ import org.jetbrains.kotlin.types.typeUtil.TypeNullability import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.nullability -fun TCallable.substituteExtensionIfCallable( - receivers: Collection, - context: BindingContext, - dataFlowInfo: DataFlowInfo, - callType: CallType<*>, - containingDeclarationOrModule: DeclarationDescriptor -): Collection { - val sequence = receivers.asSequence().flatMap { substituteExtensionIfCallable(it, callType, context, dataFlowInfo, containingDeclarationOrModule).asSequence() } - return if (typeParameters.isEmpty()) { // optimization for non-generic callables - sequence.firstOrNull()?.let { listOf(it) } ?: listOf() - } - else { - sequence.toList() - } -} - -fun TCallable.substituteExtensionIfCallableWithImplicitReceiver( - scope: LexicalScope, - context: BindingContext, - dataFlowInfo: DataFlowInfo -): Collection { - val receiverValues = scope.getImplicitReceiversWithInstance().map { it.value } - return substituteExtensionIfCallable(receiverValues, context, dataFlowInfo, CallType.DEFAULT, scope.ownerDescriptor) -} - -fun TCallable.substituteExtensionIfCallable( - receiver: ReceiverValue, - callType: CallType<*>, - bindingContext: BindingContext, - dataFlowInfo: DataFlowInfo, - containingDeclarationOrModule: DeclarationDescriptor -): Collection { - val types = SmartCastManager().getSmartCastVariants(receiver, bindingContext, containingDeclarationOrModule, dataFlowInfo) - return substituteExtensionIfCallable(types, callType) -} - fun TCallable.substituteExtensionIfCallable( receiverTypes: Collection, callType: CallType<*> diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt b/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt index ff650c34be5..fc0d0805165 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinExpressionTypeProvider.kt @@ -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. @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor +import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector @@ -111,7 +112,7 @@ class KotlinExpressionTypeProvider : ExpressionTypeProvider() { val result = expressionType?.let { typeRenderer.renderType(it) } ?: return "Type is unknown" val dataFlowValue = DataFlowValueFactory.createDataFlowValue(element, expressionType, bindingContext, element.findModuleDescriptor()) - val types = expressionTypeInfo.dataFlowInfo.getStableTypes(dataFlowValue) + val types = expressionTypeInfo.dataFlowInfo.getStableTypes(dataFlowValue, element.languageVersionSettings) if (!types.isEmpty()) { return types.joinToString(separator = " & ") { typeRenderer.renderType(it) } + " (smart cast from " + result + ")" } 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 61d6e307574..cd75b8317fc 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 @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.cfg.pseudocode.* import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.project.builtIns +import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.incremental.components.NoLookupLocation @@ -149,7 +150,8 @@ fun KtExpression.guessTypes( val theType1 = context.getType(this) if (theType1 != null && isAcceptable(theType1)) { val dataFlowInfo = context.getDataFlowInfoAfter(this) - val possibleTypes = dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValue(this, theType1, context, module)) + val possibleTypes = dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValue(this, theType1, context, module), + languageVersionSettings) return if (possibleTypes.isNotEmpty()) possibleTypes.toTypedArray() else arrayOf(theType1) } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractionData.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractionData.kt index 307aabea950..f0172b4d4a0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractionData.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractionData.kt @@ -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. @@ -22,11 +22,13 @@ import com.intellij.openapi.util.Key import com.intellij.psi.PsiElement import com.intellij.psi.PsiNameIdentifierOwner import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.core.compareDescriptors +import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.refactoring.introduce.ExtractableSubstringInfo import org.jetbrains.kotlin.idea.refactoring.introduce.extractableSubstringInfo import org.jetbrains.kotlin.idea.refactoring.introduce.substringContextOrThis @@ -183,13 +185,13 @@ data class ExtractionData( val dataFlowInfo = context.getDataFlowInfoAfter(expression) resolvedCall?.getImplicitReceiverValue()?.let { - return dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValueForStableReceiver(it)) + return dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValueForStableReceiver(it), expression.languageVersionSettings) } val type = resolvedCall?.resultingDescriptor?.returnType ?: return emptySet() val containingDescriptor = expression.getResolutionScope(context, expression.getResolutionFacade()).ownerDescriptor val dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context, containingDescriptor) - return dataFlowInfo.getCollectedTypes(dataFlowValue) + return dataFlowInfo.getCollectedTypes(dataFlowValue, expression.languageVersionSettings) } fun getBrokenReferencesInfo(body: KtBlockExpression): List { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt index d7b700e8f83..1f491d66a2b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/inferParameterInfo.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.core.KotlinNameSuggester import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator +import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.lexer.KtToken import org.jetbrains.kotlin.psi.* @@ -325,8 +326,12 @@ private fun suggestParameterType( receiverToExtract is ImplicitReceiver -> { val typeByDataFlowInfo = if (useSmartCastsIfPossible) { - val dataFlowInfo = bindingContext.getDataFlowInfoAfter(resolvedCall!!.call.callElement) - val possibleTypes = dataFlowInfo.getCollectedTypes(DataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract)) + val callElement = resolvedCall!!.call.callElement + val dataFlowInfo = bindingContext.getDataFlowInfoAfter(callElement) + val possibleTypes = dataFlowInfo.getCollectedTypes( + DataFlowValueFactory.createDataFlowValueForStableReceiver(receiverToExtract), + callElement.languageVersionSettings + ) if (possibleTypes.isNotEmpty()) CommonSupertypes.commonSupertype(possibleTypes) else null } else null typeByDataFlowInfo ?: receiverToExtract.type diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.kt index 4b3d3190a09..07919aa0435 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.translate.expression import org.jetbrains.kotlin.backend.common.CodegenUtil import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.js.backend.ast.* @@ -125,7 +126,9 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans val dataFlow = DataFlowValueFactory.createDataFlowValue( ktSubject, subjectType, bindingContext(), context().declarationDescriptor ?: context().currentModule) - val expectedTypes = bindingContext().getDataFlowInfoBefore(ktSubject).getStableTypes(dataFlow) + setOf(subjectType) + val languageVersionSettings = context().config.configuration.languageVersionSettings + val expectedTypes = bindingContext().getDataFlowInfoBefore(ktSubject).getStableTypes(dataFlow, languageVersionSettings) + + setOf(subjectType) val subject = expressionToMatch ?: return null var subjectSupplier = { subject } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt index 69d511b6b24..9f816e491a7 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/operation/EqualsBOIF.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.translate.intrinsic.operation import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.PrimitiveType +import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperation import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperator @@ -114,7 +115,8 @@ object EqualsBOIF : BinaryOperationIntrinsicFactory { val dataFlow = DataFlowValueFactory.createDataFlowValue(expression, ktType, bindingContext, descriptor) val isPrimitiveFn = KotlinBuiltIns::isPrimitiveTypeOrNullablePrimitiveType - return bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow).find(isPrimitiveFn) ?: // Smart-casts + val languageVersionSettings = context.config.configuration.languageVersionSettings + return bindingContext.getDataFlowInfoBefore(expression).getStableTypes(dataFlow, languageVersionSettings).find(isPrimitiveFn) ?: // Smart-casts TypeUtils.getAllSupertypes(ktType).find(isPrimitiveFn) ?: // Generic super-types ktType // Default }