Skip to content

Commit 67cf94f

Browse files
authored
Merge pull request #17976 from DougGregor/evaluator-override-isobjc
[Type checker] Introduce requests for @objc, override, and 'dynamic' checking
2 parents b156150 + 363ef63 commit 67cf94f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1080
-887
lines changed

include/swift/AST/AnyRequest.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,20 @@ class AnyRequest {
136136

137137
public:
138138
AnyRequest(const AnyRequest &other) = default;
139-
AnyRequest(AnyRequest &&other) = default;
140139
AnyRequest &operator=(const AnyRequest &other) = default;
141-
AnyRequest &operator=(AnyRequest &&other) = default;
140+
141+
AnyRequest(AnyRequest &&other)
142+
: storageKind(other.storageKind), stored(std::move(other.stored)) {
143+
other.storageKind = StorageKind::Empty;
144+
}
145+
146+
AnyRequest &operator=(AnyRequest &&other) {
147+
storageKind = other.storageKind;
148+
stored = std::move(other.stored);
149+
other.storageKind = StorageKind::Empty;
150+
other.stored = nullptr;
151+
return *this;
152+
}
142153

143154
AnyRequest(AnyRequest &other)
144155
: storageKind(other.storageKind), stored(other.stored) { }

include/swift/AST/Decl.h

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,8 +2242,20 @@ class ValueDecl : public Decl {
22422242
/// Whether there are any "overridden" declarations. The actual overridden
22432243
/// declarations are kept in a side table in the ASTContext.
22442244
unsigned hasOverridden : 1;
2245+
2246+
/// Whether the "isDynamic" bit has been computed yet.
2247+
unsigned isDynamicComputed : 1;
2248+
2249+
/// Whether this declaration is 'dynamic', meaning that all uses of
2250+
/// the declaration will go through an extra level of indirection that
2251+
/// allows the entity to be replaced at runtime.
2252+
unsigned isDynamic : 1;
22452253
} LazySemanticInfo;
22462254

2255+
friend class OverriddenDeclsRequest;
2256+
friend class IsObjCRequest;
2257+
friend class IsDynamicRequest;
2258+
22472259
protected:
22482260
ValueDecl(DeclKind K,
22492261
llvm::PointerUnion<DeclContext *, ASTContext *> context,
@@ -2256,6 +2268,8 @@ class ValueDecl : public Decl {
22562268
LazySemanticInfo.isObjC = false;
22572269
LazySemanticInfo.hasOverriddenComputed = false;
22582270
LazySemanticInfo.hasOverridden = false;
2271+
LazySemanticInfo.isDynamicComputed = false;
2272+
LazySemanticInfo.isDynamic = false;
22592273
}
22602274

22612275
// MemberLookupTable borrows a bit from this type
@@ -2468,18 +2482,15 @@ class ValueDecl : public Decl {
24682482
ValueDecl *getOverriddenDecl() const;
24692483

24702484
/// Retrieve the declarations that this declaration overrides, if any.
2471-
ArrayRef<ValueDecl *> getOverriddenDecls() const;
2485+
llvm::TinyPtrVector<ValueDecl *> getOverriddenDecls() const;
24722486

24732487
/// Set the declaration that this declaration overrides.
24742488
void setOverriddenDecl(ValueDecl *overridden) {
2475-
(void)setOverriddenDecls(overridden);
2489+
setOverriddenDecls(overridden);
24762490
}
24772491

24782492
/// Set the declarations that this declaration overrides.
2479-
///
2480-
/// \returns the ASTContext-allocated version of the array of overridden
2481-
/// declarations.
2482-
ArrayRef<ValueDecl *> setOverriddenDecls(ArrayRef<ValueDecl *> overridden);
2493+
void setOverriddenDecls(ArrayRef<ValueDecl *> overridden);
24832494

24842495
/// Whether the overridden declarations have already been computed.
24852496
bool overriddenDeclsComputed() const;
@@ -2507,8 +2518,14 @@ class ValueDecl : public Decl {
25072518
}
25082519

25092520
/// Is this declaration marked with 'dynamic'?
2510-
bool isDynamic() const {
2511-
return getAttrs().hasAttribute<DynamicAttr>();
2521+
bool isDynamic() const;
2522+
2523+
/// Set whether this type is 'dynamic' or not.
2524+
void setIsDynamic(bool value);
2525+
2526+
/// Whether the 'dynamic' bit has been computed already.
2527+
bool isDynamicComputed() const {
2528+
return LazySemanticInfo.isDynamicComputed;
25122529
}
25132530

25142531
/// Returns true if this decl can be found by id-style dynamic lookup.
@@ -2884,11 +2901,7 @@ class AssociatedTypeDecl : public AbstractTypeParamDecl {
28842901

28852902
/// Retrieve the set of associated types overridden by this associated
28862903
/// type.
2887-
CastArrayRefView<ValueDecl *, AssociatedTypeDecl>
2888-
getOverriddenDecls() const {
2889-
return CastArrayRefView<ValueDecl *, AssociatedTypeDecl>(
2890-
AbstractTypeParamDecl::getOverriddenDecls());
2891-
}
2904+
llvm::TinyPtrVector<AssociatedTypeDecl *> getOverriddenDecls() const;
28922905

28932906
SourceLoc getStartLoc() const { return KeywordLoc; }
28942907
SourceRange getSourceRange() const;

include/swift/AST/LazyResolver.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,6 @@ class LazyResolver {
6060
/// consistency and provides the value a type.
6161
virtual void resolveDeclSignature(ValueDecl *VD) = 0;
6262

63-
/// Resolve the "overridden" declaration of the given declaration.
64-
virtual void resolveOverriddenDecl(ValueDecl *VD) = 0;
65-
66-
/// Resolve the "is Objective-C" bit for the given declaration.
67-
virtual void resolveIsObjC(ValueDecl *VD) = 0;
68-
6963
/// Resolve the trailing where clause of the given protocol in-place.
7064
virtual void resolveTrailingWhereClause(ProtocolDecl *proto) = 0;
7165

include/swift/AST/NameLookup.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,10 @@ bool removeOverriddenDecls(SmallVectorImpl<ValueDecl*> &decls);
287287
///
288288
/// \param decls The set of declarations being considered.
289289
/// \param curModule The current module.
290-
/// \param typeResolver Used to resolve overload types.
291290
///
292291
/// \returns true if any shadowed declarations were removed.
293292
bool removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls,
294-
const ModuleDecl *curModule,
295-
LazyResolver *typeResolver);
293+
const ModuleDecl *curModule);
296294

297295
/// Finds decls visible in the given context and feeds them to the given
298296
/// VisibleDeclConsumer. If the current DeclContext is nested in a function,

include/swift/AST/TypeCheckRequests.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/SimpleRequest.h"
2222
#include "swift/Basic/Statistic.h"
2323
#include "llvm/ADT/Hashing.h"
24+
#include "llvm/ADT/TinyPtrVector.h"
2425

2526
namespace swift {
2627

@@ -121,6 +122,89 @@ class EnumRawTypeRequest :
121122
void cacheResult(Type value) const;
122123
};
123124

125+
/// Request to determine the set of declarations that were are overridden
126+
/// by the given declaration.
127+
class OverriddenDeclsRequest
128+
: public SimpleRequest<OverriddenDeclsRequest,
129+
CacheKind::SeparatelyCached,
130+
llvm::TinyPtrVector<ValueDecl *>,
131+
ValueDecl *> {
132+
public:
133+
using SimpleRequest::SimpleRequest;
134+
135+
private:
136+
friend class SimpleRequest;
137+
138+
// Evaluation.
139+
llvm::TinyPtrVector<ValueDecl *> evaluate(Evaluator &evaluator,
140+
ValueDecl *decl) const;
141+
142+
public:
143+
// Cycle handling
144+
llvm::TinyPtrVector<ValueDecl *> breakCycle() const { return { }; }
145+
void diagnoseCycle(DiagnosticEngine &diags) const;
146+
void noteCycleStep(DiagnosticEngine &diags) const;
147+
148+
// Separate caching.
149+
bool isCached() const { return true; }
150+
Optional<llvm::TinyPtrVector<ValueDecl *>> getCachedResult() const;
151+
void cacheResult(llvm::TinyPtrVector<ValueDecl *> value) const;
152+
};
153+
154+
/// Determine whether the given declaration is exposed to Objective-C.
155+
class IsObjCRequest :
156+
public SimpleRequest<IsObjCRequest,
157+
CacheKind::SeparatelyCached,
158+
bool,
159+
ValueDecl *> {
160+
public:
161+
using SimpleRequest::SimpleRequest;
162+
163+
private:
164+
friend class SimpleRequest;
165+
166+
// Evaluation.
167+
bool evaluate(Evaluator &evaluator, ValueDecl *decl) const;
168+
169+
public:
170+
// Cycle handling
171+
bool breakCycle() const;
172+
void diagnoseCycle(DiagnosticEngine &diags) const;
173+
void noteCycleStep(DiagnosticEngine &diags) const;
174+
175+
// Separate caching.
176+
bool isCached() const { return true; }
177+
Optional<bool> getCachedResult() const;
178+
void cacheResult(bool value) const;
179+
};
180+
181+
/// Determine whether the given declaration is 'dynamic''.
182+
class IsDynamicRequest :
183+
public SimpleRequest<IsDynamicRequest,
184+
CacheKind::SeparatelyCached,
185+
bool,
186+
ValueDecl *> {
187+
public:
188+
using SimpleRequest::SimpleRequest;
189+
190+
private:
191+
friend class SimpleRequest;
192+
193+
// Evaluation.
194+
bool evaluate(Evaluator &evaluator, ValueDecl *decl) const;
195+
196+
public:
197+
// Cycle handling
198+
bool breakCycle() const;
199+
void diagnoseCycle(DiagnosticEngine &diags) const;
200+
void noteCycleStep(DiagnosticEngine &diags) const;
201+
202+
// Separate caching.
203+
bool isCached() const { return true; }
204+
Optional<bool> getCachedResult() const;
205+
void cacheResult(bool value) const;
206+
};
207+
124208
/// The zone number for the type checker.
125209
#define SWIFT_TYPE_CHECKER_REQUESTS_TYPEID_ZONE 10
126210

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@
1717
SWIFT_TYPEID(InheritedTypeRequest)
1818
SWIFT_TYPEID(SuperclassTypeRequest)
1919
SWIFT_TYPEID(EnumRawTypeRequest)
20+
SWIFT_TYPEID(OverriddenDeclsRequest)
21+
SWIFT_TYPEID(IsObjCRequest)
22+
SWIFT_TYPEID(IsDynamicRequest)

lib/AST/ASTContext.cpp

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "swift/AST/RawComment.h"
3636
#include "swift/AST/SubstitutionMap.h"
3737
#include "swift/AST/SILLayout.h"
38+
#include "swift/AST/TypeCheckRequests.h"
3839
#include "swift/AST/TypeCheckerDebugConsumer.h"
3940
#include "swift/Basic/Compiler.h"
4041
#include "swift/Basic/SourceManager.h"
@@ -1594,53 +1595,47 @@ GenericEnvironment *ASTContext::getOrCreateCanonicalGenericEnvironment(
15941595
return env;
15951596
}
15961597

1597-
ArrayRef<ValueDecl *> ValueDecl::getOverriddenDecls() const {
1598-
// Check whether the overrides have already been computed.
1599-
if (LazySemanticInfo.hasOverriddenComputed) {
1600-
// If there are no overridden declarations (the common case), return.
1601-
if (!LazySemanticInfo.hasOverridden) return { };
1602-
1603-
// Look up the overridden declarations in the ASTContext.
1604-
auto known = getASTContext().getImpl().Overrides.find(this);
1605-
assert(known != getASTContext().getImpl().Overrides.end());
1606-
return known->second;
1607-
}
1598+
Optional<llvm::TinyPtrVector<ValueDecl *>>
1599+
OverriddenDeclsRequest::getCachedResult() const {
1600+
auto decl = std::get<0>(getStorage());
1601+
if (!decl->LazySemanticInfo.hasOverriddenComputed)
1602+
return None;
16081603

1609-
ASTContext &ctx = getASTContext();
1610-
if (auto resolver = ctx.getLazyResolver()) {
1611-
resolver->resolveOverriddenDecl(const_cast<ValueDecl *>(this));
1612-
assert(LazySemanticInfo.hasOverriddenComputed);
1613-
return getOverriddenDecls();
1614-
}
1604+
// If there are no overridden declarations (the common case), return.
1605+
llvm::TinyPtrVector<ValueDecl *> overridden;
1606+
if (!decl->LazySemanticInfo.hasOverridden) return overridden;
16151607

1616-
// FIXME: Shouldn't need this fallback.
1617-
return { };
1608+
// Retrieve the set of overrides from the ASTContext.
1609+
ASTContext &ctx = decl->getASTContext();
1610+
auto known = ctx.getImpl().Overrides.find(decl);
1611+
assert(known != ctx.getImpl().Overrides.end());
1612+
overridden.insert(overridden.end(),
1613+
known->second.begin(), known->second.end());
1614+
return overridden;
16181615
}
16191616

1620-
ArrayRef<ValueDecl *> ValueDecl::setOverriddenDecls(
1621-
ArrayRef<ValueDecl *> overridden) {
1622-
LazySemanticInfo.hasOverriddenComputed = true;
1617+
void OverriddenDeclsRequest::cacheResult(
1618+
llvm::TinyPtrVector<ValueDecl *> value) const {
1619+
auto decl = std::get<0>(getStorage());
1620+
decl->LazySemanticInfo.hasOverriddenComputed = true;
1621+
decl->LazySemanticInfo.hasOverridden = !value.empty();
16231622

1624-
// If the set of overridden declarations is empty, note that.
1625-
if (overridden.empty()) {
1626-
LazySemanticInfo.hasOverridden = false;
1627-
return { };
1628-
}
1623+
if (value.empty())
1624+
return;
16291625

16301626
// Sanity-check the declarations we were given.
1631-
for (auto decl : overridden) {
1632-
assert(decl->getKind() == this->getKind() &&
1627+
for (auto overriddenDecl : value) {
1628+
assert(overriddenDecl->getKind() == decl->getKind() &&
16331629
"Overridden decl kind mismatch");
1634-
if (auto func = dyn_cast<AbstractFunctionDecl>(decl))
1630+
if (auto func = dyn_cast<AbstractFunctionDecl>(overriddenDecl))
16351631
func->setIsOverridden();
16361632
}
16371633

16381634
// Record the overrides in the context.
1639-
auto &ctx = getASTContext();
1640-
LazySemanticInfo.hasOverridden = true;
1641-
auto overriddenCopy = ctx.AllocateCopy(overridden);
1642-
(void)ctx.getImpl().Overrides.insert({this, overriddenCopy});
1643-
return overriddenCopy;
1635+
auto &ctx = decl->getASTContext();
1636+
auto overriddenCopy =
1637+
ctx.AllocateCopy(value.operator ArrayRef<ValueDecl *>());
1638+
(void)ctx.getImpl().Overrides.insert({decl, overriddenCopy});
16441639
}
16451640

16461641
bool ASTContext::canImportModule(std::pair<Identifier, SourceLoc> ModulePath) {
@@ -2372,8 +2367,6 @@ void AbstractFunctionDecl::setForeignErrorConvention(
23722367

23732368
Optional<ForeignErrorConvention>
23742369
AbstractFunctionDecl::getForeignErrorConvention() const {
2375-
if (!isObjC() && !getAttrs().hasAttribute<CDeclAttr>())
2376-
return None;
23772370
if (!hasThrows())
23782371
return None;
23792372
auto &conventionsMap = getASTContext().getImpl().ForeignErrorConventions;

0 commit comments

Comments
 (0)