Skip to content

Commit 200eb30

Browse files
author
David Ungar
authored
Merge pull request #25692 from davidungar/A-6-14
[Name Lookup, ASTScope] simplified and debugged
2 parents 0438b1f + 723b391 commit 200eb30

14 files changed

+1329
-725
lines changed

include/swift/AST/ASTScope.h

Lines changed: 126 additions & 107 deletions
Large diffs are not rendered by default.

include/swift/AST/NameLookup.h

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -592,17 +592,18 @@ class AbstractASTScopeDeclConsumer {
592592
/// Takes an array in order to batch the consumption before setting
593593
/// IndexOfFirstOuterResult when necessary.
594594
virtual bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis,
595-
Optional<bool> isCascadingUse,
596595
NullablePtr<DeclContext> baseDC = nullptr) = 0;
597596

598597
/// 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;
598+
virtual bool
599+
lookInMembers(NullablePtr<DeclContext> selfDC, DeclContext *const scopeDC,
600+
NominalTypeDecl *const nominal,
601+
function_ref<bool(Optional<bool>)> calculateIsCascadingUse) = 0;
603602

604603
#ifndef NDEBUG
605-
virtual void stopForDebuggingIfTargetLookup() = 0;
604+
virtual void startingNextLookupStep() = 0;
605+
virtual void finishingLookup(std::string) const = 0;
606+
virtual bool isTargetLookup() const = 0;
606607
#endif
607608
};
608609

@@ -615,19 +616,19 @@ class ASTScopeDeclGatherer : public AbstractASTScopeDeclConsumer {
615616
virtual ~ASTScopeDeclGatherer() = default;
616617

617618
bool consume(ArrayRef<ValueDecl *> values, DeclVisibilityKind vis,
618-
Optional<bool> isCascadingUse,
619619
NullablePtr<DeclContext> baseDC = nullptr) override;
620620

621621
/// 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);
622+
bool lookInMembers(NullablePtr<DeclContext>, DeclContext *const,
623+
NominalTypeDecl *const,
624+
function_ref<bool(Optional<bool>)>) override {
625+
return false;
627626
}
628627

629628
#ifndef NDEBUG
630-
void stopForDebuggingIfTargetLookup() override {}
629+
void startingNextLookupStep() override {}
630+
void finishingLookup(std::string) const override {}
631+
bool isTargetLookup() const override { return false; }
631632
#endif
632633

633634
ArrayRef<ValueDecl *> getDecls() { return values; }
@@ -641,12 +642,17 @@ class ASTScope {
641642

642643
public:
643644
ASTScope(SourceFile *);
644-
static Optional<bool>
645+
646+
/// \return the scopes traversed
647+
static llvm::SmallVector<const ast_scope::ASTScopeImpl *, 0>
645648
unqualifiedLookup(SourceFile *, DeclName, SourceLoc,
646649
const DeclContext *startingContext,
647-
Optional<bool> isCascadingUse,
648650
namelookup::AbstractASTScopeDeclConsumer &);
649651

652+
static Optional<bool>
653+
computeIsCascadingUse(ArrayRef<const ast_scope::ASTScopeImpl *> history,
654+
Optional<bool> initialIsCascadingUse);
655+
650656
LLVM_ATTRIBUTE_DEPRECATED(void dump() const LLVM_ATTRIBUTE_USED,
651657
"only for use within the debugger");
652658
void print(llvm::raw_ostream &) const;

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,11 @@ namespace swift {
247247
bool EnableDeserializationRecovery = true;
248248

249249
/// Should we use \c ASTScope-based resolution for unqualified name lookup?
250+
/// Default is in \c ParseLangArgs
251+
///
252+
/// This is a staging flag; eventually it will be removed.
250253
bool EnableASTScopeLookup = false;
251-
254+
252255
/// Someday, ASTScopeLookup will supplant lookup in the parser
253256
bool DisableParserLookup = false;
254257

include/swift/Option/Options.td

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,12 @@ def enable_astscope_lookup : Flag<["-"], "enable-astscope-lookup">,
869869
Flags<[FrontendOption]>,
870870
HelpText<"Enable ASTScope-based unqualified name lookup">;
871871

872-
def disable_parser_lookup : Flag<["-"], "disable_parser_lookup">,
872+
def disable_astscope_lookup : Flag<["-"], "disable-astscope-lookup">,
873+
Flags<[FrontendOption]>,
874+
HelpText<"Disable ASTScope-based unqualified name lookup">;
875+
876+
def disable_parser_lookup : Flag<["-"], "disable-parser-lookup">,
877+
Flags<[FrontendOption]>,
873878
HelpText<"Disable parser lookup & use ast scope lookup only (experimental)">;
874879

875880
def index_file : Flag<["-"], "index-file">,

lib/AST/ASTScope.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,18 @@ using namespace ast_scope;
3737

3838
#pragma mark ASTScope
3939

40-
41-
Optional<bool> ASTScope::unqualifiedLookup(
40+
llvm::SmallVector<const ASTScopeImpl *, 0> ASTScope::unqualifiedLookup(
4241
SourceFile *SF, DeclName name, SourceLoc loc,
43-
const DeclContext *startingContext, Optional<bool> isCascadingUse,
42+
const DeclContext *startingContext,
4443
namelookup::AbstractASTScopeDeclConsumer &consumer) {
4544
return ASTScopeImpl::unqualifiedLookup(SF, name, loc, startingContext,
46-
isCascadingUse, consumer);
45+
consumer);
46+
}
47+
48+
Optional<bool> ASTScope::computeIsCascadingUse(
49+
ArrayRef<const ast_scope::ASTScopeImpl *> history,
50+
Optional<bool> initialIsCascadingUse) {
51+
return ASTScopeImpl::computeIsCascadingUse(history, initialIsCascadingUse);
4752
}
4853

4954
void ASTScope::dump() const { impl->dump(); }
@@ -108,6 +113,20 @@ Stmt *LabeledConditionalStmtScope::getStmt() const {
108113
return getLabeledConditionalStmt();
109114
}
110115

116+
bool AbstractFunctionBodyScope::isAMethod(
117+
const AbstractFunctionDecl *const afd) {
118+
// What makes this interesting is that a method named "init" which is not
119+
// in a nominal type or extension decl body still gets an implicit self
120+
// parameter (even though the program is illegal).
121+
// So when choosing between creating a MethodBodyScope and a
122+
// PureFunctionBodyScope do we go by the enclosing Decl (i.e.
123+
// "afd->getDeclContext()->isTypeContext()") or by
124+
// "bool(afd->getImplicitSelfDecl())"?
125+
//
126+
// Since the code uses \c getImplicitSelfDecl, use that.
127+
return afd->getImplicitSelfDecl();
128+
}
129+
111130
#pragma mark getLabeledConditionalStmt
112131
LabeledConditionalStmt *IfStmtScope::getLabeledConditionalStmt() const {
113132
return stmt;
@@ -132,6 +151,14 @@ ASTContext &ASTScopeImpl::getASTContext() const {
132151

133152
#pragma mark getDeclContext
134153

154+
NullablePtr<DeclContext> ASTScopeImpl::getDeclContext() const {
155+
return nullptr;
156+
}
157+
158+
NullablePtr<DeclContext> ASTSourceFileScope::getDeclContext() const {
159+
return NullablePtr<DeclContext>(SF);
160+
}
161+
135162
NullablePtr<DeclContext> GenericTypeOrExtensionScope::getDeclContext() const {
136163
return getGenericContext();
137164
}
@@ -168,6 +195,10 @@ NullablePtr<DeclContext> AttachedPropertyWrapperScope::getDeclContext() const {
168195
.getInitContext();
169196
}
170197

198+
NullablePtr<DeclContext> AbstractFunctionDeclScope::getDeclContext() const {
199+
return decl;
200+
}
201+
171202
NullablePtr<DeclContext> AbstractFunctionParamsScope::getDeclContext() const {
172203
return matchingContext;
173204
}

lib/AST/ASTScopeCreation.cpp

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -95,43 +95,36 @@ class ScopeCreator final {
9595
// Implicit nodes don't have source information for name lookup.
9696
if (d->isImplicit())
9797
return false;
98-
// Have also seen the following in an AST:
99-
// Source::
100-
//
101-
// func testInvalidKeyPathComponents() {
102-
// let _ = \.{return 0} // expected-error* {{}}
103-
// }
104-
// class X {
105-
// class var a: Int { return 1 }
106-
// }
107-
//
108-
// AST:
109-
// clang-format off
110-
// (source_file "test.swift"
111-
// (func_decl range=[test.swift:1:3 - line:3:3] "testInvalidKeyPathComponents()" interface type='() -> ()' access=internal
112-
// (parameter_list range=[test.swift:1:36 - line:1:37])
113-
// (brace_stmt range=[test.swift:1:39 - line:3:3]
114-
// (pattern_binding_decl range=[test.swift:2:5 - line:2:11]
115-
// (pattern_any)
116-
// (error_expr implicit type='<null>'))
117-
//
118-
// (pattern_binding_decl range=[test.swift:2:5 - line:2:5] <=== SOURCE RANGE WILL CONFUSE SCOPE CODE
119-
// (pattern_typed implicit type='<<error type>>'
120-
// (pattern_named '_')))
121-
// ...
122-
// clang-format on
123-
//
124-
// So test the SourceRange
125-
//
126-
// But wait!
127-
// var z = $x0 + $x1
128-
// z
129-
//
130-
// z has start == end, but must be pushed to expand source range
131-
//
132-
// So, only check source ranges for PatternBindingDecls
133-
if (isa<PatternBindingDecl>(d) && (d->getStartLoc() == d->getEndLoc()))
134-
return false;
98+
/// In \c Parser::parseDeclVarGetSet fake PBDs are created. Ignore them.
99+
/// Example:
100+
/// \code
101+
/// class SR10903 { static var _: Int { 0 } }
102+
/// \endcode
103+
if (const auto *PBD = dyn_cast<PatternBindingDecl>(d))
104+
if (PBD->isInvalid())
105+
return false;
106+
/// In
107+
/// \code
108+
/// @propertyWrapper
109+
/// public struct Wrapper<T> {
110+
/// public var value: T
111+
///
112+
/// public init(body: () -> T) {
113+
/// self.value = body()
114+
/// }
115+
/// }
116+
///
117+
/// let globalInt = 17
118+
///
119+
/// @Wrapper(body: { globalInt })
120+
/// public var y: Int
121+
/// \endcode
122+
/// I'm seeing a dumped AST include:
123+
/// (pattern_binding_decl range=[test.swift:13:8 - line:12:29]
124+
const auto &SM = d->getASTContext().SourceMgr;
125+
assert((d->getStartLoc().isInvalid() ||
126+
!SM.isBeforeInBuffer(d->getEndLoc(), d->getStartLoc())) &&
127+
"end-before-start will break tree search via location");
135128
return true;
136129
}
137130

@@ -179,9 +172,10 @@ class ScopeCreator final {
179172
function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
180173
foundClosure);
181174

175+
// A safe way to discover this, without creating a circular request.
176+
// Cannot call getAttachedPropertyWrappers.
182177
static bool hasCustomAttribute(VarDecl *vd) {
183-
return AttachedPropertyWrapperScope::getCustomAttributesSourceRange(vd)
184-
.isValid();
178+
return vd->getAttrs().getAttribute<CustomAttr>();
185179
}
186180

187181
public:
@@ -190,8 +184,9 @@ class ScopeCreator final {
190184

191185
void createAttachedPropertyWrapperScope(PatternBindingDecl *patternBinding,
192186
ASTScopeImpl *parent) {
187+
193188
patternBinding->getPattern(0)->forEachVariable([&](VarDecl *vd) {
194-
// assume all same as first
189+
// assume all same as first
195190
if (hasCustomAttribute(vd))
196191
createSubtree<AttachedPropertyWrapperScope>(parent, vd);
197192
});
@@ -221,7 +216,7 @@ class ScopeCreator final {
221216
void
222217
forEachSpecializeAttrInSourceOrder(Decl *declBeingSpecialized,
223218
function_ref<void(SpecializeAttr *)> fn) {
224-
llvm::SmallVector<SpecializeAttr *, 8> sortedSpecializeAttrs;
219+
SmallVector<SpecializeAttr *, 8> sortedSpecializeAttrs;
225220
for (auto *attr : declBeingSpecialized->getAttrs()) {
226221
if (auto *specializeAttr = dyn_cast<SpecializeAttr>(attr)) {
227222
if (!isDuplicate(specializeAttr))
@@ -584,6 +579,8 @@ CREATES_NEW_INSERTION_POINT(TopLevelCodeScope)
584579

585580
NO_NEW_INSERTION_POINT(AbstractFunctionBodyScope)
586581
NO_NEW_INSERTION_POINT(AbstractFunctionDeclScope)
582+
NO_NEW_INSERTION_POINT(AttachedPropertyWrapperScope)
583+
587584
NO_NEW_INSERTION_POINT(CaptureListScope)
588585
NO_NEW_INSERTION_POINT(CaseStmtScope)
589586
NO_NEW_INSERTION_POINT(CatchStmtScope)
@@ -606,7 +603,6 @@ NO_EXPANSION(ClosureParametersScope)
606603
NO_EXPANSION(SpecializeAttributeScope)
607604
// no accessors, unlike PatternEntryUseScope
608605
NO_EXPANSION(ConditionalClausePatternUseScope)
609-
NO_EXPANSION(AttachedPropertyWrapperScope)
610606
NO_EXPANSION(GuardStmtUseScope)
611607

612608
#undef CREATES_NEW_INSERTION_POINT
@@ -744,8 +740,10 @@ void AbstractFunctionDeclScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
744740
}
745741
}
746742
// Create scope for the body.
747-
if (decl->getBody()) {
748-
if (decl->getDeclContext()->isTypeContext())
743+
// We create body scopes when there is no body for source kit to complete
744+
// erroneous code in bodies.
745+
if (decl->getBodySourceRange().isValid()) {
746+
if (AbstractFunctionBodyScope::isAMethod(decl))
749747
scopeCreator.createSubtree<MethodBodyScope>(leaf, decl);
750748
else
751749
scopeCreator.createSubtree<PureFunctionBodyScope>(leaf, decl);
@@ -754,8 +752,10 @@ void AbstractFunctionDeclScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
754752

755753
void AbstractFunctionBodyScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
756754
ScopeCreator &scopeCreator) {
757-
BraceStmt *braceStmt = decl->getBody();
758-
ASTVisitorForScopeCreation().visitBraceStmt(braceStmt, this, scopeCreator);
755+
// We create body scopes when there is no body for source kit to complete
756+
// erroneous code in bodies.
757+
if (BraceStmt *braceStmt = decl->getBody())
758+
ASTVisitorForScopeCreation().visitBraceStmt(braceStmt, this, scopeCreator);
759759
}
760760

761761
void IfStmtScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
@@ -898,6 +898,15 @@ void DefaultArgumentInitializerScope::
898898
ASTVisitorForScopeCreation().visitExpr(initExpr, this, scopeCreator);
899899
}
900900

901+
void AttachedPropertyWrapperScope::
902+
expandAScopeThatDoesNotCreateANewInsertionPoint(
903+
ScopeCreator &scopeCreator) {
904+
for (auto *attr : decl->getAttrs().getAttributes<CustomAttr>()) {
905+
if (auto *expr = attr->getArg())
906+
ASTVisitorForScopeCreation().visitExpr(expr, this, scopeCreator);
907+
}
908+
}
909+
901910
#pragma mark expandScope
902911

903912
ASTScopeImpl *GenericTypeOrExtensionWholePortion::expandScope(
@@ -911,8 +920,7 @@ ASTScopeImpl *GenericTypeOrExtensionWholePortion::expandScope(
911920
scope->getDecl().get(), scope->getGenericContext()->getGenericParams(),
912921
scope);
913922
if (scope->getGenericContext()->getTrailingWhereClause())
914-
deepestScope =
915-
scope->createTrailingWhereClauseScope(deepestScope, scopeCreator);
923+
scope->createTrailingWhereClauseScope(deepestScope, scopeCreator);
916924
scope->createBodyScope(deepestScope, scopeCreator);
917925
return scope->getParent().get();
918926
}

0 commit comments

Comments
 (0)