FIR2IR: Rework resulted overridden-relation structure
The difference is how we deal with intermediate fake overrides
E.g., in case
interface A { /* $1 */ fun foo() }
interface B : A {
/* $2 */ fake_override fun foo()
}
interface C : B {
/* $3 */ override fun foo()
}
We've got FIR declarations only for $1 and $3, but we've got
a fake override for $2 in IR.
Previously, override $3 had $1 as its overridden IR symbol, just because
FIR declaration of $3 doesn't know anything about $2.
Now, when generating IR for $2, we save the necessary information
and using it for $3, so it has $2 as overridden.
So, it's consistent with the overridden structure of FE 1.0 and this
structure is necessary prerequisite for proper building of bridges
for special built-ins.
This commit is contained in:
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
|||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
|
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
@@ -24,11 +25,8 @@ import org.jetbrains.kotlin.fir.resolve.*
|
|||||||
import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol
|
import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.originalConstructorIfTypeAlias
|
import org.jetbrains.kotlin.fir.resolve.calls.originalConstructorIfTypeAlias
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
||||||
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.AccessorSymbol
|
import org.jetbrains.kotlin.fir.symbols.AccessorSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
@@ -292,45 +290,89 @@ internal fun FirSimpleFunction.generateOverriddenFunctionSymbols(
|
|||||||
containingClass: FirClass<*>,
|
containingClass: FirClass<*>,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession,
|
||||||
declarationStorage: Fir2IrDeclarationStorage
|
declarationStorage: Fir2IrDeclarationStorage,
|
||||||
|
fakeOverrideGenerator: FakeOverrideGenerator,
|
||||||
): List<IrSimpleFunctionSymbol> {
|
): List<IrSimpleFunctionSymbol> {
|
||||||
|
val superClasses = containingClass.getSuperTypesAsIrClasses(declarationStorage) ?: return emptyList()
|
||||||
|
|
||||||
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
|
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
|
||||||
scope.processFunctionsByName(name) {}
|
scope.processFunctionsByName(name) {}
|
||||||
val overriddenSet = mutableSetOf<IrSimpleFunctionSymbol>()
|
val overriddenSet = mutableSetOf<IrSimpleFunctionSymbol>()
|
||||||
scope.processDirectlyOverriddenFunctions(symbol) {
|
scope.processOverriddenFunctionsFromSuperClasses(symbol, containingClass) {
|
||||||
if (it.fir.visibility == Visibilities.Private) {
|
if (it.fir.visibility == Visibilities.Private) {
|
||||||
return@processDirectlyOverriddenFunctions ProcessorAction.NEXT
|
return@processOverriddenFunctionsFromSuperClasses ProcessorAction.NEXT
|
||||||
|
}
|
||||||
|
|
||||||
|
for (overridden in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)) {
|
||||||
|
overriddenSet += overridden
|
||||||
}
|
}
|
||||||
|
|
||||||
val overridden = declarationStorage.getIrFunctionSymbol(it.unwrapFakeOverrides())
|
|
||||||
overriddenSet += overridden as IrSimpleFunctionSymbol
|
|
||||||
ProcessorAction.NEXT
|
ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
return overriddenSet.toList()
|
return overriddenSet.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun FirTypeScope.processOverriddenFunctionsFromSuperClasses(
|
||||||
|
functionSymbol: FirNamedFunctionSymbol,
|
||||||
|
containingClass: FirClass<*>,
|
||||||
|
processor: (FirNamedFunctionSymbol) -> ProcessorAction
|
||||||
|
): ProcessorAction = processDirectOverriddenFunctionsWithBaseScope(functionSymbol) { overridden, baseScope ->
|
||||||
|
val unwrapped =
|
||||||
|
overridden.fir.delegatedWrapperData?.takeIf { it.containingClass == containingClass.symbol.toLookupTag() }?.wrapped?.symbol
|
||||||
|
?: overridden
|
||||||
|
|
||||||
|
if (unwrapped.containingClass() == containingClass.symbol.toLookupTag()) {
|
||||||
|
baseScope.processOverriddenFunctionsFromSuperClasses(unwrapped, containingClass, processor)
|
||||||
|
} else {
|
||||||
|
processor(overridden)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FirTypeScope.processOverriddenPropertiesFromSuperClasses(
|
||||||
|
propertySymbol: FirPropertySymbol,
|
||||||
|
containingClass: FirClass<*>,
|
||||||
|
processor: (FirPropertySymbol) -> ProcessorAction
|
||||||
|
): ProcessorAction = processDirectOverriddenPropertiesWithBaseScope(propertySymbol) { overridden, baseScope ->
|
||||||
|
if (overridden.containingClass() == containingClass.symbol.toLookupTag()) {
|
||||||
|
baseScope.processOverriddenPropertiesFromSuperClasses(overridden, containingClass, processor)
|
||||||
|
} else {
|
||||||
|
processor(overridden)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirClass<*>.getSuperTypesAsIrClasses(
|
||||||
|
declarationStorage: Fir2IrDeclarationStorage
|
||||||
|
): Set<IrClass>? {
|
||||||
|
val irClass =
|
||||||
|
declarationStorage.classifierStorage.getIrClassSymbol(symbol).owner as? IrClass ?: return null
|
||||||
|
|
||||||
|
return irClass.superTypes.mapNotNull { it.classifierOrNull?.owner as? IrClass }.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
internal fun FirProperty.generateOverriddenAccessorSymbols(
|
internal fun FirProperty.generateOverriddenAccessorSymbols(
|
||||||
containingClass: FirClass<*>,
|
containingClass: FirClass<*>,
|
||||||
isGetter: Boolean,
|
isGetter: Boolean,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession,
|
||||||
declarationStorage: Fir2IrDeclarationStorage
|
declarationStorage: Fir2IrDeclarationStorage,
|
||||||
|
fakeOverrideGenerator: FakeOverrideGenerator,
|
||||||
): List<IrSimpleFunctionSymbol> {
|
): List<IrSimpleFunctionSymbol> {
|
||||||
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
|
val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
|
||||||
scope.processPropertiesByName(name) {}
|
scope.processPropertiesByName(name) {}
|
||||||
val overriddenSet = mutableSetOf<IrSimpleFunctionSymbol>()
|
val overriddenSet = mutableSetOf<IrSimpleFunctionSymbol>()
|
||||||
scope.processDirectlyOverriddenProperties(symbol) {
|
val superClasses = containingClass.getSuperTypesAsIrClasses(declarationStorage) ?: return emptyList()
|
||||||
if (it is FirAccessorSymbol || it.fir.visibility == Visibilities.Private) {
|
|
||||||
return@processDirectlyOverriddenProperties ProcessorAction.NEXT
|
scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) {
|
||||||
|
if (it.fir.visibility == Visibilities.Private) {
|
||||||
|
return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
val unwrapped =
|
for (overriddenProperty in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)) {
|
||||||
it.fir.delegatedWrapperData?.takeIf { it.containingClass == containingClass.symbol.toLookupTag() }?.wrapped?.symbol ?: it
|
val overriddenAccessor = if (isGetter) overriddenProperty.owner.getter?.symbol else overriddenProperty.owner.setter?.symbol
|
||||||
|
if (overriddenAccessor != null) {
|
||||||
val overriddenProperty = declarationStorage.getIrPropertySymbol(unwrapped.unwrapFakeOverrides()) as IrPropertySymbol
|
overriddenSet += overriddenAccessor
|
||||||
val overriddenAccessor = if (isGetter) overriddenProperty.owner.getter?.symbol else overriddenProperty.owner.setter?.symbol
|
}
|
||||||
if (overriddenAccessor != null) {
|
|
||||||
overriddenSet += overriddenAccessor
|
|
||||||
}
|
}
|
||||||
ProcessorAction.NEXT
|
ProcessorAction.NEXT
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-7
@@ -76,6 +76,23 @@ class Fir2IrDeclarationStorage(
|
|||||||
|
|
||||||
private val propertyCache = ConcurrentHashMap<FirProperty, IrProperty>()
|
private val propertyCache = ConcurrentHashMap<FirProperty, IrProperty>()
|
||||||
|
|
||||||
|
// interface A { /* $1 */ fun foo() }
|
||||||
|
// interface B : A {
|
||||||
|
// /* $2 */ fake_override fun foo()
|
||||||
|
// }
|
||||||
|
// interface C : B {
|
||||||
|
// /* $3 */ override fun foo()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// We've got FIR declarations only for $1 and $3, but we've got a fake override for $2 in IR
|
||||||
|
// and just to simplify things we create a synthetic FIR for $2, while it can't be referenced from other FIR nodes.
|
||||||
|
//
|
||||||
|
// But when we binding overrides for $3, we want it had $2 ad it's overridden,
|
||||||
|
// so remember that in class B there's a fake override $2 for real $1.
|
||||||
|
//
|
||||||
|
// Thus we may obtain it by fakeOverridesInClass[ir(B)][fir(A::foo)] -> fir(B::foo)
|
||||||
|
private val fakeOverridesInClass = mutableMapOf<IrClass, MutableMap<FirCallableDeclaration<*>, FirCallableDeclaration<*>>>()
|
||||||
|
|
||||||
// For pure fields (from Java) only
|
// For pure fields (from Java) only
|
||||||
private val fieldToPropertyCache = ConcurrentHashMap<FirField, IrProperty>()
|
private val fieldToPropertyCache = ConcurrentHashMap<FirField, IrProperty>()
|
||||||
|
|
||||||
@@ -633,7 +650,7 @@ class Fir2IrDeclarationStorage(
|
|||||||
}
|
}
|
||||||
if (correspondingProperty is Fir2IrLazyProperty && !isFakeOverride && thisReceiverOwner != null) {
|
if (correspondingProperty is Fir2IrLazyProperty && !isFakeOverride && thisReceiverOwner != null) {
|
||||||
this.overriddenSymbols = correspondingProperty.fir.generateOverriddenAccessorSymbols(
|
this.overriddenSymbols = correspondingProperty.fir.generateOverriddenAccessorSymbols(
|
||||||
correspondingProperty.containingClass, !isSetter, session, scopeSession, declarationStorage
|
correspondingProperty.containingClass, !isSetter, session, scopeSession, declarationStorage, fakeOverrideGenerator
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -835,6 +852,23 @@ class Fir2IrDeclarationStorage(
|
|||||||
delegatedReverseCache[irProperty] = property
|
delegatedReverseCache[irProperty] = property
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun saveFakeOverrideInClass(
|
||||||
|
irClass: IrClass,
|
||||||
|
callableDeclaration: FirCallableDeclaration<*>,
|
||||||
|
fakeOverride: FirCallableDeclaration<*>
|
||||||
|
) {
|
||||||
|
fakeOverridesInClass.getOrPut(irClass, ::mutableMapOf)[callableDeclaration] = fakeOverride
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFakeOverrideInClass(
|
||||||
|
irClass: IrClass,
|
||||||
|
callableDeclaration: FirCallableDeclaration<*>
|
||||||
|
): FirCallableDeclaration<*>? {
|
||||||
|
// Init lazy class if necessary
|
||||||
|
irClass.declarations
|
||||||
|
return fakeOverridesInClass[irClass]?.get(callableDeclaration)
|
||||||
|
}
|
||||||
|
|
||||||
fun getCachedIrField(field: FirField): IrField? = fieldCache[field]
|
fun getCachedIrField(field: FirField): IrField? = fieldCache[field]
|
||||||
|
|
||||||
fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass<*>, irClass: IrClass): IrField {
|
fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass<*>, irClass: IrClass): IrField {
|
||||||
@@ -1108,13 +1142,27 @@ class Fir2IrDeclarationStorage(
|
|||||||
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
|
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
|
||||||
val declarationOrigin = computeDeclarationOrigin(firSymbol, parentOrigin)
|
val declarationOrigin = computeDeclarationOrigin(firSymbol, parentOrigin)
|
||||||
// TODO: package fragment members (?)
|
// TODO: package fragment members (?)
|
||||||
val parent = irParent
|
when (val parent = irParent) {
|
||||||
if (parent is Fir2IrLazyClass) {
|
is Fir2IrLazyClass -> {
|
||||||
assert(parentOrigin != IrDeclarationOrigin.DEFINED) {
|
assert(parentOrigin != IrDeclarationOrigin.DEFINED) {
|
||||||
"Should not have reference to public API uncached property from source code"
|
"Should not have reference to public API uncached property from source code"
|
||||||
|
}
|
||||||
|
signature?.let {
|
||||||
|
return createIrLazyDeclaration(it, parent, declarationOrigin).symbol
|
||||||
|
}
|
||||||
}
|
}
|
||||||
signature?.let {
|
is IrLazyClass -> {
|
||||||
return createIrLazyDeclaration(it, parent, declarationOrigin).symbol
|
val unwrapped = fir.unwrapFakeOverrides()
|
||||||
|
if (unwrapped !== fir) {
|
||||||
|
when (unwrapped) {
|
||||||
|
is FirSimpleFunction -> {
|
||||||
|
return getIrFunctionSymbol(unwrapped.symbol)
|
||||||
|
}
|
||||||
|
is FirProperty -> {
|
||||||
|
return getIrPropertySymbol(unwrapped.symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createIrDeclaration(irParent, declarationOrigin).apply {
|
return createIrDeclaration(irParent, declarationOrigin).apply {
|
||||||
|
|||||||
+2
-2
@@ -144,7 +144,7 @@ internal class ClassMemberGenerator(
|
|||||||
}
|
}
|
||||||
if (irFunction is IrSimpleFunction && firFunction is FirSimpleFunction && containingClass != null) {
|
if (irFunction is IrSimpleFunction && firFunction is FirSimpleFunction && containingClass != null) {
|
||||||
irFunction.overriddenSymbols = firFunction.generateOverriddenFunctionSymbols(
|
irFunction.overriddenSymbols = firFunction.generateOverriddenFunctionSymbols(
|
||||||
containingClass, session, scopeSession, declarationStorage
|
containingClass, session, scopeSession, declarationStorage, fakeOverrideGenerator
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,7 @@ internal class ClassMemberGenerator(
|
|||||||
}
|
}
|
||||||
if (containingClass != null) {
|
if (containingClass != null) {
|
||||||
this.overriddenSymbols = property.generateOverriddenAccessorSymbols(
|
this.overriddenSymbols = property.generateOverriddenAccessorSymbols(
|
||||||
containingClass, isGetter, session, scopeSession, declarationStorage
|
containingClass, isGetter, session, scopeSession, declarationStorage, fakeOverrideGenerator
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-3
@@ -132,7 +132,13 @@ internal class DelegatedMemberGenerator(
|
|||||||
containingClass = firSubClass.symbol.toLookupTag()
|
containingClass = firSubClass.symbol.toLookupTag()
|
||||||
)
|
)
|
||||||
delegateFunction.overriddenSymbols =
|
delegateFunction.overriddenSymbols =
|
||||||
delegateOverride.generateOverriddenFunctionSymbols(firSubClass, session, scopeSession, declarationStorage)
|
delegateOverride.generateOverriddenFunctionSymbols(
|
||||||
|
firSubClass,
|
||||||
|
session,
|
||||||
|
scopeSession,
|
||||||
|
declarationStorage,
|
||||||
|
fakeOverrideGenerator
|
||||||
|
)
|
||||||
.filter { it.owner != delegateFunction }
|
.filter { it.owner != delegateFunction }
|
||||||
annotationGenerator.generate(delegateFunction, delegateOverride)
|
annotationGenerator.generate(delegateFunction, delegateOverride)
|
||||||
|
|
||||||
@@ -201,13 +207,20 @@ internal class DelegatedMemberGenerator(
|
|||||||
|
|
||||||
delegateProperty.getter!!.body = createDelegateBody(irField, delegateProperty.getter!!, superProperty.getter!!)
|
delegateProperty.getter!!.body = createDelegateBody(irField, delegateProperty.getter!!, superProperty.getter!!)
|
||||||
delegateProperty.getter!!.overriddenSymbols =
|
delegateProperty.getter!!.overriddenSymbols =
|
||||||
firDelegateProperty.generateOverriddenAccessorSymbols(firSubClass, isGetter = true, session, scopeSession, declarationStorage)
|
firDelegateProperty.generateOverriddenAccessorSymbols(
|
||||||
|
firSubClass,
|
||||||
|
isGetter = true,
|
||||||
|
session,
|
||||||
|
scopeSession,
|
||||||
|
declarationStorage,
|
||||||
|
fakeOverrideGenerator
|
||||||
|
)
|
||||||
annotationGenerator.generate(delegateProperty.getter!!, firDelegateProperty)
|
annotationGenerator.generate(delegateProperty.getter!!, firDelegateProperty)
|
||||||
if (delegateProperty.isVar) {
|
if (delegateProperty.isVar) {
|
||||||
delegateProperty.setter!!.body = createDelegateBody(irField, delegateProperty.setter!!, superProperty.setter!!)
|
delegateProperty.setter!!.body = createDelegateBody(irField, delegateProperty.setter!!, superProperty.setter!!)
|
||||||
delegateProperty.setter!!.overriddenSymbols =
|
delegateProperty.setter!!.overriddenSymbols =
|
||||||
firDelegateProperty.generateOverriddenAccessorSymbols(
|
firDelegateProperty.generateOverriddenAccessorSymbols(
|
||||||
firSubClass, isGetter = false, session, scopeSession, declarationStorage
|
firSubClass, isGetter = false, session, scopeSession, declarationStorage, fakeOverrideGenerator
|
||||||
)
|
)
|
||||||
annotationGenerator.generate(delegateProperty.setter!!, firDelegateProperty)
|
annotationGenerator.generate(delegateProperty.setter!!, firDelegateProperty)
|
||||||
}
|
}
|
||||||
|
|||||||
+97
-20
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.*
|
|||||||
import org.jetbrains.kotlin.fir.backend.*
|
import org.jetbrains.kotlin.fir.backend.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.scopes.*
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
|
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
||||||
@@ -21,11 +22,10 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrErrorType
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||||
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||||
|
|
||||||
class FakeOverrideGenerator(
|
class FakeOverrideGenerator(
|
||||||
@@ -147,30 +147,34 @@ class FakeOverrideGenerator(
|
|||||||
|
|
||||||
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
||||||
val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S
|
val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S
|
||||||
val baseDeclaration = when {
|
|
||||||
|
val (fakeOverrideFirDeclaration, baseFirSymbolsForFakeOverride) = when {
|
||||||
originalSymbol.fir.origin.fromSupertypes && originalSymbol.dispatchReceiverClassOrNull() == classLookupTag -> {
|
originalSymbol.fir.origin.fromSupertypes && originalSymbol.dispatchReceiverClassOrNull() == classLookupTag -> {
|
||||||
// Substitution case
|
// Substitution or intersection case
|
||||||
originalDeclaration
|
// We have already a FIR declaration for such fake override
|
||||||
|
originalDeclaration to computeBaseSymbols(originalSymbol, computeDirectOverridden, scope, classLookupTag)
|
||||||
}
|
}
|
||||||
originalDeclaration.allowsToHaveFakeOverrideIn(klass) -> {
|
originalDeclaration.allowsToHaveFakeOverrideIn(klass) -> {
|
||||||
// Trivial fake override case
|
// Trivial fake override case
|
||||||
|
// We've got no relevant declaration in FIR world for such a fake override in current class, thus we're creating it here
|
||||||
val fakeOverrideSymbol = createFakeOverrideSymbol(originalDeclaration, baseSymbol)
|
val fakeOverrideSymbol = createFakeOverrideSymbol(originalDeclaration, baseSymbol)
|
||||||
|
declarationStorage.saveFakeOverrideInClass(irClass, originalDeclaration, fakeOverrideSymbol.fir)
|
||||||
classifierStorage.preCacheTypeParameters(originalDeclaration)
|
classifierStorage.preCacheTypeParameters(originalDeclaration)
|
||||||
fakeOverrideSymbol.fir
|
fakeOverrideSymbol.fir to listOf(originalSymbol)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val irDeclaration = cachedIrDeclaration(baseDeclaration) {
|
val irDeclaration = cachedIrDeclaration(fakeOverrideFirDeclaration) {
|
||||||
// Sometimes we can have clashing here when FIR substitution/intersection override
|
// Sometimes we can have clashing here when FIR substitution/intersection override
|
||||||
// have the same signature.
|
// have the same signature.
|
||||||
// Now we avoid this problem by signature caching,
|
// Now we avoid this problem by signature caching,
|
||||||
// so both FIR overrides correspond to one IR fake override
|
// so both FIR overrides correspond to one IR fake override
|
||||||
signatureComposer.composeSignature(baseDeclaration)
|
signatureComposer.composeSignature(fakeOverrideFirDeclaration)
|
||||||
}?.takeIf { it.parent == irClass }
|
}?.takeIf { it.parent == irClass }
|
||||||
?: createIrDeclaration(
|
?: createIrDeclaration(
|
||||||
baseDeclaration,
|
fakeOverrideFirDeclaration,
|
||||||
irClass,
|
irClass,
|
||||||
/* thisReceiverOwner = */ declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
/* thisReceiverOwner = */ declarationStorage.findIrParent(baseSymbol.fir) as? IrClass,
|
||||||
origin,
|
origin,
|
||||||
@@ -179,18 +183,20 @@ class FakeOverrideGenerator(
|
|||||||
if (containsErrorTypes(irDeclaration)) {
|
if (containsErrorTypes(irDeclaration)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
baseSymbols[irDeclaration] = computeBaseSymbols(originalSymbol, baseSymbol, computeDirectOverridden, scope, classLookupTag)
|
baseSymbols[irDeclaration] = baseFirSymbolsForFakeOverride
|
||||||
result += irDeclaration
|
result += irDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified S : FirCallableSymbol<*>> computeBaseSymbols(
|
private inline fun <reified S : FirCallableSymbol<*>> computeBaseSymbols(
|
||||||
symbol: S,
|
symbol: S,
|
||||||
basedSymbol: S,
|
|
||||||
directOverridden: FirTypeScope.(S) -> List<S>,
|
directOverridden: FirTypeScope.(S) -> List<S>,
|
||||||
scope: FirTypeScope,
|
scope: FirTypeScope,
|
||||||
containingClass: ConeClassLikeLookupTag,
|
containingClass: ConeClassLikeLookupTag,
|
||||||
): List<S> {
|
): List<S> {
|
||||||
if (symbol.fir.origin != FirDeclarationOrigin.IntersectionOverride) return listOf(basedSymbol)
|
if (symbol.fir.origin == FirDeclarationOrigin.SubstitutionOverride) {
|
||||||
|
return listOf(symbol.originalForSubstitutionOverride!!)
|
||||||
|
}
|
||||||
|
|
||||||
return scope.directOverridden(symbol).map {
|
return scope.directOverridden(symbol).map {
|
||||||
// Unwrapping should happen only for fake overrides members from the same class, not from supertypes
|
// Unwrapping should happen only for fake overrides members from the same class, not from supertypes
|
||||||
if (it.dispatchReceiverClassOrNull() != containingClass) return@map it
|
if (it.dispatchReceiverClassOrNull() != containingClass) return@map it
|
||||||
@@ -204,8 +210,78 @@ class FakeOverrideGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getOverriddenSymbols(function: IrSimpleFunction): List<IrSimpleFunctionSymbol>? {
|
internal fun getOverriddenSymbolsForFakeOverride(function: IrSimpleFunction): List<IrSimpleFunctionSymbol>? {
|
||||||
return baseFunctionSymbols[function]?.map { declarationStorage.getIrFunctionSymbol(it) as IrSimpleFunctionSymbol }
|
val baseSymbols = baseFunctionSymbols[function] ?: return null
|
||||||
|
return getOverriddenSymbolsInSupertypes(
|
||||||
|
function,
|
||||||
|
baseSymbols
|
||||||
|
) { declarationStorage.getIrFunctionSymbol(it) as IrSimpleFunctionSymbol }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun getOverriddenSymbolsInSupertypes(
|
||||||
|
overridden: FirNamedFunctionSymbol,
|
||||||
|
superClasses: Set<IrClass>,
|
||||||
|
): List<IrSimpleFunctionSymbol> {
|
||||||
|
return getOverriddenSymbolsInSupertypes(
|
||||||
|
overridden,
|
||||||
|
superClasses
|
||||||
|
) { declarationStorage.getIrFunctionSymbol(it) as IrSimpleFunctionSymbol }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun getOverriddenSymbolsInSupertypes(
|
||||||
|
overridden: FirPropertySymbol,
|
||||||
|
superClasses: Set<IrClass>,
|
||||||
|
): List<IrPropertySymbol> {
|
||||||
|
return getOverriddenSymbolsInSupertypes(
|
||||||
|
overridden, superClasses
|
||||||
|
) { declarationStorage.getIrPropertySymbol(it) as IrPropertySymbol }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <I : IrDeclaration, S : IrSymbol, F : FirCallableSymbol<*>> getOverriddenSymbolsInSupertypes(
|
||||||
|
declaration: I,
|
||||||
|
baseSymbols: List<F>,
|
||||||
|
irProducer: (F) -> S,
|
||||||
|
): List<S> {
|
||||||
|
val irClass = declaration.parentAsClass
|
||||||
|
val superClasses = irClass.superTypes.mapNotNull { it.classifierOrNull?.owner as? IrClass }.toSet()
|
||||||
|
|
||||||
|
return baseSymbols.flatMap { overridden ->
|
||||||
|
getOverriddenSymbolsInSupertypes(overridden, superClasses, irProducer)
|
||||||
|
}.distinct()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <F : FirCallableSymbol<*>, S : IrSymbol> getOverriddenSymbolsInSupertypes(
|
||||||
|
overridden: F,
|
||||||
|
superClasses: Set<IrClass>,
|
||||||
|
irProducer: (F) -> S
|
||||||
|
): List<S> {
|
||||||
|
val overriddenContainingClass =
|
||||||
|
overridden.containingClass()?.toSymbol(session)?.fir as? FirClass<*> ?: return emptyList()
|
||||||
|
|
||||||
|
val overriddenContainingIrClass =
|
||||||
|
declarationStorage.classifierStorage.getIrClassSymbol(overriddenContainingClass.symbol).owner as? IrClass
|
||||||
|
?: return emptyList()
|
||||||
|
|
||||||
|
return if (overriddenContainingIrClass in superClasses) {
|
||||||
|
// `overridden` was a FIR declaration in some of the supertypes
|
||||||
|
listOf(irProducer(overridden))
|
||||||
|
} else {
|
||||||
|
// There were no FIR declaration in supertypes, but we know that we have fake overrides in some of them
|
||||||
|
superClasses.mapNotNull {
|
||||||
|
declarationStorage.getFakeOverrideInClass(it, overridden.fir)?.let { fakeOverrideInClass ->
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
irProducer(fakeOverrideInClass.symbol as F)
|
||||||
|
}
|
||||||
|
}.run {
|
||||||
|
// TODO: Get rid of this hack
|
||||||
|
// It's only needed for built-in super classes, because they are built via descriptors and
|
||||||
|
// don't register fake overrides at org.jetbrains.kotlin.fir.backend.Fir2IrDeclarationStorage.fakeOverridesInClass
|
||||||
|
if (isEmpty())
|
||||||
|
listOf(irProducer(overridden))
|
||||||
|
else
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bindOverriddenSymbols(declarations: List<IrDeclaration>) {
|
fun bindOverriddenSymbols(declarations: List<IrDeclaration>) {
|
||||||
@@ -213,7 +289,7 @@ class FakeOverrideGenerator(
|
|||||||
if (declaration.origin != IrDeclarationOrigin.FAKE_OVERRIDE) continue
|
if (declaration.origin != IrDeclarationOrigin.FAKE_OVERRIDE) continue
|
||||||
when (declaration) {
|
when (declaration) {
|
||||||
is IrSimpleFunction -> {
|
is IrSimpleFunction -> {
|
||||||
val baseSymbols = getOverriddenSymbols(declaration)!!
|
val baseSymbols = getOverriddenSymbolsForFakeOverride(declaration)!!
|
||||||
declaration.withFunction {
|
declaration.withFunction {
|
||||||
overriddenSymbols = baseSymbols
|
overriddenSymbols = baseSymbols
|
||||||
}
|
}
|
||||||
@@ -249,9 +325,10 @@ class FakeOverrideGenerator(
|
|||||||
isVar: Boolean,
|
isVar: Boolean,
|
||||||
firOverriddenSymbols: List<FirPropertySymbol>
|
firOverriddenSymbols: List<FirPropertySymbol>
|
||||||
): IrProperty {
|
): IrProperty {
|
||||||
val overriddenIrProperties = firOverriddenSymbols.mapNotNull {
|
val overriddenIrProperties = getOverriddenSymbolsInSupertypes(this, firOverriddenSymbols) {
|
||||||
(declarationStorage.getIrPropertySymbol(it) as? IrPropertySymbol)?.owner
|
declarationStorage.getIrPropertySymbol(it) as IrPropertySymbol
|
||||||
}
|
}.map { it.owner }
|
||||||
|
|
||||||
getter?.apply {
|
getter?.apply {
|
||||||
overriddenSymbols = overriddenIrProperties.mapNotNull { it.getter?.symbol }
|
overriddenSymbols = overriddenIrProperties.mapNotNull { it.getter?.symbol }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class Fir2IrLazySimpleFunction(
|
|||||||
val parent = parent
|
val parent = parent
|
||||||
if (isFakeOverride && parent is Fir2IrLazyClass) {
|
if (isFakeOverride && parent is Fir2IrLazyClass) {
|
||||||
parent.declarations
|
parent.declarations
|
||||||
fakeOverrideGenerator.getOverriddenSymbols(this)?.let { return@lazyVar it }
|
fakeOverrideGenerator.getOverriddenSymbolsForFakeOverride(this)?.let { return@lazyVar it }
|
||||||
}
|
}
|
||||||
fir.generateOverriddenFunctionSymbols(firParent, session, scopeSession, declarationStorage, fakeOverrideGenerator)
|
fir.generateOverriddenFunctionSymbols(firParent, session, scopeSession, declarationStorage, fakeOverrideGenerator)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -37768,6 +37768,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/specialBuiltins/commonBridgesTarget.kt");
|
runTest("compiler/testData/codegen/box/specialBuiltins/commonBridgesTarget.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("complexMapImpl.kt")
|
||||||
|
public void testComplexMapImpl() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/specialBuiltins/complexMapImpl.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("emptyList.kt")
|
@TestMetadata("emptyList.kt")
|
||||||
public void testEmptyList() throws Exception {
|
public void testEmptyList() throws Exception {
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// DONT_TARGET_EXACT_BACKEND: WASM
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
// WASM_MUTE_REASON: STDLIB_COLLECTIONS
|
// WASM_MUTE_REASON: STDLIB_COLLECTIONS
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
import java.util.AbstractMap
|
import java.util.AbstractMap
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// DONT_TARGET_EXACT_BACKEND: WASM
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
// WASM_MUTE_REASON: STDLIB_COLLECTIONS
|
// WASM_MUTE_REASON: STDLIB_COLLECTIONS
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// KJS_WITH_FULL_RUNTIME
|
// KJS_WITH_FULL_RUNTIME
|
||||||
// IGNORE_BACKEND: NATIVE
|
// IGNORE_BACKEND: NATIVE
|
||||||
class A : HashSet<Long>()
|
class A : HashSet<Long>()
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// DONT_TARGET_EXACT_BACKEND: WASM
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
// WASM_MUTE_REASON: STDLIB_COLLECTIONS
|
// WASM_MUTE_REASON: STDLIB_COLLECTIONS
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// KJS_WITH_FULL_RUNTIME
|
// KJS_WITH_FULL_RUNTIME
|
||||||
// IGNORE_BACKEND: NATIVE
|
// IGNORE_BACKEND: NATIVE
|
||||||
class A : HashMap<String, Double>()
|
class A : HashMap<String, Double>()
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// DONT_TARGET_EXACT_BACKEND: WASM
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
// WASM_MUTE_REASON: STDLIB_COLLECTIONS
|
// WASM_MUTE_REASON: STDLIB_COLLECTIONS
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// KJS_WITH_FULL_RUNTIME
|
// KJS_WITH_FULL_RUNTIME
|
||||||
// IGNORE_BACKEND: NATIVE
|
// IGNORE_BACKEND: NATIVE
|
||||||
class A : HashSet<Long>()
|
class A : HashSet<Long>()
|
||||||
|
|||||||
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|||||||
+1
-3
@@ -1,5 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
abstract class AbstractAdd {
|
abstract class AbstractAdd {
|
||||||
abstract fun add(s: String): Any
|
abstract fun add(s: String): Any
|
||||||
}
|
}
|
||||||
@@ -23,4 +21,4 @@ fun test2(a: AbstractStringCollection) =
|
|||||||
a.add("K") as String
|
a.add("K") as String
|
||||||
|
|
||||||
fun box() =
|
fun box() =
|
||||||
test1(StringCollection()) + test2(StringCollection())
|
test1(StringCollection()) + test2(StringCollection())
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// FILE: javaCollectionWithRemovePrimitiveInt.kt
|
// FILE: javaCollectionWithRemovePrimitiveInt.kt
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// DONT_TARGET_EXACT_BACKEND: WASM
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
// WASM_MUTE_REASON: STDLIB_COLLECTIONS
|
// WASM_MUTE_REASON: STDLIB_COLLECTIONS
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// KJS_WITH_FULL_RUNTIME
|
// KJS_WITH_FULL_RUNTIME
|
||||||
// IGNORE_BACKEND: NATIVE
|
// IGNORE_BACKEND: NATIVE
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
// binary representation of fractional part of phi = (sqrt(5) - 1) / 2
|
||||||
|
private const val MAGIC: Int = 0x9E3779B9L.toInt() // ((sqrt(5.0) - 1) / 2 * pow(2.0, 32.0)).toLong().toString(16)
|
||||||
|
private const val MAX_SHIFT = 27
|
||||||
|
private const val THRESHOLD = ((1L shl 31) - 1).toInt() // 50% fill factor for speed
|
||||||
|
private val EMPTY_ARRAY = arrayOf<Any?>()
|
||||||
|
|
||||||
|
|
||||||
|
// For more details see for Knuth's multiplicative hash with golden ratio
|
||||||
|
// Shortly, we're trying to keep distribution of it uniform independently of input
|
||||||
|
// It's necessary because we use very simple linear probing
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
private inline fun Any.computeHash(shift: Int) = ((hashCode() * MAGIC) ushr shift) shl 1
|
||||||
|
|
||||||
|
|
||||||
|
internal class OpenAddressLinearProbingHashTable<K : Any, V : Any> : AbstractMutableMap<K, V>() {
|
||||||
|
// fields be initialized later in `clear()`
|
||||||
|
|
||||||
|
// capacity = 1 << (32 - shift)
|
||||||
|
private var shift = 0
|
||||||
|
// keys are stored in even elements, values are in odd ones
|
||||||
|
private var array = EMPTY_ARRAY
|
||||||
|
private var size_ = 0
|
||||||
|
|
||||||
|
init {
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val size
|
||||||
|
get() = size_
|
||||||
|
|
||||||
|
override fun get(key: K): V? {
|
||||||
|
var i = key.computeHash(shift)
|
||||||
|
var k = array[i]
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (k === null) return null
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
if (k == key) return array[i + 1] as V
|
||||||
|
if (i == 0) {
|
||||||
|
i = array.size
|
||||||
|
}
|
||||||
|
i -= 2
|
||||||
|
k = array[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Never returns previous values
|
||||||
|
*/
|
||||||
|
override fun put(key: K, value: V): V? {
|
||||||
|
if (put(array, shift, key, value)) {
|
||||||
|
if (++size_ >= (THRESHOLD ushr shift)) {
|
||||||
|
rehash()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rehash() {
|
||||||
|
val newShift = maxOf(shift - 3, 0)
|
||||||
|
val newArraySize = 1 shl (33 - newShift)
|
||||||
|
val newArray = arrayOfNulls<Any>(newArraySize)
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
val arraySize = array.size
|
||||||
|
while (i < arraySize) {
|
||||||
|
val key = array[i]
|
||||||
|
if (key != null) {
|
||||||
|
put(newArray, newShift, key, array[i + 1])
|
||||||
|
}
|
||||||
|
i += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
shift = newShift
|
||||||
|
array = newArray
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
shift = MAX_SHIFT
|
||||||
|
array = arrayOfNulls(1 shl (33 - shift))
|
||||||
|
|
||||||
|
size_ = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
|
||||||
|
get() {
|
||||||
|
|
||||||
|
throw IllegalStateException("OpenAddressLinearProbingHashTable::entries is not supported and hardly will be")
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Entry<K, V>(override val key: K, override val value: V) : MutableMap.MutableEntry<K, V> {
|
||||||
|
override fun setValue(newValue: V): V = throw UnsupportedOperationException("This Entry is not mutable.")
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// Change to "true" to be able to see the contents of the map in debugger views
|
||||||
|
private const val DEBUG = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun put(array: Array<Any?>, aShift: Int, key: Any, value: Any?): Boolean {
|
||||||
|
var i = key.computeHash(aShift)
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
val k = array[i]
|
||||||
|
if (k == null) {
|
||||||
|
array[i] = key
|
||||||
|
array[i + 1] = value
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (k == key) break
|
||||||
|
if (i == 0) {
|
||||||
|
i = array.size
|
||||||
|
}
|
||||||
|
i -= 2
|
||||||
|
}
|
||||||
|
|
||||||
|
array[i + 1] = value
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val map = OpenAddressLinearProbingHashTable<String, String>()
|
||||||
|
map.put("O", "K")
|
||||||
|
return "O" + map["O"]
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
import java.util.AbstractMap
|
import java.util.AbstractMap
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
// !JVM_DEFAULT_MODE: disable
|
// !JVM_DEFAULT_MODE: disable
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
|
|
||||||
// First item on Android is `java.lang.Thread.getStackTrace`
|
// First item on Android is `java.lang.Thread.getStackTrace`
|
||||||
|
|||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
abstract class A3<W> : java.util.AbstractList<W>()
|
abstract class A3<W> : java.util.AbstractList<W>()
|
||||||
abstract class A4<W> : java.util.AbstractList<W>() {
|
abstract class A4<W> : java.util.AbstractList<W>() {
|
||||||
override fun contains(o: W): Boolean {
|
override fun contains(o: W): Boolean {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
interface A {
|
interface A {
|
||||||
fun foo() = 42
|
fun foo() = 42
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
@@ -38,4 +37,4 @@ class MyMap: TestMap<String, String>()
|
|||||||
|
|
||||||
// JVM_IR_TEMPLATES:
|
// JVM_IR_TEMPLATES:
|
||||||
// 1 public bridge getOrDefault\(Ljava/lang/String;Ljava/lang/String;\)Ljava/lang/String;
|
// 1 public bridge getOrDefault\(Ljava/lang/String;Ljava/lang/String;\)Ljava/lang/String;
|
||||||
// 1 public final bridge getOrDefault\(Ljava/lang/Object;Ljava/lang/String;\)Ljava/lang/String;
|
// 1 public final bridge getOrDefault\(Ljava/lang/Object;Ljava/lang/String;\)Ljava/lang/String;
|
||||||
|
|||||||
+6
@@ -37768,6 +37768,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/specialBuiltins/commonBridgesTarget.kt");
|
runTest("compiler/testData/codegen/box/specialBuiltins/commonBridgesTarget.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("complexMapImpl.kt")
|
||||||
|
public void testComplexMapImpl() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/specialBuiltins/complexMapImpl.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("emptyList.kt")
|
@TestMetadata("emptyList.kt")
|
||||||
public void testEmptyList() throws Exception {
|
public void testEmptyList() throws Exception {
|
||||||
|
|||||||
+6
@@ -37768,6 +37768,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/specialBuiltins/commonBridgesTarget.kt");
|
runTest("compiler/testData/codegen/box/specialBuiltins/commonBridgesTarget.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("complexMapImpl.kt")
|
||||||
|
public void testComplexMapImpl() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/specialBuiltins/complexMapImpl.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("emptyList.kt")
|
@TestMetadata("emptyList.kt")
|
||||||
public void testEmptyList() throws Exception {
|
public void testEmptyList() throws Exception {
|
||||||
|
|||||||
+5
@@ -30208,6 +30208,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/specialBuiltins/commonBridgesTarget.kt");
|
runTest("compiler/testData/codegen/box/specialBuiltins/commonBridgesTarget.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("complexMapImpl.kt")
|
||||||
|
public void testComplexMapImpl() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/specialBuiltins/complexMapImpl.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("emptyList.kt")
|
@TestMetadata("emptyList.kt")
|
||||||
public void testEmptyList() throws Exception {
|
public void testEmptyList() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/specialBuiltins/emptyList.kt");
|
runTest("compiler/testData/codegen/box/specialBuiltins/emptyList.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user