34
34
#include " swift/Basic/Defer.h"
35
35
#include " swift/Basic/Statistic.h"
36
36
#include " llvm/ADT/GraphTraits.h"
37
+ #include " llvm/ADT/DenseMap.h"
37
38
#include " llvm/ADT/SetVector.h"
38
39
#include " llvm/ADT/SmallPtrSet.h"
39
40
#include " llvm/ADT/SmallString.h"
@@ -4889,12 +4890,8 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenTypeParameters(
4889
4890
auto T1 = OrigT1->getRepresentative ();
4890
4891
auto T2 = OrigT2->getRepresentative ();
4891
4892
4892
- // Decide which potential archetype is to be considered the representative.
4893
- // We prefer potential archetypes with lower nesting depths, because it
4894
- // prevents us from unnecessarily building deeply nested potential archetypes.
4895
- unsigned nestingDepth1 = T1->getNestingDepth ();
4896
- unsigned nestingDepth2 = T2->getNestingDepth ();
4897
- if (nestingDepth2 < nestingDepth1) {
4893
+ // Pick representative based on the canonical ordering of the type parameters.
4894
+ if (compareDependentTypes (depType2, depType1) < 0 ) {
4898
4895
std::swap (T1, T2);
4899
4896
std::swap (OrigT1, OrigT2);
4900
4897
std::swap (equivClass, equivClass2);
@@ -4906,6 +4903,8 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenTypeParameters(
4906
4903
equivClass = T1->getOrCreateEquivalenceClass (*this );
4907
4904
4908
4905
// Record this same-type constraint.
4906
+ // Let's keep type order in the new constraint the same as it's written
4907
+ // in source, which makes it much easier to diagnose later.
4909
4908
equivClass->sameTypeConstraints .push_back ({depType1, depType2, source});
4910
4909
4911
4910
// Determine the anchor types of the two equivalence classes.
@@ -6908,34 +6907,118 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
6908
6907
// connect all of the components, or else we wouldn't have an equivalence
6909
6908
// class.
6910
6909
if (intercomponentEdges.size () > numComponents - 1 ) {
6911
- std::vector<bool > connected (numComponents, false );
6912
- const auto &firstEdge = intercomponentEdges.front ();
6913
- for (const auto &edge : intercomponentEdges) {
6914
- // If both the source and target are already connected, this edge is
6915
- // not part of the spanning tree.
6916
- if (connected[edge.source ] && connected[edge.target ]) {
6917
- if (edge.constraint .source ->shouldDiagnoseRedundancy (true ) &&
6918
- firstEdge.constraint .source ->shouldDiagnoseRedundancy (false )) {
6919
- Diags.diagnose (edge.constraint .source ->getLoc (),
6920
- diag::redundant_same_type_constraint,
6921
- edge.constraint .getSubjectDependentType (
6922
- genericParams),
6923
- edge.constraint .value );
6924
-
6925
- Diags.diagnose (firstEdge.constraint .source ->getLoc (),
6926
- diag::previous_same_type_constraint,
6927
- firstEdge.constraint .source ->classifyDiagKind (),
6928
- firstEdge.constraint .getSubjectDependentType (
6929
- genericParams),
6930
- firstEdge.constraint .value );
6910
+ // First let's order all of the intercomponent edges
6911
+ // as written in source, this helps us to diagnose
6912
+ // all of the duplicate constraints in correct order.
6913
+ std::vector<IntercomponentEdge *> sourceOrderedEdges;
6914
+ for (auto &edge : intercomponentEdges)
6915
+ sourceOrderedEdges.push_back (&edge);
6916
+
6917
+ llvm::array_pod_sort (
6918
+ sourceOrderedEdges.begin (), sourceOrderedEdges.end (),
6919
+ [](IntercomponentEdge *const *a, IntercomponentEdge *const *b) -> int {
6920
+ auto &sourceMgr = (*a)->constraint .value ->getASTContext ().SourceMgr ;
6921
+
6922
+ auto locA = (*a)->constraint .source ->getLoc ();
6923
+ auto locB = (*b)->constraint .source ->getLoc ();
6924
+
6925
+ auto bufferA = sourceMgr.findBufferContainingLoc (locA);
6926
+ auto bufferB = sourceMgr.findBufferContainingLoc (locB);
6927
+
6928
+ if (bufferA != bufferB)
6929
+ return bufferA < bufferB ? -1 : 1 ;
6930
+
6931
+ auto offsetA = sourceMgr.getLocOffsetInBuffer (locA, bufferA);
6932
+ auto offsetB = sourceMgr.getLocOffsetInBuffer (locB, bufferB);
6933
+
6934
+ return offsetA < offsetB ? -1 : (offsetA == offsetB ? 0 : 1 );
6935
+ });
6936
+
6937
+ auto isDiagnosable = [](const IntercomponentEdge &edge, bool isPrimary) {
6938
+ return edge.constraint .source ->shouldDiagnoseRedundancy (isPrimary);
6939
+ };
6940
+
6941
+ using EquivClass = llvm::DenseMap<Type, unsigned >;
6942
+ llvm::DenseMap<Type, EquivClass> equivalences;
6943
+ // The idea here is to form an equivalence class per representative
6944
+ // (picked from each edge constraint in type parameter order) and
6945
+ // propagate all new equivalent types up the chain until duplicate
6946
+ // entry is found, that entry is going to point to previous
6947
+ // declaration and is going to mark current edge as a duplicate of
6948
+ // such entry.
6949
+ for (auto edgeIdx : indices (sourceOrderedEdges)) {
6950
+ const auto &edge = *sourceOrderedEdges[edgeIdx];
6951
+
6952
+ Type lhs = edge.constraint .getSubjectDependentType (genericParams);
6953
+ Type rhs = edge.constraint .value ;
6954
+
6955
+ // Make sure that representative for equivalence class is picked
6956
+ // in canonical type parameter order.
6957
+ if (compareDependentTypes (rhs, lhs) < 0 )
6958
+ std::swap (lhs, rhs);
6959
+
6960
+ // Index of the previous declaration of the same-type constraint
6961
+ // which current edge might be a duplicate of.
6962
+ Optional<unsigned > previousIndex;
6963
+
6964
+ bool isDuplicate = false ;
6965
+ auto &representative = equivalences[lhs];
6966
+ if (representative.insert ({rhs, edgeIdx}).second ) {
6967
+ // Since this is a new equivalence, and right-hand side might
6968
+ // be a representative of some other equivalence class,
6969
+ // its existing members have to be merged up.
6970
+ auto RHSEquivClass = equivalences.find (rhs);
6971
+ if (RHSEquivClass != equivalences.end ()) {
6972
+ auto &equivClass = RHSEquivClass->getSecond ();
6973
+ representative.insert (equivClass.begin (), equivClass.end ());
6931
6974
}
6932
6975
6933
- continue ;
6976
+ // If left-hand side is involved in any other equivalences
6977
+ // let's propagate new information up the chain.
6978
+ for (auto &e : equivalences) {
6979
+ auto &repr = e.first ;
6980
+ auto &equivClass = e.second ;
6981
+
6982
+ if (repr->isEqual (lhs) || !equivClass.count (lhs))
6983
+ continue ;
6984
+
6985
+ if (!equivClass.insert ({rhs, edgeIdx}).second ) {
6986
+ // Even if "previous" edge is not diagnosable we
6987
+ // still need to produce diagnostic about main duplicate.
6988
+ isDuplicate = true ;
6989
+
6990
+ auto prevIdx = equivClass[rhs];
6991
+ if (!isDiagnosable (intercomponentEdges[prevIdx],
6992
+ /* isPrimary=*/ false ))
6993
+ continue ;
6994
+
6995
+ // If there is a diagnosable duplicate equivalence,
6996
+ // it means that we've found our previous declaration.
6997
+ previousIndex = prevIdx;
6998
+ break ;
6999
+ }
7000
+ }
7001
+ } else {
7002
+ // Looks like this is a situation like T.A == T.B, ..., T.B == T.A
7003
+ previousIndex = representative[rhs];
7004
+ isDuplicate = true ;
6934
7005
}
6935
7006
6936
- // Put the source and target into the spanning tree.
6937
- connected[edge.source ] = true ;
6938
- connected[edge.target ] = true ;
7007
+ if (!isDuplicate || !isDiagnosable (edge, /* isPrimary=*/ true ))
7008
+ continue ;
7009
+
7010
+ Diags.diagnose (edge.constraint .source ->getLoc (),
7011
+ diag::redundant_same_type_constraint,
7012
+ edge.constraint .getSubjectDependentType (genericParams),
7013
+ edge.constraint .value );
7014
+
7015
+ if (previousIndex) {
7016
+ auto &prevEquiv = sourceOrderedEdges[*previousIndex]->constraint ;
7017
+ Diags.diagnose (
7018
+ prevEquiv.source ->getLoc (), diag::previous_same_type_constraint,
7019
+ prevEquiv.source ->classifyDiagKind (),
7020
+ prevEquiv.getSubjectDependentType (genericParams), prevEquiv.value );
7021
+ }
6939
7022
}
6940
7023
}
6941
7024
0 commit comments