@@ -5875,7 +5875,7 @@ void GenericSignatureBuilder::getBaseRequirements(
58755875 GenericSignatureBuilder::GetKindAndRHS getKindAndRHS,
58765876 const RequirementSource *source,
58775877 const ProtocolDecl *requirementSignatureSelfProto,
5878- ASTContext &ctx, SmallVectorImpl<ExplicitRequirement> &result) {
5878+ SmallVectorImpl<ExplicitRequirement> &result) {
58795879 // If we're building a generic signature, the base requirement is
58805880 // built from the root of the path.
58815881 if (source->parent == nullptr ) {
@@ -5900,14 +5900,44 @@ void GenericSignatureBuilder::getBaseRequirements(
59005900 }
59015901
59025902 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 ();
59075937}
59085938
59095939template <typename T, typename Filter>
5910- void GenericSignatureBuilder::checkRequirementRedundancy (
5940+ void GenericSignatureBuilder::checkIfRequirementCanBeDerived (
59115941 const ExplicitRequirement &req,
59125942 const std::vector<Constraint<T>> &constraints,
59135943 const ProtocolDecl *requirementSignatureSelfProto,
@@ -5918,34 +5948,18 @@ void GenericSignatureBuilder::checkRequirementRedundancy(
59185948 if (filter (constraint))
59195949 continue ;
59205950
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-
59445951 // If this requirement can be derived from a set of
59455952 // non-redundant base requirements, then this requirement
59465953 // 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);
59495963 }
59505964 }
59515965}
@@ -6006,7 +6020,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
60066020 auto found = equivClass->conformsTo .find (proto);
60076021 assert (found != equivClass->conformsTo .end ());
60086022
6009- checkRequirementRedundancy (
6023+ checkIfRequirementCanBeDerived (
60106024 req, found->second ,
60116025 requirementSignatureSelfProto,
60126026 [&](const Constraint<ProtocolDecl *> &constraint) {
@@ -6041,7 +6055,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
60416055 // requirement that implies 'T : D'.
60426056 Impl->ConflictingRequirements [req] = resolvedSuperclass;
60436057
6044- checkRequirementRedundancy (
6058+ checkIfRequirementCanBeDerived (
60456059 req, equivClass->superclassConstraints ,
60466060 requirementSignatureSelfProto,
60476061 [&](const Constraint<Type> &constraint) {
@@ -6062,7 +6076,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
60626076 // This means that 'T : C' is made redundant by any
60636077 // requirement that implies 'T : B', such that 'C' is a
60646078 // superclass of 'B'.
6065- checkRequirementRedundancy (
6079+ checkIfRequirementCanBeDerived (
60666080 req, equivClass->superclassConstraints ,
60676081 requirementSignatureSelfProto,
60686082 [&](const Constraint<Type> &constraint) {
@@ -6081,7 +6095,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
60816095 // requirement 'T == D'.
60826096 if (resolvedSuperclass->isExactSuperclassOf (resolvedConcreteType)) {
60836097 // 'C' is a superclass of 'D', so 'T : C' is redundant.
6084- checkRequirementRedundancy (
6098+ checkIfRequirementCanBeDerived (
60856099 req, equivClass->concreteTypeConstraints ,
60866100 requirementSignatureSelfProto,
60876101 [&](const Constraint<Type> &constraint) {
@@ -6119,7 +6133,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
61196133 // requirement that implies 'T : L2'.
61206134 Impl->ConflictingRequirements [req] = equivClass->layout ;
61216135
6122- checkRequirementRedundancy (
6136+ checkIfRequirementCanBeDerived (
61236137 req, equivClass->layoutConstraints ,
61246138 requirementSignatureSelfProto,
61256139 [&](const Constraint<LayoutConstraint> &constraint) {
@@ -6137,7 +6151,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
61376151 //
61386152 // This means that 'T : L1' is made redundant by any
61396153 // requirement that implies 'T : L1'.
6140- checkRequirementRedundancy (
6154+ checkIfRequirementCanBeDerived (
61416155 req, equivClass->layoutConstraints ,
61426156 requirementSignatureSelfProto,
61436157 [&](const Constraint<LayoutConstraint> &constraint) {
@@ -6156,7 +6170,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
61566170 layout)) {
61576171 Impl->ExplicitConformancesImpliedByConcrete .insert (req);
61586172
6159- checkRequirementRedundancy (
6173+ checkIfRequirementCanBeDerived (
61606174 req, equivClass->concreteTypeConstraints ,
61616175 requirementSignatureSelfProto,
61626176 [&](const Constraint<Type> &constraint) {
@@ -6185,7 +6199,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
61856199 // This means that 'T : L1' is made redundant by any
61866200 // requirement that implies 'T : L3', where L3 is
61876201 // mergeable with L1.
6188- checkRequirementRedundancy (
6202+ checkIfRequirementCanBeDerived (
61896203 req, equivClass->layoutConstraints ,
61906204 requirementSignatureSelfProto,
61916205 [&](const Constraint<LayoutConstraint> &constraint) {
@@ -6204,7 +6218,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
62046218 if (typeImpliesLayoutConstraint (resolvedConcreteType, layout)) {
62056219 Impl->ExplicitConformancesImpliedByConcrete .insert (req);
62066220
6207- checkRequirementRedundancy (
6221+ checkIfRequirementCanBeDerived (
62086222 req, equivClass->concreteTypeConstraints ,
62096223 requirementSignatureSelfProto,
62106224 [&](const Constraint<Type> &constraint) {
@@ -6993,15 +7007,18 @@ void GenericSignatureBuilder::diagnoseConflictingConcreteTypeRequirements(
69937007 SmallVector<ExplicitRequirement, 2 > result;
69947008 getBaseRequirements (
69957009 [&]() {
6996- return std::make_pair (RequirementKind::SameType, constraint.value );
7010+ return std::make_pair (RequirementKind::SameType,
7011+ constraint.value );
69977012 },
6998- constraint.source , requirementSignatureSelfProto, Context, result);
7013+ constraint.source , requirementSignatureSelfProto, result);
69997014
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+ });
70057022
70067023 assert (foundConcreteRequirement != equivClass->concreteTypeConstraints .end ());
70077024
0 commit comments