RequirementMachine: Perform concrete contraction on protocol requirement signatures

This commit is contained in:
Slava Pestov
2022-04-30 00:49:56 -04:00
parent 75f6682969
commit 0111618c50
7 changed files with 68 additions and 33 deletions

View File

@@ -287,6 +287,8 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
rewriteCtx.finishComputingRequirementSignatures(proto);
};
SmallVector<RequirementError, 4> errors;
// Collect user-written requirements from the protocols in this connected
// component.
llvm::DenseMap<const ProtocolDecl *,
@@ -297,6 +299,20 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
requirements.push_back(req);
for (auto req : proto->getTypeAliasRequirements())
requirements.push_back({req, SourceLoc(), /*inferred=*/false});
// Preprocess requirements to eliminate conformances on type parameters
// which are made concrete.
if (ctx.LangOpts.EnableRequirementMachineConcreteContraction) {
SmallVector<StructuralRequirement, 4> contractedRequirements;
bool debug = rewriteCtx.getDebugOptions()
.contains(DebugFlags::ConcreteContraction);
if (performConcreteContraction(requirements, contractedRequirements,
errors, debug)) {
std::swap(contractedRequirements, requirements);
}
}
}
if (rewriteCtx.getDebugOptions().contains(DebugFlags::Timers)) {
@@ -409,7 +425,6 @@ RequirementSignatureRequestRQM::evaluate(Evaluator &evaluator,
// Diagnose redundant requirements and conflicting requirements.
if (ctx.LangOpts.RequirementMachineProtocolSignatures ==
RequirementMachineMode::Enabled) {
SmallVector<RequirementError, 4> errors;
machine->computeRequirementDiagnostics(errors, proto->getLoc());
diagnoseRequirementErrors(ctx, errors,
AllowConcreteTypePolicy::NestedAssocTypes);

View File

@@ -1,8 +1,6 @@
// RUN: %target-typecheck-verify-swift
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures 2>&1 | %FileCheck %s
// rdar://problem/88135912
// XFAIL: *
protocol P {
associatedtype T
}
@@ -15,6 +13,7 @@ struct S : P {
protocol R0 {
associatedtype A where A : P, A == S
// expected-warning@-1 {{redundant conformance constraint 'S' : 'P'}}
}
////
@@ -27,6 +26,7 @@ struct G<T> : P {}
protocol R1 {
associatedtype A
associatedtype B where B : P, B == G<A>
// expected-warning@-1 {{redundant conformance constraint 'G<Self.A>' : 'P'}}
}
// CHECK-LABEL: concrete_conformances_in_protocol.(file).R2@
@@ -34,6 +34,7 @@ protocol R1 {
protocol R2 {
associatedtype A where A : P, A == G<B>
// expected-warning@-1 {{redundant conformance constraint 'G<Self.B>' : 'P'}}
associatedtype B
}
@@ -51,6 +52,7 @@ struct GG<T : P> : PP {}
protocol RR3 {
associatedtype A : P
associatedtype B where B : PP, B == GG<A>
// expected-warning@-1 {{redundant conformance constraint 'GG<Self.A>' : 'PP'}}
}
// CHECK-LABEL: concrete_conformances_in_protocol.(file).RR4@
@@ -58,6 +60,7 @@ protocol RR3 {
protocol RR4 {
associatedtype A where A : PP, A == GG<B>
// expected-warning@-1 {{redundant conformance constraint 'GG<Self.B>' : 'PP'}}
associatedtype B : P
}
@@ -67,6 +70,7 @@ protocol RR4 {
protocol RR5 {
associatedtype A : PP
associatedtype B where B : PP, B == GG<A.T>
// expected-warning@-1 {{redundant conformance constraint 'GG<Self.A.T>' : 'PP'}}
}
// CHECK-LABEL: concrete_conformances_in_protocol.(file).RR6@
@@ -74,5 +78,24 @@ protocol RR5 {
protocol RR6 {
associatedtype A where A : PP, A == GG<B.T>
// expected-warning@-1 {{redundant conformance constraint 'GG<Self.B.T>' : 'PP'}}
associatedtype B : PP
}
protocol P1 {
associatedtype T : P1
}
struct GGG<U : P1> : P1 {
typealias T = GGG<GGG<U>>
}
// CHECK-LABEL: concrete_conformances_in_protocol.(file).P2@
// CHECK-LABEL: Requirement signature: <Self where Self.[P2]T == GGG<Self.[P2]U>, Self.[P2]U : P1>
protocol P2 {
associatedtype T : P1 where T == GGG<U>
// expected-warning@-1 {{redundant conformance constraint 'GGG<Self.U>' : 'P1'}}
associatedtype U : P1
}

View File

@@ -1,18 +1,22 @@
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=verify -requirement-machine-inferred-signatures=verify 2>&1 | %FileCheck %s
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures -requirement-machine-protocol-signatures=on -requirement-machine-inferred-signatures=on 2>&1 | %FileCheck %s
// FIXME: The redundant conformance warnings here should not be emitted, since
// these requirements participate in conditional requirement inference.
// CHECK-LABEL: conditional_requirement_inference_in_protocol.(file).Good@
// CHECK-LABEL: Requirement signature: <Self where Self.[Good]T == [Self.[Good]U], Self.[Good]U : Equatable>
protocol Good {
associatedtype T : Equatable // expected-warning {{redundant conformance constraint 'Self.T' : 'Equatable'}}
associatedtype U : Equatable where T == Array<U> // expected-note {{conformance constraint 'Self.T' : 'Equatable' implied here}}
associatedtype T : Equatable // expected-warning {{redundant conformance constraint 'Array<Self.U>' : 'Equatable'}}
associatedtype U : Equatable where T == Array<U>
// expected-warning@-1 {{redundant conformance constraint 'Self.U' : 'Equatable'}}
}
// CHECK-LABEL: conditional_requirement_inference_in_protocol.(file).Bad@
// CHECK-LABEL: Requirement signature: <Self where Self.[Bad]T == [Self.[Bad]U]>
// CHECK-LABEL: Requirement signature: <Self where Self.[Bad]T == [Self.[Bad]U], Self.[Bad]U : Equatable>
protocol Bad {
associatedtype T : Equatable // expected-warning {{redundant conformance constraint 'Self.T' : 'Equatable'}}
associatedtype U where T == Array<U> // expected-note {{conformance constraint 'Self.T' : 'Equatable' implied here}}
associatedtype T : Equatable // expected-warning {{redundant conformance constraint 'Array<Self.U>' : 'Equatable'}}
associatedtype U where T == Array<U>
}

View File

@@ -1,9 +1,5 @@
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=off
// RUN: %target-swift-frontend -debug-generic-signatures -typecheck %s -requirement-machine-protocol-signatures=off 2>&1 | %FileCheck %s
// FIXME: Implement concrete contraction for the Requirement Machine's
// RequirementSignatureRequest to get this to pass without turning off
// -requirement-machine-protocol-signatures.
// RUN: %target-typecheck-verify-swift -requirement-machine-protocol-signatures=on
// RUN: %target-swift-frontend -debug-generic-signatures -typecheck %s -requirement-machine-protocol-signatures=on 2>&1 | %FileCheck %s
protocol P24 {
associatedtype C: P20
@@ -29,8 +25,8 @@ class X3 { }
// CHECK-NEXT: Requirement signature: <Self where Self.[P25a]A == X24<Self.[P25a]B>, Self.[P25a]B : P20>
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P25a]A == X24<τ_0_0.[P25a]B>, τ_0_0.[P25a]B : P20>
protocol P25a {
associatedtype A: P24 // expected-warning{{redundant conformance constraint 'Self.A' : 'P24'}}
associatedtype B: P20 where A == X24<B> // expected-note{{conformance constraint 'Self.A' : 'P24' implied here}}
associatedtype A: P24 // expected-warning{{redundant conformance constraint 'X24<Self.B>' : 'P24'}}
associatedtype B: P20 where A == X24<B>
}
// CHECK-LABEL: .P25b@
@@ -45,9 +41,9 @@ protocol P25b {
// CHECK-NEXT: Requirement signature: <Self where Self.[P27a]A == X26<Self.[P27a]B>, Self.[P27a]B : X3>
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.[P27a]A == X26<τ_0_0.[P27a]B>, τ_0_0.[P27a]B : X3>
protocol P27a {
associatedtype A: P26 // expected-warning{{redundant conformance constraint 'Self.A' : 'P26'}}
associatedtype A: P26 // expected-warning{{redundant conformance constraint 'X26<Self.B>' : 'P26'}}
associatedtype B: X3 where A == X26<B> // expected-note{{conformance constraint 'Self.A' : 'P26' implied here}}
associatedtype B: X3 where A == X26<B>
}
// CHECK-LABEL: .P27b@

View File

@@ -43,11 +43,12 @@ struct S<U : P1> : P1 {
typealias T = S<S<U>>
}
protocol P3 {
// expected-error@-1 {{cannot build rewrite system for protocol; rule length limit exceeded}}
// 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]}}
associatedtype T : P1 where T == S<U>
// expected-error@-1 {{type 'Self.U' does not conform to protocol 'P1'}}
protocol P3Base {
associatedtype T : P1
associatedtype U : P1
}
protocol P3 : P3Base where T == S<U> {
// expected-error@-1 {{cannot build rewrite system for protocol; rule length limit exceeded}}
// 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]}}
}

View File

@@ -1,6 +1,4 @@
// RUN: %target-swift-frontend -primary-file %s -emit-ir -requirement-machine-protocol-signatures=off
// TODO: Get this to pass with -requirement-machine-protocol-signatures=on.
// RUN: %target-swift-frontend -primary-file %s -emit-ir -requirement-machine-protocol-signatures=on
public protocol WrappedSignedInteger: SignedInteger where Stride == Int {
typealias WrappedInteger = Int

View File

@@ -1,6 +1,4 @@
// RUN: %target-swift-frontend -emit-ir -primary-file %s -debug-generic-signatures -requirement-machine-protocol-signatures=off 2>&1 | %FileCheck %s
// FIXME: Get this working with -requirement-machine-protocol-signatures=on again
// RUN: %target-swift-frontend -emit-ir -primary-file %s -debug-generic-signatures -requirement-machine-protocol-signatures=on 2>&1 | %FileCheck %s
public protocol FooProtocol {
associatedtype Bar