Skip to content

[NFC] ExistentialRequiresAnyRequest → HasSelfOrAssociatedTypeRequirementsRequest #65132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,11 +553,12 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
/// Whether the existential of this protocol conforms to itself.
ExistentialConformsToSelf : 1,

/// Whether the \c ExistentialRequiresAny bit is valid.
ExistentialRequiresAnyValid : 1,
/// Whether the \c HasSelfOrAssociatedTypeRequirements bit is valid.
HasSelfOrAssociatedTypeRequirementsValid : 1,

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

/// True if the protocol has requirements that cannot be satisfied (e.g.
/// because they could not be imported from Objective-C).
Expand Down Expand Up @@ -4756,19 +4757,19 @@ class ProtocolDecl final : public NominalTypeDecl {
Bits.ProtocolDecl.ExistentialConformsToSelf = result;
}

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

return None;
}

/// Caches the result of \c existentialRequiresAny
void setCachedExistentialRequiresAny(bool requiresAny) {
Bits.ProtocolDecl.ExistentialRequiresAnyValid = true;
Bits.ProtocolDecl.ExistentialRequiresAny = requiresAny;
/// Caches the result of \c hasSelfOrAssociatedTypeRequirements
void setCachedHasSelfOrAssociatedTypeRequirements(bool value) {
Bits.ProtocolDecl.HasSelfOrAssociatedTypeRequirementsValid = true;
Bits.ProtocolDecl.HasSelfOrAssociatedTypeRequirements = value;
}

bool hasLazyRequirementSignature() const {
Expand All @@ -4785,11 +4786,9 @@ class ProtocolDecl final : public NominalTypeDecl {
friend class TypeAliasRequirementsRequest;
friend class ProtocolDependenciesRequest;
friend class RequirementSignatureRequest;
friend class RequirementSignatureRequestRQM;
friend class RequirementSignatureRequestGSB;
friend class ProtocolRequiresClassRequest;
friend class ExistentialConformsToSelfRequest;
friend class ExistentialRequiresAnyRequest;
friend class HasSelfOrAssociatedTypeRequirementsRequest;
friend class InheritedProtocolsRequest;
friend class PrimaryAssociatedTypesRequest;
friend class ProtocolRequirementsRequest;
Expand Down Expand Up @@ -4888,15 +4887,20 @@ class ProtocolDecl final : public NominalTypeDecl {
/// Does this protocol require a self-conformance witness table?
bool requiresSelfConformanceWitnessTable() const;

/// Determine whether an existential type must be explicitly prefixed
/// with \c any. \c any is required if one of the following conditions is met
/// for this protocol or an inherited protocol:
/// Determine whether this protocol has `Self` or associated type
/// requirements.
///
/// This is true if one of the following conditions is met for this protocol
/// or an inherited protocol:
/// - The protocol has an associated type requirement.
/// - `Self` appears in non-covariant position in the type signature of a
/// value requirement.
bool hasSelfOrAssociatedTypeRequirements() const;

/// Determine whether an existential type constrained by this protocol must
/// be written using `any` syntax.
///
/// @Note This method does not take the state of language features into
/// account.
/// \Note This method takes language feature state into account.
bool existentialRequiresAny() const;

/// Returns a list of protocol requirements that must be assessed to
Expand Down
4 changes: 2 additions & 2 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,8 @@ class ExistentialConformsToSelfRequest :

/// Determine whether an existential type conforming to this protocol
/// requires the \c any syntax.
class ExistentialRequiresAnyRequest :
public SimpleRequest<ExistentialRequiresAnyRequest,
class HasSelfOrAssociatedTypeRequirementsRequest :
public SimpleRequest<HasSelfOrAssociatedTypeRequirementsRequest,
bool(ProtocolDecl *),
RequestFlags::SeparatelyCached> {
public:
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ SWIFT_REQUEST(TypeChecker, EnumRawTypeRequest,
Type(EnumDecl *), Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ExistentialConformsToSelfRequest,
bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ExistentialRequiresAnyRequest,
SWIFT_REQUEST(TypeChecker, HasSelfOrAssociatedTypeRequirementsRequest,
bool(ProtocolDecl *), SeparatelyCached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ExtendedTypeRequest, Type(ExtensionDecl *), Cached,
NoLocationInfo)
Expand Down
13 changes: 11 additions & 2 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6018,9 +6018,18 @@ bool ProtocolDecl::existentialConformsToSelf() const {
ExistentialConformsToSelfRequest{const_cast<ProtocolDecl *>(this)}, true);
}

bool ProtocolDecl::existentialRequiresAny() const {
bool ProtocolDecl::hasSelfOrAssociatedTypeRequirements() const {
return evaluateOrDefault(getASTContext().evaluator,
ExistentialRequiresAnyRequest{const_cast<ProtocolDecl *>(this)}, true);
HasSelfOrAssociatedTypeRequirementsRequest{
const_cast<ProtocolDecl *>(this)},
true);
}

bool ProtocolDecl::existentialRequiresAny() const {
if (getASTContext().LangOpts.hasFeature(Feature::ExistentialAny))
return true;

return hasSelfOrAssociatedTypeRequirements();
}

ArrayRef<AssociatedTypeDecl *>
Expand Down
17 changes: 10 additions & 7 deletions lib/AST/TypeCheckRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,28 +263,31 @@ void ExistentialConformsToSelfRequest::cacheResult(bool value) const {
}

//----------------------------------------------------------------------------//
// existentialRequiresAny computation.
// hasSelfOrAssociatedTypeRequirementsRequest computation.
//----------------------------------------------------------------------------//

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

void ExistentialRequiresAnyRequest::noteCycleStep(DiagnosticEngine &diags) const {
void HasSelfOrAssociatedTypeRequirementsRequest::noteCycleStep(
DiagnosticEngine &diags) const {
auto requirement = std::get<0>(getStorage());
diags.diagnose(requirement, diag::kind_declname_declared_here,
DescriptiveDeclKind::Protocol, requirement->getName());
}

Optional<bool> ExistentialRequiresAnyRequest::getCachedResult() const {
Optional<bool>
HasSelfOrAssociatedTypeRequirementsRequest::getCachedResult() const {
auto decl = std::get<0>(getStorage());
return decl->getCachedExistentialRequiresAny();
return decl->getCachedHasSelfOrAssociatedTypeRequirements();
}

void ExistentialRequiresAnyRequest::cacheResult(bool value) const {
void HasSelfOrAssociatedTypeRequirementsRequest::cacheResult(bool value) const {
auto decl = std::get<0>(getStorage());
decl->setCachedExistentialRequiresAny(value);
decl->setCachedHasSelfOrAssociatedTypeRequirements(value);
}

//----------------------------------------------------------------------------//
Expand Down
7 changes: 3 additions & 4 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,9 +711,8 @@ ExistentialConformsToSelfRequest::evaluate(Evaluator &evaluator,
return true;
}

bool
ExistentialRequiresAnyRequest::evaluate(Evaluator &evaluator,
ProtocolDecl *decl) const {
bool HasSelfOrAssociatedTypeRequirementsRequest::evaluate(
Evaluator &evaluator, ProtocolDecl *decl) const {
// ObjC protocols do not require `any`.
if (decl->isObjC())
return false;
Expand All @@ -736,7 +735,7 @@ ExistentialRequiresAnyRequest::evaluate(Evaluator &evaluator,

// Check whether any of the inherited protocols require `any`.
for (auto proto : decl->getInheritedProtocols()) {
if (proto->existentialRequiresAny())
if (proto->hasSelfOrAssociatedTypeRequirements())
return true;
}

Expand Down
6 changes: 2 additions & 4 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5202,8 +5202,7 @@ class ExistentialTypeVisitor
OS << ")";

if (auto *proto = dyn_cast_or_null<ProtocolDecl>(T->getBoundDecl())) {
if (Ctx.LangOpts.hasFeature(Feature::ExistentialAny) ||
proto->existentialRequiresAny()) {
if (proto->existentialRequiresAny()) {
Ctx.Diags.diagnose(T->getNameLoc(),
diag::existential_requires_any,
proto->getDeclaredInterfaceType(),
Expand All @@ -5221,8 +5220,7 @@ class ExistentialTypeVisitor
if (type->isConstraintType()) {
auto layout = type->getExistentialLayout();
for (auto *protoDecl : layout.getProtocols()) {
if (!Ctx.LangOpts.hasFeature(Feature::ExistentialAny) &&
!protoDecl->existentialRequiresAny())
if (!protoDecl->existentialRequiresAny())
continue;

Ctx.Diags.diagnose(T->getNameLoc(),
Expand Down
8 changes: 4 additions & 4 deletions lib/Serialization/Deserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3995,14 +3995,14 @@ class DeclDeserializer {
StringRef blobData) {
IdentifierID nameID;
DeclContextID contextID;
bool isImplicit, isClassBounded, isObjC, existentialRequiresAny;
bool isImplicit, isClassBounded, isObjC, hasSelfOrAssocTypeRequirements;
uint8_t rawAccessLevel;
unsigned numInheritedTypes;
ArrayRef<uint64_t> rawInheritedAndDependencyIDs;

decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID,
isImplicit, isClassBounded, isObjC,
existentialRequiresAny,
hasSelfOrAssocTypeRequirements,
rawAccessLevel, numInheritedTypes,
rawInheritedAndDependencyIDs);

Expand Down Expand Up @@ -4030,8 +4030,8 @@ class DeclDeserializer {

ctx.evaluator.cacheOutput(ProtocolRequiresClassRequest{proto},
std::move(isClassBounded));
ctx.evaluator.cacheOutput(ExistentialRequiresAnyRequest{proto},
std::move(existentialRequiresAny));
ctx.evaluator.cacheOutput(HasSelfOrAssociatedTypeRequirementsRequest{proto},
std::move(hasSelfOrAssocTypeRequirements));

if (auto accessLevel = getActualAccessLevel(rawAccessLevel))
proto->setAccess(*accessLevel);
Expand Down
2 changes: 1 addition & 1 deletion lib/Serialization/Serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4090,7 +4090,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
const_cast<ProtocolDecl *>(proto)
->requiresClass(),
proto->isObjC(),
proto->existentialRequiresAny(),
proto->hasSelfOrAssociatedTypeRequirements(),
rawAccessLevel, numInherited,
inheritedAndDependencyTypes);

Expand Down