Generate stub for specialized equals inside inline class
This commit is contained in:
@@ -77,6 +77,7 @@ class ErasedInlineClassBodyCodegen(
|
|||||||
|
|
||||||
generateUnboxMethod()
|
generateUnboxMethod()
|
||||||
generateFunctionsFromAny()
|
generateFunctionsFromAny()
|
||||||
|
generateSpecializedEqualsStub()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateFunctionsFromAny() {
|
private fun generateFunctionsFromAny() {
|
||||||
@@ -116,6 +117,31 @@ class ErasedInlineClassBodyCodegen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateSpecializedEqualsStub() {
|
||||||
|
val specializedEqualsDescriptor = InlineClassDescriptorResolver.createSpecializedEqualsDescriptor(descriptor) ?: return
|
||||||
|
|
||||||
|
functionCodegen.generateMethod(
|
||||||
|
Synthetic(null, specializedEqualsDescriptor), specializedEqualsDescriptor, object : FunctionGenerationStrategy.CodegenBased(state) {
|
||||||
|
override fun mapMethodSignature(
|
||||||
|
functionDescriptor: FunctionDescriptor,
|
||||||
|
typeMapper: KotlinTypeMapper,
|
||||||
|
contextKind: OwnerKind,
|
||||||
|
hasSpecialBridge: Boolean
|
||||||
|
): JvmMethodGenericSignature {
|
||||||
|
// we shouldn't use default mapping here to avoid adding parameter that relates to carrier type
|
||||||
|
return typeMapper.mapSignatureForSpecializedEqualsOfInlineClass(functionDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||||
|
val iv = codegen.v
|
||||||
|
iv.aconst(null)
|
||||||
|
iv.athrow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun generateKotlinMetadataAnnotation() {
|
override fun generateKotlinMetadataAnnotation() {
|
||||||
writeSyntheticClassMetadata(v, state)
|
writeSyntheticClassMetadata(v, state)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1162,6 +1162,11 @@ public class KotlinTypeMapper {
|
|||||||
return mapSignature(f, OwnerKind.IMPLEMENTATION, true);
|
return mapSignature(f, OwnerKind.IMPLEMENTATION, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JvmMethodGenericSignature mapSignatureForSpecializedEqualsOfInlineClass(@NotNull FunctionDescriptor f) {
|
||||||
|
return mapSignature(f, OwnerKind.IMPLEMENTATION, true);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JvmMethodSignature mapSignatureSkipGeneric(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
|
public JvmMethodSignature mapSignatureSkipGeneric(@NotNull FunctionDescriptor f, @NotNull OwnerKind kind) {
|
||||||
return mapSignature(f, kind, true);
|
return mapSignature(f, kind, true);
|
||||||
|
|||||||
+51
-2
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
|
|
||||||
object InlineClassDescriptorResolver {
|
object InlineClassDescriptorResolver {
|
||||||
@JvmField
|
@JvmField
|
||||||
@@ -18,8 +19,13 @@ object InlineClassDescriptorResolver {
|
|||||||
@JvmField
|
@JvmField
|
||||||
val UNBOX_METHOD_NAME = Name.identifier("unbox")
|
val UNBOX_METHOD_NAME = Name.identifier("unbox")
|
||||||
|
|
||||||
|
private val SPECIALIZED_EQUALS_NAME = Name.identifier("equals--impl")
|
||||||
|
|
||||||
private val BOXING_VALUE_PARAMETER_NAME = Name.identifier("v")
|
private val BOXING_VALUE_PARAMETER_NAME = Name.identifier("v")
|
||||||
|
|
||||||
|
private val SPECIALIZED_EQUALS_FIRST_PARAMETER_NAME = Name.identifier("p1")
|
||||||
|
private val SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME = Name.identifier("p2")
|
||||||
|
|
||||||
fun createBoxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? {
|
fun createBoxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? {
|
||||||
return createConversionFunctionDescriptor(true, owner)
|
return createConversionFunctionDescriptor(true, owner)
|
||||||
}
|
}
|
||||||
@@ -27,6 +33,30 @@ object InlineClassDescriptorResolver {
|
|||||||
fun createUnboxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? =
|
fun createUnboxFunctionDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? =
|
||||||
createConversionFunctionDescriptor(false, owner)
|
createConversionFunctionDescriptor(false, owner)
|
||||||
|
|
||||||
|
fun createSpecializedEqualsDescriptor(owner: ClassDescriptor): SimpleFunctionDescriptor? {
|
||||||
|
val inlinedValue = owner.underlyingRepresentation() ?: return null
|
||||||
|
|
||||||
|
val functionDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||||
|
owner,
|
||||||
|
Annotations.EMPTY,
|
||||||
|
SPECIALIZED_EQUALS_NAME,
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
|
SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
|
||||||
|
functionDescriptor.initialize(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
emptyList<TypeParameterDescriptor>(),
|
||||||
|
createValueParametersForSpecializedEquals(functionDescriptor, inlinedValue),
|
||||||
|
owner.builtIns.booleanType,
|
||||||
|
Modality.FINAL,
|
||||||
|
Visibilities.PUBLIC
|
||||||
|
)
|
||||||
|
|
||||||
|
return functionDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
private fun createConversionFunctionDescriptor(
|
private fun createConversionFunctionDescriptor(
|
||||||
isBoxMethod: Boolean,
|
isBoxMethod: Boolean,
|
||||||
owner: ClassDescriptor
|
owner: ClassDescriptor
|
||||||
@@ -57,13 +87,32 @@ object InlineClassDescriptorResolver {
|
|||||||
private fun createValueParameterForBoxing(
|
private fun createValueParameterForBoxing(
|
||||||
functionDescriptor: FunctionDescriptor,
|
functionDescriptor: FunctionDescriptor,
|
||||||
inlinedValue: ValueParameterDescriptor
|
inlinedValue: ValueParameterDescriptor
|
||||||
|
): ValueParameterDescriptorImpl {
|
||||||
|
return createValueParameter(functionDescriptor, inlinedValue, BOXING_VALUE_PARAMETER_NAME, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createValueParametersForSpecializedEquals(
|
||||||
|
functionDescriptor: FunctionDescriptor,
|
||||||
|
inlinedValue: ValueParameterDescriptor
|
||||||
|
): List<ValueParameterDescriptor> {
|
||||||
|
return listOf(
|
||||||
|
createValueParameter(functionDescriptor, inlinedValue, SPECIALIZED_EQUALS_FIRST_PARAMETER_NAME, 0),
|
||||||
|
createValueParameter(functionDescriptor, inlinedValue, SPECIALIZED_EQUALS_SECOND_PARAMETER_NAME, 1)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createValueParameter(
|
||||||
|
functionDescriptor: FunctionDescriptor,
|
||||||
|
inlinedValue: ValueParameterDescriptor,
|
||||||
|
name: Name,
|
||||||
|
index: Int
|
||||||
): ValueParameterDescriptorImpl {
|
): ValueParameterDescriptorImpl {
|
||||||
return ValueParameterDescriptorImpl(
|
return ValueParameterDescriptorImpl(
|
||||||
functionDescriptor,
|
functionDescriptor,
|
||||||
null,
|
null,
|
||||||
0,
|
index,
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
BOXING_VALUE_PARAMETER_NAME,
|
name,
|
||||||
inlinedValue.type,
|
inlinedValue.type,
|
||||||
false, false, false, null, SourceElement.NO_SOURCE
|
false, false, false, null, SourceElement.NO_SOURCE
|
||||||
)
|
)
|
||||||
|
|||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
// WITH_REFLECT
|
||||||
|
// FULL_JDK
|
||||||
|
// IGNORE_BACKEND: JVM_IR, JS_IR, JS, NATIVE
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException
|
||||||
|
|
||||||
|
inline class Simple(val x: String) {
|
||||||
|
fun somethingWeird() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var s = ""
|
||||||
|
val name = "equals--impl"
|
||||||
|
val specializedEquals =
|
||||||
|
Class.forName("Simple\$Erased").getDeclaredMethod("equals--impl", String::class.java, String::class.java)
|
||||||
|
?: return "$name not found"
|
||||||
|
|
||||||
|
try {
|
||||||
|
specializedEquals.invoke(null, "a", "b")
|
||||||
|
} catch (e: InvocationTargetException) {
|
||||||
|
return if (e.targetException is NullPointerException) "OK" else "${e.targetException}"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Reserved method invoked successfully"
|
||||||
|
}
|
||||||
Vendored
+1
@@ -12,6 +12,7 @@ static class Foo$Erased {
|
|||||||
public final static @org.jetbrains.annotations.NotNull method box(p0: int): Foo
|
public final static @org.jetbrains.annotations.NotNull method box(p0: int): Foo
|
||||||
public static method constructor(p0: int): int
|
public static method constructor(p0: int): int
|
||||||
public static method equals(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
public static method equals(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
||||||
|
public final static method equals--impl(p0: int, p1: int): boolean
|
||||||
public static method hashCode(p0: int): int
|
public static method hashCode(p0: int): int
|
||||||
public final static method inInlineClass(p0: int): void
|
public final static method inInlineClass(p0: int): void
|
||||||
public static @org.jetbrains.annotations.NotNull method toString(p0: int): java.lang.String
|
public static @org.jetbrains.annotations.NotNull method toString(p0: int): java.lang.String
|
||||||
|
|||||||
Vendored
+1
@@ -4,6 +4,7 @@ static class Foo$Erased {
|
|||||||
public final static @org.jetbrains.annotations.NotNull method box(p0: int): Foo
|
public final static @org.jetbrains.annotations.NotNull method box(p0: int): Foo
|
||||||
public static method constructor(p0: int): int
|
public static method constructor(p0: int): int
|
||||||
public static method equals(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
public static method equals(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
||||||
|
public final static method equals--impl(p0: int, p1: int): boolean
|
||||||
public final static method getAsThis(p0: int): int
|
public final static method getAsThis(p0: int): int
|
||||||
public final static method getProp(p0: int): int
|
public final static method getProp(p0: int): int
|
||||||
public static method hashCode(p0: int): int
|
public static method hashCode(p0: int): int
|
||||||
|
|||||||
+1
@@ -5,6 +5,7 @@ static class Foo$Erased {
|
|||||||
public static method constructor(p0: int): int
|
public static method constructor(p0: int): int
|
||||||
public static method constructor(p0: long): int
|
public static method constructor(p0: long): int
|
||||||
public static method equals(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
public static method equals(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
||||||
|
public final static method equals--impl(p0: int, p1: int): boolean
|
||||||
public static method hashCode(p0: int): int
|
public static method hashCode(p0: int): int
|
||||||
public static @org.jetbrains.annotations.NotNull method toString(p0: int): java.lang.String
|
public static @org.jetbrains.annotations.NotNull method toString(p0: int): java.lang.String
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -9,6 +9,7 @@ static class Foo$Erased {
|
|||||||
public final static @org.jetbrains.annotations.NotNull method box(p0: long): Foo
|
public final static @org.jetbrains.annotations.NotNull method box(p0: long): Foo
|
||||||
public static method constructor(p0: long): long
|
public static method constructor(p0: long): long
|
||||||
public static method equals(p0: long, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
public static method equals(p0: long, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
||||||
|
public final static method equals--impl(p0: long, p1: long): boolean
|
||||||
public static method foo-1e4ch6lh(p0: long, p1: long): void
|
public static method foo-1e4ch6lh(p0: long, p1: long): void
|
||||||
public static method hashCode(p0: long): int
|
public static method hashCode(p0: long): int
|
||||||
public static @org.jetbrains.annotations.NotNull method toString(p0: long): java.lang.String
|
public static @org.jetbrains.annotations.NotNull method toString(p0: long): java.lang.String
|
||||||
|
|||||||
Vendored
+1
@@ -5,6 +5,7 @@ static class Foo$Erased {
|
|||||||
public static method constructor(p0: long): long
|
public static method constructor(p0: long): long
|
||||||
public final static method empty(p0: long): void
|
public final static method empty(p0: long): void
|
||||||
public static method equals(p0: long, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
public static method equals(p0: long, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
||||||
|
public final static method equals--impl(p0: long, p1: long): boolean
|
||||||
public final static method extension(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.Object, @org.jetbrains.annotations.NotNull p2: java.lang.String): void
|
public final static method extension(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.Object, @org.jetbrains.annotations.NotNull p2: java.lang.String): void
|
||||||
public static method hashCode(p0: long): int
|
public static method hashCode(p0: long): int
|
||||||
public final static method param(p0: long, p1: double): void
|
public final static method param(p0: long, p1: double): void
|
||||||
|
|||||||
+5
@@ -11501,6 +11501,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("callSpecializedEqualsViaReflection.kt")
|
||||||
|
public void testCallSpecializedEqualsViaReflection() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inlineClasses/callSpecializedEqualsViaReflection.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("callSpeciallyOverriddenPropertyOfInlineClass.kt")
|
@TestMetadata("callSpeciallyOverriddenPropertyOfInlineClass.kt")
|
||||||
public void testCallSpeciallyOverriddenPropertyOfInlineClass() throws Exception {
|
public void testCallSpeciallyOverriddenPropertyOfInlineClass() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inlineClasses/callSpeciallyOverriddenPropertyOfInlineClass.kt");
|
runTest("compiler/testData/codegen/box/inlineClasses/callSpeciallyOverriddenPropertyOfInlineClass.kt");
|
||||||
|
|||||||
+5
@@ -11501,6 +11501,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("callSpecializedEqualsViaReflection.kt")
|
||||||
|
public void testCallSpecializedEqualsViaReflection() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inlineClasses/callSpecializedEqualsViaReflection.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("callSpeciallyOverriddenPropertyOfInlineClass.kt")
|
@TestMetadata("callSpeciallyOverriddenPropertyOfInlineClass.kt")
|
||||||
public void testCallSpeciallyOverriddenPropertyOfInlineClass() throws Exception {
|
public void testCallSpeciallyOverriddenPropertyOfInlineClass() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inlineClasses/callSpeciallyOverriddenPropertyOfInlineClass.kt");
|
runTest("compiler/testData/codegen/box/inlineClasses/callSpeciallyOverriddenPropertyOfInlineClass.kt");
|
||||||
|
|||||||
+5
@@ -11501,6 +11501,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("callSpecializedEqualsViaReflection.kt")
|
||||||
|
public void testCallSpecializedEqualsViaReflection() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inlineClasses/callSpecializedEqualsViaReflection.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("callSpeciallyOverriddenPropertyOfInlineClass.kt")
|
@TestMetadata("callSpeciallyOverriddenPropertyOfInlineClass.kt")
|
||||||
public void testCallSpeciallyOverriddenPropertyOfInlineClass() throws Exception {
|
public void testCallSpeciallyOverriddenPropertyOfInlineClass() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inlineClasses/callSpeciallyOverriddenPropertyOfInlineClass.kt");
|
runTest("compiler/testData/codegen/box/inlineClasses/callSpeciallyOverriddenPropertyOfInlineClass.kt");
|
||||||
|
|||||||
+5
@@ -10046,6 +10046,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("callSpecializedEqualsViaReflection.kt")
|
||||||
|
public void testCallSpecializedEqualsViaReflection() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inlineClasses/callSpecializedEqualsViaReflection.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("callableReferencesWithInlineClasses.kt")
|
@TestMetadata("callableReferencesWithInlineClasses.kt")
|
||||||
public void testCallableReferencesWithInlineClasses() throws Exception {
|
public void testCallableReferencesWithInlineClasses() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inlineClasses/callableReferencesWithInlineClasses.kt");
|
runTest("compiler/testData/codegen/box/inlineClasses/callableReferencesWithInlineClasses.kt");
|
||||||
|
|||||||
+5
@@ -11111,6 +11111,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
runTest("compiler/testData/codegen/box/inlineClasses/callComputablePropertyInsideInlineClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("callSpecializedEqualsViaReflection.kt")
|
||||||
|
public void testCallSpecializedEqualsViaReflection() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/inlineClasses/callSpecializedEqualsViaReflection.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("callableReferencesWithInlineClasses.kt")
|
@TestMetadata("callableReferencesWithInlineClasses.kt")
|
||||||
public void testCallableReferencesWithInlineClasses() throws Exception {
|
public void testCallableReferencesWithInlineClasses() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/inlineClasses/callableReferencesWithInlineClasses.kt");
|
runTest("compiler/testData/codegen/box/inlineClasses/callableReferencesWithInlineClasses.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user