Minor. Split method VariableTypeResolver.process

It looks much natural to differ type resolution and setting
compile time initializer to descriptor
This commit is contained in:
Denis Zharkov
2016-11-10 13:42:46 +03:00
parent bce023c8ad
commit e21ecbe702
4 changed files with 29 additions and 37 deletions
@@ -74,7 +74,7 @@ public class DescriptorResolver {
private final StorageManager storageManager; private final StorageManager storageManager;
private final KotlinBuiltIns builtIns; private final KotlinBuiltIns builtIns;
private final SupertypeLoopChecker supertypeLoopsResolver; private final SupertypeLoopChecker supertypeLoopsResolver;
private final VariableTypeResolver variableTypeResolver; private final VariableTypeAndInitializerResolver variableTypeAndInitializerResolver;
private final ExpressionTypingServices expressionTypingServices; private final ExpressionTypingServices expressionTypingServices;
private final OverloadChecker overloadChecker; private final OverloadChecker overloadChecker;
private final LanguageVersionSettings languageVersionSettings; private final LanguageVersionSettings languageVersionSettings;
@@ -88,7 +88,7 @@ public class DescriptorResolver {
@NotNull StorageManager storageManager, @NotNull StorageManager storageManager,
@NotNull TypeResolver typeResolver, @NotNull TypeResolver typeResolver,
@NotNull SupertypeLoopChecker supertypeLoopsResolver, @NotNull SupertypeLoopChecker supertypeLoopsResolver,
@NotNull VariableTypeResolver variableTypeResolver, @NotNull VariableTypeAndInitializerResolver variableTypeAndInitializerResolver,
@NotNull ExpressionTypingServices expressionTypingServices, @NotNull ExpressionTypingServices expressionTypingServices,
@NotNull OverloadChecker overloadChecker, @NotNull OverloadChecker overloadChecker,
@NotNull LanguageVersionSettings languageVersionSettings, @NotNull LanguageVersionSettings languageVersionSettings,
@@ -101,7 +101,7 @@ public class DescriptorResolver {
this.storageManager = storageManager; this.storageManager = storageManager;
this.typeResolver = typeResolver; this.typeResolver = typeResolver;
this.supertypeLoopsResolver = supertypeLoopsResolver; this.supertypeLoopsResolver = supertypeLoopsResolver;
this.variableTypeResolver = variableTypeResolver; this.variableTypeAndInitializerResolver = variableTypeAndInitializerResolver;
this.expressionTypingServices = expressionTypingServices; this.expressionTypingServices = expressionTypingServices;
this.overloadChecker = overloadChecker; this.overloadChecker = overloadChecker;
this.languageVersionSettings = languageVersionSettings; this.languageVersionSettings = languageVersionSettings;
@@ -813,11 +813,16 @@ public class DescriptorResolver {
ReceiverParameterDescriptor receiverDescriptor = ReceiverParameterDescriptor receiverDescriptor =
DescriptorFactory.createExtensionReceiverParameterForCallable(propertyDescriptor, receiverType); DescriptorFactory.createExtensionReceiverParameterForCallable(propertyDescriptor, receiverType);
KotlinType type = variableTypeResolver.process( LexicalScope scopeForInitializer = ScopeUtils.makeScopeForPropertyInitializer(scopeWithTypeParameters, propertyDescriptor);
propertyDescriptor, ScopeUtils.makeScopeForPropertyInitializer(scopeWithTypeParameters, propertyDescriptor), KotlinType type = variableTypeAndInitializerResolver.resolveType(
propertyDescriptor, scopeForInitializer,
property, dataFlowInfo, true, trace property, dataFlowInfo, true, trace
); );
variableTypeAndInitializerResolver.setConstantForVariableIfNeeded(
propertyDescriptor, scopeForInitializer, property, dataFlowInfo, type, trace
);
propertyDescriptor.setType(type, typeParameterDescriptors, getDispatchReceiverParameterIfNeeded(containingDeclaration), propertyDescriptor.setType(type, typeParameterDescriptors, getDispatchReceiverParameterIfNeeded(containingDeclaration),
receiverDescriptor); receiverDescriptor);
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.VariableDescriptorWithInitializerImpl
import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.psi.KtProperty
@@ -43,7 +44,7 @@ class LocalVariableResolver(
private val identifierChecker: IdentifierChecker, private val identifierChecker: IdentifierChecker,
private val dataFlowAnalyzer: DataFlowAnalyzer, private val dataFlowAnalyzer: DataFlowAnalyzer,
private val annotationResolver: AnnotationResolver, private val annotationResolver: AnnotationResolver,
private val variableTypeResolver: VariableTypeResolver, private val variableTypeAndInitializerResolver: VariableTypeAndInitializerResolver,
private val delegatedPropertyResolver: DelegatedPropertyResolver, private val delegatedPropertyResolver: DelegatedPropertyResolver,
private val languageVersionSettings: LanguageVersionSettings private val languageVersionSettings: LanguageVersionSettings
) { ) {
@@ -132,7 +133,7 @@ class LocalVariableResolver(
trace: BindingTrace trace: BindingTrace
): VariableDescriptor { ): VariableDescriptor {
val containingDeclaration = scope.ownerDescriptor val containingDeclaration = scope.ownerDescriptor
val result: VariableDescriptor val result: VariableDescriptorWithInitializerImpl
val type: KotlinType val type: KotlinType
if (KtPsiUtil.isScriptDeclaration(variable)) { if (KtPsiUtil.isScriptDeclaration(variable)) {
val propertyDescriptor = PropertyDescriptorImpl.create( val propertyDescriptor = PropertyDescriptorImpl.create(
@@ -148,7 +149,7 @@ class LocalVariableResolver(
/* isConst = */ false /* isConst = */ false
) )
// For a local variable the type must not be deferred // For a local variable the type must not be deferred
type = variableTypeResolver.process(propertyDescriptor, scope, variable, dataFlowInfo, false, trace) type = variableTypeAndInitializerResolver.resolveType(propertyDescriptor, scope, variable, dataFlowInfo, false, trace)
val receiverParameter = (containingDeclaration as ScriptDescriptor).thisAsReceiverParameter val receiverParameter = (containingDeclaration as ScriptDescriptor).thisAsReceiverParameter
propertyDescriptor.setType(type, emptyList<TypeParameterDescriptor>(), receiverParameter, null as? KotlinType) propertyDescriptor.setType(type, emptyList<TypeParameterDescriptor>(), receiverParameter, null as? KotlinType)
@@ -159,10 +160,11 @@ class LocalVariableResolver(
else { else {
val variableDescriptor = resolveLocalVariableDescriptorWithType(scope, variable, null, trace) val variableDescriptor = resolveLocalVariableDescriptorWithType(scope, variable, null, trace)
// For a local variable the type must not be deferred // For a local variable the type must not be deferred
type = variableTypeResolver.process(variableDescriptor, scope, variable, dataFlowInfo, false, trace) type = variableTypeAndInitializerResolver.resolveType(variableDescriptor, scope, variable, dataFlowInfo, false, trace)
variableDescriptor.setOutType(type) variableDescriptor.setOutType(type)
result = variableDescriptor result = variableDescriptor
} }
variableTypeAndInitializerResolver.setConstantForVariableIfNeeded(result, scope, variable, dataFlowInfo, type, trace)
// Type annotations also should be resolved // Type annotations also should be resolved
ForceResolveUtil.forceResolveAllContents(type.annotations) ForceResolveUtil.forceResolveAllContents(type.annotations)
return result return result
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
class VariableTypeResolver( class VariableTypeAndInitializerResolver(
private val storageManager: StorageManager, private val storageManager: StorageManager,
private val expressionTypingServices: ExpressionTypingServices, private val expressionTypingServices: ExpressionTypingServices,
private val typeResolver: TypeResolver, private val typeResolver: TypeResolver,
@@ -44,7 +44,7 @@ class VariableTypeResolver(
private val delegatedPropertyResolver: DelegatedPropertyResolver private val delegatedPropertyResolver: DelegatedPropertyResolver
) { ) {
fun process( fun resolveType(
variableDescriptor: VariableDescriptorWithInitializerImpl, variableDescriptor: VariableDescriptorWithInitializerImpl,
scopeForInitializer: LexicalScope, scopeForInitializer: LexicalScope,
variable: KtVariableDeclaration, variable: KtVariableDeclaration,
@@ -55,12 +55,8 @@ class VariableTypeResolver(
val propertyTypeRef = variable.typeReference val propertyTypeRef = variable.typeReference
val hasDelegate = variable is KtProperty && variable.hasDelegateExpression() val hasDelegate = variable is KtProperty && variable.hasDelegateExpression()
when { return when {
propertyTypeRef != null -> { propertyTypeRef != null -> typeResolver.resolveType(scopeForInitializer, propertyTypeRef, trace, true)
val type = typeResolver.resolveType(scopeForInitializer, propertyTypeRef, trace, true)
setConstantForVariableIfNeeded(variableDescriptor, scopeForInitializer, variable, dataFlowInfo, type, trace)
return type
}
!variable.hasInitializer() -> { !variable.hasInitializer() -> {
if (hasDelegate && variableDescriptor is VariableDescriptorWithAccessors) { if (hasDelegate && variableDescriptor is VariableDescriptorWithAccessors) {
val property = variable as KtProperty val property = variable as KtProperty
@@ -80,25 +76,20 @@ class VariableTypeResolver(
return ErrorUtils.createErrorType("No type, no body") return ErrorUtils.createErrorType("No type, no body")
} }
notLocal -> { notLocal -> {
return DeferredType.createRecursionIntolerant( DeferredType.createRecursionIntolerant(
storageManager, storageManager,
trace trace
) { ) {
PreliminaryDeclarationVisitor.createForDeclaration(variable, trace) PreliminaryDeclarationVisitor.createForDeclaration(variable, trace)
val initializerType = resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace) val initializerType = resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace)
setConstantForVariableIfNeeded(variableDescriptor, scopeForInitializer, variable, dataFlowInfo, initializerType, trace)
transformAnonymousTypeIfNeeded(variableDescriptor, variable, initializerType, trace) transformAnonymousTypeIfNeeded(variableDescriptor, variable, initializerType, trace)
} }
} }
else -> { else -> resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace)
val initializerType = resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace)
setConstantForVariableIfNeeded(variableDescriptor, scopeForInitializer, variable, dataFlowInfo, initializerType, trace)
return initializerType
}
} }
} }
private fun setConstantForVariableIfNeeded( fun setConstantForVariableIfNeeded(
variableDescriptor: VariableDescriptorWithInitializerImpl, variableDescriptor: VariableDescriptorWithInitializerImpl,
scope: LexicalScope, scope: LexicalScope,
variable: KtVariableDeclaration, variable: KtVariableDeclaration,
@@ -106,17 +97,16 @@ class VariableTypeResolver(
variableType: KotlinType, variableType: KotlinType,
trace: BindingTrace trace: BindingTrace
) { ) {
if (!DescriptorUtils.shouldRecordInitializerForProperty(variableDescriptor, variableType)) return if (!variable.hasInitializer() || variable.isVar) return
if (!variable.hasInitializer()) return
variableDescriptor.setCompileTimeInitializer( variableDescriptor.setCompileTimeInitializer(
storageManager.createRecursionTolerantNullableLazyValue( storageManager.createRecursionTolerantNullableLazyValue(
{ computeInitializer@{
if (!DescriptorUtils.shouldRecordInitializerForProperty(variableDescriptor, variableType)) return@computeInitializer null
val initializer = variable.initializer val initializer = variable.initializer
val initializerType = expressionTypingServices.safeGetType(scope, initializer!!, variableType, dataFlowInfo, trace) val initializerType = expressionTypingServices.safeGetType(scope, initializer!!, variableType, dataFlowInfo, trace)
val constant = constantExpressionEvaluator.evaluateExpression(initializer, trace, initializerType) val constant = constantExpressionEvaluator.evaluateExpression(initializer, trace, initializerType)
?: return@createRecursionTolerantNullableLazyValue null ?: return@computeInitializer null
if (constant.usesNonConstValAsConstant && variableDescriptor.isConst) { if (constant.usesNonConstValAsConstant && variableDescriptor.isConst) {
trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(initializer)) trace.report(Errors.NON_CONST_VAL_USED_IN_CONSTANT_EXPRESSION.on(initializer))
@@ -52,11 +52,6 @@ public abstract class VariableDescriptorWithInitializerImpl extends VariableDesc
@Nullable @Nullable
@Override @Override
public ConstantValue<?> getCompileTimeInitializer() { public ConstantValue<?> getCompileTimeInitializer() {
// Force computation and setting of compileTimeInitializer, if needed
if (compileTimeInitializer == null) {
outType.getConstructor();
}
if (compileTimeInitializer != null) { if (compileTimeInitializer != null) {
return compileTimeInitializer.invoke(); return compileTimeInitializer.invoke();
} }