@@ -900,12 +900,71 @@ namespace {
900
900
using GSBConstraint = GenericSignatureBuilder::Constraint<T>;
901
901
} // end anonymous namespace
902
902
903
+ // / Determine whether there is a conformance of the given
904
+ // / subject type to the given protocol within the given set of explicit
905
+ // / requirements.
906
+ static bool hasConformanceInSignature (ArrayRef<Requirement> requirements,
907
+ Type subjectType,
908
+ ProtocolDecl *proto) {
909
+ // Make sure this requirement exists in the requirement signature.
910
+ for (const auto & req: requirements) {
911
+ if (req.getKind () == RequirementKind::Conformance &&
912
+ req.getFirstType ()->isEqual (subjectType) &&
913
+ req.getSecondType ()->castTo <ProtocolType>()->getDecl ()
914
+ == proto) {
915
+ return true ;
916
+ }
917
+ }
918
+
919
+ return false ;
920
+ }
921
+
922
+ // / Check whether the given requirement source has any non-canonical protocol
923
+ // / requirements in it.
924
+ static bool hasNonCanonicalSelfProtocolRequirement (
925
+ const RequirementSource *source,
926
+ ProtocolDecl *conformingProto) {
927
+ for (; source; source = source->parent ) {
928
+ // Only look at protocol requirements.
929
+ if (!source->isProtocolRequirement ())
930
+ continue ;
931
+
932
+ // If we don't already have a requirement signature for this protocol,
933
+ // build one now.
934
+ auto inProto = source->getProtocolDecl ();
935
+ if (!inProto->isRequirementSignatureComputed ()) {
936
+ inProto->computeRequirementSignature ();
937
+ assert (inProto->isRequirementSignatureComputed () &&
938
+ " couldn't compute requirement signature?" );
939
+ }
940
+
941
+ // Check whether the given requirement is in the requirement signature.
942
+ if (!source->usesRequirementSignature &&
943
+ !hasConformanceInSignature (inProto->getRequirementSignature (),
944
+ source->getStoredType (), conformingProto))
945
+ return true ;
946
+
947
+ // Update the conforming protocol for the rest of the search.
948
+ conformingProto = inProto;
949
+ }
950
+
951
+ return false ;
952
+ }
953
+
903
954
// / Retrieve the best requirement source from the list
904
955
static const RequirementSource *
905
- getBestRequirementSource (ArrayRef<GSBConstraint<ProtocolDecl *>> constraints) {
956
+ getBestCanonicalRequirementSource (
957
+ ArrayRef<GSBConstraint<ProtocolDecl *>> constraints) {
906
958
const RequirementSource *bestSource = nullptr ;
907
959
for (const auto &constraint : constraints) {
908
960
auto source = constraint.source ;
961
+
962
+ // If there is a non-canonical protocol requirement next to the root,
963
+ // skip this requirement source.
964
+ if (hasNonCanonicalSelfProtocolRequirement (source, constraint.value ))
965
+ continue ;
966
+
967
+ // Check whether this is better than our best source.
909
968
if (!bestSource || source->compare (bestSource) < 0 )
910
969
bestSource = source;
911
970
}
@@ -934,27 +993,6 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
934
993
typedef GenericSignatureBuilder::RequirementSource RequirementSource;
935
994
ConformanceAccessPath path;
936
995
937
- #ifndef NDEBUG
938
- // Local function to determine whether there is a conformance of the given
939
- // subject type to the given protocol within the given set of explicit
940
- // requirements.
941
- auto hasConformanceInSignature = [&](ArrayRef<Requirement> requirements,
942
- Type subjectType,
943
- ProtocolDecl *proto) -> bool {
944
- // Make sure this requirement exists in the requirement signature.
945
- for (const auto & req: requirements) {
946
- if (req.getKind () == RequirementKind::Conformance &&
947
- req.getFirstType ()->isEqual (subjectType) &&
948
- req.getSecondType ()->castTo <ProtocolType>()->getDecl ()
949
- == proto) {
950
- return true ;
951
- }
952
- }
953
-
954
- return false ;
955
- };
956
- #endif
957
-
958
996
// Local function to construct the conformance access path from the
959
997
// requirement.
960
998
std::function<void (ArrayRef<Requirement>, const RequirementSource *,
@@ -1003,13 +1041,6 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
1003
1041
return ;
1004
1042
}
1005
1043
1006
- // Canonicalize this step with respect to the requirement signature.
1007
- if (!inProtocol->isRequirementSignatureComputed ()) {
1008
- inProtocol->computeRequirementSignature ();
1009
- assert (inProtocol->isRequirementSignatureComputed () &&
1010
- " missing signature" );
1011
- }
1012
-
1013
1044
// Get a generic signature for the protocol's signature.
1014
1045
auto inProtoSig = inProtocol->getGenericSignature ();
1015
1046
auto &inProtoSigBuilder = *inProtoSig->getGenericSignatureBuilder ();
@@ -1031,7 +1062,7 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
1031
1062
assert (conforms != equivClass->conformsTo .end ());
1032
1063
1033
1064
// Compute the root type, canonicalizing it w.r.t. the protocol context.
1034
- auto conformsSource = getBestRequirementSource (conforms->second );
1065
+ auto conformsSource = getBestCanonicalRequirementSource (conforms->second );
1035
1066
assert (conformsSource != source || !requirementSignatureProto);
1036
1067
Type localRootType = conformsSource->getRootType ();
1037
1068
localRootType = inProtoSig->getCanonicalTypeInContext (localRootType);
@@ -1079,7 +1110,7 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
1079
1110
};
1080
1111
1081
1112
// Canonicalize the root type.
1082
- auto source = getBestRequirementSource (conforms->second );
1113
+ auto source = getBestCanonicalRequirementSource (conforms->second );
1083
1114
Type rootType = source->getRootType ()->getCanonicalType (this );
1084
1115
1085
1116
// Build the path.
0 commit comments