Skip to content

Commit 06527db

Browse files
author
David Ungar
authored
Merge pull request #24594 from davidungar/A5-7-ASTOOScope-rebased
[NameLookup] ASTOOScope ontology
2 parents f2d0c9c + 320dd89 commit 06527db

Some content is hidden

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

42 files changed

+5817
-3511
lines changed

include/swift/AST/ASTScope.h

Lines changed: 1399 additions & 515 deletions
Large diffs are not rendered by default.

include/swift/AST/ExperimentalDependencies.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,7 @@ template <typename GraphT> class DotFileEmitter {
865865
void emitDotNode(StringRef id, StringRef label, StringRef shape,
866866
StringRef fillColor, StringRef style = StringRef()) {
867867
auto inserted = nodeIDs.insert(id.str());
868+
(void)inserted;
868869
assert(inserted.second && "NodeIDs must be unique.");
869870
out << "\"" << id << "\" [ "
870871
<< "label = \"" << label << "\", "

include/swift/AST/Expr.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,8 +1009,6 @@ class InterpolatedStringLiteralExpr : public LiteralExpr {
10091009
return Loc;
10101010
}
10111011
SourceLoc getTrailingQuoteLoc() const {
1012-
// Except when computing a SourceRange for an ASTScope. Then the range
1013-
// must be (Start - TrainingQuoteLoc).
10141012
return TrailingQuoteLoc;
10151013
}
10161014

include/swift/AST/Module.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ namespace clang {
4646
namespace swift {
4747
enum class ArtificialMainKind : uint8_t;
4848
class ASTContext;
49-
class ASTScope;
5049
class ASTWalker;
5150
class BraceStmt;
5251
class Decl;
@@ -80,10 +79,14 @@ namespace swift {
8079
class VarDecl;
8180
class VisibleDeclConsumer;
8281
class SyntaxParsingCache;
83-
84-
namespace syntax {
82+
class ASTScope;
83+
84+
namespace syntax {
8585
class SourceFileSyntax;
8686
}
87+
namespace ast_scope {
88+
class ASTSourceFileScope;
89+
}
8790

8891
/// Discriminator for file-units.
8992
enum class FileUnitKind {
@@ -989,7 +992,7 @@ class SourceFile final : public FileUnit {
989992
bool HasImplementationOnlyImports = false;
990993

991994
/// The scope map that describes this source file.
992-
ASTScope *Scope = nullptr;
995+
std::unique_ptr<ASTScope> Scope;
993996

994997
friend ASTContext;
995998
friend Impl;

include/swift/AST/NameLookup.h

Lines changed: 169 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "swift/AST/ASTVisitor.h"
2323
#include "swift/AST/Identifier.h"
2424
#include "swift/AST/Module.h"
25+
#include "swift/Basic/Compiler.h"
26+
#include "swift/Basic/NullablePtr.h"
2527
#include "swift/Basic/SourceLoc.h"
2628

2729
namespace swift {
@@ -36,52 +38,89 @@ namespace swift {
3638
class TypeDecl;
3739
class ValueDecl;
3840
struct SelfBounds;
39-
40-
/// LookupResultEntry - One result of unqualified lookup.
41-
struct LookupResultEntry {
42-
private:
43-
44-
/// The declaration context through which we found Value. For instance,
45-
/// class BaseClass {
46-
/// func foo() {}
47-
/// }
48-
///
49-
/// class DerivedClass : BaseClass {
50-
/// func bar() {}
51-
/// }
52-
///
53-
/// When finding foo() from the body of DerivedClass, BaseDC is DerivedClass.
54-
///
55-
/// Another example:
56-
///
57-
/// class BaseClass {
58-
/// func bar() {}
59-
/// func foo() {}
60-
/// }
61-
///
62-
/// When finding bar() from the function body of foo(), BaseDC is the method
63-
/// foo().
41+
class NominalTypeDecl;
42+
43+
namespace ast_scope {
44+
class ASTSourceFileScope;
45+
class ASTScopeImpl;
46+
} // namespace ast_scope
47+
48+
/// LookupResultEntry - One result of unqualified lookup.
49+
struct LookupResultEntry {
50+
private:
51+
/// The declaration context through which we found \c Value. For instance,
52+
/// \code
53+
/// class BaseClass {
54+
/// func foo() {}
55+
/// }
56+
///
57+
/// class DerivedClass : BaseClass {
58+
/// func bar() {}
59+
/// }
60+
/// \endcode
61+
///
62+
/// When finding \c foo() from the body of \c DerivedClass, \c BaseDC is \c
63+
/// DerivedClass.
64+
///
65+
/// Another example:
66+
/// \code
67+
/// class BaseClass {
68+
/// func bar() {}
69+
/// func foo() {}
70+
/// }
71+
/// \endcode
72+
///
73+
/// When finding \c bar() from the function body of \c foo(), \c BaseDC is
74+
/// the method \c foo().
75+
///
76+
/// \c BaseDC will be the method if \c self is needed for the lookup,
77+
/// and will be the type if not.
78+
/// In other words: If \c baseDC is a method, it means you found an instance
79+
/// member and you should add an implicit 'self.' (Each method has its own
80+
/// implicit self decl.) There's one other kind of non-method context that
81+
/// has a 'self.' -- a lazy property initializer, which unlike a non-lazy
82+
/// property can reference \c self) Hence: \code
83+
/// class Outer {
84+
///   static func s()
85+
///   func i()
86+
/// class Inner {
87+
///   static func ss()
88+
///   func ii() {
89+
///   func F() {
90+
///   ii() // OK! implicitly self.ii; BaseDC is the method
91+
///   s()  // OK! s() is defined in an outer type; BaseDC is the type
92+
///   ss() // error: must write /Inner.ss() here since its static
93+
///   i() // error: there's no outer 'self.'
94+
///   }
95+
///   }
96+
/// \endcode
97+
///
98+
/// To sum up: The distinction is whether you need to know the run-time
99+
/// value of \c self. It might be clearer if \code baseDC was always a type,
100+
/// and there was an additional \c ParamDecl field in \c LookupResult which
101+
/// would store the implicit self, if any. \c BaseDC is always one of your
102+
/// outer DCs. if you're inside a type it should never be an extension of
103+
/// that type. And if you're inside an extension it will always be an
104+
/// extension (if it found something at that level).
64105
DeclContext *BaseDC;
65106

66107
/// The declaration corresponds to the given name; i.e. the decl we are
67108
/// looking up.
68109
ValueDecl *Value;
69110

70111
public:
71-
LookupResultEntry(ValueDecl *value) : BaseDC(nullptr), Value(value) { }
112+
LookupResultEntry(ValueDecl *value) : BaseDC(nullptr), Value(value) {}
72113

73114
LookupResultEntry(DeclContext *baseDC, ValueDecl *value)
74-
: BaseDC(baseDC), Value(value) { }
115+
: BaseDC(baseDC), Value(value) {}
75116

76-
ValueDecl *getValueDecl() const {
77-
return Value;
78-
}
117+
ValueDecl *getValueDecl() const { return Value; }
79118

80-
DeclContext *getDeclContext() const {
81-
return BaseDC;
82-
}
119+
DeclContext *getDeclContext() const { return BaseDC; }
83120

84121
ValueDecl *getBaseDecl() const;
122+
123+
void print(llvm::raw_ostream &) const;
85124
};
86125

87126
/// This class implements and represents the result of performing
@@ -110,13 +149,15 @@ class UnqualifiedLookup {
110149
/// is used to determine which declarations in that body are visible.
111150
UnqualifiedLookup(DeclName Name, DeclContext *DC, LazyResolver *TypeResolver,
112151
SourceLoc Loc = SourceLoc(), Options options = Options());
113-
114-
SmallVector<LookupResultEntry, 4> Results;
152+
153+
using ResultsVector = SmallVector<LookupResultEntry, 4>;
154+
ResultsVector Results;
155+
115156
/// The index of the first result that isn't from the innermost scope
116157
/// with results.
117158
///
118159
/// That is, \c makeArrayRef(Results).take_front(IndexOfFirstOuterResults)
119-
/// will be Results from the innermost scope that had results, and the
160+
/// will be \c Results from the innermost scope that had results, and the
120161
/// remaining elements of Results will be from parent scopes of this one.
121162
///
122163
/// Allows unqualified name lookup to return results from outer scopes.
@@ -136,7 +177,6 @@ inline UnqualifiedLookup::Options operator|(UnqualifiedLookup::Flags flag1,
136177
return UnqualifiedLookup::Options(flag1) | flag2;
137178
}
138179

139-
140180
/// Describes the reason why a certain declaration is visible.
141181
enum class DeclVisibilityKind {
142182
/// Declaration is a local variable or type.
@@ -536,8 +576,100 @@ class FindLocalVal : public StmtVisitor<FindLocalVal> {
536576
void visitCatchStmt(CatchStmt *S);
537577

538578
};
579+
580+
581+
/// The bridge between the legacy UnqualifedLookupFactory and the new ASTScope
582+
/// lookup system
583+
class AbstractASTScopeDeclConsumer {
584+
public:
585+
AbstractASTScopeDeclConsumer() {}
586+
587+
virtual ~AbstractASTScopeDeclConsumer() = default;
588+
589+
/// Called for every ValueDecl visible from the lookup.
590+
/// Returns true if the lookup can be stopped at this point.
591+
/// BaseDC is per legacy
592+
/// Takes an array in order to batch the consumption before setting
593+
/// IndexOfFirstOuterResult when necessary.
594+
virtual bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis,
595+
Optional<bool> isCascadingUse,
596+
NullablePtr<DeclContext> baseDC = nullptr) = 0;
597+
598+
/// Eventually this functionality should move into ASTScopeLookup
599+
virtual std::pair<bool, Optional<bool>>
600+
lookupInSelfType(NullablePtr<DeclContext> selfDC, DeclContext *const scopeDC,
601+
NominalTypeDecl *const nominal,
602+
Optional<bool> isCascadingUse) = 0;
603+
604+
#ifndef NDEBUG
605+
virtual void stopForDebuggingIfTargetLookup() = 0;
606+
#endif
607+
};
608+
609+
/// Just used to print
610+
/// Used to gather lookup results
611+
class ASTScopeDeclGatherer : public AbstractASTScopeDeclConsumer {
612+
SmallVector<ValueDecl *, 32> values;
613+
614+
public:
615+
virtual ~ASTScopeDeclGatherer() = default;
616+
617+
bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis,
618+
Optional<bool> isCascadingUse,
619+
NullablePtr<DeclContext> baseDC = nullptr) override;
620+
621+
/// Eventually this functionality should move into ASTScopeLookup
622+
std::pair<bool, Optional<bool>>
623+
lookupInSelfType(NullablePtr<DeclContext>, DeclContext *const,
624+
NominalTypeDecl *const,
625+
Optional<bool> isCascadingUse) override {
626+
return std::make_pair(false, isCascadingUse);
627+
}
539628

629+
#ifndef NDEBUG
630+
void stopForDebuggingIfTargetLookup() override {}
631+
#endif
632+
633+
ArrayRef<ValueDecl *> getDecls() { return values; }
634+
};
540635
} // end namespace namelookup
636+
637+
/// The interface into the ASTScope subsystem
638+
class ASTScope {
639+
friend class ast_scope::ASTScopeImpl;
640+
ast_scope::ASTSourceFileScope *const impl;
641+
642+
public:
643+
ASTScope(SourceFile *);
644+
static Optional<bool>
645+
unqualifiedLookup(SourceFile *, DeclName, SourceLoc,
646+
const DeclContext *startingContext,
647+
Optional<bool> isCascadingUse,
648+
namelookup::AbstractASTScopeDeclConsumer &);
649+
650+
LLVM_ATTRIBUTE_DEPRECATED(void dump() const LLVM_ATTRIBUTE_USED,
651+
"only for use within the debugger");
652+
void print(llvm::raw_ostream &) const;
653+
void dumpOneScopeMapLocation(std::pair<unsigned, unsigned>) const;
654+
655+
// Make vanilla new illegal for ASTScopes.
656+
void *operator new(size_t bytes) = delete;
657+
// Need this because have virtual destructors
658+
void operator delete(void *data) {}
659+
660+
// Only allow allocation of scopes using the allocator of a particular source
661+
// file.
662+
void *operator new(size_t bytes, const ASTContext &ctx,
663+
unsigned alignment = alignof(ASTScope));
664+
void *operator new(size_t Bytes, void *Mem) {
665+
assert(Mem);
666+
return Mem;
667+
}
668+
669+
private:
670+
static ast_scope::ASTSourceFileScope *createScopeTree(SourceFile *);
671+
};
672+
541673
} // end namespace swift
542674

543675
#endif

include/swift/Basic/LangOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,12 @@ namespace swift {
240240

241241
/// Should we use \c ASTScope-based resolution for unqualified name lookup?
242242
bool EnableASTScopeLookup = false;
243+
244+
/// Someday, ASTScopeLookup will supplant lookup in the parser
245+
bool DisableParserLookup = false;
246+
247+
/// Sound we compare to ASTScope-based resolution for debugging?
248+
bool CompareToASTScopeLookup = false;
243249

244250
/// Whether to use the import as member inference system
245251
///

include/swift/Basic/STLExtras.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,13 @@ class RelationalOperationsBase {
833833
return !(left == right);
834834
}
835835
};
836+
837+
/// Cast a pointer to \c U to a pointer to a supertype \c T.
838+
/// Example: Wobulator *w = up_cast<Wobulator>(coloredWobulator)
839+
/// Useful with ?: where each arm is a different subtype.
840+
/// If \c U is not a subtype of \c T, the compiler will complain.
841+
template <typename T, typename U>
842+
T *up_cast(U *ptr) { return ptr; }
836843

837844
/// Removes all runs of values that match \p pred from the range of \p begin
838845
/// to \p end.

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ def enable_target_os_checking :
121121
def disable_target_os_checking :
122122
Flag<["-"], "disable-target-os-checking">,
123123
HelpText<"Disable checking the target OS of serialized modules">;
124-
125-
def enable_astscope_lookup : Flag<["-"], "enable-astscope-lookup">,
126-
HelpText<"Enable ASTScope-based unqualified name lookup">;
124+
125+
def compare_to_astscope_lookup : Flag<["-"], "compare-to-astscope-lookup">,
126+
HelpText<"Compare legacy to ASTScope-based unqualified name lookup (for debugging)">;
127127

128128
def print_clang_stats : Flag<["-"], "print-clang-stats">,
129129
HelpText<"Print Clang importer statistics">;

include/swift/Option/Options.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,13 @@ def sanitize_coverage_EQ : CommaJoined<["-"], "sanitize-coverage=">,
853853
HelpText<"Specify the type of coverage instrumentation for Sanitizers and"
854854
" additional options separated by commas">;
855855

856+
def enable_astscope_lookup : Flag<["-"], "enable-astscope-lookup">,
857+
Flags<[FrontendOption]>,
858+
HelpText<"Enable ASTScope-based unqualified name lookup">;
859+
860+
def disable_parser_lookup : Flag<["-"], "disable_parser_lookup">,
861+
HelpText<"Disable parser lookup & use ast scope lookup only (experimental)">;
862+
856863
def index_file : Flag<["-"], "index-file">,
857864
HelpText<"Produce index data for a source file">, ModeOpt,
858865
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>;

include/swift/Parse/Parser.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -714,15 +714,15 @@ class Parser {
714714

715715
/// Add the given Decl to the current scope.
716716
void addToScope(ValueDecl *D, bool diagnoseRedefinitions = true) {
717-
if (Context.LangOpts.EnableASTScopeLookup)
717+
if (Context.LangOpts.DisableParserLookup)
718718
return;
719719

720720
getScopeInfo().addToScope(D, *this, diagnoseRedefinitions);
721721
}
722722

723723
ValueDecl *lookupInScope(DeclName Name) {
724-
if (Context.LangOpts.EnableASTScopeLookup)
725-
return nullptr;
724+
if (Context.LangOpts.DisableParserLookup)
725+
return nullptr;
726726

727727
return getScopeInfo().lookupValueName(Name);
728728
}

0 commit comments

Comments
 (0)