@@ -817,175 +817,178 @@ getBestRequirementSource(ArrayRef<GSBConstraint<ProtocolDecl *>> constraints) {
817
817
return bestSource;
818
818
}
819
819
820
- ConformanceAccessPath GenericSignature::getConformanceAccessPath (
821
- Type type,
822
- ProtocolDecl *protocol) {
823
- assert (type->isTypeParameter () && " not a type parameter" );
824
-
825
- // Resolve this type to a potential archetype.
826
- auto &builder = *getGenericSignatureBuilder ();
827
- auto equivClass =
828
- builder.resolveEquivalenceClass (
829
- type,
830
- ArchetypeResolutionKind::CompleteWellFormed);
831
-
832
- // Dig out the conformance of this type to the given protocol, because we
833
- // want its requirement source.
834
- auto conforms = equivClass->conformsTo .find (protocol);
835
- assert (conforms != equivClass->conformsTo .end ());
836
-
837
- // Follow the requirement source to form the conformance access path.
838
- typedef GenericSignatureBuilder::RequirementSource RequirementSource;
839
- ConformanceAccessPath path;
840
-
841
- // Local function to construct the conformance access path from the
842
- // requirement.
843
- std::function<void (ArrayRef<Requirement>, const RequirementSource *,
844
- ProtocolDecl *, Type, ProtocolDecl *)> buildPath;
845
- buildPath = [&](ArrayRef<Requirement> reqs, const RequirementSource *source,
846
- ProtocolDecl *conformingProto, Type rootType,
847
- ProtocolDecl *requirementSignatureProto) {
848
- // Each protocol requirement is a step along the path.
849
- if (source->isProtocolRequirement ()) {
850
- // If we're expanding for a protocol that had no requirement signature
851
- // and have hit the penultimate step, this is the last step
852
- // that would occur in the requirement signature.
853
- Optional<GenericSignatureBuilder> replacementBuilder;
854
- if (!source->parent ->parent && requirementSignatureProto) {
855
- // If we have a requirement signature now, we're done.
856
- if (source->usesRequirementSignature ) {
857
- Type subjectType = source->getStoredType ()->getCanonicalType ();
858
- path.path .push_back ({subjectType, conformingProto});
859
- return ;
860
- }
861
-
862
- // The generic signature builder we're using for this protocol
863
- // wasn't built from its own requirement signature, so we can't
864
- // trust it. Make sure we have a requirement signature, then build
865
- // a new generic signature builder.
866
- // FIXME: It would be better if we could replace the canonical generic
867
- // signature builder with the rebuilt one.
868
- if (!requirementSignatureProto->isRequirementSignatureComputed ())
869
- requirementSignatureProto->computeRequirementSignature ();
870
- assert (requirementSignatureProto->isRequirementSignatureComputed ());
871
-
872
- replacementBuilder.emplace (getASTContext ());
873
- replacementBuilder->addGenericSignature (
874
- requirementSignatureProto->getGenericSignature ());
875
- replacementBuilder->processDelayedRequirements ();
876
- }
877
-
878
- // Follow the rest of the path to derive the conformance into which
879
- // this particular protocol requirement step would look.
880
- auto inProtocol = source->getProtocolDecl ();
881
- buildPath (reqs, source->parent , inProtocol, rootType,
882
- requirementSignatureProto);
883
- assert (path.path .back ().second == inProtocol &&
884
- " path produces incorrect conformance" );
885
-
886
- // If this step was computed via the requirement signature, add it
887
- // directly.
820
+ void GenericSignature::buildConformanceAccessPath (
821
+ SmallVectorImpl<ConformanceAccessPath::Entry> &path,
822
+ ArrayRef<Requirement> reqs, const void *opaqueSource,
823
+ ProtocolDecl *conformingProto, Type rootType,
824
+ ProtocolDecl *requirementSignatureProto) {
825
+ auto *source = reinterpret_cast <const RequirementSource *>(opaqueSource);
826
+ // Each protocol requirement is a step along the path.
827
+ if (source->isProtocolRequirement ()) {
828
+ // If we're expanding for a protocol that had no requirement signature
829
+ // and have hit the penultimate step, this is the last step
830
+ // that would occur in the requirement signature.
831
+ Optional<GenericSignatureBuilder> replacementBuilder;
832
+ if (!source->parent ->parent && requirementSignatureProto) {
833
+ // If we have a requirement signature now, we're done.
888
834
if (source->usesRequirementSignature ) {
889
- // Add this step along the path, which involves looking for the
890
- // conformance we want (\c conformingProto) within the protocol
891
- // described by this source.
892
-
893
- // Canonicalize the subject type within the protocol's generic
894
- // signature.
895
- Type subjectType = source->getStoredType ();
896
- subjectType = inProtocol->getGenericSignature ()
897
- ->getCanonicalTypeInContext (subjectType);
898
-
899
- assert (hasConformanceInSignature (inProtocol->getRequirementSignature (),
900
- subjectType, conformingProto) &&
901
- " missing explicit conformance in requirement signature" );
902
-
903
- // Record this step.
904
- path.path .push_back ({subjectType, conformingProto});
835
+ Type subjectType = source->getStoredType ()->getCanonicalType ();
836
+ path.push_back ({subjectType, conformingProto});
905
837
return ;
906
838
}
907
839
908
- // Get the generic signature builder for the protocol.
909
- // Get a generic signature for the protocol's signature.
910
- auto inProtoSig = inProtocol->getGenericSignature ();
911
- auto &inProtoSigBuilder =
912
- replacementBuilder ? *replacementBuilder
913
- : *inProtoSig->getGenericSignatureBuilder ();
914
-
915
- // Retrieve the stored type, but erase all of the specific associated
916
- // type declarations; we don't want any details of the enclosing context
917
- // to sneak in here.
918
- Type storedType = eraseAssociatedTypes (source->getStoredType ());
919
-
920
- // Dig out the potential archetype for this stored type.
921
- auto equivClass =
922
- inProtoSigBuilder.resolveEquivalenceClass (
923
- storedType,
924
- ArchetypeResolutionKind::CompleteWellFormed);
925
-
926
- // Find the conformance of this potential archetype to the protocol in
927
- // question.
928
- auto conforms = equivClass->conformsTo .find (conformingProto);
929
- assert (conforms != equivClass->conformsTo .end ());
930
-
931
- // Compute the root type, canonicalizing it w.r.t. the protocol context.
932
- auto conformsSource = getBestRequirementSource (conforms->second );
933
- assert (conformsSource != source || !requirementSignatureProto);
934
- Type localRootType = conformsSource->getRootType ();
935
- localRootType = inProtoSig->getCanonicalTypeInContext (localRootType);
936
-
937
- // Build the path according to the requirement signature.
938
- buildPath (inProtocol->getRequirementSignature (), conformsSource,
939
- conformingProto, localRootType, inProtocol);
940
-
941
- // We're done.
942
- return ;
840
+ // The generic signature builder we're using for this protocol
841
+ // wasn't built from its own requirement signature, so we can't
842
+ // trust it. Make sure we have a requirement signature, then build
843
+ // a new generic signature builder.
844
+ // FIXME: It would be better if we could replace the canonical generic
845
+ // signature builder with the rebuilt one.
846
+ if (!requirementSignatureProto->isRequirementSignatureComputed ())
847
+ requirementSignatureProto->computeRequirementSignature ();
848
+ assert (requirementSignatureProto->isRequirementSignatureComputed ());
849
+
850
+ replacementBuilder.emplace (getASTContext ());
851
+ replacementBuilder->addGenericSignature (
852
+ requirementSignatureProto->getGenericSignature ());
853
+ replacementBuilder->processDelayedRequirements ();
943
854
}
944
855
945
- // If we have a superclass or concrete requirement, the conformance
946
- // we need is stored in it.
947
- if (source->kind == RequirementSource::Superclass ||
948
- source->kind == RequirementSource::Concrete) {
949
- auto conformance = source->getProtocolConformance ();
950
- (void )conformance;
951
- assert (conformance.getRequirement () == conformingProto);
952
- path.path .push_back ({source->getAffectedType (), conformingProto});
856
+ // Follow the rest of the path to derive the conformance into which
857
+ // this particular protocol requirement step would look.
858
+ auto inProtocol = source->getProtocolDecl ();
859
+ buildConformanceAccessPath (path, reqs, source->parent , inProtocol, rootType,
860
+ requirementSignatureProto);
861
+ assert (path.back ().second == inProtocol &&
862
+ " path produces incorrect conformance" );
863
+
864
+ // If this step was computed via the requirement signature, add it
865
+ // directly.
866
+ if (source->usesRequirementSignature ) {
867
+ // Add this step along the path, which involves looking for the
868
+ // conformance we want (\c conformingProto) within the protocol
869
+ // described by this source.
870
+
871
+ // Canonicalize the subject type within the protocol's generic
872
+ // signature.
873
+ Type subjectType = source->getStoredType ();
874
+ subjectType = inProtocol->getGenericSignature ()
875
+ ->getCanonicalTypeInContext (subjectType);
876
+
877
+ assert (hasConformanceInSignature (inProtocol->getRequirementSignature (),
878
+ subjectType, conformingProto) &&
879
+ " missing explicit conformance in requirement signature" );
880
+
881
+ // Record this step.
882
+ path.push_back ({subjectType, conformingProto});
953
883
return ;
954
884
}
955
885
956
- // If we still have a parent, keep going .
957
- if (source-> parent ) {
958
- buildPath (reqs, source-> parent , conformingProto, rootType,
959
- requirementSignatureProto);
960
- return ;
961
- }
886
+ // Get the generic signature builder for the protocol .
887
+ // Get a generic signature for the protocol's signature.
888
+ auto inProtoSig = inProtocol-> getGenericSignature ();
889
+ auto &inProtoSigBuilder =
890
+ replacementBuilder ? *replacementBuilder
891
+ : *inProtoSig-> getGenericSignatureBuilder ();
962
892
963
- // We are at an explicit or inferred requirement.
964
- assert (source->kind == RequirementSource::Explicit ||
965
- source->kind == RequirementSource::Inferred);
893
+ // Retrieve the stored type, but erase all of the specific associated
894
+ // type declarations; we don't want any details of the enclosing context
895
+ // to sneak in here.
896
+ Type storedType = eraseAssociatedTypes (source->getStoredType ());
966
897
967
- // Skip trivial path elements. These occur when querying a requirement
968
- // signature.
969
- if (!path. path . empty () && conformingProto == path. path . back (). second &&
970
- rootType-> isEqual (conformingProto-> getSelfInterfaceType ()))
971
- return ;
898
+ // Dig out the potential archetype for this stored type.
899
+ auto equivClass =
900
+ inProtoSigBuilder. resolveEquivalenceClass (
901
+ storedType,
902
+ ArchetypeResolutionKind::CompleteWellFormed) ;
972
903
973
- assert (hasConformanceInSignature (reqs, rootType, conformingProto) &&
974
- " missing explicit conformance in signature" );
904
+ // Find the conformance of this potential archetype to the protocol in
905
+ // question.
906
+ auto conforms = equivClass->conformsTo .find (conformingProto);
907
+ assert (conforms != equivClass->conformsTo .end ());
975
908
976
- // Add the root of the path, which starts at this explicit requirement.
977
- path.path .push_back ({rootType, conformingProto});
978
- };
909
+ // Compute the root type, canonicalizing it w.r.t. the protocol context.
910
+ auto conformsSource = getBestRequirementSource (conforms->second );
911
+ assert (conformsSource != source || !requirementSignatureProto);
912
+ Type localRootType = conformsSource->getRootType ();
913
+ localRootType = inProtoSig->getCanonicalTypeInContext (localRootType);
914
+
915
+ // Build the path according to the requirement signature.
916
+ buildConformanceAccessPath (path, inProtocol->getRequirementSignature (),
917
+ conformsSource, conformingProto, localRootType,
918
+ inProtocol);
919
+
920
+ // We're done.
921
+ return ;
922
+ }
923
+
924
+ // If we have a superclass or concrete requirement, the conformance
925
+ // we need is stored in it.
926
+ if (source->kind == RequirementSource::Superclass ||
927
+ source->kind == RequirementSource::Concrete) {
928
+ auto conformance = source->getProtocolConformance ();
929
+ (void )conformance;
930
+ assert (conformance.getRequirement () == conformingProto);
931
+ path.push_back ({source->getAffectedType (), conformingProto});
932
+ return ;
933
+ }
934
+
935
+ // If we still have a parent, keep going.
936
+ if (source->parent ) {
937
+ buildConformanceAccessPath (path, reqs, source->parent , conformingProto,
938
+ rootType, requirementSignatureProto);
939
+ return ;
940
+ }
941
+
942
+ // We are at an explicit or inferred requirement.
943
+ assert (source->kind == RequirementSource::Explicit ||
944
+ source->kind == RequirementSource::Inferred);
945
+
946
+ // Skip trivial path elements. These occur when querying a requirement
947
+ // signature.
948
+ if (!path.empty () && conformingProto == path.back ().second &&
949
+ rootType->isEqual (conformingProto->getSelfInterfaceType ()))
950
+ return ;
951
+
952
+ assert (hasConformanceInSignature (reqs, rootType, conformingProto) &&
953
+ " missing explicit conformance in signature" );
954
+
955
+ // Add the root of the path, which starts at this explicit requirement.
956
+ path.push_back ({rootType, conformingProto});
957
+ }
958
+
959
+ ConformanceAccessPath
960
+ GenericSignature::getConformanceAccessPath (Type type, ProtocolDecl *protocol) {
961
+ assert (type->isTypeParameter () && " not a type parameter" );
962
+
963
+ // Resolve this type to a potential archetype.
964
+ auto &builder = *getGenericSignatureBuilder ();
965
+ auto equivClass =
966
+ builder.resolveEquivalenceClass (
967
+ type,
968
+ ArchetypeResolutionKind::CompleteWellFormed);
969
+
970
+ auto cached = equivClass->conformanceAccessPathCache .find (protocol);
971
+ if (cached != equivClass->conformanceAccessPathCache .end ())
972
+ return cached->second ;
973
+
974
+ // Dig out the conformance of this type to the given protocol, because we
975
+ // want its requirement source.
976
+ auto conforms = equivClass->conformsTo .find (protocol);
977
+ assert (conforms != equivClass->conformsTo .end ());
979
978
980
979
// Canonicalize the root type.
981
980
auto source = getBestRequirementSource (conforms->second );
982
981
Type rootType = source->getRootType ()->getCanonicalType (this );
983
982
984
983
// Build the path.
985
- buildPath (getRequirements (), source, protocol, rootType, nullptr );
984
+ SmallVector<ConformanceAccessPath::Entry, 2 > path;
985
+ buildConformanceAccessPath (path, getRequirements (), source, protocol,
986
+ rootType, nullptr );
986
987
987
988
// Return the path; we're done!
988
- return path;
989
+ ConformanceAccessPath result (getASTContext ().AllocateCopy (path));
990
+ equivClass->conformanceAccessPathCache .insert ({protocol, result});
991
+ return result;
989
992
}
990
993
991
994
unsigned GenericParamKey::findIndexIn (
0 commit comments