Skip to content

Commit 663760e

Browse files
author
David Ungar
committed
ASTOOScope ontology
1 parent 6171d68 commit 663760e

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

+5526
-3526
lines changed

Diff for: include/swift/AST/ASTScope.h

+1,282-518
Large diffs are not rendered by default.

Diff for: include/swift/AST/ASTScopeNodes.def

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===--- ASTScopeIgnoredNodes.def - Swift Scope Metaprogramming --*- C++-*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines macros used for macro-metaprogramming with ASTScopes.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef IGNORE_PARSED_STMT
18+
#define IGNORE_PARSED_STMT(DeclOrStmtKind)
19+
#endif
20+
21+
22+
23+
IGNORE_PARSED_STMT(Break)
24+
IGNORE_PARSED_STMT(Continue)
25+
IGNORE_PARSED_STMT(Fallthrough)
26+
IGNORE_PARSED_STMT(Fail)
27+
IGNORE_PARSED_STMT(Throw)
28+
IGNORE_PARSED_STMT(PoundAssert)
29+
30+
#undef IGNORE_PARSED_STMT
31+
32+

Diff for: include/swift/AST/Expr.h

+6-2
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

@@ -4666,16 +4664,19 @@ class UnresolvedPatternExpr : public Expr {
46664664
class EditorPlaceholderExpr : public Expr {
46674665
Identifier Placeholder;
46684666
SourceLoc Loc;
4667+
SourceLoc TrailingAngleBracketLoc;
46694668
TypeLoc PlaceholderTy;
46704669
TypeRepr *ExpansionTyR;
46714670
Expr *SemanticExpr;
46724671

46734672
public:
46744673
EditorPlaceholderExpr(Identifier Placeholder, SourceLoc Loc,
4674+
SourceLoc TrailingAngleBracketLoc,
46754675
TypeLoc PlaceholderTy,
46764676
TypeRepr *ExpansionTyR)
46774677
: Expr(ExprKind::EditorPlaceholder, /*Implicit=*/false),
46784678
Placeholder(Placeholder), Loc(Loc),
4679+
TrailingAngleBracketLoc(TrailingAngleBracketLoc),
46794680
PlaceholderTy(PlaceholderTy),
46804681
ExpansionTyR(ExpansionTyR),
46814682
SemanticExpr(nullptr) {
@@ -4685,6 +4686,9 @@ class EditorPlaceholderExpr : public Expr {
46854686
SourceRange getSourceRange() const { return Loc; }
46864687
TypeLoc &getTypeLoc() { return PlaceholderTy; }
46874688
TypeLoc getTypeLoc() const { return PlaceholderTy; }
4689+
SourceLoc getTrailingAngleBracketLoc() const {
4690+
return TrailingAngleBracketLoc;
4691+
}
46884692

46894693
/// The TypeRepr to be considered for placeholder expansion.
46904694
TypeRepr *getTypeForExpansion() const { return ExpansionTyR; }

Diff for: include/swift/AST/Module.h

+7-4
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 {
@@ -1189,7 +1192,7 @@ class SourceFile final : public FileUnit {
11891192
StringRef getFilename() const;
11901193

11911194
/// Retrieve the scope that describes this source file.
1192-
ASTScope &getScope();
1195+
ASTScope *getScope();
11931196

11941197
void dump() const;
11951198
void dump(raw_ostream &os) const;

Diff for: include/swift/AST/NameLookup.h

+165-43
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/AST/ASTVisitor.h"
2323
#include "swift/AST/Identifier.h"
2424
#include "swift/AST/Module.h"
25+
#include "swift/Basic/NullablePtr.h"
2526
#include "swift/Basic/SourceLoc.h"
2627

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

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().
64-
DeclContext *BaseDC;
108+
/// The declaration corresponds to the given name; i.e. the decl we are
109+
/// looking up.
110+
ValueDecl *Value;
65111

66-
/// The declaration corresponds to the given name; i.e. the decl we are
67-
/// looking up.
68-
ValueDecl *Value;
112+
public:
113+
LookupResultEntry(ValueDecl *value) : BaseDC(nullptr), Value(value) {}
69114

70-
public:
71-
LookupResultEntry(ValueDecl *value) : BaseDC(nullptr), Value(value) { }
115+
LookupResultEntry(DeclContext *baseDC, ValueDecl *value)
116+
: BaseDC(baseDC), Value(value) {}
72117

73-
LookupResultEntry(DeclContext *baseDC, ValueDecl *value)
74-
: BaseDC(baseDC), Value(value) { }
118+
ValueDecl *getValueDecl() const { return Value; }
75119

76-
ValueDecl *getValueDecl() const {
77-
return Value;
78-
}
120+
DeclContext *getDeclContext() const { return BaseDC; }
79121

80-
DeclContext *getDeclContext() const {
81-
return BaseDC;
82-
}
122+
ValueDecl *getBaseDecl() const;
83123

84-
ValueDecl *getBaseDecl() const;
124+
void print(llvm::raw_ostream &) const;
85125
};
86126

87127
/// This class implements and represents the result of performing
@@ -110,13 +150,13 @@ class UnqualifiedLookup {
110150
/// is used to determine which declarations in that body are visible.
111151
UnqualifiedLookup(DeclName Name, DeclContext *DC, LazyResolver *TypeResolver,
112152
SourceLoc Loc = SourceLoc(), Options options = Options());
113-
114-
SmallVector<LookupResultEntry, 4> Results;
153+
using ResultsVector = SmallVector<LookupResultEntry, 4>;
154+
ResultsVector Results;
115155
/// The index of the first result that isn't from the innermost scope
116156
/// with results.
117157
///
118158
/// That is, \c makeArrayRef(Results).take_front(IndexOfFirstOuterResults)
119-
/// will be Results from the innermost scope that had results, and the
159+
/// will be \c Results from the innermost scope that had results, and the
120160
/// remaining elements of Results will be from parent scopes of this one.
121161
///
122162
/// Allows unqualified name lookup to return results from outer scopes.
@@ -136,7 +176,6 @@ inline UnqualifiedLookup::Options operator|(UnqualifiedLookup::Flags flag1,
136176
return UnqualifiedLookup::Options(flag1) | flag2;
137177
}
138178

139-
140179
/// Describes the reason why a certain declaration is visible.
141180
enum class DeclVisibilityKind {
142181
/// Declaration is a local variable or type.
@@ -536,8 +575,91 @@ class FindLocalVal : public StmtVisitor<FindLocalVal> {
536575
void visitCatchStmt(CatchStmt *S);
537576

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

616+
/// Eventually this functionality should move into ASTScopeLookup
617+
std::pair<bool, Optional<bool>>
618+
lookupInSelfType(NullablePtr<DeclContext>, DeclContext *const,
619+
NominalTypeDecl *const,
620+
Optional<bool> isCascadingUse) override {
621+
return std::make_pair(false, isCascadingUse);
622+
}
623+
624+
void stopForDebuggingIfTargetLookup() override {}
625+
626+
ArrayRef<ValueDecl *> getDecls() { return values; }
627+
};
540628
} // end namespace namelookup
629+
630+
/// The interface into the ASTScope subsystem
631+
class ASTScope {
632+
friend class ast_scope::ASTScopeImpl;
633+
ast_scope::ASTSourceFileScope *const impl;
634+
635+
public:
636+
ASTScope(ast_scope::ASTSourceFileScope *sfs) : impl(sfs) {}
637+
static ASTScope *createScopeTreeFor(SourceFile *);
638+
static Optional<bool>
639+
unqualifiedLookup(SourceFile *, DeclName, SourceLoc,
640+
const DeclContext *startingContext,
641+
Optional<bool> isCascadingUse,
642+
namelookup::AbstractASTScopeDeclConsumer &);
643+
644+
void dump() const;
645+
void print(llvm::raw_ostream &) const;
646+
void dumpOneScopeMapLocation(std::pair<unsigned, unsigned>) const;
647+
648+
// Make vanilla new illegal for ASTScopes.
649+
void *operator new(size_t bytes) = delete;
650+
// Need this because have virtual destructors
651+
void operator delete(void *data) {}
652+
653+
// Only allow allocation of scopes using the allocator of a particular source
654+
// file.
655+
void *operator new(size_t bytes, const ASTContext &ctx,
656+
unsigned alignment = alignof(ASTScope));
657+
void *operator new(size_t Bytes, void *Mem) {
658+
assert(Mem);
659+
return Mem;
660+
}
661+
};
662+
541663
} // end namespace swift
542664

543665
#endif

Diff for: include/swift/Basic/LangOptions.h

+3
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ namespace swift {
241241
/// Should we use \c ASTScope-based resolution for unqualified name lookup?
242242
bool EnableASTScopeLookup = false;
243243

244+
/// Sound we compare to ASTScope-based resolution for debugging?
245+
bool CompareToASTScopeLookup = false;
246+
244247
/// Whether to use the import as member inference system
245248
///
246249
/// When importing a global, try to infer whether we can import it as a

Diff for: include/swift/Basic/STLExtras.h

+7
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.

Diff for: include/swift/Option/FrontendOptions.td

+3-3
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">;

0 commit comments

Comments
 (0)