[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.
This commit is contained in:
Stanislav Erokhin
2017-04-13 15:59:06 +03:00
parent 397103f9d0
commit 6aac67aa7e
4 changed files with 30 additions and 11 deletions
@@ -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<KotlinType> 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)
@@ -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)
}
@@ -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)
}
}
@@ -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