@@ -124,6 +124,8 @@ STATISTIC(NumRewriteRhsSimplifiedToLhs,
124
124
" # of rewrite rule right-hand sides simplified to lhs (and removed)" );
125
125
STATISTIC (NumRewriteRulesRedundant,
126
126
" # of rewrite rules that are redundant (and removed)" );
127
+ STATISTIC (NumSignaturesRebuiltWithoutRedundantRequirements,
128
+ " # of generic signatures which had a concretized conformance requirement" );
127
129
128
130
namespace {
129
131
@@ -616,6 +618,11 @@ class GenericSignatureBuilder::ExplicitRequirement {
616
618
617
619
return true ;
618
620
}
621
+
622
+ friend bool operator !=(const ExplicitRequirement &lhs,
623
+ const ExplicitRequirement &rhs) {
624
+ return !(lhs == rhs);
625
+ }
619
626
};
620
627
621
628
namespace llvm {
@@ -690,8 +697,13 @@ struct GenericSignatureBuilder::Implementation {
690
697
// / Whether there were any errors.
691
698
bool HadAnyError = false ;
692
699
693
- // / The set of computed redundant explicit requirements.
694
- llvm::DenseSet<ExplicitRequirement> RedundantRequirements;
700
+ // / A mapping of redundant explicit requirements to the best root requirement
701
+ // / that implies them.
702
+ using RedundantRequirementMap =
703
+ llvm::DenseMap<ExplicitRequirement,
704
+ llvm::SmallDenseSet<ExplicitRequirement, 2 >>;
705
+
706
+ RedundantRequirementMap RedundantRequirements;
695
707
696
708
#ifndef NDEBUG
697
709
// / Whether we've already computed redundant requiremnts.
@@ -1865,7 +1877,6 @@ FloatingRequirementSource FloatingRequirementSource::asInferred(
1865
1877
}
1866
1878
1867
1879
bool FloatingRequirementSource::isRecursive (
1868
- Type rootType,
1869
1880
GenericSignatureBuilder &builder) const {
1870
1881
llvm::SmallSet<std::pair<CanType, ProtocolDecl *>, 32 > visitedAssocReqs;
1871
1882
for (auto storedSource = storage.dyn_cast <const RequirementSource *>();
@@ -3983,12 +3994,12 @@ auto GenericSignatureBuilder::resolve(UnresolvedType paOrT,
3983
3994
return ResolvedType (pa);
3984
3995
3985
3996
// Determine what kind of resolution we want.
3986
- Type type = paOrT.get <Type>();
3987
3997
ArchetypeResolutionKind resolutionKind =
3988
3998
ArchetypeResolutionKind::WellFormed;
3989
- if (!source.isExplicit () && source.isRecursive (type, *this ))
3999
+ if (!source.isExplicit () && source.isRecursive (*this ))
3990
4000
resolutionKind = ArchetypeResolutionKind::AlreadyKnown;
3991
4001
4002
+ Type type = paOrT.get <Type>();
3992
4003
return maybeResolveEquivalenceClass (type, resolutionKind,
3993
4004
/* wantExactPotentialArchetype=*/ true );
3994
4005
}
@@ -4636,7 +4647,7 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement(
4636
4647
unresolvedHandling);
4637
4648
}
4638
4649
4639
- // If the resolved subject is a type , there may be things we can infer (if it
4650
+ // If the resolved subject is concrete , there may be things we can infer (if it
4640
4651
// conditionally conforms to the protocol), and we can probably perform
4641
4652
// diagnostics here.
4642
4653
if (auto subjectType = resolvedSubject.getAsConcreteType ()) {
@@ -5625,8 +5636,8 @@ class RedundantRequirementGraph {
5625
5636
5626
5637
SmallVector<Vertex, 2 > vertices;
5627
5638
5628
- ComponentID nextComponent = 0 ;
5629
- VertexID nextIndex = 0 ;
5639
+ ComponentID componentCount = 0 ;
5640
+ VertexID vertexCount = 0 ;
5630
5641
5631
5642
SmallVector<VertexID, 2 > stack;
5632
5643
@@ -5785,11 +5796,11 @@ class RedundantRequirementGraph {
5785
5796
void strongConnect (VertexID v) {
5786
5797
// Set the depth index for v to the smallest unused index.
5787
5798
assert (vertices[v].index == Vertex::UndefinedIndex);
5788
- vertices[v].index = nextIndex ;
5799
+ vertices[v].index = vertexCount ;
5789
5800
assert (vertices[v].lowLink == Vertex::UndefinedIndex);
5790
- vertices[v].lowLink = nextIndex ;
5801
+ vertices[v].lowLink = vertexCount ;
5791
5802
5792
- nextIndex ++;
5803
+ vertexCount ++;
5793
5804
5794
5805
stack.push_back (v);
5795
5806
assert (!vertices[v].onStack );
@@ -5827,40 +5838,60 @@ class RedundantRequirementGraph {
5827
5838
vertices[w].onStack = false ;
5828
5839
assert (vertices[w].component == Vertex::UndefinedComponent);
5829
5840
5830
- vertices[w].component = nextComponent ;
5841
+ vertices[w].component = componentCount ;
5831
5842
} while (v != w);
5832
5843
5833
- nextComponent ++;
5844
+ componentCount ++;
5834
5845
}
5835
5846
}
5836
5847
5837
5848
public:
5849
+ using RedundantRequirementMap =
5850
+ llvm::DenseMap<ExplicitRequirement,
5851
+ llvm::SmallDenseSet<ExplicitRequirement, 2 >>;
5852
+
5838
5853
void computeRedundantRequirements (SourceManager &SM,
5839
- llvm::DenseSet<ExplicitRequirement> &redundant) {
5854
+ RedundantRequirementMap &redundant) {
5840
5855
// First, compute SCCs.
5841
5856
computeSCCs ();
5842
5857
5843
- // The number of edges from other connected components to this one.
5844
- SmallVector<unsigned , 2 > inboundComponentEdges;
5845
- inboundComponentEdges.resize (nextComponent);
5858
+ // The set of edges pointing to each connected component.
5859
+ SmallVector<SmallVector<ComponentID, 2 >, 2 > inboundComponentEdges;
5860
+ inboundComponentEdges.resize (componentCount);
5861
+
5862
+ // The set of edges originating from this connected component.
5863
+ SmallVector<SmallVector<ComponentID, 2 >, 2 > outboundComponentEdges;
5864
+ outboundComponentEdges.resize (componentCount);
5846
5865
5847
- // Visit all vertices and count inter-component edges.
5866
+ // Visit all vertices and build the adjacency sets for the connected
5867
+ // component graph.
5848
5868
for (const auto &vertex : vertices) {
5849
5869
assert (vertex.component != Vertex::UndefinedComponent);
5850
5870
for (auto successor : vertex.successors ) {
5851
5871
ComponentID otherComponent = vertices[successor].component ;
5852
- if (vertex.component != otherComponent)
5853
- ++inboundComponentEdges[otherComponent];
5872
+ if (vertex.component != otherComponent) {
5873
+ inboundComponentEdges[otherComponent].push_back (vertex.component );
5874
+ outboundComponentEdges[vertex.component ].push_back (otherComponent);
5875
+ }
5854
5876
}
5855
5877
}
5856
5878
5857
- // The best explicit requirement for each root SCC.
5879
+ auto isRootComponent = [&](ComponentID component) -> bool {
5880
+ return inboundComponentEdges[component].empty ();
5881
+ };
5882
+
5883
+ // The set of root components.
5884
+ llvm::SmallDenseSet<ComponentID, 2 > rootComponents;
5885
+
5886
+ // The best explicit requirement for each root component.
5858
5887
SmallVector<Optional<ExplicitRequirement>, 2 > bestExplicitReq;
5859
- bestExplicitReq.resize (nextComponent );
5888
+ bestExplicitReq.resize (componentCount );
5860
5889
5861
- // Visit all vertices and find the best requirement for each root SCC .
5890
+ // Visit all vertices and find the best requirement for each root component .
5862
5891
for (const auto &vertex : vertices) {
5863
- if (inboundComponentEdges[vertex.component ] == 0 ) {
5892
+ if (isRootComponent (vertex.component )) {
5893
+ rootComponents.insert (vertex.component );
5894
+
5864
5895
// If this vertex is part of a root SCC, see if the requirement is
5865
5896
// better than the one we have so far.
5866
5897
auto &best = bestExplicitReq[vertex.component ];
@@ -5869,26 +5900,61 @@ class RedundantRequirementGraph {
5869
5900
}
5870
5901
}
5871
5902
5872
- // Compute the set of redundant requirements.
5873
- for (const auto &vertex : vertices) {
5874
- if (inboundComponentEdges[vertex.component ] == 0 ) {
5875
- // We have a root SCC. This requirement is redundant unless
5876
- // it is the best requirement for this SCC.
5877
- auto best = bestExplicitReq[vertex.component ];
5878
- assert (best.hasValue () &&
5879
- " Did not record best requirement for root SCC?" );
5903
+ // The set of root components that each component is reachable from.
5904
+ SmallVector<llvm::SmallDenseSet<ComponentID, 2 >, 2 > reachableFromRoot;
5905
+ reachableFromRoot.resize (componentCount);
5880
5906
5881
- if (vertex.req == *best)
5882
- continue ;
5907
+ // Traverse the graph of connected components starting from the roots.
5908
+ for (auto rootComponent : rootComponents) {
5909
+ SmallVector<ComponentID, 2 > worklist;
5910
+
5911
+ auto addToWorklist = [&](ComponentID nextComponent) {
5912
+ if (!reachableFromRoot[nextComponent].count (rootComponent))
5913
+ worklist.push_back (nextComponent);
5914
+ };
5915
+
5916
+ addToWorklist (rootComponent);
5917
+
5918
+ while (!worklist.empty ()) {
5919
+ auto component = worklist.back ();
5920
+ worklist.pop_back ();
5921
+
5922
+ reachableFromRoot[component].insert (rootComponent);
5923
+
5924
+ for (auto nextComponent : outboundComponentEdges[component])
5925
+ addToWorklist (nextComponent);
5926
+ }
5927
+ }
5928
+
5929
+ // Compute the mapping of redundant requirements to the best root
5930
+ // requirement that implies them.
5931
+ for (const auto &vertex : vertices) {
5932
+ if (isRootComponent (vertex.component )) {
5933
+ // A root component is reachable from itself, and itself only.
5934
+ assert (reachableFromRoot[vertex.component ].size () == 1 );
5935
+ assert (reachableFromRoot[vertex.component ].count (vertex.component ) == 1 );
5883
5936
} else {
5884
- // We have a non-root SCC. This requirement is always
5885
- // redundant.
5886
5937
assert (!bestExplicitReq[vertex.component ].hasValue () &&
5887
5938
" Recorded best requirement for non-root SCC?" );
5888
5939
}
5889
5940
5890
- auto inserted = redundant.insert (vertex.req );
5891
- assert (inserted.second && " Saw the same vertex twice?" );
5941
+ // We have a non-root component. This requirement is always
5942
+ // redundant.
5943
+ auto reachableFromRootSet = reachableFromRoot[vertex.component ];
5944
+ assert (reachableFromRootSet.size () > 0 );
5945
+
5946
+ for (auto rootComponent : reachableFromRootSet) {
5947
+ assert (isRootComponent (rootComponent));
5948
+
5949
+ auto best = bestExplicitReq[rootComponent];
5950
+ assert (best.hasValue () &&
5951
+ " Did not record best requirement for root SCC?" );
5952
+
5953
+ assert (vertex.req != *best || vertex.component == rootComponent);
5954
+ if (vertex.req != *best) {
5955
+ redundant[vertex.req ].insert (*best);
5956
+ }
5957
+ }
5892
5958
}
5893
5959
}
5894
5960
@@ -8108,9 +8174,60 @@ static void checkGenericSignature(CanGenericSignature canSig,
8108
8174
}
8109
8175
#endif
8110
8176
8177
+ bool GenericSignatureBuilder::hasExplicitConformancesImpliedByConcrete () const {
8178
+ for (auto pair : Impl->RedundantRequirements ) {
8179
+ if (pair.first .getKind () != RequirementKind::Conformance)
8180
+ continue ;
8181
+
8182
+ for (auto impliedByReq : pair.second ) {
8183
+ if (impliedByReq.getKind () == RequirementKind::Superclass)
8184
+ return true ;
8185
+
8186
+ if (impliedByReq.getKind () == RequirementKind::SameType)
8187
+ return true ;
8188
+ }
8189
+ }
8190
+
8191
+ return false ;
8192
+ }
8193
+
8194
+ static Type stripBoundDependentMemberTypes (Type t) {
8195
+ if (auto *depMemTy = t->getAs <DependentMemberType>()) {
8196
+ return DependentMemberType::get (
8197
+ stripBoundDependentMemberTypes (depMemTy->getBase ()),
8198
+ depMemTy->getName ());
8199
+ }
8200
+
8201
+ return t;
8202
+ }
8203
+
8204
+ static Requirement stripBoundDependentMemberTypes (Requirement req) {
8205
+ auto subjectType = stripBoundDependentMemberTypes (req.getFirstType ());
8206
+
8207
+ switch (req.getKind ()) {
8208
+ case RequirementKind::Conformance:
8209
+ return Requirement (RequirementKind::Conformance, subjectType,
8210
+ req.getSecondType ());
8211
+
8212
+ case RequirementKind::Superclass:
8213
+ case RequirementKind::SameType:
8214
+ return Requirement (req.getKind (), subjectType,
8215
+ req.getSecondType ().transform ([](Type t) {
8216
+ return stripBoundDependentMemberTypes (t);
8217
+ }));
8218
+
8219
+ case RequirementKind::Layout:
8220
+ return Requirement (RequirementKind::Conformance, subjectType,
8221
+ req.getLayoutConstraint ());
8222
+ }
8223
+
8224
+ llvm_unreachable (" Bad requirement kind" );
8225
+ }
8226
+
8111
8227
GenericSignature GenericSignatureBuilder::computeGenericSignature (
8112
8228
bool allowConcreteGenericParams,
8113
- bool allowBuilderToMove) && {
8229
+ bool buildingRequirementSignature,
8230
+ bool rebuildingWithoutRedundantConformances) && {
8114
8231
// Finalize the builder, producing any necessary diagnostics.
8115
8232
finalize (getGenericParams (), allowConcreteGenericParams);
8116
8233
@@ -8121,6 +8238,43 @@ GenericSignature GenericSignatureBuilder::computeGenericSignature(
8121
8238
// Form the generic signature.
8122
8239
auto sig = GenericSignature::get (getGenericParams (), requirements);
8123
8240
8241
+ // If any of our explicit conformance requirements were implied by
8242
+ // superclass or concrete same-type requirements, we have to build the
8243
+ // signature again, since dropping the redundant conformance requirements
8244
+ // changes the canonical type computation.
8245
+ //
8246
+ // However, if we already diagnosed an error, don't do this, because
8247
+ // we might end up emitting duplicate diagnostics.
8248
+ //
8249
+ // Also, don't do this when building a requirement signature.
8250
+ if (!buildingRequirementSignature &&
8251
+ !Impl->HadAnyError &&
8252
+ hasExplicitConformancesImpliedByConcrete ()) {
8253
+ NumSignaturesRebuiltWithoutRedundantRequirements++;
8254
+
8255
+ if (rebuildingWithoutRedundantConformances) {
8256
+ llvm::errs () << " Rebuilt signature still has "
8257
+ << " redundant conformance requirements: " ;
8258
+ llvm::errs () << sig << " \n " ;
8259
+ abort ();
8260
+ }
8261
+
8262
+ GenericSignatureBuilder newBuilder (Context);
8263
+
8264
+ for (auto param : sig->getGenericParams ())
8265
+ newBuilder.addGenericParameter (param);
8266
+
8267
+ for (auto &req : sig->getRequirements ()) {
8268
+ newBuilder.addRequirement (stripBoundDependentMemberTypes (req),
8269
+ FloatingRequirementSource::forAbstract (), nullptr );
8270
+ }
8271
+
8272
+ return std::move (newBuilder).computeGenericSignature (
8273
+ allowConcreteGenericParams,
8274
+ buildingRequirementSignature,
8275
+ /* rebuildingWithoutRedundantConformances=*/ true );
8276
+ }
8277
+
8124
8278
#ifndef NDEBUG
8125
8279
if (!Impl->HadAnyError ) {
8126
8280
checkGenericSignature (sig.getCanonicalSignature (), *this );
@@ -8132,7 +8286,9 @@ GenericSignature GenericSignatureBuilder::computeGenericSignature(
8132
8286
// will produce the same thing.
8133
8287
//
8134
8288
// We cannot do this when there were errors.
8135
- if (allowBuilderToMove && !Impl->HadAnyError ) {
8289
+ //
8290
+ // Also, we cannot do this when building a requirement signature.
8291
+ if (!buildingRequirementSignature && !Impl->HadAnyError ) {
8136
8292
// Register this generic signature builder as the canonical builder for the
8137
8293
// given signature.
8138
8294
Context.registerGenericSignatureBuilder (sig, std::move (*this ));
0 commit comments