@@ -5594,6 +5594,29 @@ static void expandSameTypeConstraints(GenericSignatureBuilder &builder,
55945594 }
55955595}
55965596
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+
55975620// / A directed graph where the vertices are explicit requirement sources and
55985621// / an edge (v, w) records that the explicit source v implies the explicit
55995622// / source w.
@@ -5992,29 +6015,10 @@ class RedundantRequirementGraph {
59926015 if (cmpTypes != 0 )
59936016 return cmpTypes < 0 ;
59946017
5995- // Prefer source-location-based over abstract.
59966018 auto existingLoc = existingSource->getLoc ();
59976019 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);
60046020
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);
60186022 }
60196023
60206024public:
@@ -6226,6 +6230,7 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar
62266230 processDelayedRequirements ();
62276231
62286232 computeRedundantRequirements ();
6233+ diagnoseRedundantRequirements ();
62296234
62306235 assert (!Impl->finalized && " Already finalized builder" );
62316236#ifndef NDEBUG
@@ -6864,41 +6869,95 @@ void GenericSignatureBuilder::checkConformanceConstraints(
68646869
68656870 // Remove any self-derived constraints.
68666871 removeSelfDerived (*this , entry.second , entry.first );
6872+ }
6873+ }
68676874
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 ;
68766896
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+ {
68806925 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 ;
68876930 }
6931+ }
68886932
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 ;
68946938
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+ }
69026961 }
69036962}
69046963
0 commit comments