Skip to content

Commit 965ba21

Browse files
authored
Merge pull request swiftlang#58553 from slavapestov/rqm-concrete-contraction-type-parameters
RequirementMachine: Teach concrete contraction about nested associated types
2 parents bda01a7 + ae56af3 commit 965ba21

14 files changed

+275
-193
lines changed

lib/AST/RequirementMachine/ConcreteContraction.cpp

Lines changed: 167 additions & 152 deletions
Large diffs are not rendered by default.

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);

lib/AST/RequirementMachine/RuleBuilder.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,21 @@ void RuleBuilder::initWithProtocolSignatureRequirements(
101101
addPermanentProtocolRules(proto);
102102

103103
auto reqs = proto->getRequirementSignature();
104+
105+
// If completion failed, we'll have a totally empty requirement signature,
106+
// but to maintain invariants around what constitutes a valid rewrite term
107+
// between getTypeForTerm() and isValidTypeInContext(), we need to add rules
108+
// for inherited protocols.
109+
if (reqs.getErrors().contains(GenericSignatureErrorFlags::CompletionFailed)) {
110+
for (auto *inheritedProto : Context.getInheritedProtocols(proto)) {
111+
Requirement req(RequirementKind::Conformance,
112+
proto->getSelfInterfaceType(),
113+
inheritedProto->getDeclaredInterfaceType());
114+
115+
addRequirement(req.getCanonical(), proto);
116+
}
117+
}
118+
104119
for (auto req : reqs.getRequirements())
105120
addRequirement(req.getCanonical(), proto);
106121
for (auto alias : reqs.getTypeAliases())

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+

test/Generics/concrete_same_type_versus_anyobject.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ extension G2 where U == S, U : AnyObject {}
2525
// CHECK: ExtensionDecl line={{.*}} base=G2
2626
// CHECK-NEXT: Generic signature: <U where U == C>
2727
extension G2 where U == C, U : AnyObject {}
28-
// expected-warning@-1 {{redundant constraint 'C' : 'AnyObject'}}
28+
// expected-warning@-1 {{redundant constraint 'U' : 'AnyObject'}}
2929

3030
// CHECK: ExtensionDecl line={{.*}} base=G2
3131
// CHECK-NEXT: Generic signature: <U where U : C>
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
}

test/Generics/rdar91594361.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
2+
3+
protocol P1 {
4+
associatedtype T
5+
}
6+
7+
protocol P2 {
8+
associatedtype T : P3
9+
}
10+
11+
protocol P3 {}
12+
13+
struct G<T : P3> : P2 {}
14+
15+
extension P1 where T : P2 {
16+
// CHECK-LABEL: .foo@
17+
// CHECK-NEXT: <Self, X where Self : P1, X : P3, Self.[P1]T == G<X>>
18+
func foo<X>(_: X) where T == G<X> {}
19+
}
20+

test/Generics/requirement_inference.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=off
2-
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
1+
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=verify
2+
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
33

44
protocol P1 {
55
func p1()

test/Generics/requirement_machine_diagnostics.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,18 +295,18 @@ func sameTypeConflicts() {
295295
fatalError()
296296
}
297297

298-
// expected-error@+1{{no type for 'T.Bar.Foo' can satisfy both 'T.Bar.Foo == X' and 'T.Bar.Foo == Z'}}
299298
func fail4<T: Barrable>(_ t: T) -> (Y, Z)
300299
where
301300
T.Bar == Y,
302301
T.Bar.Foo == Z {
302+
// expected-error@-1{{generic signature requires types 'Y.Foo' (aka 'X') and 'Z' to be the same}}
303303
fatalError()
304304
}
305305

306-
// expected-error@+1{{no type for 'T.Bar.Foo' can satisfy both 'T.Bar.Foo == X' and 'T.Bar.Foo == Z'}}
307306
func fail5<T: Barrable>(_ t: T) -> (Y, Z)
308307
where
309308
T.Bar.Foo == Z,
309+
// expected-error@-1{{generic signature requires types 'Y.Foo' (aka 'X') and 'Z' to be the same}}
310310
T.Bar == Y {
311311
fatalError()
312312
}

test/attr/accessibility_where_clause.swift

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

33
public class OuterClass {
44
class InnerClass {}
@@ -17,9 +17,6 @@ public protocol PublicProto2 {
1717
// FIXME: Once we no longer do that, come up with another strategy
1818
// to make the above diagnose.
1919

20-
// FIXME: Get this working with the Requirement Machine, or decide that it should
21-
// be unsupported: rdar://90469477
22-
2320
extension PublicProto2 where Self.T : OuterClass, Self.U == Self.T.InnerClass {
2421
public func cannotBePublic() {}
2522
// expected-error@-1 {{cannot declare a public instance method in an extension with internal requirements}}

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)