Skip to content

Commit 653977a

Browse files
committed
RequirementMachine: Rule sharing
All the pieces are now in place so that the RuleBuilder can assemble a confluent rewrite system for downstream protocol dependencies, instead of building rules from protocol requirement signatures.
1 parent 9704168 commit 653977a

File tree

7 files changed

+39
-27
lines changed

7 files changed

+39
-27
lines changed

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "swift/AST/TypeMatcher.h"
3434
#include "swift/AST/TypeRepr.h"
3535
#include "llvm/ADT/SmallVector.h"
36+
#include "RequirementMachine.h"
3637
#include "RewriteContext.h"
3738
#include "RewriteSystem.h"
3839
#include "Symbol.h"
@@ -1403,21 +1404,32 @@ void RuleBuilder::collectRulesFromReferencedProtocols() {
14031404
// if this is a rewrite system for a connected component of the protocol
14041405
// dependency graph, add rewrite rules for each referenced protocol not part
14051406
// of this connected component.
1407+
1408+
// First, collect all unique requirement machines, one for each connected
1409+
// component of each referenced protocol.
1410+
llvm::DenseSet<RequirementMachine *> machines;
1411+
1412+
// Now visit each subordinate requirement machine pull in its rules.
14061413
for (auto *proto : ProtocolsToImport) {
1414+
// This will trigger requirement signature computation for this protocol,
1415+
// if neccessary, which will cause us to re-enter into a new RuleBuilder
1416+
// instace under RuleBuilder::initWithProtocolWrittenRequirements().
14071417
if (Dump) {
1408-
llvm::dbgs() << "protocol " << proto->getName() << " {\n";
1418+
llvm::dbgs() << "importing protocol " << proto->getName() << " {\n";
14091419
}
14101420

1411-
addPermanentProtocolRules(proto);
1412-
1413-
auto reqs = proto->getRequirementSignature();
1414-
for (auto req : reqs.getRequirements())
1415-
addRequirement(req.getCanonical(), proto, /*requirementID=*/None);
1416-
for (auto alias : reqs.getTypeAliases())
1417-
addTypeAlias(alias, proto);
1418-
1419-
if (Dump) {
1420-
llvm::dbgs() << "}\n";
1421+
auto *machine = Context.getRequirementMachine(proto);
1422+
if (!machines.insert(machine).second) {
1423+
// We've already seen this connected component.
1424+
continue;
14211425
}
1426+
1427+
// We grab the machine's local rules, not *all* of its rules, to avoid
1428+
// duplicates in case multiple machines share a dependency on a downstream
1429+
// protocol connected component.
1430+
auto localRules = machine->getLocalRules();
1431+
ImportedRules.insert(ImportedRules.end(),
1432+
localRules.begin(),
1433+
localRules.end());
14221434
}
14231435
}

test/Generics/rdar79564324.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ public func test<T : P>(_ t: T) where T == T.A {
2626
// CHECK-NEXT: - [P].[P] => [P] [permanent]
2727
// CHECK-NEXT: - [P].A => [P:A] [permanent]
2828
// CHECK-NEXT: - [P:A].[P] => [P:A]
29+
// CHECK-NEXT: - [P].[P:A] => [P:A]
30+
// CHECK-NEXT: - [P:A].A => [P:A].[P:A]
2931
// CHECK-NEXT: - τ_0_0.[P:A] => τ_0_0
3032
// CHECK-NEXT: - τ_0_1.[P] => τ_0_1
3133
// CHECK-NEXT: - τ_0_1.[P:A] => τ_0_0
32-
// CHECK-NEXT: - [P].[P:A] => [P:A]
33-
// CHECK-NEXT: - [P:A].A => [P:A].[P:A]
3434
// CHECK-NEXT: - τ_0_0.[P] => τ_0_0
35-
// CHECK-NEXT: - τ_0_1.A => τ_0_0
3635
// CHECK-NEXT: - τ_0_0.A => τ_0_0
36+
// CHECK-NEXT: - τ_0_1.A => τ_0_0
3737
// CHECK-NEXT: }
3838
// CHECK: Property map: {
3939
// CHECK-NEXT: [P] => { conforms_to: [P] }

test/Generics/rdar90219229.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ protocol PBad {
2626
// FIXME: Terrible diagnostics.
2727

2828
protocol PWorse {
29-
// expected-error@-1 2{{circular reference}}
30-
// expected-note@-2 4{{through reference here}}
29+
// expected-error@-1 4{{circular reference}}
30+
// expected-note@-2 6{{through reference here}}
3131
typealias A = C
3232

3333
associatedtype T : Self.A
34-
// expected-note@-1 2{{while resolving type 'Self.A'}}
35-
// expected-note@-2 2{{through reference here}}
36-
}
34+
// expected-note@-1 4{{while resolving type 'Self.A'}}
35+
// expected-note@-2 4{{through reference here}}
36+
}

test/Generics/unify_superclass_types_1.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ extension P where Self : Derived {
1717
// CHECK-NEXT: Rewrite system: {
1818
// CHECK-NEXT: - [P].[P] => [P] [permanent]
1919
// CHECK-NEXT: - [P].[superclass: Base] => [P]
20+
// CHECK-NEXT: - [P].[layout: _NativeClass] => [P]
2021
// CHECK-NEXT: - τ_0_0.[superclass: Derived] => τ_0_0
2122
// CHECK-NEXT: - τ_0_0.[P] => τ_0_0
2223
// CHECK-NEXT: - τ_0_0.[superclass: Base] => τ_0_0
23-
// CHECK-NEXT: - [P].[layout: _NativeClass] => [P]
2424
// CHECK-NEXT: - τ_0_0.[layout: _NativeClass] => τ_0_0
2525
// CHECK-NEXT: }
2626
// CHECK: Property map: {

test/Generics/unify_superclass_types_2.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ func unifySuperclassTest<T : P1 & P2>(_: T) {
4040
// CHECK: }
4141
// CHECK: Property map: {
4242
// CHECK-NEXT: [P1] => { conforms_to: [P1] }
43-
// CHECK-NEXT: [P2] => { conforms_to: [P2] }
4443
// CHECK-NEXT: [P1:X] => { layout: _NativeClass superclass: [superclass: Generic<Int, [P1:A1], [P1:B1]>] }
44+
// CHECK-NEXT: [P2] => { conforms_to: [P2] }
4545
// CHECK-NEXT: [P2:X] => { layout: _NativeClass superclass: [superclass: Generic<[P2:A2], String, [P2:B2]>] }
4646
// CHECK-NEXT: τ_0_0 => { conforms_to: [P1 P2] }
4747
// CHECK-NEXT: τ_0_0.[P1:X] => { layout: _NativeClass superclass: [superclass: Generic<Int, String, τ_0_0.[P1:B1]>] }

test/Generics/unify_superclass_types_3.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ func unifySuperclassTest<T : P1 & P2>(_: T) {
3232

3333
// CHECK-LABEL: Requirement machine for <τ_0_0 where τ_0_0 : P1, τ_0_0 : P2>
3434
// CHECK-NEXT: Rewrite system: {
35-
// CHECK: - τ_0_0.[P2:X] => τ_0_0.[P1:X]
3635
// CHECK: - [P1:X].[layout: _NativeClass] => [P1:X]
3736
// CHECK: - [P2:X].[layout: _NativeClass] => [P2:X]
37+
// CHECK: - τ_0_0.[P2:X] => τ_0_0.[P1:X]
3838
// CHECK: - τ_0_0.[P1:X].[superclass: Generic<Int, τ_0_0.[P1:A1], τ_0_0.[P1:B1]>] => τ_0_0.[P1:X]
3939
// CHECK: - τ_0_0.[P1:X].[superclass: Generic<Int, String, τ_0_0.[P1:B1]>] => τ_0_0.[P1:X]
4040
// CHECK: - τ_0_0.[P2:A2].[concrete: Int] => τ_0_0.[P2:A2]
@@ -44,8 +44,8 @@ func unifySuperclassTest<T : P1 & P2>(_: T) {
4444
// CHECK: }
4545
// CHECK: Property map: {
4646
// CHECK-NEXT: [P1] => { conforms_to: [P1] }
47-
// CHECK-NEXT: [P2] => { conforms_to: [P2] }
4847
// CHECK-NEXT: [P1:X] => { layout: _NativeClass superclass: [superclass: Derived<[P1:A1], [P1:B1]>] }
48+
// CHECK-NEXT: [P2] => { conforms_to: [P2] }
4949
// CHECK-NEXT: [P2:X] => { layout: _NativeClass superclass: [superclass: Generic<[P2:A2], String, [P2:B2]>] }
5050
// CHECK-NEXT: τ_0_0 => { conforms_to: [P1 P2] }
5151
// CHECK-NEXT: τ_0_0.[P1:X] => { layout: _NativeClass superclass: [superclass: Derived<τ_0_0.[P1:A1], τ_0_0.[P1:B1]>] }

test/Generics/unify_superclass_types_4.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,21 @@ func unifySuperclassTest<T : P1 & P2>(_: T) {
3636
// CHECK-LABEL: Requirement machine for <τ_0_0 where τ_0_0 : P1, τ_0_0 : P2>
3737
// CHECK-NEXT: Rewrite system: {
3838
// CHECK: - [P1:X].[superclass: Base<[P1:A1]>] => [P1:X] [explicit]
39+
// CHECK: - [P1:X].[layout: _NativeClass] => [P1:X]
3940
// CHECK: - [P2:X].[superclass: Derived<[P2:A2]>] => [P2:X] [explicit]
41+
// CHECK: - [P2:X].[layout: _NativeClass] => [P2:X]
4042
// CHECK: - τ_0_0.[P2:X] => τ_0_0.[P1:X]
4143
// CHECK: - τ_0_0.[P1:X].[superclass: Derived<τ_0_0.[P2:A2]>] => τ_0_0.[P1:X]
42-
// CHECK: - [P1:X].[layout: _NativeClass] => [P1:X]
43-
// CHECK: - [P2:X].[layout: _NativeClass] => [P2:X]
4444
// CHECK: - τ_0_0.[P1:X].[superclass: Base<τ_0_0.[P2:A2].[Q:T]>] => τ_0_0.[P1:X]
4545
// CHECK: - τ_0_0.[P2:A2].[Q:T] => τ_0_0.[P1:A1]
4646
// CHECK-NEXT: }
4747
// CHECK: Property map: {
4848
// CHECK-NEXT: [P1] => { conforms_to: [P1] }
49-
// CHECK-NEXT: [P2] => { conforms_to: [P2] }
50-
// CHECK-NEXT: [Q] => { conforms_to: [Q] }
5149
// CHECK-NEXT: [P1:X] => { layout: _NativeClass superclass: [superclass: Base<[P1:A1]>] }
50+
// CHECK-NEXT: [P2] => { conforms_to: [P2] }
5251
// CHECK-NEXT: [P2:A2] => { conforms_to: [Q] }
5352
// CHECK-NEXT: [P2:X] => { layout: _NativeClass superclass: [superclass: Derived<[P2:A2]>] }
53+
// CHECK-NEXT: [Q] => { conforms_to: [Q] }
5454
// CHECK-NEXT: τ_0_0 => { conforms_to: [P1 P2] }
5555
// CHECK-NEXT: τ_0_0.[P1:X] => { layout: _NativeClass superclass: [superclass: Derived<τ_0_0.[P2:A2]>] }
5656
// CHECK-NEXT: }

0 commit comments

Comments
 (0)