Skip to content

Commit 78b0756

Browse files
committed
[RequirementMachine] Use PropertyMap::getTypeFromSubstitutionSchema when
computing a concrete same-type or superclass for conflict diagnostics. Otherwise, diagnostics will show fresh type parameters when the concrete type is generic.
1 parent 5296fbd commit 78b0756

File tree

2 files changed

+38
-16
lines changed

2 files changed

+38
-16
lines changed

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -754,15 +754,23 @@ void RewriteSystem::freeze() {
754754
}
755755

756756
static Optional<Requirement>
757-
getRequirementForDiagnostics(Type subject, Symbol property) {
757+
getRequirementForDiagnostics(Type subject, Symbol property,
758+
const PropertyMap &map,
759+
TypeArrayView<GenericTypeParamType> genericParams) {
758760
switch (property.getKind()) {
759-
case Symbol::Kind::ConcreteType:
760-
return Requirement(RequirementKind::SameType, subject,
761-
property.getConcreteType());
761+
case Symbol::Kind::ConcreteType: {
762+
auto concreteType = map.getTypeFromSubstitutionSchema(
763+
property.getConcreteType(), property.getSubstitutions(),
764+
genericParams, MutableTerm());
765+
return Requirement(RequirementKind::SameType, subject, concreteType);
766+
}
762767

763-
case Symbol::Kind::Superclass:
764-
return Requirement(RequirementKind::Superclass, subject,
765-
property.getConcreteType());
768+
case Symbol::Kind::Superclass: {
769+
auto concreteType = map.getTypeFromSubstitutionSchema(
770+
property.getConcreteType(), property.getSubstitutions(),
771+
genericParams, MutableTerm());
772+
return Requirement(RequirementKind::Superclass, subject, concreteType);
773+
}
766774

767775
case Symbol::Kind::Protocol:
768776
return Requirement(RequirementKind::Conformance, subject,
@@ -785,14 +793,11 @@ void RewriteSystem::computeConflictDiagnostics(
785793
const auto &firstRule = getRule(pair.first);
786794
const auto &secondRule = getRule(pair.second);
787795

788-
auto firstProperty = firstRule.isPropertyRule();
789-
auto secondProperty = secondRule.isPropertyRule();
790-
assert(firstProperty && secondProperty);
796+
assert(firstRule.isPropertyRule() && secondRule.isPropertyRule());
791797

792-
auto firstTerm = firstRule.getRHS();
793-
auto secondTerm = secondRule.getRHS();
794-
auto subjectTerm =
795-
firstTerm.size() > secondTerm.size() ? firstTerm : secondTerm;
798+
bool chooseFirstRule = firstRule.getRHS().size() > secondRule.getRHS().size();
799+
auto subjectRule = chooseFirstRule ? firstRule : secondRule;
800+
auto subjectTerm = subjectRule.getRHS();
796801

797802
// If the root protocol of the subject term isn't in this minimization
798803
// domain, the conflict was already diagnosed.
@@ -801,8 +806,10 @@ void RewriteSystem::computeConflictDiagnostics(
801806

802807
Type subject = propertyMap.getTypeForTerm(subjectTerm, genericParams);
803808
errors.push_back(RequirementError::forConflictingRequirement(
804-
*getRequirementForDiagnostics(subject, *firstProperty),
805-
*getRequirementForDiagnostics(subject, *secondProperty),
809+
*getRequirementForDiagnostics(subject, *firstRule.isPropertyRule(),
810+
propertyMap, genericParams),
811+
*getRequirementForDiagnostics(subject, *secondRule.isPropertyRule(),
812+
propertyMap, genericParams),
806813
signatureLoc));
807814
}
808815
}

test/Generics/requirement_machine_diagnostics.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,4 +305,19 @@ func sameTypeConflicts() {
305305

306306
// expected-error@+1{{no type for 'T.X' can satisfy both 'T.X == Int' and 'T.X == String'}}
307307
func fail6<U, T: Concrete>(_: U, _: T) where T.X == String {}
308+
309+
struct G<T> {}
310+
311+
// FIXME: conflict diagnosed twice
312+
// expected-error@+1 2{{no type for 'T.X' can satisfy both 'T.X == Int' and 'T.X == G<U.Foo>'}}
313+
func fail7<U: Fooable, T: Concrete>(_: U, _: T) where T.X == G<U.Foo> {}
314+
315+
// FIXME: conflict diagnosed twice
316+
// expected-error@+2{{no type for 'T' can satisfy both 'T == Int' and 'T == G<U.Foo>'}}
317+
// expected-error@+1{{no type for 'T' can satisfy both 'T == G<U.Foo>' and 'T == Int'}}
318+
func fail8<T, U: Fooable>(_: U, _: T) where T == G<U.Foo>, T == Int {}
319+
320+
// FIXME: conflict diagnosed twice
321+
// expected-error@+1 2{{no type for 'T' can satisfy both 'T == Int' and 'T == G<U.Foo>'}}
322+
func fail9<T, U: Fooable>(_: U, _: T) where T == Int, T == G<U.Foo> {}
308323
}

0 commit comments

Comments
 (0)