[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:
committed by
Dmitry Savvinov
parent
ab9ff786d7
commit
5c2c7e7776
+3
-2
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+46
-11
@@ -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,
|
||||||
|
|||||||
+12
-1
@@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-8
@@ -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
|
||||||
|
|||||||
+3
-2
@@ -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
|
||||||
|
|||||||
+20
-3
@@ -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()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user