Skip to content

[ABI] [Mangling] Disambiguate protocol-conformance-ref better #21448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,8 @@ Property behaviors are implemented using private protocol conformances.
::

concrete-protocol-conformance ::= type protocol-conformance-ref any-protocol-conformance-list 'HC'
protocol-conformance-ref ::= protocol module? 'HP'
protocol-conformance-ref ::= protocol
protocol-conformance-ref ::= protocol module 'HP'

any-protocol-conformance ::= concrete-protocol-conformance
any-protocol-conformance ::= dependent-protocol-conformance
Expand Down
6 changes: 3 additions & 3 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2280,10 +2280,10 @@ void ASTMangler::appendProtocolConformanceRef(
// For retroactive conformances, add a reference to the module in which the
// conformance resides. For @objc protocols, there is no point: conformances
// are global anyway.
if (isRetroactiveConformance(conformance))
if (isRetroactiveConformance(conformance)) {
appendModule(conformance->getDeclContext()->getParentModule());

appendOperator("HP");
appendOperator("HP");
}
}

/// Retrieve the index of the conformance requirement indicated by the
Expand Down
11 changes: 5 additions & 6 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1299,18 +1299,17 @@ NodePointer Demangler::demangleProtocolConformanceRef() {
NodePointer module = popModule();
NodePointer proto = popProtocol();
auto protocolConformanceRef =
createWithChild(Node::Kind::ProtocolConformanceRef, proto);

// The module is optional, present only for retroactive conformances. Add it
// as the second child.
if (protocolConformanceRef && module)
protocolConformanceRef->addChild(module, *this);
createWithChildren(Node::Kind::ProtocolConformanceRef, proto, module);
return protocolConformanceRef;
}

NodePointer Demangler::demangleConcreteProtocolConformance() {
NodePointer conditionalConformanceList = popAnyProtocolConformanceList();
NodePointer conformanceRef = popNode(Node::Kind::ProtocolConformanceRef);
if (!conformanceRef) {
NodePointer proto = popProtocol();
conformanceRef = createWithChild(Node::Kind::ProtocolConformanceRef, proto);
}
NodePointer type = popNode(Node::Kind::Type);
return createWithChildren(Node::Kind::ConcreteProtocolConformance,
type, conformanceRef, conditionalConformanceList);
Expand Down
5 changes: 3 additions & 2 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1657,9 +1657,10 @@ void Remangler::mangleProtocolConformance(Node *node) {

void Remangler::mangleProtocolConformanceRef(Node *node) {
manglePureProtocol(node->getChild(0));
if (node->getNumChildren() > 1)
if (node->getNumChildren() > 1) {
mangleChildNode(node, 1);
Buffer << "HP";
Buffer << "HP";
}
}

void Remangler::mangleConcreteProtocolConformance(Node *node) {
Expand Down
11 changes: 10 additions & 1 deletion test/SILGen/mangling_retroactive.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,14 @@ extension Z: Equatable where T: Hashable, V: Equatable {
struct RequiresEquatable<T: Equatable> { }

// Conditional requirement involves retroactive conformances.
// CHECK: sil hidden [ossa] @$s20mangling_retroactive5test2yyAA17RequiresEquatableVyAA1ZVy12RetroactiveB1XVSiAG1YVAI0F1A1PAAHPyHCg_AkL1QAAHPyHCg1_GAOSQHPAISHAAHPyHC_AKSQAAHPyHCHCg_GF
// CHECK: sil hidden [ossa] @$s20mangling_retroactive5test2yyAA17RequiresEquatableVyAA1ZVy12RetroactiveB1XVSiAG1YVAI0F1A1PAAHPyHCg_AkL1QAAHPyHCg1_GAOSQAISHAAHPyHC_AKSQAAHPyHCHCg_GF
func test2(_: RequiresEquatable<Z<X, Int, Y>>) { }

struct UnconditionallyP<T: Q>: P {}
struct RequiresP<T: P> {}

// RequiresP uses a non-retroactive conformance for its generic param
// UnconditionallyP, even though UnconditionallyP's generic param uses a
// retroactive conformance to conform to Q.
func rdar46735592(_: RequiresP<UnconditionallyP<Y>>) { }
// CHECK: sil hidden [ossa] @$s20mangling_retroactive12rdar46735592yyAA9RequiresPVyAA16UnconditionallyPVy12RetroactiveB1YVAI0F1A1QAAHPyHCg_GAlJ1PyHCg_GF