Skip to content

Commit fedbd53

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

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);

lib/Demangling/Remangler.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,15 @@ void Remangler::mangleAnyNominalType(Node *node) {
437437
mangleAnyNominalType(unboundType);
438438
char Separator = 'y';
439439
mangleGenericArgs(node, Separator);
440+
441+
if (node->getNumChildren() == 3) {
442+
// Retroactive conformances.
443+
auto listNode = node->getChild(2);
444+
for (size_t Idx = 0, Num = listNode->getNumChildren(); Idx < Num; ++Idx) {
445+
mangle(listNode->getChild(Idx));
446+
}
447+
}
448+
440449
Buffer << 'G';
441450
addSubstitution(entry);
442451
return;
@@ -1446,6 +1455,12 @@ void Remangler::mangleProtocol(Node *node) {
14461455
mangleAnyGenericType(node, "P");
14471456
}
14481457

1458+
void Remangler::mangleRetroactiveConformance(Node *node) {
1459+
mangleProtocolConformance(node->getChild(1));
1460+
Buffer << 'g';
1461+
mangleIndex(node->getChild(0)->getIndex());
1462+
}
1463+
14491464
void Remangler::mangleProtocolConformance(Node *node) {
14501465
Node *Ty = getChildOfType(node->getChild(0));
14511466
Node *GenSig = nullptr;

lib/IRGen/GenDecl.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,9 +2644,8 @@ namespace {
26442644
void addFlags() {
26452645
// Miscellaneous flags.
26462646
Flags = Flags.withIsRetroactive(Conformance->isRetroactive());
2647-
Flags = Flags.withIsSynthesizedNonUnique(
2648-
isa<ClangModuleUnit>(
2649-
Conformance->getDeclContext()->getModuleScopeContext()));
2647+
Flags =
2648+
Flags.withIsSynthesizedNonUnique(Conformance->isSynthesizedNonUnique());
26502649

26512650
// Add the flags.
26522651
B.addInt32(Flags.getIntValue());

test/Demangle/Inputs/manglings.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,4 @@ _T0So13GenericOptionas8HashableSCsACP9hashValueSivgTW ---> {T:} protocol witness
307307
_T0So11CrappyColorVs16RawRepresentableSCMA --> reflection metadata associated type descriptor __C.CrappyColor : Swift.RawRepresentable in __C_Synthesized
308308
$S28protocol_conformance_records15NativeValueTypeVAA8RuncibleAAMc --> protocol conformance descriptor for protocol_conformance_records.NativeValueType : protocol_conformance_records.Runcible in protocol_conformance_records
309309
$SSC9SomeErrorLeVD ---> __C_Synthesized.related decl 'e' for SomeError
310+
$S20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAg_AiJ1QAAg1_GF -> mangling_retroactive.test0(mangling_retroactive.Z<RetroactiveB.X, Swift.Int, RetroactiveB.Y>) -> ()

test/IRGen/objc_bridge.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ import Foundation
8888
// CHECK: { i8*, i8*, i8* } {
8989
// CHECK: i8* getelementptr inbounds ([11 x i8], [11 x i8]* @"\01L_selector_data(acceptSet:)", i64 0, i64 0),
9090
// CHECK: i8* getelementptr inbounds ([11 x i8], [11 x i8]* @{{[0-9]+}}, i64 0, i64 0),
91-
// CHECK: i8* bitcast (void (%3*, i8*, %4*)* @"$S11objc_bridge3BasC9acceptSetyys0E0VyACGFTo" to i8*)
91+
// CHECK: i8* bitcast (void (%3*, i8*, %4*)* @"$S11objc_bridge3BasC9acceptSetyys0E0VyACSo8NSObjectCs8Hashable10ObjectiveCg_GFTo" to i8*)
9292
// CHECK: }
9393
// CHECK: { i8*, i8*, i8* } {
9494
// CHECK: i8* getelementptr inbounds ([14 x i8], [14 x i8]* @"\01L_selector_data(.cxx_destruct)", i64 0, i64 0),

test/SILGen/Inputs/RetroactiveA.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
public protocol P { }
2+
public protocol Q { }

test/SILGen/Inputs/RetroactiveB.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
public struct X { }
2+
public struct Y { }
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -enable-sil-ownership -o %t %S/Inputs/RetroactiveA.swift
3+
// RUN: %target-swift-frontend -emit-module -enable-sil-ownership -o %t %S/Inputs/RetroactiveB.swift
4+
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -I %t %s | %FileCheck %s
5+
6+
7+
import RetroactiveA
8+
import RetroactiveB
9+
10+
struct Z<T: P, U: Hashable, V: Q> { }
11+
12+
extension X: P { } // retroactive
13+
extension Y: Q { } // retroactive
14+
15+
// CHECK: sil hidden @$S20mangling_retroactive5test0yyAA1ZVy12RetroactiveB1XVSiAE1YVAG0D1A1PAAg_AiJ1QAAg1_GF
16+
func test0(_: Z<X, Int, Y>) { }
17+
18+
struct Z2<T: P> {
19+
struct Inner<V: Q> { }
20+
}
21+
22+
// CHECK: sil hidden @$S20mangling_retroactive5test1yyAA2Z2V5InnerVy12RetroactiveB1XV_AG1YVAI0F1A1PAAg_AkL1QAAg0_GF
23+
func test1(_: Z2<X>.Inner<Y>) { }

test/SILGen/objc_dictionary_bridging.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,12 @@ import gizmo
5151
var property: Dictionary<Foo, Foo> = [:]
5252

5353
// Property getter
54-
// CHECK-LABEL: sil hidden [thunk] @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CGvgTo : $@convention(objc_method) (Foo) -> @autoreleased NSDictionary
54+
// CHECK-LABEL: sil hidden [thunk] @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CSo8NSObjectCs8Hashable10Foundationg_GvgTo : $@convention(objc_method) (Foo) -> @autoreleased NSDictionary
55+
// @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CSo8NSObjectCs8Hashable10Foundationg_Gvpfi
5556
// CHECK: bb0([[SELF:%[0-9]+]] : @unowned $Foo):
5657
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
5758
// CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
58-
// CHECK: [[GETTER:%[0-9]+]] = function_ref @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CGvg : $@convention(method) (@guaranteed Foo) -> @owned Dictionary<Foo, Foo>
59+
// CHECK: [[GETTER:%[0-9]+]] = function_ref @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CSo8NSObjectCs8Hashable10Foundationg_Gvg : $@convention(method) (@guaranteed Foo) -> @owned Dictionary<Foo, Foo>
5960
// CHECK: [[DICT:%[0-9]+]] = apply [[GETTER]]([[BORROWED_SELF_COPY]]) : $@convention(method) (@guaranteed Foo) -> @owned Dictionary<Foo, Foo>
6061
// CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
6162
// CHECK: destroy_value [[SELF_COPY]]
@@ -65,10 +66,10 @@ import gizmo
6566
// CHECK: end_borrow [[BORROWED_DICT]] from [[DICT]]
6667
// CHECK: destroy_value [[DICT]]
6768
// CHECK: return [[NSDICT]] : $NSDictionary
68-
// CHECK: } // end sil function '$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CGvgTo'
69+
// CHECK: } // end sil function
6970

7071
// Property setter
71-
// CHECK-LABEL: sil hidden [thunk] @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CGvsTo : $@convention(objc_method) (NSDictionary, Foo) -> ()
72+
// CHECK-LABEL: sil hidden [thunk] @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CSo8NSObjectCs8Hashable10Foundationg_GvsTo : $@convention(objc_method) (NSDictionary, Foo) -> ()
7273
// CHECK: bb0([[NSDICT:%[0-9]+]] : @unowned $NSDictionary, [[SELF:%[0-9]+]] : @unowned $Foo):
7374
// CHECK: [[NSDICT_COPY:%.*]] = copy_value [[NSDICT]]
7475
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
@@ -78,7 +79,7 @@ import gizmo
7879
// CHECK: [[DICT:%[0-9]+]] = apply [[CONVERTER]]<Foo, Foo>([[OPT_NSDICT]], [[DICT_META]])
7980

8081
// CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
81-
// CHECK: [[SETTER:%[0-9]+]] = function_ref @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CGvs : $@convention(method) (@owned Dictionary<Foo, Foo>, @guaranteed Foo) -> ()
82+
// CHECK: [[SETTER:%[0-9]+]] = function_ref @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CSo8NSObjectCs8Hashable10Foundationg_Gvs : $@convention(method) (@owned Dictionary<Foo, Foo>, @guaranteed Foo) -> ()
8283
// CHECK: [[RESULT:%[0-9]+]] = apply [[SETTER]]([[DICT]], [[BORROWED_SELF_COPY]]) : $@convention(method) (@owned Dictionary<Foo, Foo>, @guaranteed Foo) -> ()
8384
// CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
8485
// CHECK: destroy_value [[SELF_COPY]]

0 commit comments

Comments
 (0)