Skip to content

Commit 25488fe

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-rebranch
2 parents 01bf0d9 + c25de6a commit 25488fe

File tree

13 files changed

+489
-263
lines changed

13 files changed

+489
-263
lines changed

include/swift/AST/ASTScope.h

Lines changed: 103 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@
3838
#include "llvm/ADT/STLExtras.h"
3939
#include "llvm/ADT/SmallVector.h"
4040

41+
/// In case there's a bug in the ASTScope lookup system, suggest that the user
42+
/// try disabling it.
43+
/// \p message must be a string literal
44+
#define ASTScopeAssert(predicate, message) \
45+
assert((predicate) && message \
46+
" Try compiling with '-disable-astScope-lookup'.")
47+
48+
#define ASTScope_unreachable(message) \
49+
llvm_unreachable(message " Try compiling with '-disable-astScope-lookup'.")
50+
4151
namespace swift {
4252

4353
#pragma mark Forward-references
@@ -125,10 +135,10 @@ class ASTScopeImpl {
125135
/// Must clear source range change whenever this changes
126136
Children storedChildren;
127137

128-
/// Because expansion returns an insertion point,
129-
/// if a scope is reexpanded, the children added NOT by expansion must be
130-
/// rescued and reused.
131-
unsigned childrenCountWhenLastExpanded = 0;
138+
bool wasExpanded = false;
139+
140+
/// For use-before-def, ASTAncestor scopes may be added to a BraceStmt.
141+
unsigned astAncestorScopeCount = 0;
132142

133143
/// Can clear storedChildren, so must remember this
134144
bool haveAddedCleanup = false;
@@ -162,7 +172,7 @@ class ASTScopeImpl {
162172
void *operator new(size_t bytes, const ASTContext &ctx,
163173
unsigned alignment = alignof(ASTScopeImpl));
164174
void *operator new(size_t Bytes, void *Mem) {
165-
assert(Mem);
175+
ASTScopeAssert(Mem, "Allocation failed");
166176
return Mem;
167177
}
168178

@@ -180,12 +190,13 @@ class ASTScopeImpl {
180190

181191
public: // for addReusedBodyScopes
182192
void addChild(ASTScopeImpl *child, ASTContext &);
183-
std::vector<ASTScopeImpl *> rescueYoungestChildren(unsigned count);
193+
std::vector<ASTScopeImpl *> rescueASTAncestorScopesForReuseFromMe();
184194

185195
/// When reexpanding, do we always create a new body?
186-
virtual NullablePtr<ASTScopeImpl> getParentOfRescuedScopes();
187-
std::vector<ASTScopeImpl *> rescueScopesToReuse();
188-
void addReusedScopes(ArrayRef<ASTScopeImpl *>);
196+
virtual NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued();
197+
std::vector<ASTScopeImpl *>
198+
rescueASTAncestorScopesForReuseFromMeOrDescendants();
199+
void replaceASTAncestorScopes(ArrayRef<ASTScopeImpl *>);
189200

190201
private:
191202
void removeChildren();
@@ -196,6 +207,8 @@ class ASTScopeImpl {
196207

197208
public:
198209
void preOrderDo(function_ref<void(ASTScopeImpl *)>);
210+
/// Like preorderDo but without myself.
211+
void preOrderChildrenDo(function_ref<void(ASTScopeImpl *)>);
199212
void postOrderDo(function_ref<void(ASTScopeImpl *)>);
200213

201214
#pragma mark - source ranges
@@ -219,6 +232,12 @@ class ASTScopeImpl {
219232
bool doesRangeMatch(unsigned start, unsigned end, StringRef file = "",
220233
StringRef className = "");
221234

235+
unsigned countDescendants() const;
236+
237+
/// Make sure that when the argument is executed, there are as many
238+
/// descendants after as before.
239+
void assertThatTreeDoesNotShrink(function_ref<void()>);
240+
222241
private:
223242
SourceRange computeSourceRangeOfScope(bool omitAssertions = false) const;
224243
SourceRange
@@ -253,6 +272,8 @@ class ASTScopeImpl {
253272
void ensureSourceRangesAreCorrectWhenAddingDescendants(function_ref<void()>);
254273

255274
public: // public for debugging
275+
/// Returns source range of this node alone, without factoring in any
276+
/// children.
256277
virtual SourceRange
257278
getSourceRangeOfThisASTNode(bool omitAssertions = false) const = 0;
258279

@@ -314,10 +335,17 @@ class ASTScopeImpl {
314335
/// Return the scope into which to place subsequent decls
315336
ASTScopeImpl *expandAndBeCurrent(ScopeCreator &);
316337

338+
unsigned getASTAncestorScopeCount() const { return astAncestorScopeCount; }
339+
bool getWasExpanded() const { return wasExpanded; }
340+
317341
protected:
342+
void resetASTAncestorScopeCount() { astAncestorScopeCount = 0; }
343+
void increaseASTAncestorScopeCount(unsigned c) { astAncestorScopeCount += c; }
344+
void setWasExpanded() { wasExpanded = true; }
318345
virtual ASTScopeImpl *expandSpecifically(ScopeCreator &) = 0;
319346
virtual void beCurrent();
320-
virtual bool isCurrent() const;
347+
bool isCurrent() const;
348+
virtual bool isCurrentIfWasExpanded() const;
321349

322350
private:
323351
/// Compare the pre-expasion range with the post-expansion range and return
@@ -328,6 +356,8 @@ class ASTScopeImpl {
328356
/// Some scopes can be expanded lazily.
329357
/// Such scopes must: not change their source ranges after expansion, and
330358
/// their expansion must return an insertion point outside themselves.
359+
/// After a node is expanded, its source range (getSourceRangeofThisASTNode
360+
/// union children's ranges) must be same as this.
331361
virtual NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion();
332362
virtual SourceRange sourceRangeForDeferredExpansion() const;
333363

@@ -356,9 +386,6 @@ class ASTScopeImpl {
356386

357387
virtual ScopeCreator &getScopeCreator();
358388

359-
protected:
360-
void setChildrenCountWhenLastExpanded();
361-
362389
#pragma mark - - creation queries
363390
public:
364391
virtual bool isThisAnAbstractStorageDecl() const { return false; }
@@ -506,6 +533,7 @@ class ASTSourceFileScope final : public ASTScopeImpl {
506533
/// The number of \c Decls in the \c SourceFile that were already seen.
507534
/// Since parsing can be interleaved with type-checking, on every
508535
/// lookup, look at creating scopes for any \c Decls beyond this number.
536+
/// rdar://55562483 Unify with numberOfChildrenWhenLastExpanded
509537
int numberOfDeclsAlreadySeen = 0;
510538

511539
ASTSourceFileScope(SourceFile *SF, ScopeCreator *scopeCreator);
@@ -521,7 +549,9 @@ class ASTSourceFileScope final : public ASTScopeImpl {
521549
NullablePtr<DeclContext> getDeclContext() const override;
522550

523551
void addNewDeclsToScopeTree();
524-
void buildScopeTreeEagerly();
552+
void buildFullyExpandedTree();
553+
void
554+
buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals();
525555

526556
const SourceFile *getSourceFile() const override;
527557
NullablePtr<const void> addressForPrinting() const override { return SF; }
@@ -552,7 +582,7 @@ class Portion {
552582
void *operator new(size_t bytes, const ASTContext &ctx,
553583
unsigned alignment = alignof(ASTScopeImpl));
554584
void *operator new(size_t Bytes, void *Mem) {
555-
assert(Mem);
585+
ASTScopeAssert(Mem, "Allocation failed");
556586
return Mem;
557587
}
558588

@@ -575,12 +605,12 @@ class Portion {
575605
virtual const Decl *
576606
getReferrentOfScope(const GenericTypeOrExtensionScope *s) const;
577607

578-
virtual void beCurrent(IterableTypeScope *) const;
579-
virtual bool isCurrent(const IterableTypeScope *) const;
608+
virtual void beCurrent(IterableTypeScope *) const = 0;
609+
virtual bool isCurrentIfWasExpanded(const IterableTypeScope *) const = 0;
580610
virtual NullablePtr<ASTScopeImpl>
581-
insertionPointForDeferredExpansion(IterableTypeScope *) const;
611+
insertionPointForDeferredExpansion(IterableTypeScope *) const = 0;
582612
virtual SourceRange
583-
sourceRangeForDeferredExpansion(const IterableTypeScope *) const;
613+
sourceRangeForDeferredExpansion(const IterableTypeScope *) const = 0;
584614
};
585615

586616
// For the whole Decl scope of a GenericType or an Extension
@@ -601,6 +631,24 @@ class Portion {
601631

602632
const Decl *
603633
getReferrentOfScope(const GenericTypeOrExtensionScope *s) const override;
634+
635+
/// Make whole portion lazy to avoid circularity in lookup of generic
636+
/// parameters of extensions. When \c bindExtension is called, it needs to
637+
/// unqualifed-lookup the type being extended. That causes an \c
638+
/// ExtensionScope
639+
/// (\c GenericTypeOrExtensionWholePortion) to be built.
640+
/// The building process needs the generic parameters, but that results in a
641+
/// request for the extended nominal type of the \c ExtensionDecl, which is
642+
/// an endless recursion. Although we only need to make \c ExtensionScope
643+
/// lazy, might as well do it for all \c IterableTypeScopes.
644+
645+
void beCurrent(IterableTypeScope *) const override;
646+
bool isCurrentIfWasExpanded(const IterableTypeScope *) const override;
647+
648+
NullablePtr<ASTScopeImpl>
649+
insertionPointForDeferredExpansion(IterableTypeScope *) const override;
650+
SourceRange
651+
sourceRangeForDeferredExpansion(const IterableTypeScope *) const override;
604652
};
605653

606654
/// GenericTypeOrExtension = GenericType or Extension
@@ -639,6 +687,14 @@ class GenericTypeOrExtensionWherePortion final
639687

640688
SourceRange getChildlessSourceRangeOf(const GenericTypeOrExtensionScope *,
641689
bool omitAssertions) const override;
690+
691+
void beCurrent(IterableTypeScope *) const override;
692+
bool isCurrentIfWasExpanded(const IterableTypeScope *) const override;
693+
694+
NullablePtr<ASTScopeImpl>
695+
insertionPointForDeferredExpansion(IterableTypeScope *) const override;
696+
SourceRange
697+
sourceRangeForDeferredExpansion(const IterableTypeScope *) const override;
642698
};
643699

644700
/// Behavior specific to representing the Body of a NominalTypeDecl or
@@ -655,7 +711,7 @@ class IterableTypeBodyPortion final
655711
bool omitAssertions) const override;
656712

657713
void beCurrent(IterableTypeScope *) const override;
658-
bool isCurrent(const IterableTypeScope *) const override;
714+
bool isCurrentIfWasExpanded(const IterableTypeScope *) const override;
659715
NullablePtr<ASTScopeImpl>
660716
insertionPointForDeferredExpansion(IterableTypeScope *) const override;
661717
SourceRange
@@ -694,6 +750,17 @@ class GenericTypeOrExtensionScope : public ASTScopeImpl {
694750
SourceRange
695751
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
696752

753+
/// \c tryBindExtension needs to get the extended nominal, and the DeclContext
754+
/// is the parent of the \c ExtensionDecl. If the \c SourceRange of an \c
755+
/// ExtensionScope were to start where the \c ExtensionDecl says, the lookup
756+
/// source locaiton would fall within the \c ExtensionScope. This inclusion
757+
/// would cause the lazy \c ExtensionScope to be expanded which would ask for
758+
/// its generic parameters in order to create those sub-scopes. That request
759+
/// would cause a cycle because it would ask for the extended nominal. So,
760+
/// move the source range of an \c ExtensionScope *past* the extended nominal
761+
/// type, which is not in-scope there anyway.
762+
virtual SourceRange moveStartPastExtendedNominal(SourceRange) const = 0;
763+
697764
virtual GenericContext *getGenericContext() const = 0;
698765
std::string getClassName() const override;
699766
virtual std::string declKindName() const = 0;
@@ -732,6 +799,8 @@ class GenericTypeScope : public GenericTypeOrExtensionScope {
732799
public:
733800
GenericTypeScope(const Portion *p) : GenericTypeOrExtensionScope(p) {}
734801
virtual ~GenericTypeScope() {}
802+
SourceRange moveStartPastExtendedNominal(SourceRange) const override;
803+
735804
protected:
736805
NullablePtr<const GenericParamList> genericParams() const override;
737806
};
@@ -753,9 +822,11 @@ class IterableTypeScope : public GenericTypeScope {
753822

754823
protected:
755824
void beCurrent() override;
756-
bool isCurrent() const override;
825+
bool isCurrentIfWasExpanded() const override;
757826

758827
public:
828+
void makeWholeCurrent();
829+
bool isWholeCurrent() const;
759830
void makeBodyCurrent();
760831
bool isBodyCurrent() const;
761832
NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion() override;
@@ -804,6 +875,7 @@ class ExtensionScope final : public IterableTypeScope {
804875
NullablePtr<NominalTypeDecl> getCorrespondingNominalTypeDecl() const override;
805876
std::string declKindName() const override { return "Extension"; }
806877
SourceRange getBraces() const override;
878+
SourceRange moveStartPastExtendedNominal(SourceRange) const override;
807879
ASTScopeImpl *createTrailingWhereClauseScope(ASTScopeImpl *parent,
808880
ScopeCreator &) override;
809881
void createBodyScope(ASTScopeImpl *leaf, ScopeCreator &) override;
@@ -984,7 +1056,7 @@ class AbstractFunctionBodyScope : public ASTScopeImpl {
9841056
protected:
9851057
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
9861058
void beCurrent() override;
987-
bool isCurrent() const override;
1059+
bool isCurrentIfWasExpanded() const override;
9881060

9891061
private:
9901062
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
@@ -1000,7 +1072,7 @@ class AbstractFunctionBodyScope : public ASTScopeImpl {
10001072
Decl *getDecl() const { return decl; }
10011073
static bool isAMethod(const AbstractFunctionDecl *);
10021074

1003-
NullablePtr<ASTScopeImpl> getParentOfRescuedScopes() override;
1075+
NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued() override;
10041076

10051077
protected:
10061078
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
@@ -1076,11 +1148,14 @@ class AttachedPropertyWrapperScope final : public ASTScopeImpl {
10761148
/// false positives, that that doesn't hurt anything. However, the result of
10771149
/// the conservative source range computation doesn't seem to be stable. So
10781150
/// keep the original here, and use it for source range queries.
1151+
/// rdar://55263708
1152+
10791153
const SourceRange sourceRangeWhenCreated;
10801154

10811155
AttachedPropertyWrapperScope(VarDecl *e)
10821156
: decl(e), sourceRangeWhenCreated(getSourceRangeOfVarDecl(e)) {
1083-
assert(sourceRangeWhenCreated.isValid());
1157+
ASTScopeAssert(sourceRangeWhenCreated.isValid(),
1158+
"VarDecls must have ranges to be looked-up");
10841159
}
10851160
virtual ~AttachedPropertyWrapperScope() {}
10861161

@@ -1157,7 +1232,7 @@ class PatternEntryDeclScope final : public AbstractPatternEntryScope {
11571232
protected:
11581233
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
11591234
void beCurrent() override;
1160-
bool isCurrent() const override;
1235+
bool isCurrentIfWasExpanded() const override;
11611236

11621237
private:
11631238
AnnotatedInsertionPoint
@@ -1331,7 +1406,7 @@ class WholeClosureScope final : public AbstractClosureScope {
13311406
protected:
13321407
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
13331408
void beCurrent() override;
1334-
bool isCurrent() const override;
1409+
bool isCurrentIfWasExpanded() const override;
13351410

13361411
private:
13371412
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
@@ -1402,7 +1477,7 @@ class TopLevelCodeScope final : public ASTScopeImpl {
14021477
protected:
14031478
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
14041479
void beCurrent() override;
1405-
bool isCurrent() const override;
1480+
bool isCurrentIfWasExpanded() const override;
14061481

14071482
private:
14081483
AnnotatedInsertionPoint
@@ -1420,7 +1495,7 @@ class TopLevelCodeScope final : public ASTScopeImpl {
14201495
Decl *getDecl() const { return decl; }
14211496
NullablePtr<const void> getReferrent() const override;
14221497

1423-
NullablePtr<ASTScopeImpl> getParentOfRescuedScopes() override;
1498+
NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued() override;
14241499
};
14251500

14261501
/// The \c _@specialize attribute.

include/swift/AST/NameLookup.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -592,9 +592,11 @@ class ASTScope {
592592
public:
593593
ASTScope(SourceFile *);
594594

595-
/// Cannot be lazy during type-checking because it mutates the AST.
596-
/// So build eagerly before type-checking
597-
void buildScopeTreeEagerly();
595+
void
596+
buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals();
597+
598+
/// Flesh out the tree for dumping
599+
void buildFullyExpandedTree();
598600

599601
/// \return the scopes traversed
600602
static llvm::SmallVector<const ast_scope::ASTScopeImpl *, 0>

include/swift/Basic/LangOptions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ namespace swift {
252252
bool DisableParserLookup = false;
253253

254254
/// Should we compare to ASTScope-based resolution for debugging?
255-
bool CompareToASTScopeLookup = false;
255+
bool CrosscheckUnqualifiedLookup = false;
256256

257257
/// Should we stress ASTScope-based resolution for debugging?
258258
bool StressASTScopeLookup = false;

include/swift/Option/FrontendOptions.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ def disable_target_os_checking :
122122
Flag<["-"], "disable-target-os-checking">,
123123
HelpText<"Disable checking the target OS of serialized modules">;
124124

125-
def compare_to_astscope_lookup : Flag<["-"], "compare-to-astscope-lookup">,
126-
HelpText<"Compare legacy to ASTScope-based unqualified name lookup (for debugging)">;
125+
def crosscheck_unqualified_lookup : Flag<["-"], "crosscheck-unqualified-lookup">,
126+
HelpText<"Compare legacy DeclContext- to ASTScope-based unqualified name lookup (for debugging)">;
127127

128128
def stress_astscope_lookup : Flag<["-"], "stress-astscope-lookup">,
129129
HelpText<"Stress ASTScope-based unqualified name lookup (for testing)">;

0 commit comments

Comments
 (0)