Skip to content

Commit 7e5c483

Browse files
committed
[RequirementMachine] When computing requirements for conflict diagnostics,
adjust the concrete type symbol for the suffix rule by applying the prefix from the subject rule.
1 parent 78b0756 commit 7e5c483

File tree

4 files changed

+29
-24
lines changed

4 files changed

+29
-24
lines changed

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -756,19 +756,20 @@ void RewriteSystem::freeze() {
756756
static Optional<Requirement>
757757
getRequirementForDiagnostics(Type subject, Symbol property,
758758
const PropertyMap &map,
759-
TypeArrayView<GenericTypeParamType> genericParams) {
759+
TypeArrayView<GenericTypeParamType> genericParams,
760+
const MutableTerm &prefix) {
760761
switch (property.getKind()) {
761762
case Symbol::Kind::ConcreteType: {
762763
auto concreteType = map.getTypeFromSubstitutionSchema(
763764
property.getConcreteType(), property.getSubstitutions(),
764-
genericParams, MutableTerm());
765+
genericParams, prefix);
765766
return Requirement(RequirementKind::SameType, subject, concreteType);
766767
}
767768

768769
case Symbol::Kind::Superclass: {
769770
auto concreteType = map.getTypeFromSubstitutionSchema(
770771
property.getConcreteType(), property.getSubstitutions(),
771-
genericParams, MutableTerm());
772+
genericParams, prefix);
772773
return Requirement(RequirementKind::Superclass, subject, concreteType);
773774
}
774775

@@ -799,17 +800,21 @@ void RewriteSystem::computeConflictDiagnostics(
799800
auto subjectRule = chooseFirstRule ? firstRule : secondRule;
800801
auto subjectTerm = subjectRule.getRHS();
801802

803+
auto suffixRule = chooseFirstRule ? secondRule : firstRule;
804+
auto suffixTerm = suffixRule.getRHS();
805+
802806
// If the root protocol of the subject term isn't in this minimization
803807
// domain, the conflict was already diagnosed.
804808
if (!isInMinimizationDomain(subjectTerm[0].getRootProtocol()))
805809
continue;
806810

807811
Type subject = propertyMap.getTypeForTerm(subjectTerm, genericParams);
812+
MutableTerm prefix(subjectTerm.begin(), subjectTerm.end() - suffixTerm.size());
808813
errors.push_back(RequirementError::forConflictingRequirement(
809-
*getRequirementForDiagnostics(subject, *firstRule.isPropertyRule(),
810-
propertyMap, genericParams),
811-
*getRequirementForDiagnostics(subject, *secondRule.isPropertyRule(),
812-
propertyMap, genericParams),
814+
*getRequirementForDiagnostics(subject, *subjectRule.isPropertyRule(),
815+
propertyMap, genericParams, MutableTerm()),
816+
*getRequirementForDiagnostics(subject, *suffixRule.isPropertyRule(),
817+
propertyMap, genericParams, prefix),
813818
signatureLoc));
814819
}
815820
}

test/Generics/concrete_conflict.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ protocol P3 {
2424
// CHECK-LABEL: .P4@
2525
// CHECK-LABEL: Requirement signature: <Self where Self.[P4]T : P1, Self.[P4]T : P2, Self.[P4]T : P3>
2626

27-
// expected-error@+3{{no type for 'Self.T.T' can satisfy both 'Self.T.T == Int' and 'Self.T.T == String'}}
28-
// expected-error@+2{{no type for 'Self.T.T' can satisfy both 'Self.T.T == Int' and 'Self.T.T == Float'}}
29-
// expected-error@+1{{no type for 'Self.T.T' can satisfy both 'Self.T.T == String' and 'Self.T.T == Float'}}
27+
// expected-error@+3{{no type for 'Self.T.T' can satisfy both 'Self.T.T == String' and 'Self.T.T == Int'}}
28+
// expected-error@+2{{no type for 'Self.T.T' can satisfy both 'Self.T.T == Float' and 'Self.T.T == Int'}}
29+
// expected-error@+1{{no type for 'Self.T.T' can satisfy both 'Self.T.T == Float' and 'Self.T.T == String'}}
3030
protocol P4 {
3131
associatedtype T : P1 & P2 & P3
3232
}
@@ -37,5 +37,5 @@ extension Class where T == Bool {
3737
// CHECK-LABEL: .badRequirement()@
3838
// CHECK-NEXT: <T>
3939
func badRequirement() where T == Int { }
40-
// expected-error@-1 {{no type for 'T' can satisfy both 'T == Bool' and 'T == Int'}}
40+
// expected-error@-1 {{no type for 'T' can satisfy both 'T == Int' and 'T == Bool'}}
4141
}

test/Generics/protocol_self_concrete_error.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77

88
struct S {}
99

10-
// expected-error@+1 {{no type for 'Self' can satisfy both 'Self : P' and 'Self == S'}}
10+
// expected-error@+1 {{no type for 'Self' can satisfy both 'Self == S' and 'Self : P'}}
1111
protocol P where Self == S {}

test/Generics/requirement_machine_diagnostics.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ protocol ProtoAlias2 {
210210
}
211211

212212
func basicConflict<T: ProtoAlias1 & ProtoAlias2>(_:T) where T.A1 == T.A2 {}
213-
// expected-error@-1{{no type for 'T.A1' can satisfy both 'T.A1 == Int' and 'T.A1 == String'}}
213+
// expected-error@-1{{no type for 'T.A1' can satisfy both 'T.A1 == String' and 'T.A1 == Int'}}
214214

215215
protocol RequiresAnyObject {
216216
associatedtype A: AnyObject
@@ -231,14 +231,14 @@ func testMissingRequirements() {
231231
// expected-error@-1{{no type for 'T.A' can satisfy both 'T.A == S' and 'T.A : AnyObject'}}
232232

233233
func conflict2<T: RequiresConformance>(_: T) where T.A == C {}
234-
// expected-error@-1{{no type for 'T.A' can satisfy both 'T.A : P' and 'T.A == C'}}
234+
// expected-error@-1{{no type for 'T.A' can satisfy both 'T.A == C' and 'T.A : P'}}
235235

236236
class C {}
237237
func conflict3<T: RequiresSuperclass>(_: T) where T.A == C {}
238-
// expected-error@-1{{no type for 'T.A' can satisfy both 'T.A : Super' and 'T.A : C'}}
238+
// expected-error@-1{{no type for 'T.A' can satisfy both 'T.A : C' and 'T.A : Super'}}
239239

240240
func conflict4<T: RequiresSuperclass>(_: T) where T.A: C {}
241-
// expected-error@-1{{no type for 'T.A' can satisfy both 'T.A : Super' and 'T.A : C'}}
241+
// expected-error@-1{{no type for 'T.A' can satisfy both 'T.A : C' and 'T.A : Super'}}
242242
}
243243

244244
protocol Fooable {
@@ -265,51 +265,51 @@ func sameTypeConflicts() {
265265
var bar: Y { return Y() }
266266
}
267267

268-
// expected-error@+1{{no type for 'T.Foo' can satisfy both 'T.Foo == Y' and 'T.Foo == X'}}
268+
// expected-error@+1{{no type for 'T.Foo' can satisfy both 'T.Foo == X' and 'T.Foo == Y'}}
269269
func fail1<
270270
T: Fooable, U: Fooable
271271
>(_ t: T, u: U) -> (X, Y)
272272
where T.Foo == X, U.Foo == Y, T.Foo == U.Foo {
273273
fatalError()
274274
}
275275

276-
// expected-error@+1{{no type for 'T.Foo' can satisfy both 'T.Foo == X' and 'T.Foo == Y'}}
276+
// expected-error@+1{{no type for 'T.Foo' can satisfy both 'T.Foo == Y' and 'T.Foo == X'}}
277277
func fail2<
278278
T: Fooable, U: Fooable
279279
>(_ t: T, u: U) -> (X, Y)
280280
where T.Foo == U.Foo, T.Foo == X, U.Foo == Y {
281281
fatalError()
282282
}
283283

284-
// expected-error@+1{{no type for 'T.Bar' can satisfy both 'T.Bar : Fooable' and 'T.Bar == X'}}
284+
// expected-error@+1{{no type for 'T.Bar' can satisfy both 'T.Bar == X' and 'T.Bar : Fooable'}}
285285
func fail3<T: Barrable>(_ t: T) -> X
286286
where T.Bar == X {
287287
fatalError()
288288
}
289289

290-
// expected-error@+1{{no type for 'T.Bar.Foo' can satisfy both 'T.Bar.Foo == Z' and 'T.Bar.Foo == X'}}
290+
// expected-error@+1{{no type for 'T.Bar.Foo' can satisfy both 'T.Bar.Foo == X' and 'T.Bar.Foo == Z'}}
291291
func fail4<T: Barrable>(_ t: T) -> (Y, Z)
292292
where
293293
T.Bar == Y,
294294
T.Bar.Foo == Z {
295295
fatalError()
296296
}
297297

298-
// expected-error@+1{{no type for 'T.Bar.Foo' can satisfy both 'T.Bar.Foo == Z' and 'T.Bar.Foo == X'}}
298+
// expected-error@+1{{no type for 'T.Bar.Foo' can satisfy both 'T.Bar.Foo == X' and 'T.Bar.Foo == Z'}}
299299
func fail5<T: Barrable>(_ t: T) -> (Y, Z)
300300
where
301301
T.Bar.Foo == Z,
302302
T.Bar == Y {
303303
fatalError()
304304
}
305305

306-
// expected-error@+1{{no type for 'T.X' can satisfy both 'T.X == Int' and 'T.X == String'}}
306+
// expected-error@+1{{no type for 'T.X' can satisfy both 'T.X == String' and 'T.X == Int'}}
307307
func fail6<U, T: Concrete>(_: U, _: T) where T.X == String {}
308308

309309
struct G<T> {}
310310

311311
// 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>'}}
312+
// expected-error@+1 2{{no type for 'T.X' can satisfy both 'T.X == G<U.Foo>' and 'T.X == Int'}}
313313
func fail7<U: Fooable, T: Concrete>(_: U, _: T) where T.X == G<U.Foo> {}
314314

315315
// FIXME: conflict diagnosed twice
@@ -318,6 +318,6 @@ func sameTypeConflicts() {
318318
func fail8<T, U: Fooable>(_: U, _: T) where T == G<U.Foo>, T == Int {}
319319

320320
// FIXME: conflict diagnosed twice
321-
// expected-error@+1 2{{no type for 'T' can satisfy both 'T == Int' and 'T == G<U.Foo>'}}
321+
// expected-error@+1 2{{no type for 'T' can satisfy both 'T == G<U.Foo>' and 'T == Int'}}
322322
func fail9<T, U: Fooable>(_: U, _: T) where T == Int, T == G<U.Foo> {}
323323
}

0 commit comments

Comments
 (0)