[Invariant fix] Avoid re-resolving declared descriptors in lazy member scopes

It becomes necessary after scopes/types refinement
Without it being applied the code might fail with slice-rewrite errors

KT-32841
This commit is contained in:
Denis Zharkov
2019-04-01 15:18:07 +03:00
committed by Dmitry Savvinov
parent ab9ff786d7
commit 5c2c7e7776
9 changed files with 104 additions and 28 deletions
@@ -32,14 +32,14 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.Printer
import java.util.*
abstract class AbstractLazyMemberScope<out D : DeclarationDescriptor, out DP : DeclarationProvider>
protected constructor(
protected val c: LazyClassContext,
protected val declarationProvider: DP,
protected val thisDescriptor: D,
protected val trace: BindingTrace
protected val trace: BindingTrace,
protected val mainScope: AbstractLazyMemberScope<D, DP>? = null
) : MemberScopeImpl() {
protected val storageManager: StorageManager = c.storageManager
@@ -52,7 +52,14 @@ protected constructor(
private val typeAliasDescriptors: MemoizedFunctionToNotNull<Name, Collection<TypeAliasDescriptor>> =
storageManager.createMemoizedFunction { doGetTypeAliases(it) }
private val declaredFunctionDescriptors: MemoizedFunctionToNotNull<Name, Collection<SimpleFunctionDescriptor>> =
storageManager.createMemoizedFunction { getDeclaredFunctions(it) }
private val declaredPropertyDescriptors: MemoizedFunctionToNotNull<Name, Collection<PropertyDescriptor>> =
storageManager.createMemoizedFunction { getDeclaredProperties(it) }
private fun doGetClasses(name: Name): List<ClassDescriptor> {
mainScope?.classDescriptors?.invoke(name)?.let { return it }
val result = linkedSetOf<ClassDescriptor>()
declarationProvider.getClassOrObjectDeclarations(name).mapTo(result) {
val isExternal = it.modifierList?.hasModifier(KtTokens.EXTERNAL_KEYWORD) ?: false
@@ -86,8 +93,22 @@ protected constructor(
}
private fun doGetFunctions(name: Name): Collection<SimpleFunctionDescriptor> {
val result = linkedSetOf<SimpleFunctionDescriptor>()
val result = LinkedHashSet(declaredFunctionDescriptors.invoke(name))
getNonDeclaredFunctions(name, result)
return result.toList()
}
private fun getDeclaredFunctions(
name: Name
): Collection<SimpleFunctionDescriptor> {
// TODO: do we really need to copy descriptors?
if (mainScope != null) return mainScope.declaredFunctionDescriptors(name).map {
it.newCopyBuilder().setPreserveSourceElement().build()!!
}
val result = linkedSetOf<SimpleFunctionDescriptor>()
val declarations = declarationProvider.getFunctionDeclarations(name)
for (functionDeclaration in declarations) {
result.add(
@@ -101,9 +122,7 @@ protected constructor(
)
}
getNonDeclaredFunctions(name, result)
return result.toList()
return result
}
protected abstract fun getScopeForMemberDeclarationResolution(declaration: KtDeclaration): LexicalScope
@@ -120,6 +139,21 @@ protected constructor(
}
private fun doGetProperties(name: Name): Collection<PropertyDescriptor> {
val result = LinkedHashSet(declaredPropertyDescriptors(name))
getNonDeclaredProperties(name, result)
return result.toList()
}
private fun getDeclaredProperties(
name: Name
): Collection<PropertyDescriptor> {
// TODO: do we really need to copy descriptors?
if (mainScope != null) return mainScope.declaredPropertyDescriptors(name).map {
it.newCopyBuilder().setPreserveSourceElement().build()!!
}
val result = LinkedHashSet<PropertyDescriptor>()
val declarations = declarationProvider.getPropertyDeclarations(name)
@@ -149,9 +183,7 @@ protected constructor(
result.add(propertyDescriptor)
}
getNonDeclaredProperties(name, result)
return result.toList()
return result
}
protected abstract fun getNonDeclaredProperties(name: Name, result: MutableSet<PropertyDescriptor>)
@@ -161,8 +193,10 @@ protected constructor(
return typeAliasDescriptors(name)
}
private fun doGetTypeAliases(name: Name): Collection<TypeAliasDescriptor> =
declarationProvider.getTypeAliasDeclarations(name).map { ktTypeAlias ->
private fun doGetTypeAliases(name: Name): Collection<TypeAliasDescriptor> {
mainScope?.typeAliasDescriptors?.invoke(name)?.let { return it }
return declarationProvider.getTypeAliasDeclarations(name).map { ktTypeAlias ->
c.descriptorResolver.resolveTypeAliasDescriptor(
thisDescriptor,
getScopeForMemberDeclarationResolution(ktTypeAlias),
@@ -170,6 +204,7 @@ protected constructor(
trace
)
}.toList()
}
protected fun computeDescriptorsFromDeclaredElements(
kindFilter: DescriptorKindFilter,
@@ -317,7 +317,18 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
this,
c.getStorageManager(),
c.getKotlinTypeChecker().getKotlinTypeRefiner(),
kotlinTypeRefiner -> new LazyClassMemberScope(c, declarationProvider, this, c.getTrace(), kotlinTypeRefiner)
kotlinTypeRefiner -> {
LazyClassMemberScope scopeForDeclaredMembers =
!kotlinTypeRefiner.isRefinementNeededForModule(c.getModuleDescriptor())
? null
// TODO: or kotlinTypeRefiner.getModuleDescriptor()
: scopesHolderForClass.getScope(c.getKotlinTypeChecker().getKotlinTypeRefiner());
return new LazyClassMemberScope(
c, declarationProvider, this, c.getTrace(), kotlinTypeRefiner,
scopeForDeclaredMembers
);
}
);
}
@@ -51,8 +51,11 @@ open class LazyClassMemberScope(
declarationProvider: ClassMemberDeclarationProvider,
thisClass: ClassDescriptorWithResolutionScopes,
trace: BindingTrace,
private val kotlinTypeRefiner: KotlinTypeRefiner = c.kotlinTypeChecker.kotlinTypeRefiner
) : AbstractLazyMemberScope<ClassDescriptorWithResolutionScopes, ClassMemberDeclarationProvider>(c, declarationProvider, thisClass, trace) {
private val kotlinTypeRefiner: KotlinTypeRefiner = c.kotlinTypeChecker.kotlinTypeRefiner,
scopeForDeclaredMembers: LazyClassMemberScope? = null
) : AbstractLazyMemberScope<ClassDescriptorWithResolutionScopes, ClassMemberDeclarationProvider>(
c, declarationProvider, thisClass, trace, scopeForDeclaredMembers
) {
private val descriptorsFromDeclaredElements = storageManager.createLazyValue {
computeDescriptorsFromDeclaredElements(
@@ -374,10 +377,12 @@ open class LazyClassMemberScope(
val parameter = primaryConstructorParameters.get(valueParameterDescriptor.index)
if (parameter.hasValOrVar()) {
val propertyDescriptor = c.descriptorResolver.resolvePrimaryConstructorParameterToAProperty(
// TODO: can't test because we get types from cache for this case
thisDescriptor, valueParameterDescriptor, thisDescriptor.scopeForConstructorHeaderResolution, parameter, trace
)
val propertyDescriptor =
trace.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter)
?: c.descriptorResolver.resolvePrimaryConstructorParameterToAProperty(
// TODO: can't test because we get types from cache for this case
thisDescriptor, valueParameterDescriptor, thisDescriptor.scopeForConstructorHeaderResolution, parameter, trace
)
result.add(propertyDescriptor)
}
}
@@ -438,12 +443,13 @@ open class LazyClassMemberScope(
}
fun getConstructors(): Collection<ClassConstructorDescriptor> {
val result = secondaryConstructors()
val result = (mainScope as LazyClassMemberScope?)?.secondaryConstructors?.invoke() ?: secondaryConstructors()
val primaryConstructor = getPrimaryConstructor()
return if (primaryConstructor == null) result else result + primaryConstructor
}
fun getPrimaryConstructor(): ClassConstructorDescriptor? = primaryConstructor()
fun getPrimaryConstructor(): ClassConstructorDescriptor? =
(mainScope as LazyClassMemberScope?)?.primaryConstructor?.invoke() ?: primaryConstructor()
protected open fun resolvePrimaryConstructor(): ClassConstructorDescriptor? {
val classOrObject = declarationProvider.correspondingClassOrObject ?: return null