@@ -5875,7 +5875,7 @@ void GenericSignatureBuilder::getBaseRequirements(
5875
5875
GenericSignatureBuilder::GetKindAndRHS getKindAndRHS,
5876
5876
const RequirementSource *source,
5877
5877
const ProtocolDecl *requirementSignatureSelfProto,
5878
- ASTContext &ctx, SmallVectorImpl<ExplicitRequirement> &result) {
5878
+ SmallVectorImpl<ExplicitRequirement> &result) {
5879
5879
// If we're building a generic signature, the base requirement is
5880
5880
// built from the root of the path.
5881
5881
if (source->parent == nullptr ) {
@@ -5900,14 +5900,44 @@ void GenericSignatureBuilder::getBaseRequirements(
5900
5900
}
5901
5901
5902
5902
getBaseRequirements (
5903
- [&]() {
5904
- return ExplicitRequirement::getKindAndRHS (source, ctx);
5905
- },
5906
- source->parent , requirementSignatureSelfProto, ctx, result);
5903
+ [&]() { return ExplicitRequirement::getKindAndRHS (source, Context); },
5904
+ source->parent , requirementSignatureSelfProto, result);
5905
+ }
5906
+
5907
+ Optional<ExplicitRequirement>
5908
+ GenericSignatureBuilder::isValidRequirementDerivationPath (
5909
+ llvm::SmallDenseSet<ExplicitRequirement, 4 > &visited,
5910
+ RequirementKind otherKind,
5911
+ const RequirementSource *otherSource,
5912
+ RequirementRHS otherRHS,
5913
+ const ProtocolDecl *requirementSignatureSelfProto) {
5914
+
5915
+ SmallVector<ExplicitRequirement, 2 > result;
5916
+ getBaseRequirements (
5917
+ [&]() { return std::make_pair (otherKind, otherRHS); },
5918
+ otherSource, requirementSignatureSelfProto, result);
5919
+ assert (result.size () > 0 );
5920
+
5921
+ for (const auto &otherReq : result) {
5922
+ // Don't consider paths that are based on the requirement
5923
+ // itself; such a path doesn't "prove" this requirement,
5924
+ // since if we drop the requirement the path is no longer
5925
+ // valid.
5926
+ if (visited.count (otherReq))
5927
+ return None;
5928
+
5929
+ // Don't consider paths based on requirements that are already
5930
+ // known to be redundant either, since those paths become
5931
+ // invalid once redundant requirements are dropped.
5932
+ if (isRedundantExplicitRequirement (otherReq))
5933
+ return None;
5934
+ }
5935
+
5936
+ return result.front ();
5907
5937
}
5908
5938
5909
5939
template <typename T, typename Filter>
5910
- void GenericSignatureBuilder::checkRequirementRedundancy (
5940
+ void GenericSignatureBuilder::checkIfRequirementCanBeDerived (
5911
5941
const ExplicitRequirement &req,
5912
5942
const std::vector<Constraint<T>> &constraints,
5913
5943
const ProtocolDecl *requirementSignatureSelfProto,
@@ -5918,34 +5948,18 @@ void GenericSignatureBuilder::checkRequirementRedundancy(
5918
5948
if (filter (constraint))
5919
5949
continue ;
5920
5950
5921
- SmallVector<ExplicitRequirement, 2 > result;
5922
- getBaseRequirements (
5923
- [&]() {
5924
- return std::make_pair (req.getKind (), constraint.value );
5925
- },
5926
- constraint.source , requirementSignatureSelfProto, Context, result);
5927
- assert (result.size () > 0 );
5928
-
5929
- bool anyWereRedundant =
5930
- llvm::any_of (result, [&](const ExplicitRequirement &otherReq) {
5931
- // Don't consider paths that are based on the requirement
5932
- // itself; such a path doesn't "prove" this requirement,
5933
- // since if we drop the requirement the path is no longer
5934
- // valid.
5935
- if (req == otherReq)
5936
- return true ;
5937
-
5938
- // Don't consider paths based on requirements that are already
5939
- // known to be redundant either, since those paths become
5940
- // invalid once redundant requirements are dropped.
5941
- return isRedundantExplicitRequirement (otherReq);
5942
- });
5943
-
5944
5951
// If this requirement can be derived from a set of
5945
5952
// non-redundant base requirements, then this requirement
5946
5953
// is redundant.
5947
- if (!anyWereRedundant) {
5948
- Impl->RedundantRequirements [req].insert (result.front ());
5954
+ llvm::SmallDenseSet<ExplicitRequirement, 4 > visited;
5955
+ visited.insert (req);
5956
+
5957
+ if (auto representative = isValidRequirementDerivationPath (
5958
+ visited, req.getKind (),
5959
+ constraint.source ,
5960
+ constraint.value ,
5961
+ requirementSignatureSelfProto)) {
5962
+ Impl->RedundantRequirements [req].insert (*representative);
5949
5963
}
5950
5964
}
5951
5965
}
@@ -6006,7 +6020,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
6006
6020
auto found = equivClass->conformsTo .find (proto);
6007
6021
assert (found != equivClass->conformsTo .end ());
6008
6022
6009
- checkRequirementRedundancy (
6023
+ checkIfRequirementCanBeDerived (
6010
6024
req, found->second ,
6011
6025
requirementSignatureSelfProto,
6012
6026
[&](const Constraint<ProtocolDecl *> &constraint) {
@@ -6041,7 +6055,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
6041
6055
// requirement that implies 'T : D'.
6042
6056
Impl->ConflictingRequirements [req] = resolvedSuperclass;
6043
6057
6044
- checkRequirementRedundancy (
6058
+ checkIfRequirementCanBeDerived (
6045
6059
req, equivClass->superclassConstraints ,
6046
6060
requirementSignatureSelfProto,
6047
6061
[&](const Constraint<Type> &constraint) {
@@ -6062,7 +6076,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
6062
6076
// This means that 'T : C' is made redundant by any
6063
6077
// requirement that implies 'T : B', such that 'C' is a
6064
6078
// superclass of 'B'.
6065
- checkRequirementRedundancy (
6079
+ checkIfRequirementCanBeDerived (
6066
6080
req, equivClass->superclassConstraints ,
6067
6081
requirementSignatureSelfProto,
6068
6082
[&](const Constraint<Type> &constraint) {
@@ -6081,7 +6095,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
6081
6095
// requirement 'T == D'.
6082
6096
if (resolvedSuperclass->isExactSuperclassOf (resolvedConcreteType)) {
6083
6097
// 'C' is a superclass of 'D', so 'T : C' is redundant.
6084
- checkRequirementRedundancy (
6098
+ checkIfRequirementCanBeDerived (
6085
6099
req, equivClass->concreteTypeConstraints ,
6086
6100
requirementSignatureSelfProto,
6087
6101
[&](const Constraint<Type> &constraint) {
@@ -6119,7 +6133,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
6119
6133
// requirement that implies 'T : L2'.
6120
6134
Impl->ConflictingRequirements [req] = equivClass->layout ;
6121
6135
6122
- checkRequirementRedundancy (
6136
+ checkIfRequirementCanBeDerived (
6123
6137
req, equivClass->layoutConstraints ,
6124
6138
requirementSignatureSelfProto,
6125
6139
[&](const Constraint<LayoutConstraint> &constraint) {
@@ -6137,7 +6151,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
6137
6151
//
6138
6152
// This means that 'T : L1' is made redundant by any
6139
6153
// requirement that implies 'T : L1'.
6140
- checkRequirementRedundancy (
6154
+ checkIfRequirementCanBeDerived (
6141
6155
req, equivClass->layoutConstraints ,
6142
6156
requirementSignatureSelfProto,
6143
6157
[&](const Constraint<LayoutConstraint> &constraint) {
@@ -6156,7 +6170,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
6156
6170
layout)) {
6157
6171
Impl->ExplicitConformancesImpliedByConcrete .insert (req);
6158
6172
6159
- checkRequirementRedundancy (
6173
+ checkIfRequirementCanBeDerived (
6160
6174
req, equivClass->concreteTypeConstraints ,
6161
6175
requirementSignatureSelfProto,
6162
6176
[&](const Constraint<Type> &constraint) {
@@ -6185,7 +6199,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
6185
6199
// This means that 'T : L1' is made redundant by any
6186
6200
// requirement that implies 'T : L3', where L3 is
6187
6201
// mergeable with L1.
6188
- checkRequirementRedundancy (
6202
+ checkIfRequirementCanBeDerived (
6189
6203
req, equivClass->layoutConstraints ,
6190
6204
requirementSignatureSelfProto,
6191
6205
[&](const Constraint<LayoutConstraint> &constraint) {
@@ -6204,7 +6218,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
6204
6218
if (typeImpliesLayoutConstraint (resolvedConcreteType, layout)) {
6205
6219
Impl->ExplicitConformancesImpliedByConcrete .insert (req);
6206
6220
6207
- checkRequirementRedundancy (
6221
+ checkIfRequirementCanBeDerived (
6208
6222
req, equivClass->concreteTypeConstraints ,
6209
6223
requirementSignatureSelfProto,
6210
6224
[&](const Constraint<Type> &constraint) {
@@ -6993,15 +7007,18 @@ void GenericSignatureBuilder::diagnoseConflictingConcreteTypeRequirements(
6993
7007
SmallVector<ExplicitRequirement, 2 > result;
6994
7008
getBaseRequirements (
6995
7009
[&]() {
6996
- return std::make_pair (RequirementKind::SameType, constraint.value );
7010
+ return std::make_pair (RequirementKind::SameType,
7011
+ constraint.value );
6997
7012
},
6998
- constraint.source , requirementSignatureSelfProto, Context, result);
7013
+ constraint.source , requirementSignatureSelfProto, result);
6999
7014
7000
- return
7001
- !llvm::any_of (result, [&](const ExplicitRequirement &otherReq) {
7002
- return isRedundantExplicitRequirement (otherReq);
7003
- });
7004
- });
7015
+ for (const auto &otherReq : result) {
7016
+ if (isRedundantExplicitRequirement (otherReq))
7017
+ return false ;
7018
+ }
7019
+
7020
+ return true ;
7021
+ });
7005
7022
7006
7023
assert (foundConcreteRequirement != equivClass->concreteTypeConstraints .end ());
7007
7024
0 commit comments