Skip to content

Commit fedbd53

Browse files
authored
Merge pull request #14296 from DougGregor/mangle-retroactive-conformances
2 parents d2a1361 + 28c489c commit fedbd53

File tree

18 files changed

+157
-11
lines changed

18 files changed

+157
-11
lines changed

docs/ABI/Mangling.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ Types
369369
type ::= type 'Xm' METATYPE-REPR // existential metatype with representation
370370
type ::= 'Xe' // error or unresolved type
371371
372-
bound-generic-type ::= type 'y' (type* '_')* type* 'G' // one type-list per nesting level of type
372+
bound-generic-type ::= type 'y' (type* '_')* type* retroactive-conformance* 'G' // one type-list per nesting level of type
373373
bound-generic-type ::= substitution
374374

375375
FUNCTION-KIND ::= 'f' // @thin function type
@@ -559,6 +559,17 @@ values indicates a single generic parameter at the outermost depth::
559559
A generic signature must only precede an operator character which is different
560560
from any character in a ``<GENERIC-PARAM-COUNT>``.
561561

562+
::
563+
564+
retroactive-conformance ::= protocol-conformance 'g' INDEX
565+
566+
When a protocol conformance used to satisfy one of a bound generic type's
567+
generic requirements is retroactive (i.e., it is specified in a module other
568+
than the module of the conforming type or the conformed-to protocol), it is
569+
mangled with its offset into the set of conformance requirements, the
570+
root protocol conformance, and the suffix 'g'.
571+
572+
562573
Identifiers
563574
~~~~~~~~~~~
564575

include/swift/AST/ASTMangler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ class ASTMangler : public Mangler {
190190

191191
void appendBoundGenericArgs(Type type, bool &isFirstArgList);
192192

193+
/// Append any retroactive conformances.
194+
void appendRetroactiveConformances(Type type);
195+
193196
void appendImplFunctionType(SILFunctionType *fn);
194197

195198
void appendContextOf(const ValueDecl *decl);

include/swift/AST/ProtocolConformance.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,10 @@ class NormalProtocolConformance : public ProtocolConformance,
468468
/// defines the conforming type.
469469
bool isRetroactive() const;
470470

471+
/// Whether this conformance was synthesized automatically in multiple
472+
/// modules, but in a manner that ensures that all copies are equivalent.
473+
bool isSynthesizedNonUnique() const;
474+
471475
/// Retrieve the type witness and type decl (if one exists)
472476
/// for the given associated type.
473477
std::pair<Type, TypeDecl *>

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ NODE(QualifiedArchetype)
144144
NODE(ReabstractionThunk)
145145
NODE(ReabstractionThunkHelper)
146146
NODE(RelatedEntityDeclName)
147+
NODE(RetroactiveConformance)
147148
NODE(ReturnType)
148149
NODE(Shared)
149150
NODE(SILBoxType)

include/swift/Demangling/Demangler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ class Demangler : public NodeFactory {
429429
NodePointer demangleBoundGenericArgs(NodePointer nominalType,
430430
const Vector<NodePointer> &TypeLists,
431431
size_t TypeListIdx);
432+
NodePointer demangleRetroactiveConformance();
432433
NodePointer demangleInitializer();
433434
NodePointer demangleImplParamConvention();
434435
NodePointer demangleImplResultConvention(Node::Kind ConvKind);

lib/AST/ASTMangler.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "swift/AST/Module.h"
2424
#include "swift/AST/ParameterList.h"
2525
#include "swift/AST/ProtocolConformance.h"
26+
#include "swift/AST/ProtocolConformanceRef.h"
27+
#include "swift/Basic/Defer.h"
2628
#include "swift/Demangling/ManglingUtils.h"
2729
#include "swift/Demangling/Demangler.h"
2830
#include "swift/Strings.h"
@@ -856,6 +858,7 @@ void ASTMangler::appendType(Type type) {
856858
appendAnyGenericType(NDecl);
857859
bool isFirstArgList = true;
858860
appendBoundGenericArgs(type, isFirstArgList);
861+
appendRetroactiveConformances(type);
859862
appendOperator("G");
860863
}
861864
addSubstitution(type.getPointer());
@@ -1088,6 +1091,44 @@ void ASTMangler::appendBoundGenericArgs(Type type, bool &isFirstArgList) {
10881091
}
10891092
}
10901093

1094+
void ASTMangler::appendRetroactiveConformances(Type type) {
1095+
auto nominal = type->getAnyNominal();
1096+
if (!nominal) return;
1097+
1098+
auto genericSig = nominal->getGenericSignatureOfContext();
1099+
if (!genericSig) return;
1100+
1101+
auto module = Mod ? Mod : nominal->getModuleContext();
1102+
auto subMap = type->getContextSubstitutionMap(module, nominal);
1103+
if (subMap.empty()) return;
1104+
1105+
unsigned numProtocolRequirements = 0;
1106+
for (const auto &req: genericSig->getRequirements()) {
1107+
if (req.getKind() != RequirementKind::Conformance)
1108+
continue;
1109+
1110+
SWIFT_DEFER {
1111+
++numProtocolRequirements;
1112+
};
1113+
1114+
// Fast path: we're in the module of the protocol.
1115+
auto proto = req.getSecondType()->castTo<ProtocolType>()->getDecl();
1116+
if (proto->getModuleContext() == module)
1117+
continue;
1118+
1119+
auto conformance =
1120+
subMap.lookupConformance(req.getFirstType()->getCanonicalType(), proto);
1121+
if (!conformance || !conformance->isConcrete()) continue;
1122+
1123+
auto normal = conformance->getConcrete()->getRootNormalConformance();
1124+
if (!normal->isRetroactive() || normal->isSynthesizedNonUnique())
1125+
continue;
1126+
1127+
appendProtocolConformance(normal);
1128+
appendOperator("g", Index(numProtocolRequirements));
1129+
}
1130+
}
1131+
10911132
static char getParamConvention(ParameterConvention conv) {
10921133
// @in and @out are mangled the same because they're put in
10931134
// different places.

lib/AST/ProtocolConformance.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/Substitution.h"
2525
#include "swift/AST/Types.h"
2626
#include "swift/AST/TypeWalker.h"
27+
#include "swift/ClangImporter/ClangModule.h"
2728
#include "llvm/ADT/MapVector.h"
2829
#include "llvm/ADT/Statistic.h"
2930
#include "llvm/ADT/TinyPtrVector.h"
@@ -353,6 +354,10 @@ bool NormalProtocolConformance::isRetroactive() const {
353354
return true;
354355
}
355356

357+
bool NormalProtocolConformance::isSynthesizedNonUnique() const {
358+
return isa<ClangModuleUnit>(getDeclContext()->getModuleScopeContext());
359+
}
360+
356361
ArrayRef<Requirement> ProtocolConformance::getConditionalRequirements() const {
357362
CONFORMANCE_SUBCLASS_DISPATCH(getConditionalRequirements, ());
358363
}

lib/Demangling/Demangler.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ NodePointer Demangler::demangleOperator() {
458458
case 'c': return popFunctionType(Node::Kind::FunctionType);
459459
case 'd': return createNode(Node::Kind::VariadicMarker);
460460
case 'f': return demangleFunctionEntity();
461+
case 'g': return demangleRetroactiveConformance();
461462
case 'h': return createType(createWithChild(Node::Kind::Shared,
462463
popTypeAndGetChild()));
463464
case 'i': return demangleSubscript();
@@ -1060,7 +1061,27 @@ NodePointer Demangler::popProtocol() {
10601061
return createType(Proto);
10611062
}
10621063

1064+
NodePointer Demangler::demangleRetroactiveConformance() {
1065+
NodePointer Index = demangleIndexAsNode();
1066+
NodePointer Conformance = popProtocolConformance();
1067+
if (!Index || !Conformance)
1068+
return nullptr;
1069+
1070+
return createWithChildren(Node::Kind::RetroactiveConformance,
1071+
Index, Conformance);
1072+
}
1073+
10631074
NodePointer Demangler::demangleBoundGenericType() {
1075+
NodePointer RetroactiveConformances = nullptr;
1076+
while (auto RetroactiveConformance =
1077+
popNode(Node::Kind::RetroactiveConformance)) {
1078+
if (!RetroactiveConformances)
1079+
RetroactiveConformances = createNode(Node::Kind::TypeList);
1080+
RetroactiveConformances->addChild(RetroactiveConformance, *this);
1081+
}
1082+
if (RetroactiveConformances)
1083+
RetroactiveConformances->reverseChildren();
1084+
10641085
Vector<NodePointer> TypeListList(*this, 4);
10651086
for (;;) {
10661087
NodePointer TList = createNode(Node::Kind::TypeList);
@@ -1076,7 +1097,10 @@ NodePointer Demangler::demangleBoundGenericType() {
10761097
return nullptr;
10771098
}
10781099
NodePointer Nominal = popTypeAndGetAnyGeneric();
1079-
NodePointer NTy = createType(demangleBoundGenericArgs(Nominal, TypeListList, 0));
1100+
NodePointer BoundNode = demangleBoundGenericArgs(Nominal, TypeListList, 0);
1101+
if (RetroactiveConformances)
1102+
BoundNode->addChild(RetroactiveConformances, *this);
1103+
NodePointer NTy = createType(BoundNode);
10801104
addSubstitution(NTy);
10811105
return NTy;
10821106
}

lib/Demangling/NodePrinter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ class NodePrinter {
398398
case Node::Kind::ReabstractionThunk:
399399
case Node::Kind::ReabstractionThunkHelper:
400400
case Node::Kind::RelatedEntityDeclName:
401+
case Node::Kind::RetroactiveConformance:
401402
case Node::Kind::Setter:
402403
case Node::Kind::Shared:
403404
case Node::Kind::SILBoxLayout:
@@ -1083,6 +1084,14 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
10831084
printChildren(Node);
10841085
}
10851086
return nullptr;
1087+
case Node::Kind::RetroactiveConformance:
1088+
if (Node->getNumChildren() != 2)
1089+
return nullptr;
1090+
1091+
Printer << "retroactive @ ";
1092+
print(Node->getChild(0));
1093+
print(Node->getChild(1));
1094+
return nullptr;
10861095
case Node::Kind::Weak:
10871096
Printer << "weak ";
10881097
print(Node->getChild(0));

lib/Demangling/OldRemangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,10 @@ void Remangler::mangleFunctionSignatureSpecializationParamKind(Node *node) {
659659
unreachable("This should never be called");
660660
}
661661

662+
void Remangler::mangleRetroactiveConformance(Node *node) {
663+
unreachable("Retroactive conformances aren't in the old mangling");
664+
}
665+
662666
void Remangler::mangleProtocolConformance(Node *node) {
663667
// type, protocol name, context
664668
assert(node->getNumChildren() == 3);

0 commit comments

Comments
 (0)