Skip to content

Commit e05a732

Browse files
committed
Sema: Fix crash-on-invalid on protocol requirements with 'where' clause constraints
RequirementEnvironment wasn't prepared to handle a protocol requirement with additional 'where' clause constraints but no generic parameters. Since such a requirement necessarily runs afoul of the existing "protocol requirements cannot constrain Self" rule, it suffices to ignore such requirements when matching witnesses and let the declaration checker diagnose this situation later. Fixes <rdar://problem/61876053>.
1 parent c98d04b commit e05a732

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,14 @@ swift::matchWitness(WitnessChecker::RequirementEnvironmentCache &reqEnvCache,
850850
Type openedFullWitnessType;
851851
Type reqType, openedFullReqType;
852852

853-
auto reqSig = req->getInnermostDeclContext()->getGenericSignatureOfContext();
853+
GenericSignature reqSig = proto->getGenericSignature();
854+
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(req)) {
855+
if (funcDecl->isGeneric())
856+
reqSig = funcDecl->getGenericSignature();
857+
} else if (auto *subscriptDecl = dyn_cast<SubscriptDecl>(req)) {
858+
if (subscriptDecl->isGeneric())
859+
reqSig = subscriptDecl->getGenericSignature();
860+
}
854861

855862
ClassDecl *covariantSelf = nullptr;
856863
if (witness->getDeclContext()->getExtendedProtocolDecl()) {

test/decl/protocol/req/unsatisfiable.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,25 @@ protocol P4 {
5858
protocol P5 {
5959
associatedtype Y where Y : S // expected-error {{type 'Self.Y' constrained to non-protocol, non-class type 'S'}}
6060
}
61+
62+
protocol P6 {
63+
associatedtype T
64+
associatedtype U
65+
66+
func foo() where T == U
67+
// expected-error@-1 {{instance method requirement 'foo()' cannot add constraint 'Self.T == Self.U' on 'Self'}}
68+
// expected-note@-2 {{protocol requires function 'foo()' with type '() -> ()'; do you want to add a stub?}}
69+
}
70+
71+
struct S2 : P6 {
72+
// expected-error@-1 {{type 'S2' does not conform to protocol 'P6'}}
73+
typealias T = Int
74+
typealias U = String
75+
76+
func foo() {}
77+
// expected-note@-1 {{candidate has non-matching type '() -> ()'}}
78+
79+
// FIXME: This error is bogus and should be omitted on account of the protocol requirement itself
80+
// being invalid.
81+
}
82+

0 commit comments

Comments
 (0)