[objc][codegen] Fixed bug with calling fake override interface methods
This commit is contained in:
committed by
Stanislav Erokhin
parent
92f8eff958
commit
9b84d72a44
+3
-3
@@ -363,9 +363,9 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, va
|
||||
.toList()
|
||||
}
|
||||
|
||||
data class InterfaceTablePlace(val interfaceId: Int, val methodIndex: Int) {
|
||||
data class InterfaceTablePlace(val interfaceId: Int, val itableSize: Int, val methodIndex: Int) {
|
||||
companion object {
|
||||
val INVALID = InterfaceTablePlace(0, -1)
|
||||
val INVALID = InterfaceTablePlace(0, -1, -1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, va
|
||||
val itable = interfaceTableEntries
|
||||
val index = itable.indexOf(function)
|
||||
if (index >= 0)
|
||||
return InterfaceTablePlace(hierarchyInfo.interfaceId, index)
|
||||
return InterfaceTablePlace(hierarchyInfo.interfaceId, itable.size, index)
|
||||
val superFunction = function.overriddenSymbols.first().owner
|
||||
return context.getLayoutBuilder(superFunction.parentAsClass).itablePlace(superFunction)
|
||||
}
|
||||
|
||||
+1
@@ -405,6 +405,7 @@ internal class ObjCExportCodeGenerator(
|
||||
staticData.cStringLiteral(selector),
|
||||
Int64(nameSignature),
|
||||
Int32(itablePlace.interfaceId),
|
||||
Int32(itablePlace.itableSize),
|
||||
Int32(itablePlace.methodIndex),
|
||||
Int32(vtableIndex),
|
||||
kotlinImpl
|
||||
|
||||
@@ -1937,6 +1937,17 @@ __attribute__((swift_name("GH3825KotlinImpl")))
|
||||
- (BOOL)call2Callback:(void (^)(void))callback doThrow:(BOOL)doThrow error:(NSError * _Nullable * _Nullable)error __attribute__((swift_name("call2(callback:doThrow:)")));
|
||||
@end;
|
||||
|
||||
__attribute__((swift_name("Foo_FakeOverrideInInterface")))
|
||||
@protocol KtFoo_FakeOverrideInInterface
|
||||
@required
|
||||
- (void)fooT:(id _Nullable)t __attribute__((swift_name("foo(t:)")));
|
||||
@end;
|
||||
|
||||
__attribute__((swift_name("Bar_FakeOverrideInInterface")))
|
||||
@protocol KtBar_FakeOverrideInInterface <KtFoo_FakeOverrideInInterface>
|
||||
@required
|
||||
@end;
|
||||
|
||||
@interface KtEnumeration (ValuesKt)
|
||||
- (KtEnumeration *)getAnswer __attribute__((swift_name("getAnswer()")));
|
||||
@end;
|
||||
@@ -2088,6 +2099,7 @@ __attribute__((swift_name("ValuesKt")))
|
||||
+ (KtMutableDictionary<KtULong *, KtLong *> *)mutULong2Long __attribute__((swift_name("mutULong2Long()")));
|
||||
+ (KtMutableDictionary<KtFloat *, KtFloat *> *)mutFloat2Float __attribute__((swift_name("mutFloat2Float()")));
|
||||
+ (KtMutableDictionary<KtDouble *, NSString *> *)mutDouble2String __attribute__((swift_name("mutDouble2String()")));
|
||||
+ (void)callFoo_FakeOverrideInInterfaceObj:(id<KtBar_FakeOverrideInInterface>)obj __attribute__((swift_name("callFoo_FakeOverrideInInterface(obj:)")));
|
||||
@property (class, readonly) double dbl __attribute__((swift_name("dbl")));
|
||||
@property (class, readonly) float flt __attribute__((swift_name("flt")));
|
||||
@property (class, readonly) int32_t integer __attribute__((swift_name("integer")));
|
||||
|
||||
@@ -1012,3 +1012,12 @@ fun mutULong2Long(): MutableMap<ULong, Long> = mutableMapOf(Pair(0x8000_0000_000
|
||||
fun mutFloat2Float(): MutableMap<Float, Float> = mutableMapOf(Pair(3.14f, 100f))
|
||||
fun mutDouble2String(): MutableMap<Double, String> = mutableMapOf(Pair(2.718281828459045, "2.718281828459045"))
|
||||
|
||||
interface Foo_FakeOverrideInInterface<T> {
|
||||
fun foo(t: T?)
|
||||
}
|
||||
|
||||
interface Bar_FakeOverrideInInterface : Foo_FakeOverrideInInterface<String>
|
||||
|
||||
fun callFoo_FakeOverrideInInterface(obj: Bar_FakeOverrideInInterface) {
|
||||
obj.foo(null)
|
||||
}
|
||||
@@ -1318,6 +1318,14 @@ func testMapsExport() throws {
|
||||
try assertEquals(actual: (ValuesKt.mutDouble2String() as! [Double: String])[2.718281828459045], expected: "2.718281828459045")
|
||||
}
|
||||
|
||||
class Baz_FakeOverrideInInterface : Bar_FakeOverrideInInterface {
|
||||
func foo(t: Any?) {}
|
||||
}
|
||||
|
||||
func testFakeOverrideInInterface() throws {
|
||||
ValuesKt.callFoo_FakeOverrideInInterface(obj: Baz_FakeOverrideInInterface())
|
||||
}
|
||||
|
||||
// -------- Execution of the test --------
|
||||
|
||||
class ValuesTests : SimpleTestProvider {
|
||||
@@ -1374,6 +1382,7 @@ class ValuesTests : SimpleTestProvider {
|
||||
test("TestStringConversion", testStringConversion)
|
||||
test("TestGH3825", testGH3825)
|
||||
test("TestMapsExport", testMapsExport)
|
||||
test("TestFakeOverrideInInterface", testFakeOverrideInInterface)
|
||||
|
||||
// Stress test, must remain the last one:
|
||||
test("TestGH2931", testGH2931)
|
||||
|
||||
@@ -54,6 +54,7 @@ struct KotlinToObjCMethodAdapter {
|
||||
const char* selector;
|
||||
MethodNameHash nameSignature;
|
||||
ClassId interfaceId;
|
||||
int itableSize;
|
||||
int itableIndex;
|
||||
int vtableIndex;
|
||||
const void* kotlinImpl;
|
||||
@@ -889,6 +890,8 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
|
||||
supers.push_back(t);
|
||||
}
|
||||
|
||||
bool itableEqualsSuper = true;
|
||||
|
||||
auto addToITable = [&interfaceVTables](ClassId interfaceId, int methodIndex, VTableElement entry) {
|
||||
RuntimeAssert(interfaceId != kInvalidInterfaceId, "");
|
||||
auto interfaceVTableIt = interfaceVTables.find(interfaceId);
|
||||
@@ -898,7 +901,18 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
|
||||
interfaceVTable[methodIndex] = entry;
|
||||
};
|
||||
|
||||
bool itableEqualsSuper = true;
|
||||
auto addITable = [&interfaceVTables, &itableEqualsSuper](ClassId interfaceId, int itableSize) {
|
||||
RuntimeAssert(itableSize >= 0, "");
|
||||
auto interfaceVTablesIt = interfaceVTables.find(interfaceId);
|
||||
if (interfaceVTablesIt == interfaceVTables.end()) {
|
||||
itableEqualsSuper = false;
|
||||
interfaceVTables.emplace(interfaceId, KStdVector<VTableElement>(itableSize));
|
||||
} else {
|
||||
auto const& interfaceVTable = interfaceVTablesIt->second;
|
||||
RuntimeAssert(interfaceVTable.size() == static_cast<size_t>(itableSize), "");
|
||||
}
|
||||
};
|
||||
|
||||
for (const TypeInfo* t : supers) {
|
||||
const ObjCTypeAdapter* typeAdapter = getTypeAdapter(t);
|
||||
if (typeAdapter == nullptr) continue;
|
||||
@@ -924,17 +938,8 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
|
||||
if (typeAdapter == nullptr) continue;
|
||||
|
||||
if (superITable != nullptr) {
|
||||
auto interfaceId = typeInfo->classId_;
|
||||
int interfaceVTableSize = typeAdapter->kotlinItableSize;
|
||||
RuntimeAssert(interfaceVTableSize >= 0, "");
|
||||
auto interfaceVTablesIt = interfaceVTables.find(interfaceId);
|
||||
if (interfaceVTablesIt == interfaceVTables.end()) {
|
||||
itableEqualsSuper = false;
|
||||
interfaceVTables.emplace(interfaceId, KStdVector<VTableElement>(interfaceVTableSize));
|
||||
} else {
|
||||
auto const& interfaceVTable = interfaceVTablesIt->second;
|
||||
RuntimeAssert(interfaceVTable.size() == static_cast<size_t>(interfaceVTableSize), "");
|
||||
}
|
||||
// The interface vtable has to be created always in order for type checks to work.
|
||||
addITable(typeInfo->classId_, typeAdapter->kotlinItableSize);
|
||||
}
|
||||
|
||||
for (int i = 0; i < typeAdapter->reverseAdapterNum; ++i) {
|
||||
@@ -945,8 +950,12 @@ static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, co
|
||||
insertOrReplace(methodTable, adapter->nameSignature, const_cast<void*>(adapter->kotlinImpl));
|
||||
RuntimeAssert(adapter->vtableIndex == -1, "");
|
||||
|
||||
if (adapter->itableIndex != -1 && superITable != nullptr)
|
||||
addToITable(adapter->interfaceId, adapter->itableIndex, adapter->kotlinImpl);
|
||||
if (adapter->itableIndex != -1 && superITable != nullptr) {
|
||||
// In general, [adapter->interfaceId] might not be equal to [typeInfo->classId_].
|
||||
auto interfaceId = adapter->interfaceId;
|
||||
addITable(interfaceId, adapter->itableSize);
|
||||
addToITable(interfaceId, adapter->itableIndex, adapter->kotlinImpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user