38
38
#include " llvm/ADT/STLExtras.h"
39
39
#include " llvm/ADT/SmallVector.h"
40
40
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
+
41
51
namespace swift {
42
52
43
53
#pragma mark Forward-references
@@ -125,10 +135,10 @@ class ASTScopeImpl {
125
135
// / Must clear source range change whenever this changes
126
136
Children storedChildren;
127
137
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 ;
132
142
133
143
// / Can clear storedChildren, so must remember this
134
144
bool haveAddedCleanup = false ;
@@ -162,7 +172,7 @@ class ASTScopeImpl {
162
172
void *operator new (size_t bytes, const ASTContext &ctx,
163
173
unsigned alignment = alignof (ASTScopeImpl));
164
174
void *operator new (size_t Bytes, void *Mem) {
165
- assert (Mem);
175
+ ASTScopeAssert (Mem, " Allocation failed " );
166
176
return Mem;
167
177
}
168
178
@@ -180,12 +190,13 @@ class ASTScopeImpl {
180
190
181
191
public: // for addReusedBodyScopes
182
192
void addChild (ASTScopeImpl *child, ASTContext &);
183
- std::vector<ASTScopeImpl *> rescueYoungestChildren ( unsigned count );
193
+ std::vector<ASTScopeImpl *> rescueASTAncestorScopesForReuseFromMe ( );
184
194
185
195
// / 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 *>);
189
200
190
201
private:
191
202
void removeChildren ();
@@ -196,6 +207,8 @@ class ASTScopeImpl {
196
207
197
208
public:
198
209
void preOrderDo (function_ref<void (ASTScopeImpl *)>);
210
+ // / Like preorderDo but without myself.
211
+ void preOrderChildrenDo (function_ref<void (ASTScopeImpl *)>);
199
212
void postOrderDo (function_ref<void (ASTScopeImpl *)>);
200
213
201
214
#pragma mark - source ranges
@@ -219,6 +232,12 @@ class ASTScopeImpl {
219
232
bool doesRangeMatch (unsigned start, unsigned end, StringRef file = " " ,
220
233
StringRef className = " " );
221
234
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
+
222
241
private:
223
242
SourceRange computeSourceRangeOfScope (bool omitAssertions = false ) const ;
224
243
SourceRange
@@ -253,6 +272,8 @@ class ASTScopeImpl {
253
272
void ensureSourceRangesAreCorrectWhenAddingDescendants (function_ref<void ()>);
254
273
255
274
public: // public for debugging
275
+ // / Returns source range of this node alone, without factoring in any
276
+ // / children.
256
277
virtual SourceRange
257
278
getSourceRangeOfThisASTNode (bool omitAssertions = false ) const = 0 ;
258
279
@@ -314,10 +335,17 @@ class ASTScopeImpl {
314
335
// / Return the scope into which to place subsequent decls
315
336
ASTScopeImpl *expandAndBeCurrent (ScopeCreator &);
316
337
338
+ unsigned getASTAncestorScopeCount () const { return astAncestorScopeCount; }
339
+ bool getWasExpanded () const { return wasExpanded; }
340
+
317
341
protected:
342
+ void resetASTAncestorScopeCount () { astAncestorScopeCount = 0 ; }
343
+ void increaseASTAncestorScopeCount (unsigned c) { astAncestorScopeCount += c; }
344
+ void setWasExpanded () { wasExpanded = true ; }
318
345
virtual ASTScopeImpl *expandSpecifically (ScopeCreator &) = 0;
319
346
virtual void beCurrent ();
320
- virtual bool isCurrent () const ;
347
+ bool isCurrent () const ;
348
+ virtual bool isCurrentIfWasExpanded () const ;
321
349
322
350
private:
323
351
// / Compare the pre-expasion range with the post-expansion range and return
@@ -328,6 +356,8 @@ class ASTScopeImpl {
328
356
// / Some scopes can be expanded lazily.
329
357
// / Such scopes must: not change their source ranges after expansion, and
330
358
// / 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.
331
361
virtual NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion ();
332
362
virtual SourceRange sourceRangeForDeferredExpansion () const ;
333
363
@@ -356,9 +386,6 @@ class ASTScopeImpl {
356
386
357
387
virtual ScopeCreator &getScopeCreator ();
358
388
359
- protected:
360
- void setChildrenCountWhenLastExpanded ();
361
-
362
389
#pragma mark - - creation queries
363
390
public:
364
391
virtual bool isThisAnAbstractStorageDecl () const { return false ; }
@@ -506,6 +533,7 @@ class ASTSourceFileScope final : public ASTScopeImpl {
506
533
// / The number of \c Decls in the \c SourceFile that were already seen.
507
534
// / Since parsing can be interleaved with type-checking, on every
508
535
// / lookup, look at creating scopes for any \c Decls beyond this number.
536
+ // / rdar://55562483 Unify with numberOfChildrenWhenLastExpanded
509
537
int numberOfDeclsAlreadySeen = 0 ;
510
538
511
539
ASTSourceFileScope (SourceFile *SF, ScopeCreator *scopeCreator);
@@ -521,7 +549,9 @@ class ASTSourceFileScope final : public ASTScopeImpl {
521
549
NullablePtr<DeclContext> getDeclContext () const override ;
522
550
523
551
void addNewDeclsToScopeTree ();
524
- void buildScopeTreeEagerly ();
552
+ void buildFullyExpandedTree ();
553
+ void
554
+ buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals ();
525
555
526
556
const SourceFile *getSourceFile () const override ;
527
557
NullablePtr<const void > addressForPrinting () const override { return SF; }
@@ -552,7 +582,7 @@ class Portion {
552
582
void *operator new (size_t bytes, const ASTContext &ctx,
553
583
unsigned alignment = alignof (ASTScopeImpl));
554
584
void *operator new (size_t Bytes, void *Mem) {
555
- assert (Mem);
585
+ ASTScopeAssert (Mem, " Allocation failed " );
556
586
return Mem;
557
587
}
558
588
@@ -575,12 +605,12 @@ class Portion {
575
605
virtual const Decl *
576
606
getReferrentOfScope (const GenericTypeOrExtensionScope *s) const ;
577
607
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 ;
580
610
virtual NullablePtr<ASTScopeImpl>
581
- insertionPointForDeferredExpansion (IterableTypeScope *) const ;
611
+ insertionPointForDeferredExpansion (IterableTypeScope *) const = 0 ;
582
612
virtual SourceRange
583
- sourceRangeForDeferredExpansion (const IterableTypeScope *) const ;
613
+ sourceRangeForDeferredExpansion (const IterableTypeScope *) const = 0 ;
584
614
};
585
615
586
616
// For the whole Decl scope of a GenericType or an Extension
@@ -601,6 +631,24 @@ class Portion {
601
631
602
632
const Decl *
603
633
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 ;
604
652
};
605
653
606
654
// / GenericTypeOrExtension = GenericType or Extension
@@ -639,6 +687,14 @@ class GenericTypeOrExtensionWherePortion final
639
687
640
688
SourceRange getChildlessSourceRangeOf (const GenericTypeOrExtensionScope *,
641
689
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 ;
642
698
};
643
699
644
700
// / Behavior specific to representing the Body of a NominalTypeDecl or
@@ -655,7 +711,7 @@ class IterableTypeBodyPortion final
655
711
bool omitAssertions) const override ;
656
712
657
713
void beCurrent (IterableTypeScope *) const override ;
658
- bool isCurrent (const IterableTypeScope *) const override ;
714
+ bool isCurrentIfWasExpanded (const IterableTypeScope *) const override ;
659
715
NullablePtr<ASTScopeImpl>
660
716
insertionPointForDeferredExpansion (IterableTypeScope *) const override ;
661
717
SourceRange
@@ -694,6 +750,17 @@ class GenericTypeOrExtensionScope : public ASTScopeImpl {
694
750
SourceRange
695
751
getSourceRangeOfThisASTNode (bool omitAssertions = false ) const override ;
696
752
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
+
697
764
virtual GenericContext *getGenericContext () const = 0;
698
765
std::string getClassName () const override ;
699
766
virtual std::string declKindName () const = 0;
@@ -732,6 +799,8 @@ class GenericTypeScope : public GenericTypeOrExtensionScope {
732
799
public:
733
800
GenericTypeScope (const Portion *p) : GenericTypeOrExtensionScope(p) {}
734
801
virtual ~GenericTypeScope () {}
802
+ SourceRange moveStartPastExtendedNominal (SourceRange) const override ;
803
+
735
804
protected:
736
805
NullablePtr<const GenericParamList> genericParams () const override ;
737
806
};
@@ -753,9 +822,11 @@ class IterableTypeScope : public GenericTypeScope {
753
822
754
823
protected:
755
824
void beCurrent () override ;
756
- bool isCurrent () const override ;
825
+ bool isCurrentIfWasExpanded () const override ;
757
826
758
827
public:
828
+ void makeWholeCurrent ();
829
+ bool isWholeCurrent () const ;
759
830
void makeBodyCurrent ();
760
831
bool isBodyCurrent () const ;
761
832
NullablePtr<ASTScopeImpl> insertionPointForDeferredExpansion () override ;
@@ -804,6 +875,7 @@ class ExtensionScope final : public IterableTypeScope {
804
875
NullablePtr<NominalTypeDecl> getCorrespondingNominalTypeDecl () const override ;
805
876
std::string declKindName () const override { return " Extension" ; }
806
877
SourceRange getBraces () const override ;
878
+ SourceRange moveStartPastExtendedNominal (SourceRange) const override ;
807
879
ASTScopeImpl *createTrailingWhereClauseScope (ASTScopeImpl *parent,
808
880
ScopeCreator &) override ;
809
881
void createBodyScope (ASTScopeImpl *leaf, ScopeCreator &) override ;
@@ -984,7 +1056,7 @@ class AbstractFunctionBodyScope : public ASTScopeImpl {
984
1056
protected:
985
1057
ASTScopeImpl *expandSpecifically (ScopeCreator &scopeCreator) override ;
986
1058
void beCurrent () override ;
987
- bool isCurrent () const override ;
1059
+ bool isCurrentIfWasExpanded () const override ;
988
1060
989
1061
private:
990
1062
void expandAScopeThatDoesNotCreateANewInsertionPoint (ScopeCreator &);
@@ -1000,7 +1072,7 @@ class AbstractFunctionBodyScope : public ASTScopeImpl {
1000
1072
Decl *getDecl () const { return decl; }
1001
1073
static bool isAMethod (const AbstractFunctionDecl *);
1002
1074
1003
- NullablePtr<ASTScopeImpl> getParentOfRescuedScopes () override ;
1075
+ NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued () override ;
1004
1076
1005
1077
protected:
1006
1078
bool lookupLocalsOrMembers (ArrayRef<const ASTScopeImpl *>,
@@ -1076,11 +1148,14 @@ class AttachedPropertyWrapperScope final : public ASTScopeImpl {
1076
1148
// / false positives, that that doesn't hurt anything. However, the result of
1077
1149
// / the conservative source range computation doesn't seem to be stable. So
1078
1150
// / keep the original here, and use it for source range queries.
1151
+ // / rdar://55263708
1152
+
1079
1153
const SourceRange sourceRangeWhenCreated;
1080
1154
1081
1155
AttachedPropertyWrapperScope (VarDecl *e)
1082
1156
: decl(e), sourceRangeWhenCreated(getSourceRangeOfVarDecl(e)) {
1083
- assert (sourceRangeWhenCreated.isValid ());
1157
+ ASTScopeAssert (sourceRangeWhenCreated.isValid (),
1158
+ " VarDecls must have ranges to be looked-up" );
1084
1159
}
1085
1160
virtual ~AttachedPropertyWrapperScope () {}
1086
1161
@@ -1157,7 +1232,7 @@ class PatternEntryDeclScope final : public AbstractPatternEntryScope {
1157
1232
protected:
1158
1233
ASTScopeImpl *expandSpecifically (ScopeCreator &scopeCreator) override ;
1159
1234
void beCurrent () override ;
1160
- bool isCurrent () const override ;
1235
+ bool isCurrentIfWasExpanded () const override ;
1161
1236
1162
1237
private:
1163
1238
AnnotatedInsertionPoint
@@ -1331,7 +1406,7 @@ class WholeClosureScope final : public AbstractClosureScope {
1331
1406
protected:
1332
1407
ASTScopeImpl *expandSpecifically (ScopeCreator &scopeCreator) override ;
1333
1408
void beCurrent () override ;
1334
- bool isCurrent () const override ;
1409
+ bool isCurrentIfWasExpanded () const override ;
1335
1410
1336
1411
private:
1337
1412
void expandAScopeThatDoesNotCreateANewInsertionPoint (ScopeCreator &);
@@ -1402,7 +1477,7 @@ class TopLevelCodeScope final : public ASTScopeImpl {
1402
1477
protected:
1403
1478
ASTScopeImpl *expandSpecifically (ScopeCreator &scopeCreator) override ;
1404
1479
void beCurrent () override ;
1405
- bool isCurrent () const override ;
1480
+ bool isCurrentIfWasExpanded () const override ;
1406
1481
1407
1482
private:
1408
1483
AnnotatedInsertionPoint
@@ -1420,7 +1495,7 @@ class TopLevelCodeScope final : public ASTScopeImpl {
1420
1495
Decl *getDecl () const { return decl; }
1421
1496
NullablePtr<const void > getReferrent () const override ;
1422
1497
1423
- NullablePtr<ASTScopeImpl> getParentOfRescuedScopes () override ;
1498
+ NullablePtr<ASTScopeImpl> getParentOfASTAncestorScopesToBeRescued () override ;
1424
1499
};
1425
1500
1426
1501
// / The \c _@specialize attribute.
0 commit comments