1515#include " llvm/Support/raw_ostream.h"
1616#include < algorithm>
1717#include < vector>
18+ #include " PropertyMap.h"
1819#include " RewriteContext.h"
1920#include " RewriteLoop.h"
2021#include " RewriteSystem.h"
@@ -753,7 +754,9 @@ void RewriteSystem::freeze() {
753754}
754755
755756void RewriteSystem::computeConflictDiagnostics (
756- SmallVectorImpl<RequirementError> &errors, SourceLoc signatureLoc) {
757+ SmallVectorImpl<RequirementError> &errors, SourceLoc signatureLoc,
758+ const PropertyMap &propertyMap,
759+ TypeArrayView<GenericTypeParamType> genericParams) {
757760 for (auto pair : ConflictingRules) {
758761 auto *firstRule = &getRule (pair.first );
759762 auto *secondRule = &getRule (pair.second );
@@ -763,6 +766,48 @@ void RewriteSystem::computeConflictDiagnostics(
763766 if (!firstProperty || !secondProperty)
764767 continue ;
765768
769+ MutableTerm firstTerm (
770+ firstRule->getLHS ().begin (), firstRule->getLHS ().end () - 1 );
771+ MutableTerm secondTerm (
772+ secondRule->getLHS ().begin (), secondRule->getLHS ().end () - 1 );
773+
774+ auto firstSubject = propertyMap.getTypeForTerm (firstTerm, genericParams);
775+ auto secondSubject = propertyMap.getTypeForTerm (secondTerm, genericParams);
776+ assert (firstSubject && secondSubject);
777+
778+ // Record conflicting requirements on a type parameter, e.g.
779+ // conflicting superclass requirements:
780+ //
781+ // class C1 {}
782+ // class C2 {}
783+ // protocol P { associatedtype A: C1 }
784+ // func conflict<T: P>(_: T) where T.A: C2 {}
785+ if (firstProperty->getKind () == secondProperty->getKind () &&
786+ firstTerm.back ().getKind () != Symbol::Kind::Name &&
787+ firstSubject->isEqual (secondSubject)) {
788+ switch (firstProperty->getKind ()) {
789+ case Symbol::Kind::ConcreteType:
790+ errors.push_back (RequirementError::forConflictingRequirement (firstSubject,
791+ {RequirementKind::SameType, firstProperty->getConcreteType (),
792+ secondProperty->getConcreteType ()},
793+ signatureLoc));
794+ continue ;
795+
796+ case Symbol::Kind::Superclass:
797+ // FIXME: shoving the conflicting superclass types into a superclass
798+ // requiement is a little gross.
799+ errors.push_back (RequirementError::forConflictingRequirement (firstSubject,
800+ {RequirementKind::Superclass, firstProperty->getConcreteType (),
801+ secondProperty->getConcreteType ()},
802+ signatureLoc));
803+ continue ;
804+
805+ // FIXME: Conflicting layout requirements?
806+ default :
807+ continue ;
808+ }
809+ }
810+
766811 auto recordError = [&](Symbol subject, Symbol constraint) {
767812 auto subjectType = subject.getConcreteType ();
768813 switch (constraint.getKind ()) {
@@ -802,19 +847,6 @@ void RewriteSystem::computeConflictDiagnostics(
802847 recordError (*firstProperty, *secondProperty);
803848 } else if (secondProperty->getKind () == Symbol::Kind::ConcreteType) {
804849 recordError (*secondProperty, *firstProperty);
805- } else {
806- // FIXME: This can happen when there are conflicting requirements
807- // on a type parameter, e.g. conflicting superclass requirements:
808- //
809- // class C1 {}
810- // class C2 {}
811- // protocol P { associatedtype A: C1 }
812- // func conflict<T: P>(_: T) where T.A: C2 {}
813- //
814- // In this case, we want to compute the type `T.A` from
815- // its corresponding term. For this, we need the property map
816- // from the RequirementMachine.
817- continue ;
818850 }
819851 }
820852}
0 commit comments