Skip to content

Commit 31028e5

Browse files
committed
[RequirementMachine] When computing conflict diagnostics, only compute the
type for the longer subject term between the two conflicting rules.
1 parent 964c11a commit 31028e5

File tree

2 files changed

+18
-14
lines changed

2 files changed

+18
-14
lines changed

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -763,17 +763,19 @@ void RewriteSystem::computeConflictDiagnostics(
763763

764764
auto firstProperty = firstRule->isPropertyRule();
765765
auto secondProperty = secondRule->isPropertyRule();
766-
if (!firstProperty || !secondProperty)
767-
continue;
766+
assert(firstProperty && secondProperty);
767+
768+
auto firstTerm = firstRule->getRHS();
769+
auto secondTerm = secondRule->getRHS();
770+
auto subjectTerm =
771+
firstTerm.size() > secondTerm.size() ? firstTerm : secondTerm;
768772

769-
MutableTerm firstTerm(
770-
firstRule->getLHS().begin(), firstRule->getLHS().end() - 1);
771-
MutableTerm secondTerm(
772-
secondRule->getLHS().begin(), secondRule->getLHS().end() - 1);
773+
// If the root protocol of the subject term isn't in this minimization
774+
// domain, the conflict was already diagnosed.
775+
if (!isInMinimizationDomain(subjectTerm[0].getRootProtocol()))
776+
continue;
773777

774-
auto firstSubject = propertyMap.getTypeForTerm(firstTerm, genericParams);
775-
auto secondSubject = propertyMap.getTypeForTerm(secondTerm, genericParams);
776-
assert(firstSubject && secondSubject);
778+
Type subject = propertyMap.getTypeForTerm(subjectTerm, genericParams);
777779

778780
// Record conflicting requirements on a type parameter, e.g.
779781
// conflicting superclass requirements:
@@ -783,11 +785,10 @@ void RewriteSystem::computeConflictDiagnostics(
783785
// protocol P { associatedtype A: C1 }
784786
// func conflict<T: P>(_: T) where T.A: C2 {}
785787
if (firstProperty->getKind() == secondProperty->getKind() &&
786-
firstTerm.back().getKind() != Symbol::Kind::Name &&
787-
firstSubject->isEqual(secondSubject)) {
788+
firstTerm.back().getKind() != Symbol::Kind::Name) {
788789
switch (firstProperty->getKind()) {
789790
case Symbol::Kind::ConcreteType:
790-
errors.push_back(RequirementError::forConflictingRequirement(firstSubject,
791+
errors.push_back(RequirementError::forConflictingRequirement(subject,
791792
{RequirementKind::SameType, firstProperty->getConcreteType(),
792793
secondProperty->getConcreteType()},
793794
signatureLoc));
@@ -796,7 +797,7 @@ void RewriteSystem::computeConflictDiagnostics(
796797
case Symbol::Kind::Superclass:
797798
// FIXME: shoving the conflicting superclass types into a superclass
798799
// requiement is a little gross.
799-
errors.push_back(RequirementError::forConflictingRequirement(firstSubject,
800+
errors.push_back(RequirementError::forConflictingRequirement(subject,
800801
{RequirementKind::Superclass, firstProperty->getConcreteType(),
801802
secondProperty->getConcreteType()},
802803
signatureLoc));

test/Generics/requirement_machine_diagnostics.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ func testMissingRequirements() {
243243

244244
protocol Fooable {
245245
associatedtype Foo
246-
247246
var foo: Foo { get }
248247
}
249248

@@ -252,6 +251,8 @@ protocol Barrable {
252251
var bar: Bar { get }
253252
}
254253

254+
protocol Concrete { associatedtype X where X == Int }
255+
255256
func sameTypeConflicts() {
256257

257258
struct X {}
@@ -302,4 +303,6 @@ func sameTypeConflicts() {
302303
fatalError()
303304
}
304305

306+
// expected-error@+1{{generic parameter 'T.X' cannot be equal to both 'Int' and 'String'}}
307+
func fail6<U, T: Concrete>(_: U, _: T) where T.X == String {}
305308
}

0 commit comments

Comments
 (0)