mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Fix a bug with inlining self-conformances.
This commit is contained in:
@@ -570,6 +570,57 @@ void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results) const {
|
||||
FORWARD(getDisplayDecls, (Results));
|
||||
}
|
||||
|
||||
Optional<ProtocolConformanceRef>
|
||||
ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
|
||||
assert(type->isExistentialType());
|
||||
|
||||
// If the existential type cannot be represented or the protocol does not
|
||||
// conform to itself, there's no point in looking further.
|
||||
if (!protocol->existentialConformsToSelf())
|
||||
return None;
|
||||
|
||||
auto layout = type->getExistentialLayout();
|
||||
|
||||
// Due to an IRGen limitation, witness tables cannot be passed from an
|
||||
// existential to an archetype parameter, so for now we restrict this to
|
||||
// @objc protocols.
|
||||
if (!layout.isObjC()) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// If the existential is class-constrained, the class might conform
|
||||
// concretely.
|
||||
if (auto superclass = layout.explicitSuperclass) {
|
||||
if (auto result = lookupConformance(superclass, protocol))
|
||||
return result;
|
||||
}
|
||||
|
||||
// Otherwise, the existential might conform abstractly.
|
||||
for (auto proto : layout.getProtocols()) {
|
||||
auto *protoDecl = proto->getDecl();
|
||||
|
||||
// If we found the protocol we're looking for, return an abstract
|
||||
// conformance to it.
|
||||
if (protoDecl == protocol)
|
||||
return ProtocolConformanceRef(protocol);
|
||||
|
||||
// If the protocol has a superclass constraint, we might conform
|
||||
// concretely.
|
||||
if (auto superclass = protoDecl->getSuperclass()) {
|
||||
if (auto result = lookupConformance(superclass, protocol))
|
||||
return result;
|
||||
}
|
||||
|
||||
// Now check refined protocols.
|
||||
if (protoDecl->inheritsFrom(protocol))
|
||||
return ProtocolConformanceRef(protocol);
|
||||
}
|
||||
|
||||
// We didn't find our protocol in the existential's list; it doesn't
|
||||
// conform.
|
||||
return None;
|
||||
}
|
||||
|
||||
Optional<ProtocolConformanceRef>
|
||||
ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol) {
|
||||
ASTContext &ctx = getASTContext();
|
||||
@@ -609,52 +660,8 @@ ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol) {
|
||||
// An existential conforms to a protocol if the protocol is listed in the
|
||||
// existential's list of conformances and the existential conforms to
|
||||
// itself.
|
||||
if (type->isExistentialType()) {
|
||||
// If the existential type cannot be represented or the protocol does not
|
||||
// conform to itself, there's no point in looking further.
|
||||
if (!protocol->existentialConformsToSelf())
|
||||
return None;
|
||||
|
||||
auto layout = type->getExistentialLayout();
|
||||
|
||||
// Due to an IRGen limitation, witness tables cannot be passed from an
|
||||
// existential to an archetype parameter, so for now we restrict this to
|
||||
// @objc protocols.
|
||||
if (!layout.isObjC())
|
||||
return None;
|
||||
|
||||
// If the existential is class-constrained, the class might conform
|
||||
// concretely.
|
||||
if (auto superclass = layout.explicitSuperclass) {
|
||||
if (auto result = lookupConformance(superclass, protocol))
|
||||
return result;
|
||||
}
|
||||
|
||||
// Otherwise, the existential might conform abstractly.
|
||||
for (auto proto : layout.getProtocols()) {
|
||||
auto *protoDecl = proto->getDecl();
|
||||
|
||||
// If we found the protocol we're looking for, return an abstract
|
||||
// conformance to it.
|
||||
if (protoDecl == protocol)
|
||||
return ProtocolConformanceRef(protocol);
|
||||
|
||||
// If the protocol has a superclass constraint, we might conform
|
||||
// concretely.
|
||||
if (auto superclass = protoDecl->getSuperclass()) {
|
||||
if (auto result = lookupConformance(superclass, protocol))
|
||||
return result;
|
||||
}
|
||||
|
||||
// Now check refined protocols.
|
||||
if (protoDecl->inheritsFrom(protocol))
|
||||
return ProtocolConformanceRef(protocol);
|
||||
}
|
||||
|
||||
// We didn't find our protocol in the existential's list; it doesn't
|
||||
// conform.
|
||||
return None;
|
||||
}
|
||||
if (type->isExistentialType())
|
||||
return lookupExistentialConformance(type, protocol);
|
||||
|
||||
// Type variables have trivial conformances.
|
||||
if (type->isTypeVariableOrMember())
|
||||
|
||||
Reference in New Issue
Block a user