@@ -434,19 +434,6 @@ Type RequirementMachine::getCanonicalTypeInContext(
434
434
});
435
435
}
436
436
437
- // / Replace 'Self' in the given dependent type (\c depTy) with the given
438
- // / dependent type, producing a type that refers to the nested type.
439
- static Type replaceSelfWithType (Type selfType, Type depTy) {
440
- if (auto depMemTy = depTy->getAs <DependentMemberType>()) {
441
- Type baseType = replaceSelfWithType (selfType, depMemTy->getBase ());
442
- assert (depMemTy->getAssocType () && " Missing associated type" );
443
- return DependentMemberType::get (baseType, depMemTy->getAssocType ());
444
- }
445
-
446
- assert (depTy->is <GenericTypeParamType>() && " missing Self?" );
447
- return selfType;
448
- }
449
-
450
437
// / Retrieve the conformance access path used to extract the conformance of
451
438
// / interface \c type to the given \c protocol.
452
439
// /
@@ -462,12 +449,29 @@ static Type replaceSelfWithType(Type selfType, Type depTy) {
462
449
ConformanceAccessPath
463
450
RequirementMachine::getConformanceAccessPath (Type type,
464
451
ProtocolDecl *protocol) {
465
- auto canType = getCanonicalTypeInContext (type, { })->getCanonicalType ();
466
- assert (canType->isTypeParameter ());
452
+ assert (type->isTypeParameter ());
453
+
454
+ auto mutTerm = Context.getMutableTermForType (type->getCanonicalType (),
455
+ /* proto=*/ nullptr );
456
+ System.simplify (mutTerm);
457
+ verify (mutTerm);
458
+
459
+ #ifndef NDEBUG
460
+ auto *props = Map.lookUpProperties (mutTerm);
461
+ assert (props &&
462
+ " Subject type of conformance access path should be known" );
463
+ assert (!props->isConcreteType () &&
464
+ " Concrete types do not have conformance access paths" );
465
+ auto conformsTo = props->getConformsTo ();
466
+ assert (std::find (conformsTo.begin (), conformsTo.end (), protocol) &&
467
+ " Subject type of conformance access path must conform to protocol" );
468
+ #endif
469
+
470
+ auto term = Term::get (mutTerm, Context);
467
471
468
472
// Check if we've already cached the result before doing anything else.
469
473
auto found = ConformanceAccessPaths.find (
470
- std::make_pair (canType , protocol));
474
+ std::make_pair (term , protocol));
471
475
if (found != ConformanceAccessPaths.end ()) {
472
476
return found->second ;
473
477
}
@@ -476,13 +480,13 @@ RequirementMachine::getConformanceAccessPath(Type type,
476
480
477
481
FrontendStatsTracer tracer (Stats, " get-conformance-access-path" );
478
482
479
- auto recordPath = [&](CanType type , ProtocolDecl *proto,
483
+ auto recordPath = [&](Term term , ProtocolDecl *proto,
480
484
ConformanceAccessPath path) {
481
485
// Add the path to the buffer.
482
- CurrentConformanceAccessPaths.emplace_back (type , path);
486
+ CurrentConformanceAccessPaths.emplace_back (term , path);
483
487
484
488
// Add the path to the map.
485
- auto key = std::make_pair (type , proto);
489
+ auto key = std::make_pair (term , proto);
486
490
auto inserted = ConformanceAccessPaths.insert (
487
491
std::make_pair (key, path));
488
492
assert (inserted.second );
@@ -508,22 +512,27 @@ RequirementMachine::getConformanceAccessPath(Type type,
508
512
ArrayRef<ConformanceAccessPath::Entry> path (root);
509
513
ConformanceAccessPath result (ctx.AllocateCopy (path));
510
514
511
- recordPath (rootType, rootProto, result);
515
+ auto mutTerm = Context.getMutableTermForType (rootType, nullptr );
516
+ System.simplify (mutTerm);
517
+
518
+ auto rootTerm = Term::get (mutTerm, Context);
519
+ recordPath (rootTerm, rootProto, result);
512
520
}
513
521
}
514
522
515
523
// We enumerate conformance access paths in shortlex order until we find the
516
524
// path whose corresponding type canonicalizes to the one we are looking for.
517
525
while (true ) {
518
526
auto found = ConformanceAccessPaths.find (
519
- std::make_pair (canType , protocol));
527
+ std::make_pair (term , protocol));
520
528
if (found != ConformanceAccessPaths.end ()) {
521
529
return found->second ;
522
530
}
523
531
524
532
if (CurrentConformanceAccessPaths.empty ()) {
525
533
llvm::errs () << " Failed to find conformance access path for " ;
526
- llvm::errs () << type << " " << protocol->getName () << " :\n " ;
534
+ llvm::errs () << type << " (" << term << " )" << " : " ;
535
+ llvm::errs () << protocol->getName () << " :\n " ;
527
536
type.dump (llvm::errs ());
528
537
llvm::errs () << " \n " ;
529
538
dump (llvm::errs ());
@@ -533,7 +542,7 @@ RequirementMachine::getConformanceAccessPath(Type type,
533
542
// The buffer consists of all conformance access paths of length N.
534
543
// Swap it out with an empty buffer, and fill it with all paths of
535
544
// length N+1.
536
- std::vector<std::pair<CanType , ConformanceAccessPath>> oldPaths;
545
+ std::vector<std::pair<Term , ConformanceAccessPath>> oldPaths;
537
546
std::swap (CurrentConformanceAccessPaths, oldPaths);
538
547
539
548
for (const auto &pair : oldPaths) {
@@ -551,21 +560,19 @@ RequirementMachine::getConformanceAccessPath(Type type,
551
560
auto nextSubjectType = req.getFirstType ()->getCanonicalType ();
552
561
auto *nextProto = req.getProtocolDecl ();
553
562
554
- // Compute the canonical anchor for this conformance requirement.
555
- auto nextType = replaceSelfWithType (pair. first , nextSubjectType);
556
- auto nextCanType = getCanonicalTypeInContext (nextType, { })
557
- -> getCanonicalType ( );
563
+ MutableTerm mutTerm (pair. first );
564
+ mutTerm. append (Context. getMutableTermForType ( nextSubjectType,
565
+ /* proto= */ lastProto));
566
+ System. simplify (mutTerm );
558
567
559
- // Skip "derived via concrete" sources.
560
- if (!nextCanType->isTypeParameter ())
561
- continue ;
568
+ auto nextTerm = Term::get (mutTerm, Context);
562
569
563
570
// If we've already seen a path for this conformance, skip it and
564
571
// don't add it to the buffer. Note that because we iterate over
565
572
// conformance access paths in shortlex order, the existing
566
573
// conformance access path is shorter than the one we found just now.
567
574
if (ConformanceAccessPaths.count (
568
- std::make_pair (nextCanType , nextProto)))
575
+ std::make_pair (nextTerm , nextProto)))
569
576
continue ;
570
577
571
578
if (entries.empty ()) {
@@ -580,7 +587,7 @@ RequirementMachine::getConformanceAccessPath(Type type,
580
587
ConformanceAccessPath result = ctx.AllocateCopy (entries);
581
588
entries.pop_back ();
582
589
583
- recordPath (nextCanType , nextProto, result);
590
+ recordPath (nextTerm , nextProto, result);
584
591
}
585
592
}
586
593
}
0 commit comments