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