[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
@@ -377,9 +377,10 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
newVisibility: Visibility,
original: PropertyDescriptor?,
kind: CallableMemberDescriptor.Kind,
newName: Name
newName: Name,
source: SourceElement
): PropertyDescriptorImpl {
return MyPropertyDescriptor(newOwner, this, annotations, newModality, newVisibility, isVar, newName, kind, source).apply {
return MyPropertyDescriptor(newOwner, this, annotations, newModality, newVisibility, isVar, newName, kind, this.source).apply {
getMethod = this@MyPropertyDescriptor.getMethod
setMethod = this@MyPropertyDescriptor.setMethod
}
@@ -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
@@ -81,10 +81,11 @@ public class JavaPropertyDescriptor extends PropertyDescriptorImpl implements Ja
@NotNull Visibility newVisibility,
@Nullable PropertyDescriptor original,
@NotNull Kind kind,
@NotNull Name newName
@NotNull Name newName,
@NotNull SourceElement source
) {
return new JavaPropertyDescriptor(
newOwner, getAnnotations(), newModality, newVisibility, isVar(), newName, SourceElement.NO_SOURCE, original,
newOwner, getAnnotations(), newModality, newVisibility, isVar(), newName, source, original,
kind, isStaticFinal,
singleUserData);
}
@@ -90,6 +90,9 @@ public interface CallableMemberDescriptor extends CallableDescriptor, MemberDesc
@NotNull
CopyBuilder<D> setOriginal(@Nullable CallableMemberDescriptor original);
@NotNull
CopyBuilder<D> setPreserveSourceElement();
@Nullable
D build();
}
@@ -122,6 +122,7 @@ public interface FunctionDescriptor extends CallableMemberDescriptor {
CopyBuilder<D> setSignatureChange();
@NotNull
@Override
CopyBuilder<D> setPreserveSourceElement();
@NotNull
@@ -252,6 +252,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
private Modality modality = getModality();
private Visibility visibility = getVisibility();
private PropertyDescriptor original = null;
private boolean preserveSourceElement = false;
private Kind kind = getKind();
private TypeSubstitution substitution = TypeSubstitution.EMPTY;
private boolean copyOverrides = true;
@@ -273,6 +274,13 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
return this;
}
@NotNull
@Override
public CopyConfiguration setPreserveSourceElement() {
preserveSourceElement = true;
return this;
}
@NotNull
@Override
public CopyConfiguration setModality(@NotNull Modality modality) {
@@ -352,11 +360,19 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
return new CopyConfiguration();
}
@NotNull
private SourceElement getSourceToUseForCopy(boolean preserveSource, @Nullable PropertyDescriptor original) {
return preserveSource
? (original != null ? original : getOriginal()).getSource()
: SourceElement.NO_SOURCE;
}
@Nullable
protected PropertyDescriptor doSubstitute(@NotNull CopyConfiguration copyConfiguration) {
PropertyDescriptorImpl substitutedDescriptor = createSubstitutedCopy(
copyConfiguration.owner, copyConfiguration.modality, copyConfiguration.visibility,
copyConfiguration.original, copyConfiguration.kind, copyConfiguration.name);
copyConfiguration.original, copyConfiguration.kind, copyConfiguration.name,
getSourceToUseForCopy(copyConfiguration.preserveSourceElement, copyConfiguration.original));
List<TypeParameterDescriptor> originalTypeParameters =
copyConfiguration.newTypeParameters == null ? getTypeParameters() : copyConfiguration.newTypeParameters;
@@ -486,10 +502,11 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
@NotNull Visibility newVisibility,
@Nullable PropertyDescriptor original,
@NotNull Kind kind,
@NotNull Name newName
@NotNull Name newName,
@NotNull SourceElement source
) {
return new PropertyDescriptorImpl(
newOwner, original, getAnnotations(), newModality, newVisibility, isVar(), newName, kind, SourceElement.NO_SOURCE,
newOwner, original, getAnnotations(), newModality, newVisibility, isVar(), newName, kind, source,
isLateInit(), isConst(), isExpect(), isActual(), isExternal(), isDelegated()
);
}
@@ -164,7 +164,8 @@ class DeserializedPropertyDescriptor(
newVisibility: Visibility,
original: PropertyDescriptor?,
kind: CallableMemberDescriptor.Kind,
newName: Name
newName: Name,
source: SourceElement
): PropertyDescriptorImpl {
return DeserializedPropertyDescriptor(
newOwner, original, annotations, newModality, newVisibility, isVar, newName, kind, isLateInit, isConst, isExternal,