@@ -5594,6 +5594,29 @@ static void expandSameTypeConstraints(GenericSignatureBuilder &builder,
5594
5594
}
5595
5595
}
5596
5596
5597
+ static bool compareSourceLocs (SourceManager &SM, SourceLoc lhsLoc, SourceLoc rhsLoc) {
5598
+ if (lhsLoc.isValid () != rhsLoc.isValid ())
5599
+ return lhsLoc.isValid ();
5600
+
5601
+ if (lhsLoc.isValid () && rhsLoc.isValid ()) {
5602
+ unsigned lhsBuffer = SM.findBufferContainingLoc (lhsLoc);
5603
+ unsigned rhsBuffer = SM.findBufferContainingLoc (rhsLoc);
5604
+
5605
+ // If the buffers are the same, use source location ordering.
5606
+ if (lhsBuffer == rhsBuffer) {
5607
+ if (SM.isBeforeInBuffer (lhsLoc, rhsLoc))
5608
+ return true ;
5609
+ } else {
5610
+ // Otherwise, order by buffer identifier.
5611
+ if (SM.getIdentifierForBuffer (lhsBuffer)
5612
+ .compare (SM.getIdentifierForBuffer (lhsBuffer)))
5613
+ return true ;
5614
+ }
5615
+ }
5616
+
5617
+ return false ;
5618
+ }
5619
+
5597
5620
// / A directed graph where the vertices are explicit requirement sources and
5598
5621
// / an edge (v, w) records that the explicit source v implies the explicit
5599
5622
// / source w.
@@ -5992,29 +6015,10 @@ class RedundantRequirementGraph {
5992
6015
if (cmpTypes != 0 )
5993
6016
return cmpTypes < 0 ;
5994
6017
5995
- // Prefer source-location-based over abstract.
5996
6018
auto existingLoc = existingSource->getLoc ();
5997
6019
auto currentLoc = currentSource->getLoc ();
5998
- if (existingLoc.isValid () != currentLoc.isValid ())
5999
- return currentLoc.isValid ();
6000
-
6001
- if (existingLoc.isValid () && currentLoc.isValid ()) {
6002
- unsigned existingBuffer = SM.findBufferContainingLoc (existingLoc);
6003
- unsigned currentBuffer = SM.findBufferContainingLoc (currentLoc);
6004
6020
6005
- // If the buffers are the same, use source location ordering.
6006
- if (existingBuffer == currentBuffer) {
6007
- if (SM.isBeforeInBuffer (currentLoc, existingLoc))
6008
- return true ;
6009
- } else {
6010
- // Otherwise, order by buffer identifier.
6011
- if (SM.getIdentifierForBuffer (currentBuffer)
6012
- .compare (SM.getIdentifierForBuffer (existingBuffer)))
6013
- return true ;
6014
- }
6015
- }
6016
-
6017
- return true ;
6021
+ return compareSourceLocs (SM, currentLoc, existingLoc);
6018
6022
}
6019
6023
6020
6024
public:
@@ -6226,6 +6230,7 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar
6226
6230
processDelayedRequirements ();
6227
6231
6228
6232
computeRedundantRequirements ();
6233
+ diagnoseRedundantRequirements ();
6229
6234
6230
6235
assert (!Impl->finalized && " Already finalized builder" );
6231
6236
#ifndef NDEBUG
@@ -6864,41 +6869,95 @@ void GenericSignatureBuilder::checkConformanceConstraints(
6864
6869
6865
6870
// Remove any self-derived constraints.
6866
6871
removeSelfDerived (*this , entry.second , entry.first );
6872
+ }
6873
+ }
6867
6874
6868
- checkConstraintList<ProtocolDecl *, ProtocolDecl *>(
6869
- genericParams, entry.second , RequirementKind::Conformance,
6870
- [](const Constraint<ProtocolDecl *> &constraint) {
6871
- return true ;
6872
- },
6873
- [&](const Constraint<ProtocolDecl *> &constraint) {
6874
- auto proto = constraint.value ;
6875
- assert (proto == entry.first && " Mixed up protocol constraints" );
6875
+ void GenericSignatureBuilder::diagnoseRedundantRequirements () const {
6876
+ SmallVector<ExplicitRequirement, 2 > redundantRequirements;
6877
+
6878
+ for (auto pair : Impl->RedundantRequirements ) {
6879
+ auto *source = pair.first .getSource ();
6880
+
6881
+ // Don't diagnose anything without a source location.
6882
+ if (source->getLoc ().isInvalid ())
6883
+ continue ;
6884
+
6885
+ // Don't diagnose redundant inferred requirements.
6886
+ if (source->isInferredRequirement ())
6887
+ continue ;
6888
+
6889
+ // Don't diagnose explicit requirements that are implied by
6890
+ // inferred requirements.
6891
+ if (llvm::all_of (pair.second ,
6892
+ [&](const ExplicitRequirement &otherReq) {
6893
+ return otherReq.getSource ()->isInferredRequirement ();
6894
+ }))
6895
+ continue ;
6876
6896
6877
- // If this conformance requirement recursively makes a protocol
6878
- // conform to itself, don't complain here.
6879
- auto source = constraint.source ;
6897
+ redundantRequirements.push_back (pair.first );
6898
+ }
6899
+
6900
+ auto &SM = Context.SourceMgr ;
6901
+
6902
+ std::sort (redundantRequirements.begin (), redundantRequirements.end (),
6903
+ [&](ExplicitRequirement lhs, ExplicitRequirement rhs) {
6904
+ return compareSourceLocs (SM,
6905
+ lhs.getSource ()->getLoc (),
6906
+ rhs.getSource ()->getLoc ());
6907
+ });
6908
+
6909
+ for (const auto &req : redundantRequirements) {
6910
+ auto *source = req.getSource ();
6911
+ auto loc = source->getLoc ();
6912
+ assert (loc.isValid ());
6913
+
6914
+ auto subjectType = getSugaredDependentType (source->getStoredType (),
6915
+ getGenericParams ());
6916
+
6917
+ switch (req.getKind ()) {
6918
+ case RequirementKind::Conformance: {
6919
+ auto *proto = req.getRHS ().get <ProtocolDecl *>();
6920
+
6921
+ // If this conformance requirement recursively makes a protocol
6922
+ // conform to itself, don't complain here, because we diagnose
6923
+ // the circular inheritance elsewhere.
6924
+ {
6880
6925
auto rootSource = source->getRoot ();
6881
- if (rootSource->kind == RequirementSource::RequirementSignatureSelf &&
6882
- source != rootSource &&
6883
- proto == rootSource->getProtocolDecl () &&
6884
- areInSameEquivalenceClass (rootSource->getRootType (),
6885
- source->getAffectedType ())) {
6886
- return ConstraintRelation::Unrelated;
6926
+ if (proto == rootSource->getProtocolDecl () &&
6927
+ rootSource->kind == RequirementSource::RequirementSignatureSelf &&
6928
+ rootSource->getRootType ()->isEqual (source->getAffectedType ())) {
6929
+ break ;
6887
6930
}
6931
+ }
6888
6932
6889
- // If this is a redundantly inherited Objective-C protocol, treat it
6890
- // as "unrelated" to silence the warning about the redundant
6891
- // conformance.
6892
- if (isRedundantlyInheritableObjCProtocol (proto, constraint. source ))
6893
- return ConstraintRelation::Unrelated ;
6933
+ // If this is a redundantly inherited Objective-C protocol, treat it
6934
+ // as "unrelated" to silence the warning about the redundant
6935
+ // conformance.
6936
+ if (isRedundantlyInheritableObjCProtocol (proto, source))
6937
+ break ;
6894
6938
6895
- return ConstraintRelation::Redundant;
6896
- },
6897
- None,
6898
- diag::redundant_conformance_constraint,
6899
- diag::redundant_conformance_here,
6900
- [](ProtocolDecl *proto) { return proto; },
6901
- /* removeSelfDerived=*/ false );
6939
+ Context.Diags .diagnose (loc, diag::redundant_conformance_constraint,
6940
+ subjectType, proto);
6941
+
6942
+ for (auto otherReq : Impl->RedundantRequirements [req]) {
6943
+ auto *otherSource = otherReq.getSource ();
6944
+ auto otherLoc = otherSource->getLoc ();
6945
+ if (otherLoc.isInvalid ())
6946
+ continue ;
6947
+
6948
+ Context.Diags .diagnose (otherLoc, diag::redundant_conformance_here,
6949
+ 1 , subjectType, proto);
6950
+ }
6951
+
6952
+ break ;
6953
+ }
6954
+
6955
+ case RequirementKind::Superclass:
6956
+ case RequirementKind::Layout:
6957
+ case RequirementKind::SameType:
6958
+ // TODO
6959
+ break ;
6960
+ }
6902
6961
}
6903
6962
}
6904
6963
0 commit comments