Skip to content

Commit 3dd66b7

Browse files
authored
Merge pull request #42044 from slavapestov/rqm-test-cases
RequirementMachine: Add some test cases reduced from https://github.com/RemiBardon/swift-geo
2 parents 21c5b88 + dbb6c81 commit 3dd66b7

File tree

7 files changed

+254
-13
lines changed

7 files changed

+254
-13
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,10 @@ namespace swift {
549549
/// enabled. It can be disabled for debugging and testing.
550550
bool EnableRequirementMachineLoopNormalization = true;
551551

552+
/// Enable reuse of requirement machines for minimization. Usually you want
553+
/// this enabled. It can be disabled for debugging and testing.
554+
bool EnableRequirementMachineReuse = true;
555+
552556
/// Enable experimental, more correct support for opaque result types as
553557
/// concrete types. This will sometimes fail to produce a convergent
554558
/// rewrite system.

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,9 @@ def disable_requirement_machine_concrete_contraction : Flag<["-"], "disable-requ
368368
def disable_requirement_machine_loop_normalization : Flag<["-"], "disable-requirement-machine-loop-normalization">,
369369
HelpText<"Disable stronger minimization algorithm, for debugging only">;
370370

371+
def disable_requirement_machine_reuse : Flag<["-"], "disable-requirement-machine-reuse">,
372+
HelpText<"Disable re-use of requirement machines for minimization, for debugging only">;
373+
371374
def enable_requirement_machine_opaque_archetypes : Flag<["-"], "enable-requirement-machine-opaque-archetypes">,
372375
HelpText<"Enable more correct opaque archetype support, which is off by default because it might fail to produce a convergent rewrite system">;
373376

lib/AST/RequirementMachine/RewriteContext.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,15 @@ bool RewriteContext::isRecursivelyConstructingRequirementMachine(
201201
void RewriteContext::installRequirementMachine(
202202
CanGenericSignature sig,
203203
std::unique_ptr<RequirementMachine> machine) {
204-
auto *machinePtr = machine.release();
204+
if (!Context.LangOpts.EnableRequirementMachineReuse)
205+
return;
205206

206-
machinePtr->freeze();
207+
auto &entry = Machines[sig];
208+
if (entry != nullptr)
209+
return;
207210

208-
auto inserted = Machines.insert(std::make_pair(sig, machinePtr)).second;
209-
if (!inserted)
210-
delete machinePtr;
211+
machine->freeze();
212+
entry = machine.release();
211213
}
212214

213215
/// Implement Tarjan's algorithm to compute strongly-connected components in
@@ -455,22 +457,22 @@ bool RewriteContext::isRecursivelyConstructingRequirementMachine(
455457
!component->second.ComputedRequirementSignatures);
456458
}
457459

458-
/// Given a reuirement machine that built the requirement signatures for a
460+
/// Given a requirement machine that built the requirement signatures for a
459461
/// protocol connected component, attempt to re-use it for subsequent
460462
/// queries against the connected component, instead of building a new one
461463
/// later.
462464
void RewriteContext::installRequirementMachine(
463465
const ProtocolDecl *proto,
464466
std::unique_ptr<RequirementMachine> machine) {
465-
auto *machinePtr = machine.release();
466-
467-
machinePtr->freeze();
467+
if (!Context.LangOpts.EnableRequirementMachineReuse)
468+
return;
468469

469470
auto &component = getProtocolComponentImpl(proto);
470-
if (component.Machine == nullptr)
471-
component.Machine = machinePtr;
472-
else
473-
delete machinePtr;
471+
if (component.Machine != nullptr)
472+
return;
473+
474+
machine->freeze();
475+
component.Machine = machine.release();
474476
}
475477

476478
/// We print stats in the destructor, which should get executed at the end of

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,9 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
10011001
if (Args.hasArg(OPT_disable_requirement_machine_loop_normalization))
10021002
Opts.EnableRequirementMachineLoopNormalization = false;
10031003

1004+
if (Args.hasArg(OPT_disable_requirement_machine_reuse))
1005+
Opts.EnableRequirementMachineReuse = false;
1006+
10041007
if (Args.hasArg(OPT_enable_requirement_machine_opaque_archetypes))
10051008
Opts.EnableRequirementMachineOpaqueArchetypes = true;
10061009

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on
2+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
3+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -disable-requirement-machine-reuse -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
4+
5+
// CHECK-LABEL: .NonEmptyProtocol@
6+
// CHECK-NEXT: Requirement signature: <Self where Self : Collection, Self.[NonEmptyProtocol]C : Collection, Self.[Sequence]Element == Self.[NonEmptyProtocol]C.[Sequence]Element, Self.[Collection]Index == Self.[NonEmptyProtocol]C.[Collection]Index>
7+
8+
public protocol NonEmptyProtocol: Collection
9+
where Element == C.Element,
10+
Index == C.Index {
11+
associatedtype C: Collection
12+
}
13+
14+
// CHECK-LABEL: .MultiPoint@
15+
// CHECK-NEXT: Requirement signature: <Self where Self.[MultiPoint]C : CoordinateSystem, Self.[MultiPoint]X : NonEmptyProtocol, Self.[MultiPoint]C.[CoordinateSystem]P == Self.[MultiPoint]X.[Sequence]Element, Self.[MultiPoint]X.[NonEmptyProtocol]C : NonEmptyProtocol>
16+
17+
public protocol MultiPoint {
18+
associatedtype C: CoordinateSystem
19+
20+
typealias P = Self.C.P
21+
// expected-warning@-1 {{redundant same-type constraint 'Self.P' == 'Self.C.P'}}
22+
// FIXME: This is bogus
23+
24+
associatedtype X: NonEmptyProtocol
25+
where X.C: NonEmptyProtocol,
26+
X.Element == Self.P
27+
}
28+
29+
// CHECK-LABEL: .CoordinateSystem@
30+
// CHECK-NEXT: Requirement signature: <Self where Self == Self.[CoordinateSystem]B.[BoundingBox]C, Self.[CoordinateSystem]B : BoundingBox, Self.[CoordinateSystem]L : Line, Self.[CoordinateSystem]P : Point, Self.[CoordinateSystem]S : Size, Self.[CoordinateSystem]B.[BoundingBox]C == Self.[CoordinateSystem]L.[MultiPoint]C, Self.[CoordinateSystem]L.[MultiPoint]C == Self.[CoordinateSystem]P.[Point]C, Self.[CoordinateSystem]P.[Point]C == Self.[CoordinateSystem]S.[Size]C>
31+
32+
public protocol CoordinateSystem {
33+
associatedtype P: Point where Self.P.C == Self
34+
associatedtype S: Size where Self.S.C == Self
35+
associatedtype L: Line where Self.L.C == Self
36+
associatedtype B: BoundingBox where Self.B.C == Self
37+
}
38+
39+
// CHECK-LABEL: .Line@
40+
// CHECK-NEXT: Requirement signature: <Self where Self : MultiPoint>
41+
42+
public protocol Line: MultiPoint {}
43+
44+
// CHECK-LABEL: .Size@
45+
// CHECK-NEXT: Requirement signature: <Self where Self == Self.[Size]C.[CoordinateSystem]S, Self.[Size]C : CoordinateSystem>
46+
47+
public protocol Size {
48+
associatedtype C: CoordinateSystem where Self.C.S == Self
49+
}
50+
51+
// CHECK-LABEL: .BoundingBox@
52+
// CHECK-NEXT: Requirement signature: <Self where Self.[BoundingBox]C : CoordinateSystem>
53+
54+
public protocol BoundingBox {
55+
associatedtype C: CoordinateSystem
56+
typealias P = Self.C.P
57+
typealias S = Self.C.S
58+
}
59+
60+
// CHECK-LABEL: .Point@
61+
// CHECK-NEXT: Requirement signature: <Self where Self == Self.[Point]C.[CoordinateSystem]P, Self.[Point]C : CoordinateSystem>
62+
63+
public protocol Point {
64+
associatedtype C: CoordinateSystem where Self.C.P == Self
65+
}
66+
67+
func sameType<T>(_: T, _: T) {}
68+
69+
func conformsToPoint<T : Point>(_: T.Type) {}
70+
71+
func testMultiPoint<T : MultiPoint>(_: T) {
72+
sameType(T.C.P.self, T.X.Element.self)
73+
conformsToPoint(T.P.self)
74+
}
75+
76+
func testCoordinateSystem<T : CoordinateSystem>(_: T) {
77+
sameType(T.P.C.self, T.self)
78+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on
2+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
3+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -disable-requirement-machine-reuse -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
4+
5+
// CHECK-LABEL: .NonEmptyProtocol@
6+
// CHECK-NEXT: Requirement signature: <Self where Self : Collection, Self.[NonEmptyProtocol]C : Collection, Self.[Sequence]Element == Self.[NonEmptyProtocol]C.[Sequence]Element, Self.[Collection]Index == Self.[NonEmptyProtocol]C.[Collection]Index>
7+
8+
public protocol NonEmptyProtocol: Collection
9+
where Element == C.Element,
10+
Index == C.Index {
11+
associatedtype C: Collection
12+
}
13+
14+
// CHECK-LABEL: .MultiPoint@
15+
// CHECK-NEXT: Requirement signature: <Self where Self.[MultiPoint]C : CoordinateSystem, Self.[MultiPoint]P == Self.[MultiPoint]C.[CoordinateSystem]P, Self.[MultiPoint]X : NonEmptyProtocol, Self.[MultiPoint]C.[CoordinateSystem]P == Self.[MultiPoint]X.[Sequence]Element, Self.[MultiPoint]X.[NonEmptyProtocol]C : NonEmptyProtocol>
16+
17+
public protocol MultiPoint {
18+
associatedtype C: CoordinateSystem
19+
associatedtype P where Self.P == Self.C.P
20+
21+
associatedtype X: NonEmptyProtocol
22+
where X.C: NonEmptyProtocol,
23+
X.Element == Self.P
24+
}
25+
26+
// CHECK-LABEL: .CoordinateSystem@
27+
// CHECK-NEXT: Requirement signature: <Self where Self == Self.[CoordinateSystem]B.[BoundingBox]C, Self.[CoordinateSystem]B : BoundingBox, Self.[CoordinateSystem]L : Line, Self.[CoordinateSystem]P : Point, Self.[CoordinateSystem]S : Size, Self.[CoordinateSystem]B.[BoundingBox]C == Self.[CoordinateSystem]L.[MultiPoint]C, Self.[CoordinateSystem]L.[MultiPoint]C == Self.[CoordinateSystem]S.[Size]C>
28+
29+
public protocol CoordinateSystem {
30+
associatedtype P: Point where Self.P.C == Self
31+
associatedtype S: Size where Self.S.C == Self
32+
associatedtype L: Line where Self.L.C == Self
33+
associatedtype B: BoundingBox where Self.B.C == Self
34+
}
35+
36+
// CHECK-LABEL: .Line@
37+
// CHECK-NEXT: Requirement signature: <Self where Self : MultiPoint, Self.[MultiPoint]C == Self.[MultiPoint]P.[Point]C>
38+
39+
public protocol Line: MultiPoint {}
40+
41+
// CHECK-LABEL: .Size@
42+
// CHECK-NEXT: Requirement signature: <Self where Self == Self.[Size]C.[CoordinateSystem]S, Self.[Size]C : CoordinateSystem>
43+
44+
public protocol Size {
45+
associatedtype C: CoordinateSystem where Self.C.S == Self
46+
}
47+
48+
// CHECK-LABEL: .BoundingBox@
49+
// CHECK-NEXT: Requirement signature: <Self where Self.[BoundingBox]C : CoordinateSystem>
50+
51+
public protocol BoundingBox {
52+
associatedtype C: CoordinateSystem
53+
typealias P = Self.C.P
54+
typealias S = Self.C.S
55+
}
56+
57+
// CHECK-LABEL: .Point@
58+
// CHECK-NEXT: Requirement signature: <Self where Self == Self.[Point]C.[CoordinateSystem]P, Self.[Point]C : CoordinateSystem>
59+
60+
public protocol Point {
61+
associatedtype C: CoordinateSystem where Self.C.P == Self
62+
}
63+
64+
func sameType<T>(_: T, _: T) {}
65+
66+
func conformsToPoint<T : Point>(_: T.Type) {}
67+
68+
func testMultiPoint<T : MultiPoint>(_: T) {
69+
sameType(T.C.P.self, T.X.Element.self)
70+
conformsToPoint(T.P.self)
71+
}
72+
73+
func testCoordinateSystem<T : CoordinateSystem>(_: T) {
74+
sameType(T.P.C.self, T.self)
75+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on
2+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
3+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -disable-requirement-machine-reuse -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
4+
5+
// CHECK-LABEL: .NonEmptyProtocol@
6+
// CHECK-NEXT: Requirement signature: <Self where Self : Collection, Self.[NonEmptyProtocol]C : Collection, Self.[Sequence]Element == Self.[NonEmptyProtocol]C.[Sequence]Element, Self.[Collection]Index == Self.[NonEmptyProtocol]C.[Collection]Index>
7+
8+
public protocol NonEmptyProtocol: Collection
9+
where Element == C.Element,
10+
Index == C.Index {
11+
associatedtype C: Collection
12+
}
13+
14+
// CHECK-LABEL: .MultiPoint@
15+
// CHECK-NEXT: Requirement signature: <Self where Self.[MultiPoint]C : CoordinateSystem, Self.[MultiPoint]P == Self.[MultiPoint]C.[CoordinateSystem]P, Self.[MultiPoint]X : NonEmptyProtocol, Self.[MultiPoint]C.[CoordinateSystem]P == Self.[MultiPoint]X.[Sequence]Element, Self.[MultiPoint]X.[NonEmptyProtocol]C : NonEmptyProtocol>
16+
17+
public protocol MultiPoint {
18+
associatedtype C: CoordinateSystem
19+
associatedtype P: Point where Self.P == Self.C.P
20+
// expected-warning@-1 {{redundant conformance constraint 'Self.P' : 'Point'}}
21+
22+
associatedtype X: NonEmptyProtocol
23+
where X.C: NonEmptyProtocol,
24+
X.Element == Self.P
25+
}
26+
27+
// CHECK-LABEL: .CoordinateSystem@
28+
// CHECK-NEXT: Requirement signature: <Self where Self == Self.[CoordinateSystem]B.[BoundingBox]C, Self.[CoordinateSystem]B : BoundingBox, Self.[CoordinateSystem]L : Line, Self.[CoordinateSystem]P : Point, Self.[CoordinateSystem]S : Size, Self.[CoordinateSystem]B.[BoundingBox]C == Self.[CoordinateSystem]L.[MultiPoint]C, Self.[CoordinateSystem]L.[MultiPoint]C == Self.[CoordinateSystem]S.[Size]C>
29+
30+
public protocol CoordinateSystem {
31+
associatedtype P: Point where Self.P.C == Self
32+
associatedtype S: Size where Self.S.C == Self
33+
associatedtype L: Line where Self.L.C == Self
34+
associatedtype B: BoundingBox where Self.B.C == Self
35+
}
36+
37+
// CHECK-LABEL: .Line@
38+
// CHECK-NEXT: Requirement signature: <Self where Self : MultiPoint, Self.[MultiPoint]C == Self.[MultiPoint]P.[Point]C>
39+
40+
public protocol Line: MultiPoint {}
41+
42+
// CHECK-LABEL: .Size@
43+
// CHECK-NEXT: Requirement signature: <Self where Self == Self.[Size]C.[CoordinateSystem]S, Self.[Size]C : CoordinateSystem>
44+
45+
public protocol Size {
46+
associatedtype C: CoordinateSystem where Self.C.S == Self
47+
}
48+
49+
// CHECK-LABEL: .BoundingBox@
50+
// CHECK-NEXT: Requirement signature: <Self where Self.[BoundingBox]C : CoordinateSystem>
51+
52+
public protocol BoundingBox {
53+
associatedtype C: CoordinateSystem
54+
typealias P = Self.C.P
55+
typealias S = Self.C.S
56+
}
57+
58+
// CHECK-LABEL: .Point@
59+
// CHECK-NEXT: Requirement signature: <Self where Self == Self.[Point]C.[CoordinateSystem]P, Self.[Point]C : CoordinateSystem>
60+
61+
public protocol Point {
62+
associatedtype C: CoordinateSystem where Self.C.P == Self
63+
}
64+
65+
func sameType<T>(_: T, _: T) {}
66+
67+
func conformsToPoint<T : Point>(_: T.Type) {}
68+
69+
func testMultiPoint<T : MultiPoint>(_: T) {
70+
sameType(T.C.P.self, T.X.Element.self)
71+
conformsToPoint(T.P.self)
72+
}
73+
74+
func testCoordinateSystem<T : CoordinateSystem>(_: T) {
75+
sameType(T.P.C.self, T.self)
76+
}

0 commit comments

Comments
 (0)