Skip to content

Commit 598034e

Browse files
committed
---
yaml --- r: 323583 b: refs/heads/tensorflow-next c: 4535431 h: refs/heads/master i: 323581: 41139a8 323579: c409f39 323575: e690598 323567: af7c459 323551: 599cbb3 323519: b81473b 323455: 409f553 323327: 38c0cad 323071: 028338f 322559: db0db42 321535: 6830862 319487: e9b3cb6
1 parent 51e5e94 commit 598034e

File tree

7 files changed

+100
-46
lines changed

7 files changed

+100
-46
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1461,4 +1461,4 @@ refs/heads/master-rebranch: 86e95c23aa0d37f24ec138b7853146c1cead2e40
14611461
refs/heads/rdar-53901732: 9bd06af3284e18a109cdbf9aa59d833b24eeca7b
14621462
refs/heads/revert-26776-subst-always-returns-a-type: 1b8e18fdd391903a348970a4c848995d4cdd789c
14631463
refs/heads/tensorflow-merge: 8b854f62f80d4476cb383d43c4aac2001dde3cec
1464-
refs/heads/tensorflow-next: 7cef4e7c915746312dbbc59e28bec79389f602b1
1464+
refs/heads/tensorflow-next: 45354312e7ca6af2a16e3d660256b749ed960f59

branches/tensorflow-next/include/swift/AST/Decl.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4120,7 +4120,20 @@ class ProtocolDecl final : public NominalTypeDecl {
41204120
Bits.ProtocolDecl.RequiresClass = requiresClass;
41214121
}
41224122

4123-
bool existentialConformsToSelfSlow();
4123+
/// Returns the cached result of \c existentialConformsToSelf or \c None if it
4124+
/// hasn't yet been computed.
4125+
Optional<bool> getCachedExistentialConformsToSelf() const {
4126+
if (Bits.ProtocolDecl.ExistentialConformsToSelfValid)
4127+
return Bits.ProtocolDecl.ExistentialConformsToSelf;
4128+
4129+
return None;
4130+
}
4131+
4132+
/// Caches the result of \c existentialConformsToSelf
4133+
void setCachedExistentialConformsToSelf(bool result) {
4134+
Bits.ProtocolDecl.ExistentialConformsToSelfValid = true;
4135+
Bits.ProtocolDecl.ExistentialConformsToSelf = result;
4136+
}
41244137

41254138
bool existentialTypeSupportedSlow();
41264139

@@ -4134,6 +4147,7 @@ class ProtocolDecl final : public NominalTypeDecl {
41344147
friend class SuperclassTypeRequest;
41354148
friend class RequirementSignatureRequest;
41364149
friend class ProtocolRequiresClassRequest;
4150+
friend class ExistentialConformsToSelfRequest;
41374151
friend class TypeChecker;
41384152

41394153
public:
@@ -4204,13 +4218,7 @@ class ProtocolDecl final : public NominalTypeDecl {
42044218
/// This is only permitted if there is nothing "non-trivial" that we
42054219
/// can do with the metatype, which means the protocol must not have
42064220
/// any static methods and must be declared @objc.
4207-
bool existentialConformsToSelf() const {
4208-
if (Bits.ProtocolDecl.ExistentialConformsToSelfValid)
4209-
return Bits.ProtocolDecl.ExistentialConformsToSelf;
4210-
4211-
return const_cast<ProtocolDecl *>(this)
4212-
->existentialConformsToSelfSlow();
4213-
}
4221+
bool existentialConformsToSelf() const;
42144222

42154223
/// Does this protocol require a self-conformance witness table?
42164224
bool requiresSelfConformanceWitnessTable() const;

branches/tensorflow-next/include/swift/AST/TypeCheckRequests.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,32 @@ class ProtocolRequiresClassRequest:
201201
void cacheResult(bool value) const;
202202
};
203203

204+
/// Determine whether an existential conforming to a protocol can be matched
205+
/// with a generic type parameter constrained to that protocol.
206+
class ExistentialConformsToSelfRequest:
207+
public SimpleRequest<ExistentialConformsToSelfRequest,
208+
bool(ProtocolDecl *),
209+
CacheKind::SeparatelyCached> {
210+
public:
211+
using SimpleRequest::SimpleRequest;
212+
213+
private:
214+
friend SimpleRequest;
215+
216+
// Evaluation.
217+
llvm::Expected<bool> evaluate(Evaluator &evaluator, ProtocolDecl *decl) const;
218+
219+
public:
220+
// Cycle handling.
221+
void diagnoseCycle(DiagnosticEngine &diags) const;
222+
void noteCycleStep(DiagnosticEngine &diags) const;
223+
224+
// Separate caching.
225+
bool isCached() const { return true; }
226+
Optional<bool> getCachedResult() const;
227+
void cacheResult(bool value) const;
228+
};
229+
204230
/// Determine whether the given declaration is 'final'.
205231
class IsFinalRequest :
206232
public SimpleRequest<IsFinalRequest,

branches/tensorflow-next/include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ SWIFT_TYPEID(EnumRawTypeRequest)
2020
SWIFT_TYPEID(OverriddenDeclsRequest)
2121
SWIFT_TYPEID(IsObjCRequest)
2222
SWIFT_TYPEID(ProtocolRequiresClassRequest)
23+
SWIFT_TYPEID(ExistentialConformsToSelfRequest)
2324
SWIFT_TYPEID(IsFinalRequest)
2425
SWIFT_TYPEID(IsDynamicRequest)
2526
SWIFT_TYPEID(RequirementRequest)

branches/tensorflow-next/lib/AST/Decl.cpp

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4329,43 +4329,9 @@ bool ProtocolDecl::requiresSelfConformanceWitnessTable() const {
43294329
return isSpecificProtocol(KnownProtocolKind::Error);
43304330
}
43314331

4332-
bool ProtocolDecl::existentialConformsToSelfSlow() {
4333-
// Assume for now that the existential conforms to itself; this
4334-
// prevents circularity issues.
4335-
Bits.ProtocolDecl.ExistentialConformsToSelfValid = true;
4336-
Bits.ProtocolDecl.ExistentialConformsToSelf = true;
4337-
4338-
// If it's not @objc, it conforms to itself only if it has a
4339-
// self-conformance witness table.
4340-
if (!isObjC()) {
4341-
bool hasSelfConformance = requiresSelfConformanceWitnessTable();
4342-
Bits.ProtocolDecl.ExistentialConformsToSelf = hasSelfConformance;
4343-
return hasSelfConformance;
4344-
}
4345-
4346-
// Check whether this protocol conforms to itself.
4347-
for (auto member : getMembers()) {
4348-
if (member->isInvalid())
4349-
continue;
4350-
4351-
if (auto vd = dyn_cast<ValueDecl>(member)) {
4352-
if (!vd->isInstanceMember()) {
4353-
// A protocol cannot conform to itself if it has static members.
4354-
Bits.ProtocolDecl.ExistentialConformsToSelf = false;
4355-
return false;
4356-
}
4357-
}
4358-
}
4359-
4360-
// Check whether any of the inherited protocols fail to conform to
4361-
// themselves.
4362-
for (auto proto : getInheritedProtocols()) {
4363-
if (!proto->existentialConformsToSelf()) {
4364-
Bits.ProtocolDecl.ExistentialConformsToSelf = false;
4365-
return false;
4366-
}
4367-
}
4368-
return true;
4332+
bool ProtocolDecl::existentialConformsToSelf() const {
4333+
return evaluateOrDefault(getASTContext().evaluator,
4334+
ExistentialConformsToSelfRequest{const_cast<ProtocolDecl *>(this)}, true);
43694335
}
43704336

43714337
/// Classify usages of Self in the given type.

branches/tensorflow-next/lib/AST/TypeCheckRequests.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,31 @@ void ProtocolRequiresClassRequest::cacheResult(bool value) const {
211211
decl->setCachedRequiresClass(value);
212212
}
213213

214+
//----------------------------------------------------------------------------//
215+
// existentialConformsToSelf computation.
216+
//----------------------------------------------------------------------------//
217+
218+
void ExistentialConformsToSelfRequest::diagnoseCycle(DiagnosticEngine &diags) const {
219+
auto decl = std::get<0>(getStorage());
220+
diags.diagnose(decl, diag::circular_protocol_def, decl->getName());
221+
}
222+
223+
void ExistentialConformsToSelfRequest::noteCycleStep(DiagnosticEngine &diags) const {
224+
auto requirement = std::get<0>(getStorage());
225+
diags.diagnose(requirement, diag::kind_declname_declared_here,
226+
DescriptiveDeclKind::Protocol, requirement->getName());
227+
}
228+
229+
Optional<bool> ExistentialConformsToSelfRequest::getCachedResult() const {
230+
auto decl = std::get<0>(getStorage());
231+
return decl->getCachedExistentialConformsToSelf();
232+
}
233+
234+
void ExistentialConformsToSelfRequest::cacheResult(bool value) const {
235+
auto decl = std::get<0>(getStorage());
236+
decl->setCachedExistentialConformsToSelf(value);
237+
}
238+
214239
//----------------------------------------------------------------------------//
215240
// isFinal computation.
216241
//----------------------------------------------------------------------------//

branches/tensorflow-next/lib/Sema/TypeCheckDecl.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,34 @@ ProtocolRequiresClassRequest::evaluate(Evaluator &evaluator,
12691269
return false;
12701270
}
12711271

1272+
llvm::Expected<bool>
1273+
ExistentialConformsToSelfRequest::evaluate(Evaluator &evaluator,
1274+
ProtocolDecl *decl) const {
1275+
// If it's not @objc, it conforms to itself only if it has a self-conformance
1276+
// witness table.
1277+
if (!decl->isObjC())
1278+
return decl->requiresSelfConformanceWitnessTable();
1279+
1280+
// Check whether this protocol conforms to itself.
1281+
for (auto member : decl->getMembers()) {
1282+
if (member->isInvalid()) continue;
1283+
1284+
if (auto vd = dyn_cast<ValueDecl>(member)) {
1285+
// A protocol cannot conform to itself if it has static members.
1286+
if (!vd->isInstanceMember())
1287+
return false;
1288+
}
1289+
}
1290+
1291+
// Check whether any of the inherited protocols fail to conform to themselves.
1292+
for (auto proto : decl->getInheritedProtocols()) {
1293+
if (!proto->existentialConformsToSelf())
1294+
return false;
1295+
}
1296+
1297+
return true;
1298+
}
1299+
12721300
llvm::Expected<bool>
12731301
IsFinalRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
12741302
if (isa<ClassDecl>(decl))

0 commit comments

Comments
 (0)