JVM_IR. Proper lower toArray functions
This commit is contained in:
+10
-1
@@ -484,7 +484,8 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
|||||||
/// We assume that IR code that reaches us has been checked for correctness at the frontend.
|
/// We assume that IR code that reaches us has been checked for correctness at the frontend.
|
||||||
/// This function needs to single out those cases where Java accessibility rules differ from Kotlin's.
|
/// This function needs to single out those cases where Java accessibility rules differ from Kotlin's.
|
||||||
|
|
||||||
val declarationRaw = owner as IrDeclarationWithVisibility
|
val symbolOwner = owner
|
||||||
|
val declarationRaw = symbolOwner as IrDeclarationWithVisibility
|
||||||
val declaration =
|
val declaration =
|
||||||
(declarationRaw as? IrSimpleFunction)?.resolveFakeOverride()
|
(declarationRaw as? IrSimpleFunction)?.resolveFakeOverride()
|
||||||
?: (declarationRaw as? IrField)?.resolveFakeOverride() ?: declarationRaw
|
?: (declarationRaw as? IrField)?.resolveFakeOverride() ?: declarationRaw
|
||||||
@@ -495,6 +496,14 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
|||||||
// `internal` maps to public and requires no accessor.
|
// `internal` maps to public and requires no accessor.
|
||||||
if (!withSuper && !declaration.visibility.isPrivate && !declaration.visibility.isProtected) return true
|
if (!withSuper && !declaration.visibility.isPrivate && !declaration.visibility.isProtected) return true
|
||||||
|
|
||||||
|
//`toArray` is always accessible cause mapped to public functions
|
||||||
|
if (symbolOwner is IrSimpleFunction && (symbolOwner.isNonGenericToArray() || symbolOwner.isGenericToArray(context))) {
|
||||||
|
val parent = symbolOwner.parent
|
||||||
|
if (parent is IrClass && parent.isCollectionSubClass()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If local variables are accessible by Kotlin rules, they also are by Java rules.
|
// If local variables are accessible by Kotlin rules, they also are by Java rules.
|
||||||
val symbolDeclarationContainer = (declaration.parent as? IrDeclarationContainer) as? IrElement ?: return true
|
val symbolDeclarationContainer = (declaration.parent as? IrDeclarationContainer) as? IrElement ?: return true
|
||||||
val contextDeclarationContainer = (currentScope!!.irElement as IrDeclaration).getAccessContext(withSuper) ?: return false
|
val contextDeclarationContainer = (currentScope!!.irElement as IrDeclaration).getAccessContext(withSuper) ?: return false
|
||||||
|
|||||||
+147
-136
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
|||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
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.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
@@ -18,7 +19,6 @@ import org.jetbrains.kotlin.ir.builders.irBlockBody
|
|||||||
import org.jetbrains.kotlin.ir.builders.irCall
|
import org.jetbrains.kotlin.ir.builders.irCall
|
||||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
@@ -35,7 +35,9 @@ import org.jetbrains.kotlin.ir.types.*
|
|||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.isClass
|
import org.jetbrains.kotlin.ir.util.isClass
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
|
|
||||||
internal val toArrayPhase = makeIrFilePhase(
|
internal val toArrayPhase = makeIrFilePhase(
|
||||||
@@ -46,173 +48,162 @@ internal val toArrayPhase = makeIrFilePhase(
|
|||||||
|
|
||||||
private class ToArrayLowering(private val context: JvmBackendContext) : ClassLoweringPass {
|
private class ToArrayLowering(private val context: JvmBackendContext) : ClassLoweringPass {
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
if (irClass.isJvmInterface || !irClass.isDirectCollectionSubClass()) return
|
if (irClass.isJvmInterface || !irClass.isCollectionSubClass()) return
|
||||||
|
|
||||||
val irBuiltIns = context.irBuiltIns
|
val irBuiltIns = context.irBuiltIns
|
||||||
val symbols = context.ir.symbols
|
val symbols = context.ir.symbols
|
||||||
|
|
||||||
val toArrayName = Name.identifier("toArray")
|
val toArrayName = Name.identifier("toArray")
|
||||||
val genericToArray = irClass.declarations.find { it.isGenericToArray() }
|
val genericToArray = irClass.declarations.filterIsInstance<IrSimpleFunction>().find { it.isGenericToArray(context) }
|
||||||
val nonGenericToArray = irClass.declarations.find { it.isNonGenericToArray() }
|
val nonGenericToArray = irClass.declarations.filterIsInstance<IrSimpleFunction>().find { it.isNonGenericToArray() }
|
||||||
|
val isDirectCollectionSubClass = irClass.isDirectCollectionSubClass()
|
||||||
if (genericToArray == null) {
|
if (genericToArray == null) {
|
||||||
val typeParameterDescriptor = WrappedTypeParameterDescriptor()
|
if (isDirectCollectionSubClass) {
|
||||||
val typeParameter = IrTypeParameterImpl(
|
val typeParameterDescriptor = WrappedTypeParameterDescriptor()
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
val typeParameter = IrTypeParameterImpl(
|
||||||
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
|
||||||
IrTypeParameterSymbolImpl(typeParameterDescriptor),
|
|
||||||
Name.identifier("T"),
|
|
||||||
index = 0,
|
|
||||||
variance = Variance.INVARIANT,
|
|
||||||
isReified = false
|
|
||||||
).apply {
|
|
||||||
typeParameterDescriptor.bind(this)
|
|
||||||
superTypes.add(irBuiltIns.anyNType)
|
|
||||||
}
|
|
||||||
|
|
||||||
val substitutedArrayType = irBuiltIns.arrayClass.typeWith(typeParameter.defaultType)
|
|
||||||
val functionDescriptor = WrappedSimpleFunctionDescriptor()
|
|
||||||
val irFunction = IrFunctionImpl(
|
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
|
||||||
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
|
||||||
IrSimpleFunctionSymbolImpl(functionDescriptor),
|
|
||||||
toArrayName,
|
|
||||||
Visibilities.PUBLIC,
|
|
||||||
Modality.OPEN,
|
|
||||||
returnType = substitutedArrayType,
|
|
||||||
isInline = false,
|
|
||||||
isExternal = false,
|
|
||||||
isTailrec = false,
|
|
||||||
isSuspend = false,
|
|
||||||
isExpect = false,
|
|
||||||
isFakeOverride = false
|
|
||||||
)
|
|
||||||
functionDescriptor.bind(irFunction)
|
|
||||||
irFunction.parent = irClass
|
|
||||||
|
|
||||||
typeParameter.parent = irFunction
|
|
||||||
irFunction.typeParameters.add(typeParameter)
|
|
||||||
|
|
||||||
val dispatchReceiverParameterDescriptor = WrappedValueParameterDescriptor()
|
|
||||||
irFunction.dispatchReceiverParameter = IrValueParameterImpl(
|
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
|
||||||
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
|
||||||
IrValueParameterSymbolImpl(dispatchReceiverParameterDescriptor),
|
|
||||||
Name.special("<this>"),
|
|
||||||
index = -1,
|
|
||||||
type = irClass.defaultType,
|
|
||||||
varargElementType = null,
|
|
||||||
isCrossinline = false,
|
|
||||||
isNoinline = false
|
|
||||||
).apply {
|
|
||||||
parent = irFunction
|
|
||||||
}
|
|
||||||
val valueParameterDescriptor = WrappedValueParameterDescriptor()
|
|
||||||
irFunction.valueParameters.add(
|
|
||||||
IrValueParameterImpl(
|
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
||||||
IrValueParameterSymbolImpl(valueParameterDescriptor),
|
IrTypeParameterSymbolImpl(typeParameterDescriptor),
|
||||||
Name.identifier("array"),
|
Name.identifier("T"),
|
||||||
index = 0,
|
index = 0,
|
||||||
|
variance = Variance.INVARIANT,
|
||||||
|
isReified = false
|
||||||
|
).apply {
|
||||||
|
typeParameterDescriptor.bind(this)
|
||||||
|
superTypes.add(irBuiltIns.anyNType)
|
||||||
|
}
|
||||||
|
|
||||||
|
val substitutedArrayType = irBuiltIns.arrayClass.typeWith(typeParameter.defaultType)
|
||||||
|
val functionDescriptor = WrappedSimpleFunctionDescriptor()
|
||||||
|
val irFunction = IrFunctionImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
||||||
|
IrSimpleFunctionSymbolImpl(functionDescriptor),
|
||||||
|
toArrayName,
|
||||||
|
Visibilities.PUBLIC,
|
||||||
|
Modality.OPEN,
|
||||||
|
returnType = substitutedArrayType,
|
||||||
|
isInline = false,
|
||||||
|
isExternal = false,
|
||||||
|
isTailrec = false,
|
||||||
|
isSuspend = false,
|
||||||
|
isExpect = false,
|
||||||
|
isFakeOverride = false
|
||||||
|
)
|
||||||
|
functionDescriptor.bind(irFunction)
|
||||||
|
irFunction.parent = irClass
|
||||||
|
|
||||||
|
typeParameter.parent = irFunction
|
||||||
|
irFunction.typeParameters.add(typeParameter)
|
||||||
|
|
||||||
|
val dispatchReceiverParameterDescriptor = WrappedValueParameterDescriptor()
|
||||||
|
irFunction.dispatchReceiverParameter = IrValueParameterImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
||||||
|
IrValueParameterSymbolImpl(dispatchReceiverParameterDescriptor),
|
||||||
|
Name.special("<this>"),
|
||||||
|
index = -1,
|
||||||
|
type = irClass.defaultType,
|
||||||
varargElementType = null,
|
varargElementType = null,
|
||||||
type = substitutedArrayType,
|
|
||||||
isCrossinline = false,
|
isCrossinline = false,
|
||||||
isNoinline = false
|
isNoinline = false
|
||||||
).apply {
|
).apply {
|
||||||
valueParameterDescriptor.bind(this)
|
|
||||||
parent = irFunction
|
parent = irFunction
|
||||||
}
|
}
|
||||||
)
|
val valueParameterDescriptor = WrappedValueParameterDescriptor()
|
||||||
|
irFunction.valueParameters.add(
|
||||||
|
IrValueParameterImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
|
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
||||||
|
IrValueParameterSymbolImpl(valueParameterDescriptor),
|
||||||
|
Name.identifier("array"),
|
||||||
|
index = 0,
|
||||||
|
varargElementType = null,
|
||||||
|
type = substitutedArrayType,
|
||||||
|
isCrossinline = false,
|
||||||
|
isNoinline = false
|
||||||
|
).apply {
|
||||||
|
valueParameterDescriptor.bind(this)
|
||||||
|
parent = irFunction
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
|
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
|
||||||
+irReturn(
|
+irReturn(
|
||||||
irCall(symbols.genericToArray, symbols.genericToArray.owner.returnType).apply {
|
irCall(symbols.genericToArray, symbols.genericToArray.owner.returnType).apply {
|
||||||
putValueArgument(
|
putValueArgument(
|
||||||
0,
|
0,
|
||||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.dispatchReceiverParameter!!.symbol)
|
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.dispatchReceiverParameter!!.symbol)
|
||||||
)
|
)
|
||||||
putValueArgument(1, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.valueParameters[0].symbol))
|
putValueArgument(1, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.valueParameters[0].symbol))
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
irClass.declarations.add(irFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
irClass.declarations.add(irFunction)
|
|
||||||
} else {
|
} else {
|
||||||
//TODO patch visibility
|
(genericToArray as IrFunctionImpl).visibility = Visibilities.PUBLIC
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nonGenericToArray == null) {
|
if (nonGenericToArray == null) {
|
||||||
val functionDescriptor = WrappedSimpleFunctionDescriptor()
|
if (isDirectCollectionSubClass) {
|
||||||
val irFunction = IrFunctionImpl(
|
val functionDescriptor = WrappedSimpleFunctionDescriptor()
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
val irFunction = IrFunctionImpl(
|
||||||
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
IrSimpleFunctionSymbolImpl(functionDescriptor),
|
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
||||||
toArrayName,
|
IrSimpleFunctionSymbolImpl(functionDescriptor),
|
||||||
Visibilities.PUBLIC,
|
toArrayName,
|
||||||
Modality.OPEN,
|
Visibilities.PUBLIC,
|
||||||
returnType = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType),
|
Modality.OPEN,
|
||||||
isInline = false,
|
returnType = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType),
|
||||||
isExternal = false,
|
isInline = false,
|
||||||
isTailrec = false,
|
isExternal = false,
|
||||||
isSuspend = false,
|
isTailrec = false,
|
||||||
isExpect = false,
|
isSuspend = false,
|
||||||
isFakeOverride = false
|
isExpect = false,
|
||||||
)
|
isFakeOverride = false
|
||||||
functionDescriptor.bind(irFunction)
|
)
|
||||||
irFunction.parent = irClass
|
functionDescriptor.bind(irFunction)
|
||||||
|
irFunction.parent = irClass
|
||||||
|
|
||||||
val dispatchReceiverParameterDescriptor = WrappedValueParameterDescriptor()
|
val dispatchReceiverParameterDescriptor = WrappedValueParameterDescriptor()
|
||||||
irFunction.dispatchReceiverParameter = IrValueParameterImpl(
|
irFunction.dispatchReceiverParameter = IrValueParameterImpl(
|
||||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||||
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
JvmLoweredDeclarationOrigin.TO_ARRAY,
|
||||||
IrValueParameterSymbolImpl(dispatchReceiverParameterDescriptor),
|
IrValueParameterSymbolImpl(dispatchReceiverParameterDescriptor),
|
||||||
Name.special("<this>"),
|
Name.special("<this>"),
|
||||||
index = -1,
|
index = -1,
|
||||||
type = irClass.defaultType,
|
type = irClass.defaultType,
|
||||||
varargElementType = null,
|
varargElementType = null,
|
||||||
isCrossinline = false,
|
isCrossinline = false,
|
||||||
isNoinline = false
|
isNoinline = false
|
||||||
).apply {
|
).apply {
|
||||||
parent = irFunction
|
parent = irFunction
|
||||||
|
}
|
||||||
|
|
||||||
|
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
|
||||||
|
+irReturn(
|
||||||
|
irCall(symbols.nonGenericToArray, symbols.nonGenericToArray.owner.returnType).apply {
|
||||||
|
putValueArgument(
|
||||||
|
0,
|
||||||
|
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.dispatchReceiverParameter!!.symbol)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
irClass.declarations.add(irFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
irFunction.body = context.createIrBuilder(irFunction.symbol).irBlockBody {
|
|
||||||
+irReturn(
|
|
||||||
irCall(symbols.nonGenericToArray, symbols.nonGenericToArray.owner.returnType).apply {
|
|
||||||
putValueArgument(
|
|
||||||
0,
|
|
||||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFunction.dispatchReceiverParameter!!.symbol)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
irClass.declarations.add(irFunction)
|
|
||||||
} else {
|
} else {
|
||||||
//TODO patch visibility
|
(nonGenericToArray as IrFunctionImpl).visibility = Visibilities.PUBLIC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrDeclaration.isGenericToArray(): Boolean {
|
|
||||||
if (this !is IrSimpleFunction) return false
|
|
||||||
val signature = context.methodSignatureMapper.mapAsmMethod(this)
|
|
||||||
return signature.toString() == "toArray([Ljava/lang/Object;)[Ljava/lang/Object;"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrDeclaration.isNonGenericToArray(): Boolean {
|
|
||||||
if (this !is IrSimpleFunction) return false
|
|
||||||
if (this.name.asString() != "toArray") return false
|
|
||||||
if (typeParameters.isNotEmpty() || valueParameters.isNotEmpty()) return false
|
|
||||||
if (!returnType.isArray()) return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val IrClass.superClasses
|
private val IrClass.superClasses
|
||||||
get() = superTypes.mapNotNull { it.getClass() }
|
get() = superTypes.mapNotNull { it.getClass() }
|
||||||
|
|
||||||
// Have to check by name, since irBuiltins is unreliable.
|
// Have to check by name, since irBuiltins is unreliable.
|
||||||
private fun IrClass.isCollectionSubClass() =
|
internal fun IrClass.isCollectionSubClass() =
|
||||||
DFS.ifAny(listOf(this), IrClass::superClasses) { it.defaultType.isCollection() }
|
DFS.ifAny(listOf(this), IrClass::superClasses) { it.defaultType.isCollection() }
|
||||||
|
|
||||||
// If this class inherits from another Kotlin class that implements Collection, it already has toArray.
|
// If this class inherits from another Kotlin class that implements Collection, it already has toArray.
|
||||||
@@ -220,3 +211,23 @@ private fun IrClass.isDirectCollectionSubClass() =
|
|||||||
isCollectionSubClass() && !superClasses.any {
|
isCollectionSubClass() && !superClasses.any {
|
||||||
it.isClass && it.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && it.isCollectionSubClass()
|
it.isClass && it.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB && it.isCollectionSubClass()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal fun IrSimpleFunction.isGenericToArray(context: JvmBackendContext): Boolean {
|
||||||
|
if (name.asString() != "toArray") return false
|
||||||
|
if (typeParameters.size != 1 || valueParameters.size != 1 || extensionReceiverParameter != null) return false
|
||||||
|
|
||||||
|
val paramType = valueParameters[0].type
|
||||||
|
|
||||||
|
if (!returnType.isArray() || !paramType.isArray()) return false
|
||||||
|
|
||||||
|
val elementType = typeParameters[0].defaultType
|
||||||
|
val expectedType = context.ir.symbols.array.typeWith(elementType)
|
||||||
|
return expectedType == paramType && expectedType == returnType
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrSimpleFunction.isNonGenericToArray(): Boolean {
|
||||||
|
if (name.asString() != "toArray") return false
|
||||||
|
if (typeParameters.isNotEmpty() || valueParameters.isNotEmpty() || extensionReceiverParameter != null) return false
|
||||||
|
return returnType.isArray()
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
// FILE: SingletonCollection.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
open class SingletonCollection<T>(val value: T) : AbstractCollection<T>() {
|
||||||
|
override val size = 1
|
||||||
|
override fun iterator(): Iterator<T> = listOf(value).iterator()
|
||||||
|
|
||||||
|
protected override final fun toArray(): Array<Any?> =
|
||||||
|
arrayOf<Any?>(value)
|
||||||
|
|
||||||
|
protected override final fun <E> toArray(a: Array<E>): Array<E> {
|
||||||
|
a[0] = value as E
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class SingletonCollection2<T>(val value: T) : AbstractCollection<T>() {
|
||||||
|
override val size = 1
|
||||||
|
override fun iterator(): Iterator<T> = listOf(value).iterator()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: DerivedSingletonCollection.kt
|
||||||
|
package test2
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
class DerivedSingletonCollection<T>(value: T) : SingletonCollection<T>(value) {
|
||||||
|
fun test() = object {
|
||||||
|
fun test() = toArray()
|
||||||
|
}.test()
|
||||||
|
|
||||||
|
fun <E> test(a: Array<E>) = object {
|
||||||
|
fun test() = toArray(a)
|
||||||
|
}.test()
|
||||||
|
}
|
||||||
|
|
||||||
|
class DerivedSingletonCollection2<T>(value: T) : SingletonCollection2<T>(value) {
|
||||||
|
fun test() = object {
|
||||||
|
fun test() = toArray()
|
||||||
|
}.test()
|
||||||
|
|
||||||
|
fun <E> test(a: Array<E>) = object {
|
||||||
|
fun test() = toArray(a)
|
||||||
|
}.test()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// @test/SingletonCollection.class:
|
||||||
|
// 0 access\$
|
||||||
|
// 2 public final toArray
|
||||||
|
// 0 \.toArray
|
||||||
|
|
||||||
|
// @test/SingletonCollection2.class:
|
||||||
|
// 0 access\$
|
||||||
|
// 0 toArray
|
||||||
|
|
||||||
|
// @test2/DerivedSingletonCollection.class:
|
||||||
|
// 0 access\$
|
||||||
|
// 0 toArray
|
||||||
|
|
||||||
|
// @test2/DerivedSingletonCollection2.class:
|
||||||
|
// 0 access\$
|
||||||
|
// 0 toArray
|
||||||
@@ -4061,6 +4061,24 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/bytecodeText/toArray")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ToArray extends AbstractBytecodeTextTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInToArray() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/toArray"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noAccessorForToArray.kt")
|
||||||
|
public void testNoAccessorForToArray() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/toArray/noAccessorForToArray.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/bytecodeText/unsignedTypes")
|
@TestMetadata("compiler/testData/codegen/bytecodeText/unsignedTypes")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+18
@@ -3979,6 +3979,24 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/bytecodeText/toArray")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ToArray extends AbstractIrBytecodeTextTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInToArray() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/toArray"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noAccessorForToArray.kt")
|
||||||
|
public void testNoAccessorForToArray() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/toArray/noAccessorForToArray.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/bytecodeText/unsignedTypes")
|
@TestMetadata("compiler/testData/codegen/bytecodeText/unsignedTypes")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user