Skip to content

Commit 0111618

Browse files
committed
RequirementMachine: Perform concrete contraction on protocol requirement signatures
1 parent 75f6682 commit 0111618

File tree

7 files changed

+67
-32
lines changed

7 files changed

+67
-32
lines changed

lib/AST/RequirementMachine/RequirementMachineRequests.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
287287
rewriteCtx.finishComputingRequirementSignatures(proto);
288288
};
289289

290+
SmallVector<RequirementError, 4> errors;
291+
290292
// Collect user-written requirements from the protocols in this connected
291293
// component.
292294
llvm::DenseMap<const ProtocolDecl *,
@@ -297,6 +299,20 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
297299
requirements.push_back(req);
298300
for (auto req : proto->getTypeAliasRequirements())
299301
requirements.push_back({req, SourceLoc(), /*inferred=*/false});
302+
303+
// Preprocess requirements to eliminate conformances on type parameters
304+
// which are made concrete.
305+
if (ctx.LangOpts.EnableRequirementMachineConcreteContraction) {
306+
SmallVector<StructuralRequirement, 4> contractedRequirements;
307+
308+
bool debug = rewriteCtx.getDebugOptions()
309+
.contains(DebugFlags::ConcreteContraction);
310+
311+
if (performConcreteContraction(requirements, contractedRequirements,
312+
errors, debug)) {
313+
std::swap(contractedRequirements, requirements);
314+
}
315+
}
300316
}
301317

302318
if (rewriteCtx.getDebugOptions().contains(DebugFlags::Timers)) {
@@ -409,7 +425,6 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
409425
// Diagnose redundant requirements and conflicting requirements.
410426
if (ctx.LangOpts.RequirementMachineProtocolSignatures ==
411427
RequirementMachineMode::Enabled) {
412-
SmallVector<RequirementError, 4> errors;
413428
machine->computeRequirementDiagnostics(errors, proto->getLoc());
414429
diagnoseRequirementErrors(ctx, errors,
415430
AllowConcreteTypePolicy::NestedAssocTypes);

test/Generics/concrete_conformances_in_protocol.swift

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1+
// RUN: %target-typecheck-verify-swift
12
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures 2>&1 | %FileCheck %s
23

3-
// rdar://problem/88135912
4-
// XFAIL: *
5-
64
protocol P {
75
associatedtype T
86
}
@@ -15,6 +13,7 @@ struct S : P {
1513

1614
protocol R0 {
1715
associatedtype A where A : P, A == S
16+
// expected-warning@-1 {{redundant conformance constraint 'S' : 'P'}}
1817
}
1918

2019
////
@@ -27,13 +26,15 @@ struct G<T> : P {}
2726
protocol R1 {
2827
associatedtype A
2928
associatedtype B where B : P, B == G<A>
29+
// expected-warning@-1 {{redundant conformance constraint 'G<Self.A>' : 'P'}}
3030
}
3131

3232
// CHECK-LABEL: concrete_conformances_in_protocol.(file).R2@
3333
// CHECK-LABEL: Requirement signature: <Self where Self.[R2]A == G<Self.[R2]B>>
3434

3535
protocol R2 {
3636
associatedtype A where A : P, A == G<B>
37+
// expected-warning@-1 {{redundant conformance constraint 'G<Self.B>' : 'P'}}
3738
associatedtype B
3839
}
3940

@@ -51,13 +52,15 @@ struct GG<T : P> : PP {}
5152
protocol RR3 {
5253
associatedtype A : P
5354
associatedtype B where B : PP, B == GG<A>
55+
// expected-warning@-1 {{redundant conformance constraint 'GG<Self.A>' : 'PP'}}
5456
}
5557

5658
// CHECK-LABEL: concrete_conformances_in_protocol.(file).RR4@
5759
// CHECK-LABEL: Requirement signature: <Self where Self.[RR4]A == GG<Self.[RR4]B>, Self.[RR4]B : P>
5860

5961
protocol RR4 {
6062
associatedtype A where A : PP, A == GG<B>
63+
// expected-warning@-1 {{redundant conformance constraint 'GG<Self.B>' : 'PP'}}
6164
associatedtype B : P
6265
}
6366

@@ -67,12 +70,32 @@ protocol RR4 {
6770
protocol RR5 {
6871
associatedtype A : PP
6972
associatedtype B where B : PP, B == GG<A.T>
73+
// expected-warning@-1 {{redundant conformance constraint 'GG<Self.A.T>' : 'PP'}}
7074
}
7175

7276
// CHECK-LABEL: concrete_conformances_in_protocol.(file).RR6@
7377
// CHECK-LABEL: Requirement signature: <Self where Self.[RR6]A == GG<Self.[RR6]B.[PP]T>, Self.[RR6]B : PP>
7478

7579
protocol RR6 {
7680
associatedtype A where A : PP, A == GG<B.T>
81+
// expected-warning@-1 {{redundant conformance constraint 'GG<Self.B.T>' : 'PP'}}
7782
associatedtype B : PP
7883
}
84+
85+
protocol P1 {
86+
associatedtype T : P1
87+
}
88+
89+
struct GGG<U : P1> : P1 {
90+
typealias T = GGG<GGG<U>>
91+
}
92+
93+
// CHECK-LABEL: concrete_conformances_in_protocol.(file).P2@
94+
// CHECK-LABEL: Requirement signature: <Self where Self.[P2]T == GGG<Self.[P2]U>, Self.[P2]U : P1>
95+
96+
protocol P2 {
97+
associatedtype T : P1 where T == GGG<U>
98+
// expected-warning@-1 {{redundant conformance constraint 'GGG<Self.U>' : 'P1'}}
99+
associatedtype U : P1
100+
}
101+
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
2-
// RUN: %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 -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+
4+
// FIXME: The redundant conformance warnings here should not be emitted, since
5+
// these requirements participate in conditional requirement inference.
36

47
// CHECK-LABEL: conditional_requirement_inference_in_protocol.(file).Good@
58
// CHECK-LABEL: Requirement signature: <Self where Self.[Good]T == [Self.[Good]U], Self.[Good]U : Equatable>
69

710
protocol Good {
8-
associatedtype T : Equatable // expected-warning {{redundant conformance constraint 'Self.T' : 'Equatable'}}
9-
associatedtype U : Equatable where T == Array<U> // expected-note {{conformance constraint 'Self.T' : 'Equatable' implied here}}
11+
associatedtype T : Equatable // expected-warning {{redundant conformance constraint 'Array<Self.U>' : 'Equatable'}}
12+
associatedtype U : Equatable where T == Array<U>
13+
// expected-warning@-1 {{redundant conformance constraint 'Self.U' : 'Equatable'}}
1014
}
1115

1216
// CHECK-LABEL: conditional_requirement_inference_in_protocol.(file).Bad@
13-
// CHECK-LABEL: Requirement signature: <Self where Self.[Bad]T == [Self.[Bad]U]>
17+
// CHECK-LABEL: Requirement signature: <Self where Self.[Bad]T == [Self.[Bad]U], Self.[Bad]U : Equatable>
1418

1519
protocol Bad {
16-
associatedtype T : Equatable // expected-warning {{redundant conformance constraint 'Self.T' : 'Equatable'}}
17-
associatedtype U where T == Array<U> // expected-note {{conformance constraint 'Self.T' : 'Equatable' implied here}}
20+
associatedtype T : Equatable // expected-warning {{redundant conformance constraint 'Array<Self.U>' : 'Equatable'}}
21+
associatedtype U where T == Array<U>
1822
}

test/Generics/derived_via_concrete_in_protocol.swift

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=off
2-
// RUN: %target-swift-frontend -debug-generic-signatures -typecheck %s -requirement-machine-protocol-signatures=off 2>&1 | %FileCheck %s
3-
4-
// FIXME: Implement concrete contraction for the Requirement Machine's
5-
// RequirementSignatureRequest to get this to pass without turning off
6-
// -requirement-machine-protocol-signatures.
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on
2+
// RUN: %target-swift-frontend -debug-generic-signatures -typecheck %s -requirement-machine-protocol-signatures=on 2>&1 | %FileCheck %s
73

84
protocol P24 {
95
associatedtype C: P20
@@ -29,8 +25,8 @@ class X3 { }
2925
// CHECK-NEXT: Requirement signature: <Self where Self.[P25a]A == X24<Self.[P25a]B>, Self.[P25a]B : P20>
3026
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P25a]A == X24<τ_0_0.[P25a]B>, τ_0_0.[P25a]B : P20>
3127
protocol P25a {
32-
associatedtype A: P24 // expected-warning{{redundant conformance constraint 'Self.A' : 'P24'}}
33-
associatedtype B: P20 where A == X24<B> // expected-note{{conformance constraint 'Self.A' : 'P24' implied here}}
28+
associatedtype A: P24 // expected-warning{{redundant conformance constraint 'X24<Self.B>' : 'P24'}}
29+
associatedtype B: P20 where A == X24<B>
3430
}
3531

3632
// CHECK-LABEL: .P25b@
@@ -45,9 +41,9 @@ protocol P25b {
4541
// CHECK-NEXT: Requirement signature: <Self where Self.[P27a]A == X26<Self.[P27a]B>, Self.[P27a]B : X3>
4642
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P27a]A == X26<τ_0_0.[P27a]B>, τ_0_0.[P27a]B : X3>
4743
protocol P27a {
48-
associatedtype A: P26 // expected-warning{{redundant conformance constraint 'Self.A' : 'P26'}}
44+
associatedtype A: P26 // expected-warning{{redundant conformance constraint 'X26<Self.B>' : 'P26'}}
4945

50-
associatedtype B: X3 where A == X26<B> // expected-note{{conformance constraint 'Self.A' : 'P26' implied here}}
46+
associatedtype B: X3 where A == X26<B>
5147
}
5248

5349
// CHECK-LABEL: .P27b@

test/Generics/non_confluent.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ struct S<U : P1> : P1 {
4343
typealias T = S<S<U>>
4444
}
4545

46-
protocol P3 {
46+
protocol P3Base {
47+
associatedtype T : P1
48+
associatedtype U : P1
49+
}
50+
51+
protocol P3 : P3Base where T == S<U> {
4752
// expected-error@-1 {{cannot build rewrite system for protocol; rule length limit exceeded}}
4853
// expected-note@-2 {{failed rewrite rule is [P3:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[concrete: S<S<S<S<S<S<S<S<S<S<S<S<S<S<[P3:U]>>>>>>>>>>>>>>] => [P3:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T].[P1:T]}}
49-
50-
associatedtype T : P1 where T == S<U>
51-
// expected-error@-1 {{type 'Self.U' does not conform to protocol 'P1'}}
52-
associatedtype U : P1
5354
}

validation-test/compiler_crashers_2_fixed/rdar56398071.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// RUN: %target-swift-frontend -primary-file %s -emit-ir -requirement-machine-protocol-signatures=off
2-
3-
// TODO: Get this to pass with -requirement-machine-protocol-signatures=on.
1+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -requirement-machine-protocol-signatures=on
42

53
public protocol WrappedSignedInteger: SignedInteger where Stride == Int {
64
typealias WrappedInteger = Int

validation-test/compiler_crashers_2_fixed/sr11639.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// RUN: %target-swift-frontend -emit-ir -primary-file %s -debug-generic-signatures -requirement-machine-protocol-signatures=off 2>&1 | %FileCheck %s
2-
3-
// FIXME: Get this working with -requirement-machine-protocol-signatures=on again
1+
// RUN: %target-swift-frontend -emit-ir -primary-file %s -debug-generic-signatures -requirement-machine-protocol-signatures=on 2>&1 | %FileCheck %s
42

53
public protocol FooProtocol {
64
associatedtype Bar

0 commit comments

Comments
 (0)