@@ -234,8 +234,7 @@ SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
234
234
235
235
CanType depTy = req.getFirstType ()->getCanonicalType ();
236
236
auto replacement = depTy.subst (subs, lookupConformance);
237
- auto protoType = req.getSecondType ()->castTo <ProtocolType>();
238
- auto proto = protoType->getDecl ();
237
+ auto *proto = req.getProtocolDecl ();
239
238
auto conformance = lookupConformance (depTy, replacement, proto);
240
239
conformances.push_back (conformance);
241
240
}
@@ -334,38 +333,27 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
334
333
335
334
auto genericSig = getGenericSignature ();
336
335
337
- // Fast path
338
- unsigned index = 0 ;
339
- for (auto reqt : genericSig->getRequirements ()) {
340
- if (reqt.getKind () == RequirementKind::Conformance) {
341
- if (reqt.getFirstType ()->isEqual (type) &&
342
- reqt.getSecondType ()->isEqual (proto->getDeclaredInterfaceType ()))
343
- return getConformances ()[index ];
336
+ auto getSignatureConformance =
337
+ [&](Type type, ProtocolDecl *proto) -> Optional<ProtocolConformanceRef> {
338
+ unsigned index = 0 ;
339
+ for (auto reqt : genericSig->getRequirements ()) {
340
+ if (reqt.getKind () == RequirementKind::Conformance) {
341
+ if (reqt.getFirstType ()->isEqual (type) &&
342
+ reqt.getProtocolDecl () == proto)
343
+ return getConformances ()[index ];
344
344
345
- ++index ;
346
- }
347
- }
348
-
349
- // Retrieve the starting conformance from the conformance map.
350
- auto getInitialConformance =
351
- [&](Type type, ProtocolDecl *proto) -> ProtocolConformanceRef {
352
- unsigned conformanceIndex = 0 ;
353
- for (const auto &req : getGenericSignature ()->getRequirements ()) {
354
- if (req.getKind () != RequirementKind::Conformance)
355
- continue ;
356
-
357
- // Is this the conformance we're looking for?
358
- if (req.getFirstType ()->isEqual (type) &&
359
- req.getSecondType ()->castTo <ProtocolType>()->getDecl () == proto) {
360
- return getConformances ()[conformanceIndex];
345
+ ++index ;
361
346
}
362
-
363
- ++conformanceIndex;
364
347
}
365
348
366
- return ProtocolConformanceRef::forInvalid () ;
349
+ return None ;
367
350
};
368
351
352
+ // Fast path -- check if the generic signature directly states the
353
+ // conformance.
354
+ if (auto directConformance = getSignatureConformance (type, proto))
355
+ return *directConformance;
356
+
369
357
// Check whether the superclass conforms.
370
358
if (auto superclass = genericSig->getSuperclassBound (type)) {
371
359
LookUpConformanceInSignature lookup (getGenericSignature ().getPointer ());
@@ -388,16 +376,16 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
388
376
for (const auto &step : accessPath) {
389
377
// For the first step, grab the initial conformance.
390
378
if (conformance.isInvalid ()) {
391
- conformance = getInitialConformance (step.first , step.second );
392
- if (conformance.isInvalid ())
393
- return ProtocolConformanceRef::forInvalid ();
379
+ if (auto initialConformance = getSignatureConformance (
380
+ step.first , step.second )) {
381
+ conformance = *initialConformance;
382
+ continue ;
383
+ }
394
384
395
- continue ;
385
+ // We couldn't find the initial conformance, fail.
386
+ return ProtocolConformanceRef::forInvalid ();
396
387
}
397
388
398
- if (conformance.isInvalid ())
399
- return conformance;
400
-
401
389
// If we've hit an abstract conformance, everything from here on out is
402
390
// abstract.
403
391
// FIXME: This may not always be true, but it holds for now.
@@ -436,6 +424,8 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
436
424
437
425
// Get the associated conformance.
438
426
conformance = concrete->getAssociatedConformance (step.first , step.second );
427
+ if (conformance.isInvalid ())
428
+ return conformance;
439
429
}
440
430
441
431
return conformance;
0 commit comments