-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[NameLookup] ASTOOScope ontology #24594
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
Changes from all commits
663760e
c7a6f80
173bc09
3f820c3
741a0bf
6942344
36234c3
2b9480d
8814390
10affe2
80ccbcf
5aa5809
2e7756c
40b0080
9035ab8
11a9ee7
2ad2bac
da8ab75
e6012a4
005e259
23bddf1
e3d7fc3
044f6f8
013a45a
d652360
99a36f1
32744e6
ce50e12
5043d56
501b38d
d914ec2
e86080f
935587e
ab8b49a
8e729aa
e48ea31
5b2bf12
91c6de9
665a282
29f0204
ad77af1
5c3bea5
e90a809
3f3f51c
8ff4309
bae074e
94bd4a8
606ce7b
e42ee81
15cc98c
50e599b
1c0da75
dd5d4ab
73279c9
7bc8129
ee6c49c
85a5514
f366484
480807f
05d38e0
fc4cc21
614f1cd
15d8a38
670eb61
1e9bc84
13d3c00
f997446
3b8359c
3abfa1f
253f16b
bbd1f76
9dd2cae
2e9f6c0
c0af241
a724ff1
d3cf74b
2869b4e
cbed414
1d5b9ea
c4322de
22d37ec
d96896c
8d526b3
2e46fe1
2baa473
7d1f024
17bb031
6a8d91f
f203509
2b7b7cf
edc6a5c
455b344
e7cd534
2b63173
6cdb147
6b6c983
2d0a8f2
6cfcabd
69f6b41
884648d
916b217
21905c1
9b40b39
55323bb
4122438
b418588
16ca723
2f2bbfb
72b2096
3e95844
8988fa9
6f6a772
40cd518
44c6248
50358b2
320dd89
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,8 @@ | |
#include "swift/AST/ASTVisitor.h" | ||
#include "swift/AST/Identifier.h" | ||
#include "swift/AST/Module.h" | ||
#include "swift/Basic/Compiler.h" | ||
#include "swift/Basic/NullablePtr.h" | ||
#include "swift/Basic/SourceLoc.h" | ||
|
||
namespace swift { | ||
|
@@ -36,52 +38,89 @@ namespace swift { | |
class TypeDecl; | ||
class ValueDecl; | ||
struct SelfBounds; | ||
|
||
/// LookupResultEntry - One result of unqualified lookup. | ||
struct LookupResultEntry { | ||
private: | ||
|
||
/// The declaration context through which we found Value. For instance, | ||
/// class BaseClass { | ||
/// func foo() {} | ||
/// } | ||
/// | ||
/// class DerivedClass : BaseClass { | ||
/// func bar() {} | ||
/// } | ||
/// | ||
/// When finding foo() from the body of DerivedClass, BaseDC is DerivedClass. | ||
/// | ||
/// Another example: | ||
/// | ||
/// class BaseClass { | ||
/// func bar() {} | ||
/// func foo() {} | ||
/// } | ||
/// | ||
/// When finding bar() from the function body of foo(), BaseDC is the method | ||
/// foo(). | ||
class NominalTypeDecl; | ||
|
||
namespace ast_scope { | ||
class ASTSourceFileScope; | ||
class ASTScopeImpl; | ||
} // namespace ast_scope | ||
|
||
/// LookupResultEntry - One result of unqualified lookup. | ||
struct LookupResultEntry { | ||
private: | ||
/// The declaration context through which we found \c Value. For instance, | ||
/// \code | ||
/// class BaseClass { | ||
/// func foo() {} | ||
/// } | ||
/// | ||
/// class DerivedClass : BaseClass { | ||
/// func bar() {} | ||
/// } | ||
/// \endcode | ||
/// | ||
/// When finding \c foo() from the body of \c DerivedClass, \c BaseDC is \c | ||
/// DerivedClass. | ||
/// | ||
/// Another example: | ||
/// \code | ||
/// class BaseClass { | ||
/// func bar() {} | ||
/// func foo() {} | ||
/// } | ||
/// \endcode | ||
/// | ||
/// When finding \c bar() from the function body of \c foo(), \c BaseDC is | ||
/// the method \c foo(). | ||
/// | ||
/// \c BaseDC will be the method if \c self is needed for the lookup, | ||
/// and will be the type if not. | ||
/// In other words: If \c baseDC is a method, it means you found an instance | ||
/// member and you should add an implicit 'self.' (Each method has its own | ||
/// implicit self decl.) There's one other kind of non-method context that | ||
/// has a 'self.' -- a lazy property initializer, which unlike a non-lazy | ||
/// property can reference \c self) Hence: \code | ||
/// class Outer { | ||
/// static func s() | ||
/// func i() | ||
/// class Inner { | ||
/// static func ss() | ||
/// func ii() { | ||
/// func F() { | ||
/// ii() // OK! implicitly self.ii; BaseDC is the method | ||
/// s() // OK! s() is defined in an outer type; BaseDC is the type | ||
/// ss() // error: must write /Inner.ss() here since its static | ||
/// i() // error: there's no outer 'self.' | ||
/// } | ||
/// } | ||
/// \endcode | ||
/// | ||
/// To sum up: The distinction is whether you need to know the run-time | ||
/// value of \c self. It might be clearer if \code baseDC was always a type, | ||
/// and there was an additional \c ParamDecl field in \c LookupResult which | ||
/// would store the implicit self, if any. \c BaseDC is always one of your | ||
/// outer DCs. if you're inside a type it should never be an extension of | ||
/// that type. And if you're inside an extension it will always be an | ||
/// extension (if it found something at that level). | ||
DeclContext *BaseDC; | ||
|
||
/// The declaration corresponds to the given name; i.e. the decl we are | ||
/// looking up. | ||
ValueDecl *Value; | ||
|
||
public: | ||
LookupResultEntry(ValueDecl *value) : BaseDC(nullptr), Value(value) { } | ||
LookupResultEntry(ValueDecl *value) : BaseDC(nullptr), Value(value) {} | ||
|
||
LookupResultEntry(DeclContext *baseDC, ValueDecl *value) | ||
: BaseDC(baseDC), Value(value) { } | ||
: BaseDC(baseDC), Value(value) {} | ||
|
||
ValueDecl *getValueDecl() const { | ||
return Value; | ||
} | ||
ValueDecl *getValueDecl() const { return Value; } | ||
|
||
DeclContext *getDeclContext() const { | ||
return BaseDC; | ||
} | ||
DeclContext *getDeclContext() const { return BaseDC; } | ||
|
||
ValueDecl *getBaseDecl() const; | ||
|
||
void print(llvm::raw_ostream &) const; | ||
}; | ||
|
||
/// This class implements and represents the result of performing | ||
|
@@ -110,13 +149,15 @@ class UnqualifiedLookup { | |
/// is used to determine which declarations in that body are visible. | ||
UnqualifiedLookup(DeclName Name, DeclContext *DC, LazyResolver *TypeResolver, | ||
SourceLoc Loc = SourceLoc(), Options options = Options()); | ||
|
||
SmallVector<LookupResultEntry, 4> Results; | ||
|
||
using ResultsVector = SmallVector<LookupResultEntry, 4>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you using this type outside of the class? If not, why create this? If you are using it outside, it is better to use SmallVectorImpl. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why wont it do. If you are passing it to someone, you can use SmallVectorImpl< LookupResultEntry> & There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In
The code needs to create a results vector, so it can make another factory for comparison purposes. Publishing the type seemed like the clearest way. I suppose the code could use a |
||
ResultsVector Results; | ||
|
||
/// The index of the first result that isn't from the innermost scope | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please put a newline line here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, good catch, thanks! |
||
/// with results. | ||
/// | ||
/// That is, \c makeArrayRef(Results).take_front(IndexOfFirstOuterResults) | ||
/// will be Results from the innermost scope that had results, and the | ||
/// will be \c Results from the innermost scope that had results, and the | ||
/// remaining elements of Results will be from parent scopes of this one. | ||
/// | ||
/// Allows unqualified name lookup to return results from outer scopes. | ||
|
@@ -136,7 +177,6 @@ inline UnqualifiedLookup::Options operator|(UnqualifiedLookup::Flags flag1, | |
return UnqualifiedLookup::Options(flag1) | flag2; | ||
} | ||
|
||
|
||
/// Describes the reason why a certain declaration is visible. | ||
enum class DeclVisibilityKind { | ||
/// Declaration is a local variable or type. | ||
|
@@ -536,8 +576,100 @@ class FindLocalVal : public StmtVisitor<FindLocalVal> { | |
void visitCatchStmt(CatchStmt *S); | ||
|
||
}; | ||
|
||
|
||
/// The bridge between the legacy UnqualifedLookupFactory and the new ASTScope | ||
/// lookup system | ||
class AbstractASTScopeDeclConsumer { | ||
public: | ||
AbstractASTScopeDeclConsumer() {} | ||
|
||
virtual ~AbstractASTScopeDeclConsumer() = default; | ||
|
||
/// Called for every ValueDecl visible from the lookup. | ||
/// Returns true if the lookup can be stopped at this point. | ||
/// BaseDC is per legacy | ||
/// Takes an array in order to batch the consumption before setting | ||
/// IndexOfFirstOuterResult when necessary. | ||
virtual bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis, | ||
Optional<bool> isCascadingUse, | ||
NullablePtr<DeclContext> baseDC = nullptr) = 0; | ||
|
||
/// Eventually this functionality should move into ASTScopeLookup | ||
virtual std::pair<bool, Optional<bool>> | ||
lookupInSelfType(NullablePtr<DeclContext> selfDC, DeclContext *const scopeDC, | ||
NominalTypeDecl *const nominal, | ||
Optional<bool> isCascadingUse) = 0; | ||
|
||
#ifndef NDEBUG | ||
virtual void stopForDebuggingIfTargetLookup() = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this going to be called in the code always? If this is only for debugging the compiler, it should be hidden behind an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point! Will do. |
||
#endif | ||
}; | ||
|
||
/// Just used to print | ||
/// Used to gather lookup results | ||
class ASTScopeDeclGatherer : public AbstractASTScopeDeclConsumer { | ||
SmallVector<ValueDecl *, 32> values; | ||
|
||
public: | ||
virtual ~ASTScopeDeclGatherer() = default; | ||
|
||
bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis, | ||
Optional<bool> isCascadingUse, | ||
NullablePtr<DeclContext> baseDC = nullptr) override; | ||
|
||
/// Eventually this functionality should move into ASTScopeLookup | ||
std::pair<bool, Optional<bool>> | ||
lookupInSelfType(NullablePtr<DeclContext>, DeclContext *const, | ||
NominalTypeDecl *const, | ||
Optional<bool> isCascadingUse) override { | ||
return std::make_pair(false, isCascadingUse); | ||
} | ||
|
||
#ifndef NDEBUG | ||
void stopForDebuggingIfTargetLookup() override {} | ||
#endif | ||
|
||
ArrayRef<ValueDecl *> getDecls() { return values; } | ||
}; | ||
} // end namespace namelookup | ||
|
||
/// The interface into the ASTScope subsystem | ||
class ASTScope { | ||
friend class ast_scope::ASTScopeImpl; | ||
ast_scope::ASTSourceFileScope *const impl; | ||
|
||
public: | ||
ASTScope(SourceFile *); | ||
static Optional<bool> | ||
unqualifiedLookup(SourceFile *, DeclName, SourceLoc, | ||
const DeclContext *startingContext, | ||
Optional<bool> isCascadingUse, | ||
namelookup::AbstractASTScopeDeclConsumer &); | ||
|
||
LLVM_ATTRIBUTE_DEPRECATED(void dump() const LLVM_ATTRIBUTE_USED, | ||
"only for use within the debugger"); | ||
void print(llvm::raw_ostream &) const; | ||
void dumpOneScopeMapLocation(std::pair<unsigned, unsigned>) const; | ||
|
||
// Make vanilla new illegal for ASTScopes. | ||
void *operator new(size_t bytes) = delete; | ||
// Need this because have virtual destructors | ||
void operator delete(void *data) {} | ||
|
||
// Only allow allocation of scopes using the allocator of a particular source | ||
// file. | ||
void *operator new(size_t bytes, const ASTContext &ctx, | ||
unsigned alignment = alignof(ASTScope)); | ||
void *operator new(size_t Bytes, void *Mem) { | ||
assert(Mem); | ||
return Mem; | ||
} | ||
|
||
private: | ||
static ast_scope::ASTSourceFileScope *createScopeTree(SourceFile *); | ||
}; | ||
|
||
} // end namespace swift | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -833,6 +833,13 @@ class RelationalOperationsBase { | |
return !(left == right); | ||
} | ||
}; | ||
|
||
/// Cast a pointer to \c U to a pointer to a supertype \c T. | ||
/// Example: Wobulator *w = up_cast<Wobulator>(coloredWobulator) | ||
/// Useful with ?: where each arm is a different subtype. | ||
/// If \c U is not a subtype of \c T, the compiler will complain. | ||
template <typename T, typename U> | ||
T *up_cast(U *ptr) { return ptr; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We follow camelCase for functions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But |
||
|
||
/// Removes all runs of values that match \p pred from the range of \p begin | ||
/// to \p end. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you indenting this out, that just increases the diff without need.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably a git-clang-format thing--I'll fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's fixed. Let me know if not. I have tried to git-format it all but may have missed something.