From 6aac67aa7e8de572c63fa4519ec54f0bafa2558d Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Thu, 13 Apr 2017 15:59:06 +0300 Subject: [PATCH] [NI] Approximate captured types when set them into variable. Also do not store type with captured type inside possible types. It is hack for now, but without it captured types can flow to resolution and exception will be thrown. --- .../kotlin/resolve/DescriptorResolver.java | 8 +++++-- .../VariableTypeAndInitializerResolver.kt | 21 ++++++++++++------- .../smartcasts/DelegatingDataFlowInfo.kt | 4 +++- .../kotlin/types/TypeApproximator.kt | 8 +++++++ 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index a0b41b54549..e7e49db1971 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -86,6 +86,7 @@ public class DescriptorResolver { private final ModifiersChecker modifiersChecker; private final WrappedTypeFactory wrappedTypeFactory; private final SyntheticResolveExtension syntheticResolveExtension; + private final TypeApproximator typeApproximator; public DescriptorResolver( @NotNull AnnotationResolver annotationResolver, @@ -101,7 +102,8 @@ public class DescriptorResolver { @NotNull DestructuringDeclarationResolver destructuringDeclarationResolver, @NotNull ModifiersChecker modifiersChecker, @NotNull WrappedTypeFactory wrappedTypeFactory, - @NotNull Project project + @NotNull Project project, + TypeApproximator approximator ) { this.annotationResolver = annotationResolver; this.builtIns = builtIns; @@ -117,6 +119,7 @@ public class DescriptorResolver { this.modifiersChecker = modifiersChecker; this.wrappedTypeFactory = wrappedTypeFactory; this.syntheticResolveExtension = SyntheticResolveExtension.Companion.getInstance(project); + typeApproximator = approximator; } public List resolveSupertypes( @@ -666,11 +669,12 @@ public class DescriptorResolver { BindingTrace trace, @NotNull LexicalScope scope ) { + UnwrappedType approximatedType = typeApproximator.approximateDeclarationType(type, true); VariableDescriptor variableDescriptor = new LocalVariableDescriptor( scope.getOwnerDescriptor(), annotationResolver.resolveAnnotationsWithArguments(scope, parameter.getModifierList(), trace), KtPsiUtil.safeName(parameter.getName()), - type, + approximatedType, false, false, KotlinSourceElementKt.toSourceElement(parameter) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/VariableTypeAndInitializerResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/VariableTypeAndInitializerResolver.kt index 9256129bb2e..a170bcb0540 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/VariableTypeAndInitializerResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/VariableTypeAndInitializerResolver.kt @@ -38,7 +38,8 @@ class VariableTypeAndInitializerResolver( private val typeResolver: TypeResolver, private val constantExpressionEvaluator: ConstantExpressionEvaluator, private val delegatedPropertyResolver: DelegatedPropertyResolver, - private val wrappedTypeFactory: WrappedTypeFactory + private val wrappedTypeFactory: WrappedTypeFactory, + private val typeApproximator: TypeApproximator ) { companion object { @JvmField @@ -76,7 +77,7 @@ class VariableTypeAndInitializerResolver( !variable.hasInitializer() && variable is KtProperty && variableDescriptor is VariableDescriptorWithAccessors && variable.hasDelegateExpression() -> - resolveDelegatedPropertyType(variable, variableDescriptor, scopeForInitializer, dataFlowInfo, trace) + resolveDelegatedPropertyType(variable, variableDescriptor, scopeForInitializer, dataFlowInfo, trace, local) variable.hasInitializer() -> when { !local -> @@ -84,11 +85,11 @@ class VariableTypeAndInitializerResolver( trace ) { PreliminaryDeclarationVisitor.createForDeclaration(variable, trace) - val initializerType = resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace) + val initializerType = resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace, local) transformAnonymousTypeIfNeeded(variableDescriptor, variable, initializerType, trace) } - else -> resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace) + else -> resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace, local) } else -> null } @@ -129,7 +130,8 @@ class VariableTypeAndInitializerResolver( variableDescriptor: VariableDescriptorWithAccessors, scopeForInitializer: LexicalScope, dataFlowInfo: DataFlowInfo, - trace: BindingTrace + trace: BindingTrace, + local: Boolean ) = wrappedTypeFactory.createRecursionIntolerantDeferredType(trace) { val delegateExpression = property.delegateExpression!! val type = delegatedPropertyResolver.resolveDelegateExpression( @@ -139,15 +141,18 @@ class VariableTypeAndInitializerResolver( variableDescriptor, delegateExpression, type, trace, scopeForInitializer, dataFlowInfo ) - getterReturnType ?: ErrorUtils.createErrorType("Type from delegate") + getterReturnType?.let { approximateType(it, local) } ?: ErrorUtils.createErrorType("Type from delegate") } private fun resolveInitializerType( scope: LexicalScope, initializer: KtExpression, dataFlowInfo: DataFlowInfo, - trace: BindingTrace + trace: BindingTrace, + local: Boolean ): KotlinType { - return expressionTypingServices.safeGetType(scope, initializer, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, trace) + return approximateType(expressionTypingServices.safeGetType(scope, initializer, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, trace), local) } + + private fun approximateType(type: KotlinType, local: Boolean): UnwrappedType = typeApproximator.approximateDeclarationType(type, local) } 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 b88de259f43..eb8624860d7 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 @@ -28,6 +28,8 @@ 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.checker.NewCapturedTypeConstructor +import org.jetbrains.kotlin.types.typeUtil.contains import java.util.* internal class DelegatingDataFlowInfo private constructor( @@ -329,7 +331,7 @@ internal class DelegatingDataFlowInfo private constructor( for (value in typeInfo.keys()) { for (type in typeInfo[value]) { // Remove original type (see also KT-10666) - if (value.type == type) { + if (value.type == type || type.contains { it.constructor is NewCapturedTypeConstructor }) { toDelete.put(value, type) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt b/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt index 6ff74ad76ff..efab5200e72 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.resolve.calls.components.CommonSupertypeCalculator +import org.jetbrains.kotlin.resolve.calls.USE_NEW_INFERENCE import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableTypeConstructor import org.jetbrains.kotlin.types.TypeApproximatorConfiguration.IntersectionStrategy.* import org.jetbrains.kotlin.types.checker.* @@ -58,6 +59,7 @@ open class TypeApproximatorConfiguration { object PublicDeclaration : AllFlexibleSameValue() { override val allFlexible get() = true + override val errorType get() = true } abstract class AbstractCapturedTypesApproximation(val approximatedCapturedStatus: CaptureStatus): TypeApproximatorConfiguration.AllFlexibleSameValue() { @@ -78,6 +80,12 @@ class TypeApproximator(private val commonSupertypeCalculator: CommonSupertypeCal private val referenceApproximateToSuperType = this::approximateToSuperType private val referenceApproximateToSubType = this::approximateToSubType + fun approximateDeclarationType(baseType: KotlinType, local: Boolean): UnwrappedType { + if (!USE_NEW_INFERENCE) return baseType.unwrap() + + val configuration = if (local) TypeApproximatorConfiguration.LocalDeclaration else TypeApproximatorConfiguration.PublicDeclaration + return approximateToSuperType(baseType.unwrap(), configuration) ?: baseType.unwrap() + } // null means that this input type is the result, i.e. input type not contains not-allowed kind of types // type <: resultType