@@ -959,20 +959,32 @@ static bool hasNonCanonicalSelfProtocolRequirement(
959
959
960
960
// / Retrieve the best requirement source from the list
961
961
static const RequirementSource *
962
- getBestCanonicalRequirementSource (
963
- ArrayRef<GSBConstraint<ProtocolDecl *>> constraints) {
962
+ getBestRequirementSource (ArrayRef<GSBConstraint<ProtocolDecl *>> constraints) {
964
963
const RequirementSource *bestSource = nullptr ;
964
+ bool bestIsNonCanonical = false ;
965
+
966
+ auto isBetter = [&](const RequirementSource *source, bool isNonCanonical) {
967
+ if (!bestSource) return true ;
968
+
969
+ if (bestIsNonCanonical != isNonCanonical)
970
+ return bestIsNonCanonical;
971
+
972
+ return bestSource->compare (source) > 0 ;
973
+ };
974
+
965
975
for (const auto &constraint : constraints) {
966
976
auto source = constraint.source ;
967
977
968
978
// If there is a non-canonical protocol requirement next to the root,
969
979
// skip this requirement source.
970
- if ( hasNonCanonicalSelfProtocolRequirement (source, constraint. value ))
971
- continue ;
980
+ bool isNonCanonical =
981
+ hasNonCanonicalSelfProtocolRequirement (source, constraint. value ) ;
972
982
973
- // Check whether this is better than our best source.
974
- if (!bestSource || source->compare (bestSource) < 0 )
983
+ if (isBetter (source, isNonCanonical)) {
975
984
bestSource = source;
985
+ bestIsNonCanonical = isNonCanonical;
986
+ continue ;
987
+ }
976
988
}
977
989
978
990
return bestSource;
@@ -1008,13 +1020,32 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
1008
1020
ProtocolDecl *requirementSignatureProto) {
1009
1021
// Each protocol requirement is a step along the path.
1010
1022
if (source->isProtocolRequirement ()) {
1011
- // If we're expanding for a protocol that has no requirement signature
1012
- // (yet) and have hit the penultimate step, this is the last step
1023
+ // If we're expanding for a protocol that had no requirement signature
1024
+ // and have hit the penultimate step, this is the last step
1013
1025
// that would occur in the requirement signature.
1026
+ Optional<GenericSignatureBuilder> replacementBuilder;
1014
1027
if (!source->parent ->parent && requirementSignatureProto) {
1015
- Type subjectType = source->getStoredType ()->getCanonicalType ();
1016
- path.path .push_back ({subjectType, conformingProto});
1017
- return ;
1028
+ // If we have a requirement signature now, we're done.
1029
+ if (source->usesRequirementSignature || true ) {
1030
+ Type subjectType = source->getStoredType ()->getCanonicalType ();
1031
+ path.path .push_back ({subjectType, conformingProto});
1032
+ return ;
1033
+ }
1034
+
1035
+ // The generic signature builder we're using for this protocol
1036
+ // wasn't built from its own requirement signature, so we can't
1037
+ // trust it. Make sure we have a requirement signature, then build
1038
+ // a new generic signature builder.
1039
+ // FIXME: It would be better if we could replace the canonical generic
1040
+ // signature builder with the rebuilt one.
1041
+ if (!requirementSignatureProto->isRequirementSignatureComputed ())
1042
+ requirementSignatureProto->computeRequirementSignature ();
1043
+ assert (requirementSignatureProto->isRequirementSignatureComputed ());
1044
+
1045
+ replacementBuilder.emplace (getASTContext ());
1046
+ replacementBuilder->addGenericSignature (
1047
+ requirementSignatureProto->getGenericSignature ());
1048
+ replacementBuilder->processDelayedRequirements ();
1018
1049
}
1019
1050
1020
1051
// Follow the rest of the path to derive the conformance into which
@@ -1047,9 +1078,12 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
1047
1078
return ;
1048
1079
}
1049
1080
1081
+ // Get the generic signature builder for the protocol.
1050
1082
// Get a generic signature for the protocol's signature.
1051
1083
auto inProtoSig = inProtocol->getGenericSignature ();
1052
- auto &inProtoSigBuilder = *inProtoSig->getGenericSignatureBuilder ();
1084
+ auto &inProtoSigBuilder =
1085
+ replacementBuilder ? *replacementBuilder
1086
+ : *inProtoSig->getGenericSignatureBuilder ();
1053
1087
1054
1088
// Retrieve the stored type, but erase all of the specific associated
1055
1089
// type declarations; we don't want any details of the enclosing context
@@ -1068,7 +1102,7 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
1068
1102
assert (conforms != equivClass->conformsTo .end ());
1069
1103
1070
1104
// Compute the root type, canonicalizing it w.r.t. the protocol context.
1071
- auto conformsSource = getBestCanonicalRequirementSource (conforms->second );
1105
+ auto conformsSource = getBestRequirementSource (conforms->second );
1072
1106
assert (conformsSource != source || !requirementSignatureProto);
1073
1107
Type localRootType = conformsSource->getRootType ();
1074
1108
localRootType = inProtoSig->getCanonicalTypeInContext (localRootType);
@@ -1116,7 +1150,7 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
1116
1150
};
1117
1151
1118
1152
// Canonicalize the root type.
1119
- auto source = getBestCanonicalRequirementSource (conforms->second );
1153
+ auto source = getBestRequirementSource (conforms->second );
1120
1154
Type rootType = source->getRootType ()->getCanonicalType (this );
1121
1155
1122
1156
// Build the path.
0 commit comments