diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index a330b63faedcb..8d570aa307800 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -4946,21 +4946,19 @@ ProtocolDecl::findProtocolSelfReferences(const ValueDecl *value, return result; } - return ::findProtocolSelfReferences(this, type, - skipAssocTypes); - } else if (auto subscript = dyn_cast(value)) { - // Check the requirements of a generic subscript. - if (subscript->isGeneric()) { - if (auto result = - ::findProtocolSelfReferences(this, - subscript->getGenericSignature())) - return result; - } - return ::findProtocolSelfReferences(this, type, skipAssocTypes); } else { - assert(isa(value)); + assert(isa(value)); + + if (auto *const subscript = dyn_cast(value)) { + // Check the requirements of a generic subscript. + if (subscript->isGeneric()) { + if (auto result = ::findProtocolSelfReferences( + this, subscript->getGenericSignature())) + return result; + } + } return ::findProtocolSelfReferences(this, type, skipAssocTypes); @@ -4978,6 +4976,12 @@ bool ProtocolDecl::isAvailableInExistential(const ValueDecl *decl) const { if (selfKind.parameter || selfKind.other) return false; + // FIXME: Appropriately diagnose assignments instead. + if (auto *const storageDecl = dyn_cast(decl)) { + if (selfKind.result && storageDecl->supportsMutation()) + return false; + } + return true; } diff --git a/test/decl/protocol/req/dynamic_self.swift b/test/decl/protocol/req/dynamic_self.swift index 758a301ef6f22..ef4f33a100b1d 100644 --- a/test/decl/protocol/req/dynamic_self.swift +++ b/test/decl/protocol/req/dynamic_self.swift @@ -86,3 +86,39 @@ enum EError : P { // expected-error{{type 'EError' does not conform to protocol subscript() -> Int { 0 } // expected-note{{candidate has non-matching type '() -> Int'}} func f() -> Int { 0 } // expected-note{{candidate has non-matching type '() -> Int'}} } + + +// Settable storage declaration requirements with a 'Self' result type may not +// be used with an existential base. +protocol P2 { + subscript() -> Self { get set } +} +protocol P3 { + var prop: Self { get set } +} +protocol P4 { + subscript() -> T where T.Element == Self { get set } +} +func takesP2P3P4(p2: P2, p3: P3, p4: P4) { } +// expected-error@-1{{protocol 'P2' can only be used as a generic constraint because it has Self or associated type requirements}} +// expected-error@-2{{protocol 'P3' can only be used as a generic constraint because it has Self or associated type requirements}} + +protocol P5 { +} +extension P5 { + var prop: Self { + get { self } + set { } + } + + subscript() -> Self { + get { self } + set { } + } +} +func takesP5(p5: P5) { + _ = p5[] + // expected-error@-1{{member 'subscript' cannot be used on value of protocol type 'P5'; use a generic constraint instead}} + _ = p5.prop + // expected-error@-1{{member 'prop' cannot be used on value of protocol type 'P5'; use a generic constraint instead}} +}