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