Skip to content

Commit 6b6b8da

Browse files
Merge pull request #65146 from AnthonyLatsis/existential-any-multimodule-5.9
[5.9 🍒] TypeCheckType: Fix existential `any` migration diagnostics for extra-modular protocols
2 parents d4327cc + f0d5990 commit 6b6b8da

14 files changed

+139
-63
lines changed

include/swift/AST/Decl.h

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -553,11 +553,12 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
553553
/// Whether the existential of this protocol conforms to itself.
554554
ExistentialConformsToSelf : 1,
555555

556-
/// Whether the \c ExistentialRequiresAny bit is valid.
557-
ExistentialRequiresAnyValid : 1,
556+
/// Whether the \c HasSelfOrAssociatedTypeRequirements bit is valid.
557+
HasSelfOrAssociatedTypeRequirementsValid : 1,
558558

559-
/// Whether the existential of this protocol must be spelled with \c any.
560-
ExistentialRequiresAny : 1,
559+
/// Whether this protocol has \c Self or associated type requirements.
560+
/// See \c hasSelfOrAssociatedTypeRequirements() for clarification.
561+
HasSelfOrAssociatedTypeRequirements : 1,
561562

562563
/// True if the protocol has requirements that cannot be satisfied (e.g.
563564
/// because they could not be imported from Objective-C).
@@ -4770,19 +4771,19 @@ class ProtocolDecl final : public NominalTypeDecl {
47704771
Bits.ProtocolDecl.ExistentialConformsToSelf = result;
47714772
}
47724773

4773-
/// Returns the cached result of \c existentialRequiresAny or \c None if it
4774-
/// hasn't yet been computed.
4775-
Optional<bool> getCachedExistentialRequiresAny() {
4776-
if (Bits.ProtocolDecl.ExistentialRequiresAnyValid)
4777-
return Bits.ProtocolDecl.ExistentialRequiresAny;
4774+
/// Returns the cached result of \c hasSelfOrAssociatedTypeRequirements or
4775+
/// \c None if it hasn't yet been computed.
4776+
Optional<bool> getCachedHasSelfOrAssociatedTypeRequirements() {
4777+
if (Bits.ProtocolDecl.HasSelfOrAssociatedTypeRequirementsValid)
4778+
return Bits.ProtocolDecl.HasSelfOrAssociatedTypeRequirements;
47784779

47794780
return None;
47804781
}
47814782

4782-
/// Caches the result of \c existentialRequiresAny
4783-
void setCachedExistentialRequiresAny(bool requiresAny) {
4784-
Bits.ProtocolDecl.ExistentialRequiresAnyValid = true;
4785-
Bits.ProtocolDecl.ExistentialRequiresAny = requiresAny;
4783+
/// Caches the result of \c hasSelfOrAssociatedTypeRequirements
4784+
void setCachedHasSelfOrAssociatedTypeRequirements(bool value) {
4785+
Bits.ProtocolDecl.HasSelfOrAssociatedTypeRequirementsValid = true;
4786+
Bits.ProtocolDecl.HasSelfOrAssociatedTypeRequirements = value;
47864787
}
47874788

47884789
bool hasLazyRequirementSignature() const {
@@ -4803,7 +4804,7 @@ class ProtocolDecl final : public NominalTypeDecl {
48034804
friend class RequirementSignatureRequestGSB;
48044805
friend class ProtocolRequiresClassRequest;
48054806
friend class ExistentialConformsToSelfRequest;
4806-
friend class ExistentialRequiresAnyRequest;
4807+
friend class HasSelfOrAssociatedTypeRequirementsRequest;
48074808
friend class InheritedProtocolsRequest;
48084809
friend class PrimaryAssociatedTypesRequest;
48094810
friend class ProtocolRequirementsRequest;
@@ -4902,9 +4903,20 @@ class ProtocolDecl final : public NominalTypeDecl {
49024903
/// Does this protocol require a self-conformance witness table?
49034904
bool requiresSelfConformanceWitnessTable() const;
49044905

4905-
/// Determine whether an existential type must be explicitly prefixed
4906-
/// with \c any. \c any is required if any of the members contain
4907-
/// an associated type, or if \c Self appears in non-covariant position.
4906+
/// Determine whether this protocol has `Self` or associated type
4907+
/// requirements.
4908+
///
4909+
/// This is true if one of the following conditions is met for this protocol
4910+
/// or an inherited protocol:
4911+
/// - The protocol has an associated type requirement.
4912+
/// - `Self` appears in non-covariant position in the type signature of a
4913+
/// value requirement.
4914+
bool hasSelfOrAssociatedTypeRequirements() const;
4915+
4916+
/// Determine whether an existential type constrained by this protocol must
4917+
/// be written using `any` syntax.
4918+
///
4919+
/// \Note This method takes language feature state into account.
49084920
bool existentialRequiresAny() const;
49094921

49104922
/// Returns a list of protocol requirements that must be assessed to

include/swift/AST/TypeCheckRequests.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,8 @@ class ExistentialConformsToSelfRequest :
300300

301301
/// Determine whether an existential type conforming to this protocol
302302
/// requires the \c any syntax.
303-
class ExistentialRequiresAnyRequest :
304-
public SimpleRequest<ExistentialRequiresAnyRequest,
303+
class HasSelfOrAssociatedTypeRequirementsRequest :
304+
public SimpleRequest<HasSelfOrAssociatedTypeRequirementsRequest,
305305
bool(ProtocolDecl *),
306306
RequestFlags::SeparatelyCached> {
307307
public:

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ SWIFT_REQUEST(TypeChecker, EnumRawTypeRequest,
9595
Type(EnumDecl *), Cached, NoLocationInfo)
9696
SWIFT_REQUEST(TypeChecker, ExistentialConformsToSelfRequest,
9797
bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo)
98-
SWIFT_REQUEST(TypeChecker, ExistentialRequiresAnyRequest,
98+
SWIFT_REQUEST(TypeChecker, HasSelfOrAssociatedTypeRequirementsRequest,
9999
bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo)
100100
SWIFT_REQUEST(TypeChecker, ExtendedTypeRequest, Type(ExtensionDecl *), Cached,
101101
NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6052,9 +6052,18 @@ bool ProtocolDecl::existentialConformsToSelf() const {
60526052
ExistentialConformsToSelfRequest{const_cast<ProtocolDecl *>(this)}, true);
60536053
}
60546054

6055-
bool ProtocolDecl::existentialRequiresAny() const {
6055+
bool ProtocolDecl::hasSelfOrAssociatedTypeRequirements() const {
60566056
return evaluateOrDefault(getASTContext().evaluator,
6057-
ExistentialRequiresAnyRequest{const_cast<ProtocolDecl *>(this)}, true);
6057+
HasSelfOrAssociatedTypeRequirementsRequest{
6058+
const_cast<ProtocolDecl *>(this)},
6059+
true);
6060+
}
6061+
6062+
bool ProtocolDecl::existentialRequiresAny() const {
6063+
if (getASTContext().LangOpts.hasFeature(Feature::ExistentialAny))
6064+
return true;
6065+
6066+
return hasSelfOrAssociatedTypeRequirements();
60586067
}
60596068

60606069
ArrayRef<AssociatedTypeDecl *>

lib/AST/TypeCheckRequests.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -263,28 +263,31 @@ void ExistentialConformsToSelfRequest::cacheResult(bool value) const {
263263
}
264264

265265
//----------------------------------------------------------------------------//
266-
// existentialRequiresAny computation.
266+
// hasSelfOrAssociatedTypeRequirementsRequest computation.
267267
//----------------------------------------------------------------------------//
268268

269-
void ExistentialRequiresAnyRequest::diagnoseCycle(DiagnosticEngine &diags) const {
269+
void HasSelfOrAssociatedTypeRequirementsRequest::diagnoseCycle(
270+
DiagnosticEngine &diags) const {
270271
auto decl = std::get<0>(getStorage());
271272
diags.diagnose(decl, diag::circular_protocol_def, decl->getName());
272273
}
273274

274-
void ExistentialRequiresAnyRequest::noteCycleStep(DiagnosticEngine &diags) const {
275+
void HasSelfOrAssociatedTypeRequirementsRequest::noteCycleStep(
276+
DiagnosticEngine &diags) const {
275277
auto requirement = std::get<0>(getStorage());
276278
diags.diagnose(requirement, diag::kind_declname_declared_here,
277279
DescriptiveDeclKind::Protocol, requirement->getName());
278280
}
279281

280-
Optional<bool> ExistentialRequiresAnyRequest::getCachedResult() const {
282+
Optional<bool>
283+
HasSelfOrAssociatedTypeRequirementsRequest::getCachedResult() const {
281284
auto decl = std::get<0>(getStorage());
282-
return decl->getCachedExistentialRequiresAny();
285+
return decl->getCachedHasSelfOrAssociatedTypeRequirements();
283286
}
284287

285-
void ExistentialRequiresAnyRequest::cacheResult(bool value) const {
288+
void HasSelfOrAssociatedTypeRequirementsRequest::cacheResult(bool value) const {
286289
auto decl = std::get<0>(getStorage());
287-
decl->setCachedExistentialRequiresAny(value);
290+
decl->setCachedHasSelfOrAssociatedTypeRequirements(value);
288291
}
289292

290293
//----------------------------------------------------------------------------//

lib/Sema/TypeCheckDecl.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -711,13 +711,8 @@ ExistentialConformsToSelfRequest::evaluate(Evaluator &evaluator,
711711
return true;
712712
}
713713

714-
bool
715-
ExistentialRequiresAnyRequest::evaluate(Evaluator &evaluator,
716-
ProtocolDecl *decl) const {
717-
auto &ctx = decl->getASTContext();
718-
if (ctx.LangOpts.hasFeature(Feature::ExistentialAny))
719-
return true;
720-
714+
bool HasSelfOrAssociatedTypeRequirementsRequest::evaluate(
715+
Evaluator &evaluator, ProtocolDecl *decl) const {
721716
// ObjC protocols do not require `any`.
722717
if (decl->isObjC())
723718
return false;
@@ -740,7 +735,7 @@ ExistentialRequiresAnyRequest::evaluate(Evaluator &evaluator,
740735

741736
// Check whether any of the inherited protocols require `any`.
742737
for (auto proto : decl->getInheritedProtocols()) {
743-
if (proto->existentialRequiresAny())
738+
if (proto->hasSelfOrAssociatedTypeRequirements())
744739
return true;
745740
}
746741

lib/Sema/TypeCheckType.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5176,6 +5176,10 @@ class ExistentialTypeVisitor
51765176
if (T->isInvalid())
51775177
return;
51785178

5179+
if (Ctx.LangOpts.hasFeature(Feature::ImplicitSome)) {
5180+
return;
5181+
}
5182+
51795183
// Compute the type repr to attach 'any' to.
51805184
TypeRepr *replaceRepr = T;
51815185
// Insert parens in expression context for '(any P).self'
@@ -5208,7 +5212,7 @@ class ExistentialTypeVisitor
52085212
OS << ")";
52095213

52105214
if (auto *proto = dyn_cast_or_null<ProtocolDecl>(T->getBoundDecl())) {
5211-
if (proto->existentialRequiresAny() && !Ctx.LangOpts.hasFeature(Feature::ImplicitSome)) {
5215+
if (proto->existentialRequiresAny()) {
52125216
Ctx.Diags.diagnose(T->getNameLoc(),
52135217
diag::existential_requires_any,
52145218
proto->getDeclaredInterfaceType(),
@@ -5226,7 +5230,7 @@ class ExistentialTypeVisitor
52265230
if (type->isConstraintType()) {
52275231
auto layout = type->getExistentialLayout();
52285232
for (auto *protoDecl : layout.getProtocols()) {
5229-
if (!protoDecl->existentialRequiresAny() || Ctx.LangOpts.hasFeature(Feature::ImplicitSome))
5233+
if (!protoDecl->existentialRequiresAny())
52305234
continue;
52315235

52325236
Ctx.Diags.diagnose(T->getNameLoc(),

lib/Serialization/Deserialization.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4075,14 +4075,14 @@ class DeclDeserializer {
40754075
StringRef blobData) {
40764076
IdentifierID nameID;
40774077
DeclContextID contextID;
4078-
bool isImplicit, isClassBounded, isObjC, existentialRequiresAny;
4078+
bool isImplicit, isClassBounded, isObjC, hasSelfOrAssocTypeRequirements;
40794079
uint8_t rawAccessLevel;
40804080
unsigned numInheritedTypes;
40814081
ArrayRef<uint64_t> rawInheritedAndDependencyIDs;
40824082

40834083
decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID,
40844084
isImplicit, isClassBounded, isObjC,
4085-
existentialRequiresAny,
4085+
hasSelfOrAssocTypeRequirements,
40864086
rawAccessLevel, numInheritedTypes,
40874087
rawInheritedAndDependencyIDs);
40884088

@@ -4110,8 +4110,8 @@ class DeclDeserializer {
41104110

41114111
ctx.evaluator.cacheOutput(ProtocolRequiresClassRequest{proto},
41124112
std::move(isClassBounded));
4113-
ctx.evaluator.cacheOutput(ExistentialRequiresAnyRequest{proto},
4114-
std::move(existentialRequiresAny));
4113+
ctx.evaluator.cacheOutput(HasSelfOrAssociatedTypeRequirementsRequest{proto},
4114+
std::move(hasSelfOrAssocTypeRequirements));
41154115

41164116
if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
41174117
proto->setAccess(*accessLevel);

lib/Serialization/Serialization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4127,7 +4127,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
41274127
const_cast<ProtocolDecl *>(proto)
41284128
->requiresClass(),
41294129
proto->isObjC(),
4130-
proto->existentialRequiresAny(),
4130+
proto->hasSelfOrAssociatedTypeRequirements(),
41314131
rawAccessLevel, numInherited,
41324132
inheritedAndDependencyTypes);
41334133

test/expr/postfix/call/forward_trailing_closure_errors.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func testUnlabeledParamMatching(i: Int, fn: ((Int) -> Int) -> Void) {
2020

2121
// When "fuzzy matching is disabled, this will fail.
2222
func forwardMatchFailure( // expected-note{{declared here}}
23-
onError: ((Error) -> Void)? = nil,
23+
onError: ((any Error) -> Void)? = nil,
2424
onCompletion: (Int) -> Void
2525
) { }
2626

0 commit comments

Comments
 (0)