@@ -1112,6 +1112,48 @@ void ASTMangler::appendBoundGenericArgs(Type type, bool &isFirstArgList) {
1112
1112
}
1113
1113
}
1114
1114
1115
+ // / Determine whether the given protocol conformance is itself retroactive,
1116
+ // / meaning that there might be multiple conflicting conformances of the
1117
+ // / same type to the same protocol.
1118
+ static bool isRetroactiveConformance (
1119
+ const NormalProtocolConformance *conformance) {
1120
+ // / Non-retroactive conformances are... never retroactive.
1121
+ if (!conformance->isRetroactive ())
1122
+ return false ;
1123
+
1124
+ // / Synthesized non-unique conformances all get collapsed together at run
1125
+ // / time.
1126
+ if (conformance->isSynthesizedNonUnique ())
1127
+ return false ;
1128
+
1129
+ // / Objective-C protocol conformances don't have identity.
1130
+ if (conformance->getProtocol ()->isObjC ())
1131
+ return false ;
1132
+
1133
+ return true ;
1134
+ }
1135
+
1136
+ // / Determine whether the given protocol conformance contains a retroactive
1137
+ // / protocol conformance anywhere in it.
1138
+ static bool containsRetroactiveConformance (
1139
+ const ProtocolConformance *conformance,
1140
+ ModuleDecl *module ) {
1141
+ // If the root conformance is retroactive, it's retroactive.
1142
+ if (isRetroactiveConformance (conformance->getRootNormalConformance ()))
1143
+ return true ;
1144
+
1145
+ // If any of the substitutions used to form this conformance are retroactive,
1146
+ // it's retroactive.
1147
+ auto subMap = conformance->getSubstitutions (module );
1148
+ for (auto conformance : subMap.getConformances ()) {
1149
+ if (conformance.isConcrete () &&
1150
+ containsRetroactiveConformance (conformance.getConcrete (), module ))
1151
+ return true ;
1152
+ }
1153
+
1154
+ return false ;
1155
+ }
1156
+
1115
1157
void ASTMangler::appendRetroactiveConformances (Type type) {
1116
1158
auto nominal = type->getAnyNominal ();
1117
1159
if (!nominal) return ;
@@ -1124,28 +1166,20 @@ void ASTMangler::appendRetroactiveConformances(Type type) {
1124
1166
if (subMap.empty ()) return ;
1125
1167
1126
1168
unsigned numProtocolRequirements = 0 ;
1127
- for (const auto &req: genericSig->getRequirements ()) {
1128
- if (req.getKind () != RequirementKind::Conformance)
1129
- continue ;
1130
-
1169
+ for (auto conformance : subMap.getConformances ()) {
1131
1170
SWIFT_DEFER {
1132
1171
++numProtocolRequirements;
1133
1172
};
1134
1173
1135
- // Fast path: we're in the module of the protocol.
1136
- auto proto = req.getSecondType ()->castTo <ProtocolType>()->getDecl ();
1137
- if (proto->getModuleContext () == module )
1174
+ // Ignore abstract conformances.
1175
+ if (!conformance.isConcrete ())
1138
1176
continue ;
1139
1177
1140
- auto conformance =
1141
- subMap.lookupConformance (req.getFirstType ()->getCanonicalType (), proto);
1142
- if (!conformance || !conformance->isConcrete ()) continue ;
1143
-
1144
- auto normal = conformance->getConcrete ()->getRootNormalConformance ();
1145
- if (!normal->isRetroactive () || normal->isSynthesizedNonUnique ())
1178
+ // Skip non-retroactive conformances.
1179
+ if (!containsRetroactiveConformance (conformance.getConcrete (), module ))
1146
1180
continue ;
1147
1181
1148
- appendProtocolConformance (normal );
1182
+ appendConcreteProtocolConformance (conformance. getConcrete () );
1149
1183
appendOperator (" g" , Index (numProtocolRequirements));
1150
1184
}
1151
1185
}
@@ -2240,6 +2274,138 @@ ASTMangler::appendProtocolConformance(const ProtocolConformance *conformance) {
2240
2274
}
2241
2275
}
2242
2276
2277
+ void ASTMangler::appendProtocolConformanceRef (
2278
+ const NormalProtocolConformance *conformance) {
2279
+ // FIXME: Symbolic reference to the protocol conformance descriptor.
2280
+ appendProtocolName (conformance->getProtocol ());
2281
+
2282
+ // For retroactive conformances, add a reference to the module in which the
2283
+ // conformance resides. For @objc protocols, there is no point: conformances
2284
+ // are global anyway.
2285
+ if (conformance->isRetroactive () && !conformance->isSynthesizedNonUnique () &&
2286
+ !conformance->getProtocol ()->isObjC ())
2287
+ appendModule (conformance->getDeclContext ()->getParentModule ());
2288
+ }
2289
+
2290
+ // / Retrieve the index of the conformance requirement indicated by the
2291
+ // / conformance access path entry within the given set of requirements.
2292
+ static unsigned conformanceRequirementIndex (
2293
+ const ConformanceAccessPath::Entry &entry,
2294
+ ArrayRef<Requirement> requirements) {
2295
+ unsigned result = 0 ;
2296
+ for (const auto &req : requirements) {
2297
+ if (req.getKind () != RequirementKind::Conformance)
2298
+ continue ;
2299
+
2300
+ if (req.getFirstType ()->isEqual (entry.first ) &&
2301
+ req.getSecondType ()->castTo <ProtocolType>()->getDecl () == entry.second )
2302
+ return result;
2303
+
2304
+ ++result;
2305
+ }
2306
+
2307
+ llvm_unreachable (" Conformance access path step is missing from requirements" );
2308
+ }
2309
+
2310
+ void ASTMangler::appendDependentProtocolConformance (
2311
+ const ConformanceAccessPath &path) {
2312
+ ProtocolDecl *currentProtocol = nullptr ;
2313
+ for (const auto &entry : path) {
2314
+ // After each step, update the current protocol to refer to where we
2315
+ // are.
2316
+ SWIFT_DEFER {
2317
+ currentProtocol = entry.second ;
2318
+ };
2319
+
2320
+ // The first entry is the "root". Find this requirement in the generic
2321
+ // signature.
2322
+ if (!currentProtocol) {
2323
+ appendType (entry.first );
2324
+ appendProtocolName (entry.second );
2325
+ auto index =
2326
+ conformanceRequirementIndex (entry,
2327
+ CurGenericSignature->getRequirements ());
2328
+ appendOperator (" HD" , index + 1 );
2329
+ continue ;
2330
+ }
2331
+
2332
+ // Conformances are relative to the current protocol's requirement
2333
+ // signature.
2334
+ auto index =
2335
+ conformanceRequirementIndex (entry,
2336
+ currentProtocol->getRequirementSignature ());
2337
+
2338
+ // Inherited conformance.
2339
+ bool isInheritedConformance =
2340
+ entry.first ->isEqual (currentProtocol->getProtocolSelfType ());
2341
+ if (isInheritedConformance) {
2342
+ appendProtocolName (entry.second );
2343
+ appendOperator (" HI" , index + 1 );
2344
+ continue ;
2345
+ }
2346
+
2347
+ // Associated conformance.
2348
+ // FIXME: Symbolic reference.
2349
+ appendType (entry.first );
2350
+ appendProtocolName (entry.second );
2351
+
2352
+ // For non-resilient protocols, encode the index.
2353
+ bool isResilient =
2354
+ currentProtocol->isResilient (Mod, ResilienceExpansion::Maximal);
2355
+ appendOperator (" HA" , isResilient ? 0 : index + 1 );
2356
+ }
2357
+ }
2358
+
2359
+ void ASTMangler::appendConcreteProtocolConformance (
2360
+ const ProtocolConformance *conformance) {
2361
+ auto module = conformance->getDeclContext ()->getParentModule ();
2362
+
2363
+ // Conforming type.
2364
+ Type conformingType = conformance->getType ();
2365
+ if (conformingType->hasArchetype ())
2366
+ conformingType = conformingType->mapTypeOutOfContext ();
2367
+ appendType (conformingType->getCanonicalType ());
2368
+
2369
+ // Protocol conformance reference.
2370
+ appendProtocolConformanceRef (conformance->getRootNormalConformance ());
2371
+
2372
+ // Conditional conformance requirements.
2373
+ bool firstRequirement = true ;
2374
+ for (const auto &conditionalReq : conformance->getConditionalRequirements ()) {
2375
+ switch (conditionalReq.getKind ()) {
2376
+ case RequirementKind::Layout:
2377
+ case RequirementKind::SameType:
2378
+ case RequirementKind::Superclass:
2379
+ continue ;
2380
+
2381
+ case RequirementKind::Conformance: {
2382
+ auto type = conditionalReq.getFirstType ();
2383
+ if (type->hasArchetype ())
2384
+ type = type->mapTypeOutOfContext ();
2385
+ CanType canType = type->getCanonicalType (CurGenericSignature);
2386
+ auto proto =
2387
+ conditionalReq.getSecondType ()->castTo <ProtocolType>()->getDecl ();
2388
+ if (canType->isTypeParameter ()) {
2389
+ assert (CurGenericSignature &&
2390
+ " Need a generic signature to resolve conformance" );
2391
+ auto conformanceAccessPath =
2392
+ CurGenericSignature->getConformanceAccessPath (type, proto);
2393
+ appendDependentProtocolConformance (conformanceAccessPath);
2394
+ } else {
2395
+ auto conditionalConf = module ->lookupConformance (canType, proto);
2396
+ appendConcreteProtocolConformance (conditionalConf->getConcrete ());
2397
+ }
2398
+ appendListSeparator (firstRequirement);
2399
+ break ;
2400
+ }
2401
+ }
2402
+ }
2403
+ if (firstRequirement)
2404
+ appendOperator (" y" );
2405
+
2406
+ appendOperator (" HC" );
2407
+ }
2408
+
2243
2409
void ASTMangler::appendOpParamForLayoutConstraint (LayoutConstraint layout) {
2244
2410
assert (layout);
2245
2411
switch (layout->getKind ()) {
0 commit comments