Skip to content

Commit 0ca4d55

Browse files
committed
[Mangling] Split up protocol-conformance-ref further
New(er) grammar: // same module as conforming type, or non-unique protocol-conformance-ref ::= protocol 'HP' // same module as protocol protocol-conformance-ref ::= protocol 'Hp' // retroactive protocol-conformance-ref ::= protocol module We don't make use of this distinction anywhere yet, but we could in the future.
1 parent d5cbd3e commit 0ca4d55

File tree

10 files changed

+113
-47
lines changed

10 files changed

+113
-47
lines changed

docs/ABI/Mangling.rst

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,9 @@ Property behaviors are implemented using private protocol conformances.
633633
::
634634

635635
concrete-protocol-conformance ::= type protocol-conformance-ref any-protocol-conformance-list 'HC'
636-
protocol-conformance-ref ::= protocol
637-
protocol-conformance-ref ::= protocol module 'HP'
636+
protocol-conformance-ref ::= protocol 'HP' // same module as conforming type
637+
protocol-conformance-ref ::= protocol 'Hp' // same module as protocol
638+
protocol-conformance-ref ::= protocol module // "retroactive"
638639

639640
any-protocol-conformance ::= concrete-protocol-conformance
640641
any-protocol-conformance ::= dependent-protocol-conformance
@@ -652,10 +653,13 @@ Property behaviors are implemented using private protocol conformances.
652653
dependent-associated-conformance ::= type protocol
653654

654655
A compact representation used to represent mangled protocol conformance witness
655-
arguments at runtime. The ``module`` is only specified for conformances that are
656-
"retroactive", meaning that the context in which the conformance is defined is
657-
in neither the protocol or type module. The concrete protocol conformances that
658-
follow are for the conditional conformance requirements.
656+
arguments at runtime. The ``module`` is only specified for conformances that
657+
are "retroactive", meaning that the context in which the conformance is defined
658+
is in neither the protocol or type module. For a non-retroactive conformance
659+
where both the type *and* the protocol are in the same module, or for
660+
synthesized conformances that have no owning module, the "HP" operator is
661+
preferred. The concrete protocol conformances that follow are for the
662+
conditional conformance requirements.
659663

660664
Dependent protocol conformances mangle the access path required to extract a
661665
protocol conformance from some conformance passed into the environment. The

include/swift/Demangling/DemangleNodes.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,9 @@ NODE(PropertyDescriptor)
156156
CONTEXT_NODE(Protocol)
157157
CONTEXT_NODE(ProtocolSymbolicReference)
158158
NODE(ProtocolConformance)
159-
NODE(ProtocolConformanceRef)
159+
NODE(ProtocolConformanceRefInTypeModule)
160+
NODE(ProtocolConformanceRefInProtocolModule)
161+
NODE(ProtocolConformanceRefInOtherModule)
160162
NODE(ProtocolDescriptor)
161163
NODE(ProtocolConformanceDescriptor)
162164
NODE(ProtocolList)

include/swift/Demangling/Demangler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ class Demangler : public NodeFactory {
458458
NodePointer getDependentGenericParamType(int depth, int index);
459459
NodePointer demangleGenericParamIndex();
460460
NodePointer popProtocolConformance();
461-
NodePointer demangleProtocolConformanceRef();
461+
NodePointer demangleRetroactiveProtocolConformanceRef();
462462
NodePointer popAnyProtocolConformance();
463463
NodePointer demangleConcreteProtocolConformance();
464464
NodePointer popDependentProtocolConformance();

lib/AST/ASTMangler.cpp

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,32 +1105,37 @@ void ASTMangler::appendBoundGenericArgs(Type type, bool &isFirstArgList) {
11051105
}
11061106
}
11071107

1108-
/// Determine whether the given protocol conformance is itself retroactive,
1109-
/// meaning that there might be multiple conflicting conformances of the
1110-
/// same type to the same protocol.
1111-
static bool isRetroactiveConformance(const RootProtocolConformance *root) {
1108+
static bool conformanceHasIdentity(const RootProtocolConformance *root) {
11121109
auto conformance = dyn_cast<NormalProtocolConformance>(root);
11131110
if (!conformance) {
11141111
assert(isa<SelfProtocolConformance>(root));
1115-
return false; // self-conformances are never retroactive.
1112+
return true;
11161113
}
11171114

1118-
/// Non-retroactive conformances are... never retroactive.
1119-
if (!conformance->isRetroactive())
1120-
return false;
1121-
1122-
/// Synthesized non-unique conformances all get collapsed together at run
1123-
/// time.
1115+
// Synthesized non-unique conformances all get collapsed together at run time.
11241116
if (conformance->isSynthesizedNonUnique())
11251117
return false;
11261118

1127-
/// Objective-C protocol conformances don't have identity.
1119+
// Objective-C protocol conformances are checked by the ObjC runtime.
11281120
if (conformance->getProtocol()->isObjC())
11291121
return false;
11301122

11311123
return true;
11321124
}
11331125

1126+
/// Determine whether the given protocol conformance is itself retroactive,
1127+
/// meaning that there might be multiple conflicting conformances of the
1128+
/// same type to the same protocol.
1129+
static bool isRetroactiveConformance(const RootProtocolConformance *root) {
1130+
auto conformance = dyn_cast<NormalProtocolConformance>(root);
1131+
if (!conformance) {
1132+
assert(isa<SelfProtocolConformance>(root));
1133+
return false; // self-conformances are never retroactive.
1134+
}
1135+
1136+
return conformance->isRetroactive();
1137+
}
1138+
11341139
/// Determine whether the given protocol conformance contains a retroactive
11351140
/// protocol conformance anywhere in it.
11361141
static bool containsRetroactiveConformance(
@@ -1139,7 +1144,8 @@ static bool containsRetroactiveConformance(
11391144
// If the root conformance is retroactive, it's retroactive.
11401145
const RootProtocolConformance *rootConformance =
11411146
conformance->getRootConformance();
1142-
if (isRetroactiveConformance(rootConformance))
1147+
if (isRetroactiveConformance(rootConformance) &&
1148+
conformanceHasIdentity(rootConformance))
11431149
return true;
11441150

11451151
// If the conformance is conditional and any of the substitutions used to
@@ -2293,11 +2299,18 @@ void ASTMangler::appendProtocolConformanceRef(
22932299
appendProtocolName(conformance->getProtocol());
22942300

22952301
// For retroactive conformances, add a reference to the module in which the
2296-
// conformance resides. For @objc protocols, there is no point: conformances
2297-
// are global anyway.
2298-
if (isRetroactiveConformance(conformance)) {
2302+
// conformance resides. Otherwise, use an operator to indicate which known
2303+
// module it's associated with.
2304+
if (!conformanceHasIdentity(conformance)) {
2305+
// Same as "conformance module matches type", below.
2306+
appendOperator("HP");
2307+
} else if (isRetroactiveConformance(conformance)) {
22992308
appendModule(conformance->getDeclContext()->getParentModule());
2309+
} else if (conformance->getDeclContext()->getParentModule() ==
2310+
conformance->getType()->getAnyNominal()->getParentModule()) {
23002311
appendOperator("HP");
2312+
} else {
2313+
appendOperator("Hp");
23012314
}
23022315
}
23032316

lib/Demangling/Demangler.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,12 @@ NodePointer Demangler::demangleOperator() {
610610
case 'C': return demangleConcreteProtocolConformance();
611611
case 'D': return demangleDependentProtocolConformanceRoot();
612612
case 'I': return demangleDependentProtocolConformanceInherited();
613-
case 'P': return demangleProtocolConformanceRef();
613+
case 'P':
614+
return createWithChild(
615+
Node::Kind::ProtocolConformanceRefInTypeModule, popProtocol());
616+
case 'p':
617+
return createWithChild(
618+
Node::Kind::ProtocolConformanceRefInProtocolModule, popProtocol());
614619
default:
615620
pushBack();
616621
pushBack();
@@ -1295,21 +1300,27 @@ NodePointer Demangler::popAnyProtocolConformance() {
12951300
});
12961301
}
12971302

1298-
NodePointer Demangler::demangleProtocolConformanceRef() {
1303+
NodePointer Demangler::demangleRetroactiveProtocolConformanceRef() {
12991304
NodePointer module = popModule();
13001305
NodePointer proto = popProtocol();
13011306
auto protocolConformanceRef =
1302-
createWithChildren(Node::Kind::ProtocolConformanceRef, proto, module);
1307+
createWithChildren(Node::Kind::ProtocolConformanceRefInOtherModule,
1308+
proto, module);
13031309
return protocolConformanceRef;
13041310
}
13051311

13061312
NodePointer Demangler::demangleConcreteProtocolConformance() {
13071313
NodePointer conditionalConformanceList = popAnyProtocolConformanceList();
1308-
NodePointer conformanceRef = popNode(Node::Kind::ProtocolConformanceRef);
1314+
1315+
NodePointer conformanceRef =
1316+
popNode(Node::Kind::ProtocolConformanceRefInTypeModule);
13091317
if (!conformanceRef) {
1310-
NodePointer proto = popProtocol();
1311-
conformanceRef = createWithChild(Node::Kind::ProtocolConformanceRef, proto);
1318+
conformanceRef =
1319+
popNode(Node::Kind::ProtocolConformanceRefInProtocolModule);
13121320
}
1321+
if (!conformanceRef)
1322+
conformanceRef = demangleRetroactiveProtocolConformanceRef();
1323+
13131324
NodePointer type = popNode(Node::Kind::Type);
13141325
return createWithChildren(Node::Kind::ConcreteProtocolConformance,
13151326
type, conformanceRef, conditionalConformanceList);

lib/Demangling/NodePrinter.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,9 @@ class NodePrinter {
497497
case Node::Kind::DependentProtocolConformanceAssociated:
498498
case Node::Kind::DependentProtocolConformanceInherited:
499499
case Node::Kind::DependentProtocolConformanceRoot:
500-
case Node::Kind::ProtocolConformanceRef:
500+
case Node::Kind::ProtocolConformanceRefInTypeModule:
501+
case Node::Kind::ProtocolConformanceRefInProtocolModule:
502+
case Node::Kind::ProtocolConformanceRefInOtherModule:
501503
case Node::Kind::DynamicallyReplaceableFunctionKey:
502504
case Node::Kind::DynamicallyReplaceableFunctionImpl:
503505
case Node::Kind::DynamicallyReplaceableFunctionVar:
@@ -2172,7 +2174,16 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
21722174
<< " ";
21732175
printChildren(Node);
21742176
return nullptr;
2175-
case Node::Kind::ProtocolConformanceRef:
2177+
case Node::Kind::ProtocolConformanceRefInTypeModule:
2178+
Printer << "protocol conformance ref (type's module) ";
2179+
printChildren(Node);
2180+
return nullptr;
2181+
case Node::Kind::ProtocolConformanceRefInProtocolModule:
2182+
Printer << "protocol conformance ref (protocol's module) ";
2183+
printChildren(Node);
2184+
return nullptr;
2185+
case Node::Kind::ProtocolConformanceRefInOtherModule:
2186+
Printer << "protocol conformance ref (retroactive) ";
21762187
printChildren(Node);
21772188
return nullptr;
21782189
}

lib/Demangling/OldRemangler.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,15 @@ void Remangler::mangleRetroactiveConformance(Node *node) {
680680
unreachable("Retroactive conformances aren't in the old mangling");
681681
}
682682

683-
void Remangler::mangleProtocolConformanceRef(Node *node) {
683+
void Remangler::mangleProtocolConformanceRefInTypeModule(Node *node) {
684+
unreachable("Protocol conformance references aren't in the old mangling");
685+
}
686+
687+
void Remangler::mangleProtocolConformanceRefInProtocolModule(Node *node) {
688+
unreachable("Protocol conformance references aren't in the old mangling");
689+
}
690+
691+
void Remangler::mangleProtocolConformanceRefInOtherModule(Node *node) {
684692
unreachable("Protocol conformance references aren't in the old mangling");
685693
}
686694

lib/Demangling/Remangler.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,17 +1655,24 @@ void Remangler::mangleProtocolConformance(Node *node) {
16551655
mangle(GenSig);
16561656
}
16571657

1658-
void Remangler::mangleProtocolConformanceRef(Node *node) {
1658+
void Remangler::mangleProtocolConformanceRefInTypeModule(Node *node) {
16591659
manglePureProtocol(node->getChild(0));
1660-
if (node->getNumChildren() > 1) {
1661-
mangleChildNode(node, 1);
1662-
Buffer << "HP";
1663-
}
1660+
Buffer << "HP";
1661+
}
1662+
1663+
void Remangler::mangleProtocolConformanceRefInProtocolModule(Node *node) {
1664+
manglePureProtocol(node->getChild(0));
1665+
Buffer << "Hp";
1666+
}
1667+
1668+
void Remangler::mangleProtocolConformanceRefInOtherModule(Node *node) {
1669+
manglePureProtocol(node->getChild(0));
1670+
mangleChildNode(node, 1);
16641671
}
16651672

16661673
void Remangler::mangleConcreteProtocolConformance(Node *node) {
16671674
mangleType(node->getChild(0));
1668-
mangleProtocolConformanceRef(node->getChild(1));
1675+
mangle(node->getChild(1));
16691676
if (node->getNumChildren() > 2)
16701677
mangleAnyProtocolConformanceList(node->getChild(2));
16711678
else

test/Demangle/Inputs/manglings.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,9 @@ _T0So13GenericOptionas8HashableSCsACP9hashValueSivgTW ---> {T:} protocol witness
301301
_T0So11CrappyColorVs16RawRepresentableSCMA ---> reflection metadata associated type descriptor __C.CrappyColor : Swift.RawRepresentable in __C_Synthesized
302302
$S28protocol_conformance_records15NativeValueTypeVAA8RuncibleAAMc ---> protocol conformance descriptor for protocol_conformance_records.NativeValueType : protocol_conformance_records.Runcible in protocol_conformance_records
303303
$SSC9SomeErrorLeVD ---> __C_Synthesized.related decl 'e' for SomeError
304-
$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAHPyHCg_AiJ1QAAHPyHCg1_GF ---> mangling_retroactive.test0(mangling_retroactive.Z<RetroactiveB.X, Swift.Int, RetroactiveB.Y>) -> ()
304+
$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAyHCg_AiJ1QAAyHCg1_GF ---> mangling_retroactive.test0(mangling_retroactive.Z<RetroactiveB.X, Swift.Int, RetroactiveB.Y>) -> ()
305+
$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PHPyHCg_AiJ1QHPyHCg1_GF ---> mangling_retroactive.test0(mangling_retroactive.Z<RetroactiveB.X, Swift.Int, RetroactiveB.Y>) -> ()
306+
$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PHpyHCg_AiJ1QHpyHCg1_GF ---> mangling_retroactive.test0(mangling_retroactive.Z<RetroactiveB.X, Swift.Int, RetroactiveB.Y>) -> ()
305307
_T0LiteralAByxGxd_tcfC ---> _T0LiteralAByxGxd_tcfC
306308
_T0XZ ---> _T0XZ
307309
_TTSf0os___TFVs17_LegacyStringCore15_invariantCheckfT_T_ ---> function signature specialization <Arg[0] = Guaranteed To Owned and Exploded> of Swift._LegacyStringCore._invariantCheck() -> ()

test/SILGen/mangling_retroactive.swift

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ struct Z<T: P, U: Hashable, V: Q> { }
1212
extension X: P { } // retroactive
1313
extension Y: Q { } // retroactive
1414

15-
// CHECK: sil hidden [ossa] @$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAHPyHCg_AiJ1QAAHPyHCg1_GF
15+
// CHECK: sil hidden [ossa] @$s20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAyHCg_AiJ1QAAyHCg1_GF
1616
func test0(_: Z<X, Int, Y>) { }
1717

1818
struct Z2<T: P> {
1919
struct Inner<V: Q> { }
2020
}
2121

22-
// CHECK: sil hidden [ossa] @$s20mangling_retroactive5test1yyAA2Z2V5InnerVy12RetroactiveB1XV_AG1YVAI0F1A1PAAHPyHCg_AkL1QAAHPyHCg0_GF
22+
// CHECK: sil hidden [ossa] @$s20mangling_retroactive5test1yyAA2Z2V5InnerVy12RetroactiveB1XV_AG1YVAI0F1A1PAAyHCg_AkL1QAAyHCg0_GF
2323
func test1(_: Z2<X>.Inner<Y>) { }
2424

2525
extension X: Hashable {
@@ -38,7 +38,7 @@ extension Z: Equatable where T: Hashable, V: Equatable {
3838
struct RequiresEquatable<T: Equatable> { }
3939

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

4444
struct UnconditionallyP<T: Q>: P {}
@@ -48,7 +48,7 @@ struct RequiresP<T: P> {}
4848
// UnconditionallyP, even though UnconditionallyP's generic param uses a
4949
// retroactive conformance to conform to Q.
5050
func rdar46735592(_: RequiresP<UnconditionallyP<Y>>) { }
51-
// CHECK: sil hidden [ossa] @$s20mangling_retroactive12rdar46735592yyAA9RequiresPVyAA16UnconditionallyPVy12RetroactiveB1YVAI0F1A1QAAHPyHCg_GGF
51+
// CHECK: sil hidden [ossa] @$s20mangling_retroactive12rdar46735592yyAA9RequiresPVyAA16UnconditionallyPVy12RetroactiveB1YVAI0F1A1QAAyHCg_GGF
5252

5353
struct QImpl: Q {}
5454
struct ConditionallyP<T> {}
@@ -57,7 +57,7 @@ extension ConditionallyP: P where T: Q {}
5757
func useConditionallyP(_: RequiresP<ConditionallyP<QImpl>>) {}
5858
func useConditionallyP_retroactive(_: RequiresP<ConditionallyP<Y>>) {}
5959
// CHECK: sil hidden [ossa] @$s20mangling_retroactive17useConditionallyPyyAA9RequiresPVyAA0D1PVyAA5QImplVGGF
60-
// CHECK: sil hidden [ossa] @$s20mangling_retroactive018useConditionallyP_B0yyAA9RequiresPVyAA0D1PVy12RetroactiveB1YVGAJ0F1A1PAiK1QAAHPyHC_HCg_GF
60+
// CHECK: sil hidden [ossa] @$s20mangling_retroactive018useConditionallyP_B0yyAA9RequiresPVyAA0D1PVy12RetroactiveB1YVGAJ0F1A1PHPAiK1QAAyHC_HCg_GF
6161

6262
protocol Wrapper {
6363
associatedtype Wrapped
@@ -70,12 +70,20 @@ extension IndirectlyConditionallyP: P where T.Wrapped: Q {}
7070
func useIndirectlyConditionallyP(_: RequiresP<IndirectlyConditionallyP<WrapperImpl<QImpl>>>) {}
7171
func useIndirectlyConditionallyP_retroactive(_: RequiresP<IndirectlyConditionallyP<WrapperImpl<Y>>>) {}
7272
// CHECK: sil hidden [ossa] @$s20mangling_retroactive27useIndirectlyConditionallyPyyAA9RequiresPVyAA0dE1PVyAA11WrapperImplVyAA5QImplVGGGF
73-
// CHECK: sil hidden [ossa] @$s20mangling_retroactive028useIndirectlyConditionallyP_B0yyAA9RequiresPVyAA0dE1PVyAA11WrapperImplVy12RetroactiveB1YVGGAM0I1A1PAkN1QAAHPyHC_HCg_GF
73+
// CHECK: sil hidden [ossa] @$s20mangling_retroactive028useIndirectlyConditionallyP_B0yyAA9RequiresPVyAA0dE1PVyAA11WrapperImplVy12RetroactiveB1YVGGAM0I1A1PHPAkN1QAAyHC_HCg_GF
7474

7575
struct IndirectlyConditionallyP2<T> {}
7676
extension IndirectlyConditionallyP2: P where T: Wrapper, T.Wrapped: Q {}
7777

7878
func useIndirectlyConditionallyP2(_: RequiresP<IndirectlyConditionallyP<WrapperImpl<QImpl>>>) {}
7979
func useIndirectlyConditionallyP2_retroactive(_: RequiresP<IndirectlyConditionallyP<WrapperImpl<Y>>>) {}
8080
// CHECK: sil hidden [ossa] @$s20mangling_retroactive28useIndirectlyConditionallyP2yyAA9RequiresPVyAA0dE1PVyAA11WrapperImplVyAA5QImplVGGGF
81-
// CHECK: sil hidden [ossa] @$s20mangling_retroactive029useIndirectlyConditionallyP2_B0yyAA9RequiresPVyAA0dE1PVyAA11WrapperImplVy12RetroactiveB1YVGGAM0J1A1PAkN1QAAHPyHC_HCg_GF
81+
// CHECK: sil hidden [ossa] @$s20mangling_retroactive029useIndirectlyConditionallyP2_B0yyAA9RequiresPVyAA0dE1PVyAA11WrapperImplVy12RetroactiveB1YVGGAM0J1A1PHPAkN1QAAyHC_HCg_GF
82+
83+
protocol NonRetroactive {}
84+
extension Y: NonRetroactive {}
85+
struct ConditionallyP2<T> {}
86+
extension ConditionallyP2: P where T: Q, T: NonRetroactive {}
87+
88+
func useConditionallyP2(_: RequiresP<ConditionallyP2<Y>>) {}
89+
// CHECK: sil hidden [ossa] @$s20mangling_retroactive18useConditionallyP2yyAA9RequiresPVyAA0dE0Vy12RetroactiveB1YVGAJ0G1A1PHPAiK1QAAyHC_AiA03NonG0HpyHCHCg_GF

0 commit comments

Comments
 (0)