mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Type metadata] @objc protocol conformance requirements don't have arguments.
@objc protocols don't have witness tables. However, both type metadata (in the nominal type descriptors) and the runtime code to demangle type names into metadata weren't acknowledging this. Fix type metadata emission to not count an "extra argument" for @objc protocol conformance requirements, and teach the runtime code to properly look for conformances to @objc protocols (through the Objective-C runtime) and not record witness tables for them.
This commit is contained in:
@@ -6237,11 +6237,13 @@ GenericRequirementsMetadata irgen::addGenericRequirements(
|
||||
case RequirementKind::Conformance: {
|
||||
// ABI TODO: We also need a *key* argument that uniquely identifies
|
||||
// the conformance for conformance requirements as well.
|
||||
auto flags = GenericRequirementFlags(GenericRequirementKind::Protocol,
|
||||
/*TODO key argument*/ false,
|
||||
/*extra argument*/ true);
|
||||
auto protocol = requirement.getSecondType()->castTo<ProtocolType>()
|
||||
->getDecl();
|
||||
bool needsWitnessTable =
|
||||
Lowering::TypeConverter::protocolRequiresWitnessTable(protocol);
|
||||
auto flags = GenericRequirementFlags(GenericRequirementKind::Protocol,
|
||||
/*TODO key argument*/ false,
|
||||
needsWitnessTable);
|
||||
auto descriptorRef =
|
||||
IGM.getConstantReferenceForProtocolDescriptor(protocol);
|
||||
addGenericRequirement(IGM, B, metadata, sig, flags,
|
||||
|
||||
@@ -305,14 +305,7 @@ static bool _unknownClassConformsToObjCProtocol(const OpaqueValue *value,
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Check whether a type conforms to a protocol.
|
||||
///
|
||||
/// \param value - can be null, in which case the question should
|
||||
/// be answered abstractly if possible
|
||||
/// \param conformance - if non-null, and the protocol requires a
|
||||
/// witness table, and the type implements the protocol, the witness
|
||||
/// table will be placed here
|
||||
static bool _conformsToProtocol(const OpaqueValue *value,
|
||||
bool swift::_conformsToProtocol(const OpaqueValue *value,
|
||||
const Metadata *type,
|
||||
const ProtocolDescriptor *protocol,
|
||||
const WitnessTable **conformance) {
|
||||
|
||||
@@ -313,6 +313,17 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Check whether a type conforms to a protocol.
|
||||
///
|
||||
/// \param value - can be null, in which case the question should
|
||||
/// be answered abstractly if possible
|
||||
/// \param conformance - if non-null, and the protocol requires a
|
||||
/// witness table, and the type implements the protocol, the witness
|
||||
/// table will be placed here
|
||||
bool _conformsToProtocol(const OpaqueValue *value,
|
||||
const Metadata *type,
|
||||
const ProtocolDescriptor *protocol,
|
||||
const WitnessTable **conformance);
|
||||
} // end namespace swift
|
||||
|
||||
#endif /* SWIFT_RUNTIME_PRIVATE_H */
|
||||
|
||||
@@ -747,15 +747,16 @@ bool swift::_checkGenericRequirements(
|
||||
// Check the requirement.
|
||||
switch (req.getKind()) {
|
||||
case GenericRequirementKind::Protocol: {
|
||||
// Look for a witness table to satisfy this conformance.
|
||||
auto witnessTable =
|
||||
swift_conformsToProtocol(subjectType, req.getProtocol());
|
||||
if (!witnessTable) return true;
|
||||
const WitnessTable *witnessTable = nullptr;
|
||||
if (!_conformsToProtocol(nullptr, subjectType, req.getProtocol(),
|
||||
&witnessTable))
|
||||
return true;
|
||||
|
||||
// If this requirement provides an extra argument, add the witness table
|
||||
// as that argument.
|
||||
if (req.getFlags().hasExtraArgument())
|
||||
// If we need a witness table, add it.
|
||||
if (req.getProtocol()->Flags.needsWitnessTable()) {
|
||||
assert(witnessTable);
|
||||
extraArguments.push_back(witnessTable);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -64,3 +64,11 @@ sil @$S20generic_classes_objc20GenericInheritsObjC2C7bellsOnACyxGSgSi_tcfcTo : $
|
||||
bb0(%0 : $Int, %1 : $GenericInheritsObjC<T>):
|
||||
unreachable
|
||||
}
|
||||
|
||||
@objc protocol P1 { }
|
||||
protocol P2 { }
|
||||
|
||||
// CHECK: @"$S20generic_classes_objc16Generic3WithReqsCMn" = hidden constant
|
||||
// CHECK-SAME: i32 3, i32 3, i32 3, i32 2
|
||||
class Generic3WithReqs<T: P1, U: P2, V: P2> { }
|
||||
sil_vtable Generic3WithReqs { }
|
||||
@@ -62,5 +62,17 @@ DemangleToMetadataTests.test("Imported enum types") {
|
||||
_typeByMangledName("So21NSURLSessionTaskStateV")!)
|
||||
}
|
||||
|
||||
class CG4<T: P1, U: P2> { }
|
||||
extension C : P1 { }
|
||||
extension C : P2 { }
|
||||
|
||||
class D: P2 { }
|
||||
|
||||
DemangleToMetadataTests.test("@objc protocol conformances") {
|
||||
expectEqual(CG4<C, C>.self,
|
||||
_typeByMangledName("4main3CG4CyAA1CCAA1CCG")!)
|
||||
expectNil(_typeByMangledName("4main3CG4CyAA1DCAA1DCG"))
|
||||
}
|
||||
|
||||
runAllTests()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user