IR: Make sure that symbols refer to original descriptors only

If a descriptor is a WrappedDeclarationDescriptor, it SHOULD NOT be
substituted.
This commit is contained in:
Dmitry Petrov
2019-03-28 14:35:45 +03:00
parent cd6c88fa2c
commit 8be7f7f1f7
14 changed files with 74 additions and 57 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBasedDeclarationDescriptor
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.types.toKotlinType
@@ -31,9 +32,12 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import java.lang.UnsupportedOperationException
abstract class WrappedDeclarationDescriptor<T : IrDeclaration>(annotations: Annotations) : DeclarationDescriptor { abstract class WrappedDeclarationDescriptor<T : IrDeclaration>(annotations: Annotations) :
DeclarationDescriptor, IrBasedDeclarationDescriptor {
private val annotations_ = annotations private val annotations_ = annotations
override val annotations: Annotations override val annotations: Annotations
@@ -112,9 +116,8 @@ abstract class WrappedCallableDescriptor<T : IrDeclaration>(
) : CallableDescriptor, WrappedDeclarationDescriptor<T>(annotations) { ) : CallableDescriptor, WrappedDeclarationDescriptor<T>(annotations) {
override fun getOriginal() = this override fun getOriginal() = this
override fun substitute(substitutor: TypeSubstitutor): CallableDescriptor { override fun substitute(substitutor: TypeSubstitutor): CallableDescriptor =
TODO("not implemented") throw UnsupportedOperationException("Wrapped descriptors SHOULD NOT be substituted")
}
override fun getOverriddenDescriptors(): Collection<CallableDescriptor> { override fun getOverriddenDescriptors(): Collection<CallableDescriptor> {
TODO("not implemented") TODO("not implemented")
@@ -190,9 +193,8 @@ open class WrappedValueParameterDescriptor(
override fun getOriginal() = this override fun getOriginal() = this
override fun substitute(substitutor: TypeSubstitutor): ValueParameterDescriptor { override fun substitute(substitutor: TypeSubstitutor): ValueParameterDescriptor =
TODO("") throw UnsupportedOperationException("Wrapped descriptors SHOULD NOT be substituted")
}
override fun getReturnType(): KotlinType? = owner.type.toKotlinType() override fun getReturnType(): KotlinType? = owner.type.toKotlinType()
@@ -583,9 +585,8 @@ open class WrappedClassDescriptor(
override fun isExpect() = false override fun isExpect() = false
override fun substitute(substitutor: TypeSubstitutor): ClassifierDescriptorWithTypeParameters { override fun substitute(substitutor: TypeSubstitutor): ClassifierDescriptorWithTypeParameters =
TODO("not implemented") throw UnsupportedOperationException("Wrapped descriptors SHOULD NOT be substituted")
}
override fun isActual() = false override fun isActual() = false
@@ -696,9 +697,8 @@ open class WrappedEnumEntryDescriptor(
override fun isExpect() = false override fun isExpect() = false
override fun substitute(substitutor: TypeSubstitutor): ClassifierDescriptorWithTypeParameters { override fun substitute(substitutor: TypeSubstitutor): ClassifierDescriptorWithTypeParameters =
TODO("not implemented") throw UnsupportedOperationException("Wrapped descriptors SHOULD NOT be substituted")
}
override fun isActual() = false override fun isActual() = false
@@ -783,9 +783,8 @@ open class WrappedPropertyDescriptor(
override fun isExpect() = false override fun isExpect() = false
override fun substitute(substitutor: TypeSubstitutor): PropertyDescriptor { override fun substitute(substitutor: TypeSubstitutor): PropertyDescriptor =
TODO("not implemented") throw UnsupportedOperationException("Wrapped descriptors SHOULD NOT be substituted")
}
override fun isActual() = false override fun isActual() = false
@@ -888,9 +887,8 @@ open class WrappedFieldDescriptor(
override fun isExpect() = false override fun isExpect() = false
override fun substitute(substitutor: TypeSubstitutor): PropertyDescriptor { override fun substitute(substitutor: TypeSubstitutor): PropertyDescriptor =
TODO("not implemented") throw UnsupportedOperationException("Wrapped descriptors SHOULD NOT be substituted")
}
override fun isActual() = false override fun isActual() = false
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.descriptors
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
interface IrBasedDeclarationDescriptor : DeclarationDescriptor
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.ir.symbols.impl
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBasedDeclarationDescriptor
import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
@@ -25,27 +26,28 @@ abstract class IrSymbolBase<out D : DeclarationDescriptor>(override val descript
abstract class IrBindableSymbolBase<out D : DeclarationDescriptor, B : IrSymbolOwner>(descriptor: D) : abstract class IrBindableSymbolBase<out D : DeclarationDescriptor, B : IrSymbolOwner>(descriptor: D) :
IrBindableSymbol<D, B>, IrSymbolBase<D>(descriptor) { IrBindableSymbol<D, B>, IrSymbolBase<D>(descriptor) {
init { init {
// assert(isOriginalDescriptor(descriptor)) { assert(isOriginalDescriptor(descriptor)) {
// "Substituted descriptor $descriptor for ${descriptor.original}" "Substituted descriptor $descriptor for ${descriptor.original}"
// } }
} }
private fun isOriginalDescriptor(descriptor: DeclarationDescriptor): Boolean = private fun isOriginalDescriptor(descriptor: DeclarationDescriptor): Boolean =
if (descriptor is ValueParameterDescriptor) descriptor is IrBasedDeclarationDescriptor ||
isOriginalDescriptor(descriptor.containingDeclaration) descriptor is ValueParameterDescriptor && isOriginalDescriptor(descriptor.containingDeclaration) ||
else descriptor == descriptor.original
descriptor == descriptor.original
private var _owner: B? = null private var _owner: B? = null
override val owner: B override val owner: B
get() = _owner ?: throw IllegalStateException("Symbol for $descriptor is unbound") get() = _owner ?: throw IllegalStateException("Symbol for $descriptor is unbound")
override fun bind(owner: B) { override fun bind(owner: B) {
if (_owner == null) if (_owner == null) {
_owner = owner _owner = owner
else } else {
throw IllegalStateException("${javaClass.simpleName} for $descriptor is already bound") throw IllegalStateException("${javaClass.simpleName} for $descriptor is already bound")
}
} }
override val isBound: Boolean override val isBound: Boolean
@@ -17,20 +17,15 @@
package org.jetbrains.kotlin.ir.util package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazySymbolTable import org.jetbrains.kotlin.ir.declarations.lazy.IrLazySymbolTable
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.* import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
interface IrDeserializer { interface IrDeserializer {
fun findDeserializedDeclaration(symbol: IrSymbol): IrDeclaration? fun findDeserializedDeclaration(symbol: IrSymbol): IrDeclaration?
@@ -78,10 +73,15 @@ open class SymbolTable : ReferenceSymbolTable {
abstract fun set(d: D, s: S) abstract fun set(d: D, s: S)
inline fun declare(d: D, createSymbol: () -> S, createOwner: (S) -> B): B { inline fun declare(d: D, createSymbol: () -> S, createOwner: (S) -> B): B {
val existing = get(d) @Suppress("UNCHECKED_CAST")
val d0 = d.original as D
assert(d0 === d) {
"Non-original descriptor in declaration: $d\n\tExpected: $d0"
}
val existing = get(d0)
val symbol = if (existing == null) { val symbol = if (existing == null) {
val new = createSymbol() val new = createSymbol()
set(d, new) set(d0, new)
new new
} else { } else {
unboundSymbols.remove(existing) unboundSymbols.remove(existing)
@@ -91,13 +91,18 @@ open class SymbolTable : ReferenceSymbolTable {
} }
inline fun referenced(d: D, orElse: () -> S): S { inline fun referenced(d: D, orElse: () -> S): S {
val s = get(d) @Suppress("UNCHECKED_CAST")
val d0 = d.original as D
assert(d0 === d) {
"Non-original descriptor in declaration: $d\n\tExpected: $d0"
}
val s = get(d0)
if (s == null) { if (s == null) {
val new = orElse() val new = orElse()
assert(unboundSymbols.add(new)) { assert(unboundSymbols.add(new)) {
"Symbol for ${new.descriptor} was already referenced" "Symbol for ${new.descriptor} was already referenced"
} }
set(d, new) set(d0, new)
return new return new
} }
return s return s
@@ -113,13 +118,6 @@ open class SymbolTable : ReferenceSymbolTable {
override fun set(d: D, s: S) { override fun set(d: D, s: S) {
descriptorToSymbol[d] = s descriptorToSymbol[d] = s
} }
fun copyTo(other: FlatSymbolTable<D, B, S>) {
for ((d, s) in descriptorToSymbol) {
other.descriptorToSymbol[d] = s
}
other.unboundSymbols.addAll(unboundSymbols)
}
} }
private class ScopedSymbolTable<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> private class ScopedSymbolTable<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>>
@@ -1,5 +1,4 @@
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
import java.util.AbstractMap import java.util.AbstractMap
import java.util.Collections import java.util.Collections
@@ -1,6 +1,5 @@
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: NATIVE // IGNORE_BACKEND: NATIVE
// IGNORE_BACKEND: JVM_IR
class A : HashMap<String, Double>() class A : HashMap<String, Double>()
fun box(): String { fun box(): String {
@@ -1,5 +1,4 @@
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
class Itr : Iterator<String> by ArrayList<String>().iterator() class Itr : Iterator<String> by ArrayList<String>().iterator()
@@ -1,5 +1,4 @@
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
class Itr : Iterator<String> by ArrayList<String>().iterator() class Itr : Iterator<String> by ArrayList<String>().iterator()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
import java.util.IdentityHashMap import java.util.IdentityHashMap
@@ -1,5 +1,4 @@
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: JVM_IR
fun box() : String { fun box() : String {
if (!testIteratingOverMap1()) return "fail 1" if (!testIteratingOverMap1()) return "fail 1"
@@ -1,5 +1,4 @@
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: NATIVE // IGNORE_BACKEND: NATIVE
open class Map1 : HashMap<String, Any?>() open class Map1 : HashMap<String, Any?>()
@@ -1,5 +1,4 @@
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
// FULL_JDK // FULL_JDK
@@ -102,6 +102,7 @@ public class JavaPropertyDescriptor extends PropertyDescriptorImpl implements Ja
@NotNull KotlinType enhancedReturnType, @NotNull KotlinType enhancedReturnType,
@Nullable Pair<UserDataKey<?>, ?> additionalUserData @Nullable Pair<UserDataKey<?>, ?> additionalUserData
) { ) {
PropertyDescriptor enhancedOriginal = getOriginal() == this ? null : getOriginal();
JavaPropertyDescriptor enhanced = new JavaPropertyDescriptor( JavaPropertyDescriptor enhanced = new JavaPropertyDescriptor(
getContainingDeclaration(), getContainingDeclaration(),
getAnnotations(), getAnnotations(),
@@ -110,7 +111,7 @@ public class JavaPropertyDescriptor extends PropertyDescriptorImpl implements Ja
isVar(), isVar(),
getName(), getName(),
getSource(), getSource(),
getOriginal() == this ? null : getOriginal(), enhancedOriginal,
getKind(), getKind(),
isStaticFinal, isStaticFinal,
additionalUserData); additionalUserData);
@@ -120,7 +121,9 @@ public class JavaPropertyDescriptor extends PropertyDescriptorImpl implements Ja
if (getter != null) { if (getter != null) {
newGetter = new PropertyGetterDescriptorImpl( newGetter = new PropertyGetterDescriptorImpl(
enhanced, getter.getAnnotations(), getter.getModality(), getter.getVisibility(), enhanced, getter.getAnnotations(), getter.getModality(), getter.getVisibility(),
getter.isDefault(), getter.isExternal(), getter.isInline(), getKind(), getter, getter.getSource() getter.isDefault(), getter.isExternal(), getter.isInline(), getKind(),
enhancedOriginal == null ? null : enhancedOriginal.getGetter(),
getter.getSource()
); );
newGetter.setInitialSignatureDescriptor(getter.getInitialSignatureDescriptor()); newGetter.setInitialSignatureDescriptor(getter.getInitialSignatureDescriptor());
newGetter.initialize(enhancedReturnType); newGetter.initialize(enhancedReturnType);
@@ -131,7 +134,9 @@ public class JavaPropertyDescriptor extends PropertyDescriptorImpl implements Ja
if (setter != null) { if (setter != null) {
newSetter = new PropertySetterDescriptorImpl( newSetter = new PropertySetterDescriptorImpl(
enhanced, setter.getAnnotations(), setter.getModality(), setter.getVisibility(), enhanced, setter.getAnnotations(), setter.getModality(), setter.getVisibility(),
setter.isDefault(), setter.isExternal(), setter.isInline(), getKind(), setter, setter.getSource() setter.isDefault(), setter.isExternal(), setter.isInline(), getKind(),
enhancedOriginal == null ? null : enhancedOriginal.getSetter(),
setter.getSource()
); );
newSetter.setInitialSignatureDescriptor(newSetter.getInitialSignatureDescriptor()); newSetter.setInitialSignatureDescriptor(newSetter.getInitialSignatureDescriptor());
newSetter.initialize(setter.getValueParameters().get(0)); newSetter.initialize(setter.getValueParameters().get(0));
@@ -334,6 +334,16 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
public PropertyDescriptor build() { public PropertyDescriptor build() {
return doSubstitute(this); return doSubstitute(this);
} }
PropertyGetterDescriptor getOriginalGetter() {
if (original == null) return null;
return original.getGetter();
}
PropertySetterDescriptor getOriginalSetter() {
if (original == null) return null;
return original.getSetter();
}
} }
@NotNull @NotNull
@@ -389,7 +399,8 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
PropertyGetterDescriptorImpl newGetter = getter == null ? null : new PropertyGetterDescriptorImpl( PropertyGetterDescriptorImpl newGetter = getter == null ? null : new PropertyGetterDescriptorImpl(
substitutedDescriptor, getter.getAnnotations(), copyConfiguration.modality, normalizeVisibility(getter.getVisibility(), copyConfiguration.kind), substitutedDescriptor, getter.getAnnotations(), copyConfiguration.modality, normalizeVisibility(getter.getVisibility(), copyConfiguration.kind),
getter.isDefault(), getter.isExternal(), getter.isInline(), copyConfiguration.kind, copyConfiguration.original == null ? null : copyConfiguration.original.getGetter(), getter.isDefault(), getter.isExternal(), getter.isInline(), copyConfiguration.kind,
copyConfiguration.getOriginalGetter(),
SourceElement.NO_SOURCE SourceElement.NO_SOURCE
); );
if (newGetter != null) { if (newGetter != null) {
@@ -399,7 +410,8 @@ public class PropertyDescriptorImpl extends VariableDescriptorWithInitializerImp
} }
PropertySetterDescriptorImpl newSetter = setter == null ? null : new PropertySetterDescriptorImpl( PropertySetterDescriptorImpl newSetter = setter == null ? null : new PropertySetterDescriptorImpl(
substitutedDescriptor, setter.getAnnotations(), copyConfiguration.modality, normalizeVisibility(setter.getVisibility(), copyConfiguration.kind), substitutedDescriptor, setter.getAnnotations(), copyConfiguration.modality, normalizeVisibility(setter.getVisibility(), copyConfiguration.kind),
setter.isDefault(), setter.isExternal(), setter.isInline(), copyConfiguration.kind, copyConfiguration.original == null ? null : copyConfiguration.original.getSetter(), setter.isDefault(), setter.isExternal(), setter.isInline(), copyConfiguration.kind,
copyConfiguration.getOriginalSetter(),
SourceElement.NO_SOURCE SourceElement.NO_SOURCE
); );
if (newSetter != null) { if (newSetter != null) {