|
15 | 15 | #include "llvm/Support/raw_ostream.h" |
16 | 16 | #include <algorithm> |
17 | 17 | #include <vector> |
| 18 | +#include "PropertyMap.h" |
18 | 19 | #include "RewriteContext.h" |
19 | 20 | #include "RewriteLoop.h" |
20 | 21 | #include "RewriteSystem.h" |
@@ -752,6 +753,76 @@ void RewriteSystem::freeze() { |
752 | 753 | ConflictingRules.clear(); |
753 | 754 | } |
754 | 755 |
|
| 756 | +static Optional<Requirement> |
| 757 | +getRequirementForDiagnostics(Type subject, Symbol property, |
| 758 | + const PropertyMap &map, |
| 759 | + TypeArrayView<GenericTypeParamType> genericParams, |
| 760 | + const MutableTerm &prefix) { |
| 761 | + switch (property.getKind()) { |
| 762 | + case Symbol::Kind::ConcreteType: { |
| 763 | + auto concreteType = map.getTypeFromSubstitutionSchema( |
| 764 | + property.getConcreteType(), property.getSubstitutions(), |
| 765 | + genericParams, prefix); |
| 766 | + return Requirement(RequirementKind::SameType, subject, concreteType); |
| 767 | + } |
| 768 | + |
| 769 | + case Symbol::Kind::Superclass: { |
| 770 | + auto concreteType = map.getTypeFromSubstitutionSchema( |
| 771 | + property.getConcreteType(), property.getSubstitutions(), |
| 772 | + genericParams, prefix); |
| 773 | + return Requirement(RequirementKind::Superclass, subject, concreteType); |
| 774 | + } |
| 775 | + |
| 776 | + case Symbol::Kind::Protocol: |
| 777 | + return Requirement(RequirementKind::Conformance, subject, |
| 778 | + property.getProtocol()->getDeclaredInterfaceType()); |
| 779 | + |
| 780 | + case Symbol::Kind::Layout: |
| 781 | + return Requirement(RequirementKind::Layout, subject, |
| 782 | + property.getLayoutConstraint()); |
| 783 | + |
| 784 | + default: |
| 785 | + return None; |
| 786 | + } |
| 787 | +} |
| 788 | + |
| 789 | +void RewriteSystem::computeConflictDiagnostics( |
| 790 | + SmallVectorImpl<RequirementError> &errors, SourceLoc signatureLoc, |
| 791 | + const PropertyMap &propertyMap, |
| 792 | + TypeArrayView<GenericTypeParamType> genericParams) { |
| 793 | + for (auto pair : ConflictingRules) { |
| 794 | + const auto &firstRule = getRule(pair.first); |
| 795 | + const auto &secondRule = getRule(pair.second); |
| 796 | + |
| 797 | + assert(firstRule.isPropertyRule() && secondRule.isPropertyRule()); |
| 798 | + |
| 799 | + if (firstRule.isSubstitutionSimplified() || |
| 800 | + secondRule.isSubstitutionSimplified()) |
| 801 | + continue; |
| 802 | + |
| 803 | + bool chooseFirstRule = firstRule.getRHS().size() > secondRule.getRHS().size(); |
| 804 | + auto subjectRule = chooseFirstRule ? firstRule : secondRule; |
| 805 | + auto subjectTerm = subjectRule.getRHS(); |
| 806 | + |
| 807 | + auto suffixRule = chooseFirstRule ? secondRule : firstRule; |
| 808 | + auto suffixTerm = suffixRule.getRHS(); |
| 809 | + |
| 810 | + // If the root protocol of the subject term isn't in this minimization |
| 811 | + // domain, the conflict was already diagnosed. |
| 812 | + if (!isInMinimizationDomain(subjectTerm[0].getRootProtocol())) |
| 813 | + continue; |
| 814 | + |
| 815 | + Type subject = propertyMap.getTypeForTerm(subjectTerm, genericParams); |
| 816 | + MutableTerm prefix(subjectTerm.begin(), subjectTerm.end() - suffixTerm.size()); |
| 817 | + errors.push_back(RequirementError::forConflictingRequirement( |
| 818 | + *getRequirementForDiagnostics(subject, *subjectRule.isPropertyRule(), |
| 819 | + propertyMap, genericParams, MutableTerm()), |
| 820 | + *getRequirementForDiagnostics(subject, *suffixRule.isPropertyRule(), |
| 821 | + propertyMap, genericParams, prefix), |
| 822 | + signatureLoc)); |
| 823 | + } |
| 824 | +} |
| 825 | + |
755 | 826 | void RewriteSystem::dump(llvm::raw_ostream &out) const { |
756 | 827 | out << "Rewrite system: {\n"; |
757 | 828 | for (const auto &rule : Rules) { |
|
0 commit comments