Skip to content

Commit 06b181a

Browse files
committed
RequirementMachine: Don't record duplicate conflicts in PropertyMap::checkConcreteTypeRequirements()
1 parent d385b73 commit 06b181a

File tree

3 files changed

+60
-56
lines changed

3 files changed

+60
-56
lines changed

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -666,51 +666,59 @@ void PropertyMap::checkConcreteTypeRequirements() {
666666
auto concreteType = pair.first;
667667
unsigned concreteTypeRule = pair.second;
668668

669-
// A rule (T.[concrete: C] => T) where C is a class type induces a rule
670-
// (T.[superclass: C] => T).
671-
if (concreteType.getConcreteType()->getClassOrBoundGenericClass()) {
672-
auto superclassSymbol = Symbol::forSuperclass(
673-
concreteType.getConcreteType(),
674-
concreteType.getSubstitutions(),
675-
Context);
676-
677-
recordRelation(props->getKey(), concreteTypeRule,
678-
superclassSymbol, System, debug);
679-
680669
// If the concrete type is not a class and we have a superclass
681670
// requirement, we have a conflict.
682-
} else if (props->hasSuperclassBound()) {
671+
if (!concreteType.getConcreteType()->getClassOrBoundGenericClass() &&
672+
props->hasSuperclassBound()) {
683673
const auto &req = props->getSuperclassRequirement();
684674
for (auto pair : req.SuperclassRules) {
685-
System.recordConflict(concreteTypeRule, pair.second);
675+
if (checkRulePairOnce(concreteTypeRule, pair.second))
676+
System.recordConflict(concreteTypeRule, pair.second);
686677
}
687678
}
688679

689-
// A rule (T.[concrete: C] => T) where C is a class type induces a rule
690-
// (T.[layout: L] => T), where L is either AnyObject or _NativeObject.
691-
if (concreteType.getConcreteType()->satisfiesClassConstraint()) {
692-
Type superclassType = concreteType.getConcreteType();
693-
if (!superclassType->getClassOrBoundGenericClass())
694-
superclassType = superclassType->getSuperclass();
695-
696-
auto layoutConstraint = LayoutConstraintKind::Class;
697-
if (superclassType)
698-
if (auto *classDecl = superclassType->getClassOrBoundGenericClass())
699-
layoutConstraint = classDecl->getLayoutConstraintKind();
700-
701-
auto layout =
702-
LayoutConstraint::getLayoutConstraint(
703-
layoutConstraint, Context.getASTContext());
704-
auto layoutSymbol = Symbol::forLayout(layout, Context);
680+
if (checkRuleOnce(concreteTypeRule)) {
681+
if (concreteType.getConcreteType()->getClassOrBoundGenericClass()) {
682+
// A rule (T.[concrete: C] => T) where C is a class type induces a rule
683+
// (T.[superclass: C] => T).
684+
auto superclassSymbol = Symbol::forSuperclass(
685+
concreteType.getConcreteType(),
686+
concreteType.getSubstitutions(),
687+
Context);
688+
689+
recordRelation(props->getKey(), concreteTypeRule,
690+
superclassSymbol, System, debug);
691+
}
705692

706-
recordRelation(props->getKey(), concreteTypeRule,
707-
layoutSymbol, System, debug);
693+
// A rule (T.[concrete: C] => T) where C is a class type induces a rule
694+
// (T.[layout: L] => T), where L is either AnyObject or _NativeObject.
695+
if (concreteType.getConcreteType()->satisfiesClassConstraint()) {
696+
Type superclassType = concreteType.getConcreteType();
697+
if (!superclassType->getClassOrBoundGenericClass())
698+
superclassType = superclassType->getSuperclass();
699+
700+
auto layoutConstraint = LayoutConstraintKind::Class;
701+
if (superclassType)
702+
if (auto *classDecl = superclassType->getClassOrBoundGenericClass())
703+
layoutConstraint = classDecl->getLayoutConstraintKind();
704+
705+
auto layout =
706+
LayoutConstraint::getLayoutConstraint(
707+
layoutConstraint, Context.getASTContext());
708+
auto layoutSymbol = Symbol::forLayout(layout, Context);
709+
710+
recordRelation(props->getKey(), concreteTypeRule,
711+
layoutSymbol, System, debug);
712+
}
713+
}
708714

709715
// If the concrete type does not satisfy a class layout constraint and
710716
// we have such a layout requirement, we have a conflict.
711-
} else if (props->LayoutRule &&
712-
props->Layout->isClass()) {
713-
System.recordConflict(concreteTypeRule, *props->LayoutRule);
717+
if (!concreteType.getConcreteType()->satisfiesClassConstraint() &&
718+
props->LayoutRule &&
719+
props->Layout->isClass()) {
720+
if (checkRulePairOnce(concreteTypeRule, *props->LayoutRule))
721+
System.recordConflict(concreteTypeRule, *props->LayoutRule);
714722
}
715723
}
716724
}

test/Generics/same_type_constraints.swift

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -swift-version 4
1+
// RUN: %target-typecheck-verify-swift -swift-version 4 -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on
22

33
protocol Fooable {
44
associatedtype Foo
@@ -328,12 +328,12 @@ protocol P9 {
328328

329329
struct X7<T: P9> where T.A : C { }
330330

331-
extension X7 where T.A == Int { } // expected-error {{'T.A' requires that 'Int' inherit from 'C'}}
332-
// expected-note@-1 {{same-type constraint 'T.A' == 'Int' implied here}}
331+
extension X7 where T.A == Int { } // expected-error {{no type for 'T.A' can satisfy both 'T.A : _NativeClass' and 'T.A == Int}}
332+
// expected-error@-1 {{no type for 'T.A' can satisfy both 'T.A : C' and 'T.A == Int'}}
333333
struct X8<T: C> { }
334334

335-
extension X8 where T == Int { } // expected-error {{'T' requires that 'Int' inherit from 'C'}}
336-
// expected-note@-1 {{same-type constraint 'T' == 'Int' implied here}}
335+
extension X8 where T == Int { } // expected-error {{no type for 'T' can satisfy both 'T : _NativeClass' and 'T == Int'}}
336+
// expected-error@-1 {{no type for 'T' can satisfy both 'T : C' and 'T == Int'}}
337337

338338
protocol P10 {
339339
associatedtype A
@@ -345,17 +345,17 @@ protocol P10 {
345345

346346
protocol P11: P10 where A == B { }
347347

348-
func intracomponent<T: P11>(_: T) // expected-note{{previous same-type constraint 'T.A' == 'T.B' implied here}}
348+
func intracomponent<T: P11>(_: T)
349349
where T.A == T.B { } // expected-warning{{redundant same-type constraint 'T.A' == 'T.B'}}
350350

351351
func intercomponentSameComponents<T: P10>(_: T)
352-
where T.A == T.B, // expected-warning{{redundant same-type constraint 'T.A' == 'T.B'}}
353-
T.B == T.A { } // expected-note{{previous same-type constraint 'T.B' == 'T.A' written here}}
352+
where T.A == T.B,
353+
T.B == T.A { } // expected-warning{{redundant same-type constraint 'T.B' == 'T.A'}}
354354

355355
func intercomponentMoreThanSpanningTree<T: P10>(_: T)
356356
where T.A == T.B,
357357
T.B == T.C,
358-
T.D == T.E, // expected-note{{previous same-type constraint 'T.D' == 'T.E' written here}}
358+
T.D == T.E,
359359
T.D == T.B,
360360
T.E == T.B // expected-warning{{redundant same-type constraint 'T.E' == 'T.B'}}
361361
{ }
@@ -407,5 +407,6 @@ func bad<S: FakeSequence, O>(_: S, _: O) where S.Element : ObserverType, O == S.
407407
}
408408

409409
func ugly<S: FakeSequence, O>(_: S, _: O) where S.Element : ObserverType, O == S.Iterator.Element.E, O == S.Element.E {
410+
// expected-warning@-1 {{redundant same-type constraint 'O' == 'S.Element.E'}}
410411
_ = Bad<S, O>()
411412
}
Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-inferred-signatures=verify
2-
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify 2>&1 | %FileCheck %s
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on
2+
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on 2>&1 | %FileCheck %s
33

44
class C {}
55

@@ -10,25 +10,22 @@ struct S {}
1010
protocol P1 {
1111
associatedtype T where T : C, T == C
1212
// expected-warning@-1 {{redundant superclass constraint 'Self.T' : 'C'}}
13-
// expected-note@-2 {{superclass constraint 'Self.T' : 'C' implied here}}
1413
}
1514

1615
// CHECK-LABEL: .P2@
1716
// CHECK-NEXT: Requirement signature: <Self>
1817
protocol P2 {
18+
// expected-error@-1 {{no type for 'Self.T' can satisfy both 'Self.T : C' and 'Self.T == S'}}
19+
// expected-error@-2 {{no type for 'Self.T' can satisfy both 'Self.T : _NativeClass' and 'Self.T == S'}}
1920
associatedtype T where T : C, T == S
20-
// expected-error@-1 {{'Self.T' requires that 'S' inherit from 'C'}}
21-
// expected-note@-2 {{superclass constraint 'Self.T' : 'C' implied here}}
22-
// expected-note@-3 {{same-type constraint 'Self.T' == 'S' implied here}}
2321
}
2422

2523
// CHECK-LABEL: .P3@
2624
// CHECK-NEXT: Requirement signature: <Self>
2725
protocol P3 {
26+
// expected-error@-1 {{no type for 'Self.T' can satisfy both 'Self.T : C' and 'Self.T == S'}}
27+
// expected-error@-2 {{no type for 'Self.T' can satisfy both 'Self.T : _NativeClass' and 'Self.T == S'}}
2828
associatedtype T where T == S, T : C
29-
// expected-error@-1 {{'Self.T' requires that 'S' inherit from 'C'}}
30-
// expected-note@-2 {{same-type constraint 'Self.T' == 'S' implied here}}
31-
// expected-note@-3 {{superclass constraint 'Self.T' : 'C' implied here}}
3229
}
3330

3431
protocol P4a {
@@ -38,17 +35,15 @@ protocol P4a {
3835
// CHECK-LABEL: .P4@
3936
// CHECK-NEXT: Requirement signature: <Self where Self.[P4]T : P4>
4037
protocol P4 {
38+
// expected-error@-1 {{no type for 'Self.T.T' can satisfy both 'Self.T.T == S' and 'Self.T.T : P4'}}
4139
associatedtype T : P4 where T.T == S
42-
// expected-error@-1 2{{same-type constraint type 'S' does not conform to required protocol 'P4'}}
4340
}
4441

4542
class D {}
4643

4744
// CHECK-LABEL: .P5@
4845
// CHECK-NEXT: Requirement signature: <Self where Self.[P5]T == D>
4946
protocol P5 {
47+
// expected-error@-1 {{no type for 'Self.T' can satisfy both 'Self.T : D' and 'Self.T : C'}}
5048
associatedtype T where T : C, T == D
51-
// expected-error@-1 {{'Self.T' requires that 'D' inherit from 'C'}}
52-
// expected-note@-2 {{superclass constraint 'Self.T' : 'C' implied here}}
53-
// expected-note@-3 {{same-type constraint 'Self.T' == 'D' implied here}}
5449
}

0 commit comments

Comments
 (0)