[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, newVisibility: Visibility,
original: PropertyDescriptor?, original: PropertyDescriptor?,
kind: CallableMemberDescriptor.Kind, kind: CallableMemberDescriptor.Kind,
newName: Name newName: Name,
source: SourceElement
): PropertyDescriptorImpl { ): 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 getMethod = this@MyPropertyDescriptor.getMethod
setMethod = this@MyPropertyDescriptor.setMethod 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.MemoizedFunctionToNotNull
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
import java.util.*
abstract class AbstractLazyMemberScope<out D : DeclarationDescriptor, out DP : DeclarationProvider> abstract class AbstractLazyMemberScope<out D : DeclarationDescriptor, out DP : DeclarationProvider>
protected constructor( protected constructor(
protected val c: LazyClassContext, protected val c: LazyClassContext,
protected val declarationProvider: DP, protected val declarationProvider: DP,
protected val thisDescriptor: D, protected val thisDescriptor: D,
protected val trace: BindingTrace protected val trace: BindingTrace,
protected val mainScope: AbstractLazyMemberScope<D, DP>? = null
) : MemberScopeImpl() { ) : MemberScopeImpl() {
protected val storageManager: StorageManager = c.storageManager protected val storageManager: StorageManager = c.storageManager
@@ -52,7 +52,14 @@ protected constructor(
private val typeAliasDescriptors: MemoizedFunctionToNotNull<Name, Collection<TypeAliasDescriptor>> = private val typeAliasDescriptors: MemoizedFunctionToNotNull<Name, Collection<TypeAliasDescriptor>> =
storageManager.createMemoizedFunction { doGetTypeAliases(it) } 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> { private fun doGetClasses(name: Name): List<ClassDescriptor> {
mainScope?.classDescriptors?.invoke(name)?.let { return it }
val result = linkedSetOf<ClassDescriptor>() val result = linkedSetOf<ClassDescriptor>()
declarationProvider.getClassOrObjectDeclarations(name).mapTo(result) { declarationProvider.getClassOrObjectDeclarations(name).mapTo(result) {
val isExternal = it.modifierList?.hasModifier(KtTokens.EXTERNAL_KEYWORD) ?: false val isExternal = it.modifierList?.hasModifier(KtTokens.EXTERNAL_KEYWORD) ?: false
@@ -86,8 +93,22 @@ protected constructor(
} }
private fun doGetFunctions(name: Name): Collection<SimpleFunctionDescriptor> { 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) val declarations = declarationProvider.getFunctionDeclarations(name)
for (functionDeclaration in declarations) { for (functionDeclaration in declarations) {
result.add( result.add(
@@ -101,9 +122,7 @@ protected constructor(
) )
} }
getNonDeclaredFunctions(name, result) return result
return result.toList()
} }
protected abstract fun getScopeForMemberDeclarationResolution(declaration: KtDeclaration): LexicalScope protected abstract fun getScopeForMemberDeclarationResolution(declaration: KtDeclaration): LexicalScope
@@ -120,6 +139,21 @@ protected constructor(
} }
private fun doGetProperties(name: Name): Collection<PropertyDescriptor> { 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 result = LinkedHashSet<PropertyDescriptor>()
val declarations = declarationProvider.getPropertyDeclarations(name) val declarations = declarationProvider.getPropertyDeclarations(name)
@@ -149,9 +183,7 @@ protected constructor(
result.add(propertyDescriptor) result.add(propertyDescriptor)
} }
getNonDeclaredProperties(name, result) return result
return result.toList()
} }
protected abstract fun getNonDeclaredProperties(name: Name, result: MutableSet<PropertyDescriptor>) protected abstract fun getNonDeclaredProperties(name: Name, result: MutableSet<PropertyDescriptor>)
@@ -161,8 +193,10 @@ protected constructor(
return typeAliasDescriptors(name) return typeAliasDescriptors(name)
} }
private fun doGetTypeAliases(name: Name): Collection<TypeAliasDescriptor> = private fun doGetTypeAliases(name: Name): Collection<TypeAliasDescriptor> {
declarationProvider.getTypeAliasDeclarations(name).map { ktTypeAlias -> mainScope?.typeAliasDescriptors?.invoke(name)?.let { return it }
return declarationProvider.getTypeAliasDeclarations(name).map { ktTypeAlias ->
c.descriptorResolver.resolveTypeAliasDescriptor( c.descriptorResolver.resolveTypeAliasDescriptor(
thisDescriptor, thisDescriptor,
getScopeForMemberDeclarationResolution(ktTypeAlias), getScopeForMemberDeclarationResolution(ktTypeAlias),
@@ -170,6 +204,7 @@ protected constructor(
trace trace
) )
}.toList() }.toList()
}
protected fun computeDescriptorsFromDeclaredElements( protected fun computeDescriptorsFromDeclaredElements(
kindFilter: DescriptorKindFilter, kindFilter: DescriptorKindFilter,
@@ -317,7 +317,18 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
this, this,
c.getStorageManager(), c.getStorageManager(),
c.getKotlinTypeChecker().getKotlinTypeRefiner(), 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, declarationProvider: ClassMemberDeclarationProvider,
thisClass: ClassDescriptorWithResolutionScopes, thisClass: ClassDescriptorWithResolutionScopes,
trace: BindingTrace, trace: BindingTrace,
private val kotlinTypeRefiner: KotlinTypeRefiner = c.kotlinTypeChecker.kotlinTypeRefiner private val kotlinTypeRefiner: KotlinTypeRefiner = c.kotlinTypeChecker.kotlinTypeRefiner,
) : AbstractLazyMemberScope<ClassDescriptorWithResolutionScopes, ClassMemberDeclarationProvider>(c, declarationProvider, thisClass, trace) { scopeForDeclaredMembers: LazyClassMemberScope? = null
) : AbstractLazyMemberScope<ClassDescriptorWithResolutionScopes, ClassMemberDeclarationProvider>(
c, declarationProvider, thisClass, trace, scopeForDeclaredMembers
) {
private val descriptorsFromDeclaredElements = storageManager.createLazyValue { private val descriptorsFromDeclaredElements = storageManager.createLazyValue {
computeDescriptorsFromDeclaredElements( computeDescriptorsFromDeclaredElements(
@@ -374,10 +377,12 @@ open class LazyClassMemberScope(
val parameter = primaryConstructorParameters.get(valueParameterDescriptor.index) val parameter = primaryConstructorParameters.get(valueParameterDescriptor.index)
if (parameter.hasValOrVar()) { if (parameter.hasValOrVar()) {
val propertyDescriptor = c.descriptorResolver.resolvePrimaryConstructorParameterToAProperty( val propertyDescriptor =
// TODO: can't test because we get types from cache for this case trace.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter)
thisDescriptor, valueParameterDescriptor, thisDescriptor.scopeForConstructorHeaderResolution, parameter, trace ?: 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) result.add(propertyDescriptor)
} }
} }
@@ -438,12 +443,13 @@ open class LazyClassMemberScope(
} }
fun getConstructors(): Collection<ClassConstructorDescriptor> { fun getConstructors(): Collection<ClassConstructorDescriptor> {
val result = secondaryConstructors() val result = (mainScope as LazyClassMemberScope?)?.secondaryConstructors?.invoke() ?: secondaryConstructors()
val primaryConstructor = getPrimaryConstructor() val primaryConstructor = getPrimaryConstructor()
return if (primaryConstructor == null) result else result + primaryConstructor 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? { protected open fun resolvePrimaryConstructor(): ClassConstructorDescriptor? {
val classOrObject = declarationProvider.correspondingClassOrObject ?: return null val classOrObject = declarationProvider.correspondingClassOrObject ?: return null
@@ -81,10 +81,11 @@ public class JavaPropertyDescriptor extends PropertyDescriptorImpl implements Ja
@NotNull Visibility newVisibility, @NotNull Visibility newVisibility,
@Nullable PropertyDescriptor original, @Nullable PropertyDescriptor original,
@NotNull Kind kind, @NotNull Kind kind,
@NotNull Name newName @NotNull Name newName,
@NotNull SourceElement source
) { ) {
return new JavaPropertyDescriptor( return new JavaPropertyDescriptor(
newOwner, getAnnotations(), newModality, newVisibility, isVar(), newName, SourceElement.NO_SOURCE, original, newOwner, getAnnotations(), newModality, newVisibility, isVar(), newName, source, original,
kind, isStaticFinal, kind, isStaticFinal,
singleUserData); singleUserData);
} }
@@ -90,6 +90,9 @@ public interface CallableMemberDescriptor extends CallableDescriptor, MemberDesc
@NotNull @NotNull
CopyBuilder<D> setOriginal(@Nullable CallableMemberDescriptor original); CopyBuilder<D> setOriginal(@Nullable CallableMemberDescriptor original);
@NotNull
CopyBuilder<D> setPreserveSourceElement();
@Nullable @Nullable
D build(); D build();
} }
@@ -122,6 +122,7 @@ public interface FunctionDescriptor extends CallableMemberDescriptor {
CopyBuilder<D> setSignatureChange(); CopyBuilder<D> setSignatureChange();
@NotNull @NotNull
@Override
CopyBuilder<D> setPreserveSourceElement(); CopyBuilder<D> setPreserveSourceElement();
@NotNull @NotNull
@@ -252,6 +252,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
private Modality modality = getModality(); private Modality modality = getModality();
private Visibility visibility = getVisibility(); private Visibility visibility = getVisibility();
private PropertyDescriptor original = null; private PropertyDescriptor original = null;
private boolean preserveSourceElement = false;
private Kind kind = getKind(); private Kind kind = getKind();
private TypeSubstitution substitution = TypeSubstitution.EMPTY; private TypeSubstitution substitution = TypeSubstitution.EMPTY;
private boolean copyOverrides = true; private boolean copyOverrides = true;
@@ -273,6 +274,13 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
return this; return this;
} }
@NotNull
@Override
public CopyConfiguration setPreserveSourceElement() {
preserveSourceElement = true;
return this;
}
@NotNull @NotNull
@Override @Override
public CopyConfiguration setModality(@NotNull Modality modality) { public CopyConfiguration setModality(@NotNull Modality modality) {
@@ -352,11 +360,19 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
return new CopyConfiguration(); return new CopyConfiguration();
} }
@NotNull
private SourceElement getSourceToUseForCopy(boolean preserveSource, @Nullable PropertyDescriptor original) {
return preserveSource
? (original != null ? original : getOriginal()).getSource()
: SourceElement.NO_SOURCE;
}
@Nullable @Nullable
protected PropertyDescriptor doSubstitute(@NotNull CopyConfiguration copyConfiguration) { protected PropertyDescriptor doSubstitute(@NotNull CopyConfiguration copyConfiguration) {
PropertyDescriptorImpl substitutedDescriptor = createSubstitutedCopy( PropertyDescriptorImpl substitutedDescriptor = createSubstitutedCopy(
copyConfiguration.owner, copyConfiguration.modality, copyConfiguration.visibility, 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 = List<TypeParameterDescriptor> originalTypeParameters =
copyConfiguration.newTypeParameters == null ? getTypeParameters() : copyConfiguration.newTypeParameters; copyConfiguration.newTypeParameters == null ? getTypeParameters() : copyConfiguration.newTypeParameters;
@@ -486,10 +502,11 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
@NotNull Visibility newVisibility, @NotNull Visibility newVisibility,
@Nullable PropertyDescriptor original, @Nullable PropertyDescriptor original,
@NotNull Kind kind, @NotNull Kind kind,
@NotNull Name newName @NotNull Name newName,
@NotNull SourceElement source
) { ) {
return new PropertyDescriptorImpl( 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() isLateInit(), isConst(), isExpect(), isActual(), isExternal(), isDelegated()
); );
} }
@@ -164,7 +164,8 @@ class DeserializedPropertyDescriptor(
newVisibility: Visibility, newVisibility: Visibility,
original: PropertyDescriptor?, original: PropertyDescriptor?,
kind: CallableMemberDescriptor.Kind, kind: CallableMemberDescriptor.Kind,
newName: Name newName: Name,
source: SourceElement
): PropertyDescriptorImpl { ): PropertyDescriptorImpl {
return DeserializedPropertyDescriptor( return DeserializedPropertyDescriptor(
newOwner, original, annotations, newModality, newVisibility, isVar, newName, kind, isLateInit, isConst, isExternal, newOwner, original, annotations, newModality, newVisibility, isVar, newName, kind, isLateInit, isConst, isExternal,