@@ -576,154 +576,11 @@ CanGenericSignature::getGenericParams() const{
576576 return {base, params.size ()};
577577}
578578
579- namespace {
580- typedef GenericSignatureBuilder::RequirementSource RequirementSource;
581-
582- template <typename T>
583- using GSBConstraint = GenericSignatureBuilder::Constraint<T>;
584- } // end anonymous namespace
585-
586- // / Determine whether there is a conformance of the given
587- // / subject type to the given protocol within the given set of explicit
588- // / requirements.
589- static bool hasConformanceInSignature (ArrayRef<Requirement> requirements,
590- Type subjectType,
591- ProtocolDecl *proto) {
592- // Make sure this requirement exists in the requirement signature.
593- for (const auto &req: requirements) {
594- if (req.getKind () == RequirementKind::Conformance &&
595- req.getFirstType ()->isEqual (subjectType) &&
596- req.getProtocolDecl () == proto) {
597- return true ;
598- }
599- }
600-
601- return false ;
602- }
603-
604579ConformanceAccessPath
605580GenericSignatureImpl::getConformanceAccessPath (Type type,
606581 ProtocolDecl *protocol) const {
607- assert (type->isTypeParameter () && " not a type parameter" );
608-
609- // Look up the equivalence class for this type.
610- auto &builder = *getGenericSignatureBuilder ();
611- auto equivClass =
612- builder.resolveEquivalenceClass (
613- type,
614- ArchetypeResolutionKind::CompleteWellFormed);
615-
616- assert (!equivClass->concreteType &&
617- " Concrete types don't have conformance access paths" );
618-
619- auto cached = equivClass->conformanceAccessPathCache .find (protocol);
620- if (cached != equivClass->conformanceAccessPathCache .end ())
621- return cached->second ;
622-
623- // Dig out the conformance of this type to the given protocol, because we
624- // want its requirement source.
625- auto conforms = equivClass->conformsTo .find (protocol);
626- assert (conforms != equivClass->conformsTo .end ());
627-
628- auto rootType = equivClass->getAnchor (builder, { });
629- if (hasConformanceInSignature (getRequirements (), rootType, protocol)) {
630- ConformanceAccessPath::Entry root (rootType, protocol);
631- ArrayRef<ConformanceAccessPath::Entry> path (root);
632-
633- ConformanceAccessPath result (builder.getASTContext ().AllocateCopy (path));
634- equivClass->conformanceAccessPathCache .insert ({protocol, result});
635-
636- return result;
637- }
638-
639- // This conformance comes from a derived source.
640- //
641- // To recover this the conformance, we recursively recover the conformance
642- // of the shortest parent type to the parent protocol first.
643- Type shortestParentType;
644- Type shortestSubjectType;
645- ProtocolDecl *shortestParentProto = nullptr ;
646-
647- auto isShortestPath = [&](Type parentType,
648- Type subjectType,
649- ProtocolDecl *parentProto) -> bool {
650- if (!shortestParentType)
651- return true ;
652-
653- int cmpParentTypes = compareDependentTypes (parentType, shortestParentType);
654- if (cmpParentTypes != 0 )
655- return cmpParentTypes < 0 ;
656-
657- int cmpSubjectTypes = compareDependentTypes (subjectType, shortestSubjectType);
658- if (cmpSubjectTypes != 0 )
659- return cmpSubjectTypes < 0 ;
660-
661- int cmpParentProtos = TypeDecl::compare (parentProto, shortestParentProto);
662- return cmpParentProtos < 0 ;
663- };
664-
665- auto recordShortestParentType = [&](Type parentType,
666- Type subjectType,
667- ProtocolDecl *parentProto) {
668- if (isShortestPath (parentType, subjectType, parentProto)) {
669- shortestParentType = parentType;
670- shortestSubjectType = subjectType;
671- shortestParentProto = parentProto;
672- }
673- };
674-
675- for (auto constraint : conforms->second ) {
676- auto *source = constraint.source ;
677-
678- switch (source->kind ) {
679- case RequirementSource::Explicit:
680- case RequirementSource::Inferred:
681- // This is not a derived source, so it contributes nothing to the
682- // "shortest parent type" computation.
683- break ;
684-
685- case RequirementSource::ProtocolRequirement:
686- case RequirementSource::InferredProtocolRequirement: {
687- assert (source->parent ->kind != RequirementSource::RequirementSignatureSelf);
688-
689- // If we have a derived conformance requirement like T[.P].X : Q, we can
690- // recursively compute the conformance access path for T : P, and append
691- // the path element (Self.X : Q).
692- auto parentType = source->parent ->getAffectedType ()->getCanonicalType ();
693- auto subjectType = source->getStoredType ()->getCanonicalType ();
694- auto *parentProto = source->getProtocolDecl ();
695-
696- // We might have multiple candidate parent types and protocols for the
697- // recursive step, so pick the shortest one.
698- recordShortestParentType (parentType, subjectType, parentProto);
699-
700- break ;
701- }
702-
703- default :
704- // There should be no other way of testifying to a conformance on a
705- // dependent type.
706- llvm_unreachable (" Bad requirement source for conformance on dependent type" );
707- }
708- }
709-
710- assert (shortestParentType);
711-
712- SmallVector<ConformanceAccessPath::Entry, 2 > path;
713-
714- auto parentPath = getConformanceAccessPath (
715- shortestParentType, shortestParentProto);
716- for (auto entry : parentPath)
717- path.push_back (entry);
718-
719- // Then, we add the subject type from the parent protocol's requirement
720- // signature.
721- path.emplace_back (shortestSubjectType, protocol);
722-
723- ConformanceAccessPath result (builder.getASTContext ().AllocateCopy (path));
724- equivClass->conformanceAccessPathCache .insert ({protocol, result});
725-
726- return result;
582+ return getGenericSignatureBuilder ()->getConformanceAccessPath (
583+ type, protocol, this );
727584}
728585
729586unsigned GenericParamKey::findIndexIn (
0 commit comments