@@ -798,6 +798,23 @@ Optional<unsigned> findAssociatedTypeByName(const ProtocolDescriptor *protocol,
798
798
swift_runtime_unreachable (" associated type names don't line up" );
799
799
}
800
800
801
+ // / Retrieve the generic parameters introduced in this context.
802
+ static ArrayRef<GenericParamDescriptor> getLocalGenericParams (
803
+ const ContextDescriptor *context) {
804
+ if (!context->isGeneric ())
805
+ return { };
806
+
807
+ // Determine where to start looking at generic parameters.
808
+ unsigned startParamIndex;
809
+ if (auto parent = context->Parent .get ())
810
+ startParamIndex = parent->getNumGenericParams ();
811
+ else
812
+ startParamIndex = 0 ;
813
+
814
+ auto genericContext = context->getGenericContext ();
815
+ return genericContext->getGenericParams ().slice (startParamIndex);
816
+ }
817
+
801
818
// / Constructs metadata by decoding a mangled type name, for use with
802
819
// / \c TypeDecoder.
803
820
class DecodedMetadataBuilder {
@@ -1223,49 +1240,106 @@ swift_getTypeByMangledNameImpl(const char *typeNameStart, size_t typeNameLength,
1223
1240
return swift_checkMetadataState (MetadataState::Complete, metadata).Value ;
1224
1241
}
1225
1242
1243
+ unsigned SubstGenericParametersFromMetadata::
1244
+ buildDescriptorPath (const ContextDescriptor *context) const {
1245
+ // Terminating condition: we don't have a context.
1246
+ if (!context)
1247
+ return 0 ;
1248
+
1249
+ // Add the parent's contributino to the descriptor path.
1250
+ unsigned numKeyGenericParamsInParent =
1251
+ buildDescriptorPath (context->Parent .get ());
1252
+
1253
+ // If this context is non-generic, we're done.
1254
+ if (!context->isGeneric ())
1255
+ return numKeyGenericParamsInParent;
1256
+
1257
+ // Count the number of key generic params at this level.
1258
+ unsigned numKeyGenericParamsHere = 0 ;
1259
+ bool hasNonKeyGenericParams = false ;
1260
+ for (const auto &genericParam : getLocalGenericParams (context)) {
1261
+ if (genericParam.hasKeyArgument ())
1262
+ ++numKeyGenericParamsHere;
1263
+ else
1264
+ hasNonKeyGenericParams = true ;
1265
+ }
1266
+
1267
+ // Form the path element.
1268
+ descriptorPath.push_back (PathElement{context, numKeyGenericParamsInParent,
1269
+ numKeyGenericParamsHere,
1270
+ hasNonKeyGenericParams});
1271
+ return numKeyGenericParamsInParent + numKeyGenericParamsHere;
1272
+ }
1273
+
1274
+ void SubstGenericParametersFromMetadata::setup () const {
1275
+ if (!descriptorPath.empty () || !base)
1276
+ return ;
1277
+
1278
+ buildDescriptorPath (base->getTypeContextDescriptor ());
1279
+ }
1280
+
1226
1281
const Metadata *
1227
1282
SubstGenericParametersFromMetadata::operator ()(unsigned flatIndex) const {
1228
- // FIXME: Adjust for non-key arguments.
1229
- return base->getGenericArgs ()[flatIndex];
1283
+ // On first access, compute the descriptor path.
1284
+ setup ();
1285
+
1286
+ // Find the depth at which this parameter occurs.
1287
+ unsigned depth = descriptorPath.size ();
1288
+ unsigned index = flatIndex;
1289
+ for (const auto &pathElement : descriptorPath) {
1290
+ // If the flat index is beyond the element at this position, we're done.
1291
+ if (flatIndex >= pathElement.context ->getNumGenericParams ()) {
1292
+ // Subtract off the number of parameters.
1293
+ index -= pathElement.context ->getNumGenericParams ();
1294
+ break ;
1295
+ }
1296
+
1297
+ --depth;
1298
+ }
1299
+
1300
+ // Perform the access based on depth/index.
1301
+ return (*this )(depth, index);
1230
1302
}
1231
1303
1232
1304
const Metadata *
1233
1305
SubstGenericParametersFromMetadata::operator ()(
1234
1306
unsigned depth, unsigned index) const {
1235
1307
// On first access, compute the descriptor path.
1236
- if (descriptorPath.empty ()) {
1237
- if (auto *baseDesc = base->getTypeContextDescriptor ()) {
1238
- const auto *parent = reinterpret_cast <
1239
- const ContextDescriptor *>(baseDesc);
1240
- while (parent) {
1241
- if (parent->isGeneric ())
1242
- descriptorPath.push_back (parent);
1243
-
1244
- parent = parent->Parent .get ();
1245
- }
1246
- }
1247
- }
1308
+ setup ();
1248
1309
1310
+ // If the depth is too great, there is nothing to do.
1249
1311
if (depth >= descriptorPath.size ())
1250
1312
return nullptr ;
1251
1313
1252
- unsigned currentDepth = 0 ;
1253
- unsigned flatIndex = index;
1254
- const ContextDescriptor *currentContext = descriptorPath.back ();
1255
-
1256
- for (const auto *context : llvm::reverse (descriptorPath)) {
1257
- if (currentDepth >= depth)
1258
- break ;
1259
-
1260
- flatIndex += context->getNumGenericParams ();
1261
- currentContext = context;
1262
- ++currentDepth;
1263
- }
1314
+ // / Retrieve the descriptor path element at this depth.
1315
+ auto &pathElement = descriptorPath[depth];
1316
+ auto currentContext = pathElement.context ;
1264
1317
1318
+ // Check whether the index is clearly out of bounds.
1265
1319
if (index >= currentContext->getNumGenericParams ())
1266
1320
return nullptr ;
1267
1321
1268
- // FIXME: Adjust for non-key arguments.
1322
+ // Compute the flat index.
1323
+ unsigned flatIndex = pathElement.numKeyGenericParamsInParent ;
1324
+ if (pathElement.hasNonKeyGenericParams > 0 ) {
1325
+ // We have non-key generic parameters at this level, so the index needs to
1326
+ // be checked more carefully.
1327
+ auto genericParams = getLocalGenericParams (currentContext);
1328
+
1329
+ // Make sure that the requested parameter itself has a key argument.
1330
+ if (!genericParams[index].hasKeyArgument ())
1331
+ return nullptr ;
1332
+
1333
+ // Increase the flat index for each parameter with a key argument, up to
1334
+ // the given index.
1335
+ for (const auto &genericParam : genericParams.slice (0 , index)) {
1336
+ if (genericParam.hasKeyArgument ())
1337
+ ++flatIndex;
1338
+ }
1339
+ } else {
1340
+ flatIndex += index;
1341
+ }
1342
+
1269
1343
return base->getGenericArgs ()[flatIndex];
1270
1344
}
1271
1345
0 commit comments