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