1414//
1515// ===----------------------------------------------------------------------===//
1616
17+ #include " swift/AST/TypeRefinementContext.h"
18+
1719#include " swift/AST/ASTContext.h"
1820#include " swift/AST/Decl.h"
19- #include " swift/AST/Module.h"
20- #include " swift/AST/Stmt.h"
2121#include " swift/AST/Expr.h"
22+ #include " swift/AST/Module.h"
2223#include " swift/AST/SourceFile.h"
24+ #include " swift/AST/Stmt.h"
2325#include " swift/AST/TypeCheckRequests.h"
24- #include " swift/AST/TypeRefinementContext.h"
2526#include " swift/Basic/Assertions.h"
2627#include " swift/Basic/SourceManager.h"
2728
@@ -35,7 +36,7 @@ TypeRefinementContext::TypeRefinementContext(
3536 ExplicitAvailabilityInfo(ExplicitInfo) {
3637 if (Parent) {
3738 assert (SrcRange.isValid ());
38- Parent->addChild (this );
39+ Parent->addChild (this , Ctx );
3940 assert (Info.isContainedIn (Parent->getAvailabilityInfo ()));
4041 }
4142 Ctx.addDestructorCleanup (Children);
@@ -169,6 +170,36 @@ TypeRefinementContext::createForWhileStmtBody(ASTContext &Ctx, WhileStmt *S,
169170 Ctx, S, Parent, S->getBody ()->getSourceRange (), Info, /* ExplicitInfo */ Info);
170171}
171172
173+ void TypeRefinementContext::addChild (TypeRefinementContext *Child,
174+ ASTContext &Ctx) {
175+ assert (Child->getSourceRange ().isValid ());
176+
177+ // Handle the first child.
178+ if (Children.empty ()) {
179+ Children.push_back (Child);
180+ return ;
181+ }
182+
183+ // Handle a child that is ordered after the existing children (this should be
184+ // the common case).
185+ auto &srcMgr = Ctx.SourceMgr ;
186+ if (srcMgr.isBefore (Children.back ()->getSourceRange ().Start ,
187+ Child->getSourceRange ().Start )) {
188+ Children.push_back (Child);
189+ return ;
190+ }
191+
192+ // Insert the child amongst the existing sorted children.
193+ auto iter = std::upper_bound (
194+ Children.begin (), Children.end (), Child,
195+ [&srcMgr](TypeRefinementContext *lhs, TypeRefinementContext *rhs) {
196+ return srcMgr.isBefore (lhs->getSourceRange ().Start ,
197+ rhs->getSourceRange ().Start );
198+ });
199+
200+ Children.insert (iter, Child);
201+ }
202+
172203TypeRefinementContext *
173204TypeRefinementContext::findMostRefinedSubContext (SourceLoc Loc,
174205 ASTContext &Ctx) {
@@ -180,16 +211,23 @@ TypeRefinementContext::findMostRefinedSubContext(SourceLoc Loc,
180211 auto expandedChildren = evaluateOrDefault (
181212 Ctx.evaluator , ExpandChildTypeRefinementContextsRequest{this }, {});
182213
183- // For the moment, we perform a linear search here, but we can and should
184- // do something more efficient.
185- for (TypeRefinementContext *Child : expandedChildren) {
186- if (auto *Found = Child->findMostRefinedSubContext (Loc, Ctx)) {
187- return Found;
188- }
214+ // Do a binary search to find the first child with a source range that
215+ // ends after the given location.
216+ auto iter = std::lower_bound (
217+ expandedChildren.begin (), expandedChildren.end (), Loc,
218+ [&Ctx](TypeRefinementContext *context, SourceLoc loc) {
219+ return Ctx.SourceMgr .isBefore (context->getSourceRange ().End , loc);
220+ });
221+
222+ // Check whether the matching child or any of its descendants contain
223+ // the given location.
224+ if (iter != expandedChildren.end ()) {
225+ if (auto found = (*iter)->findMostRefinedSubContext (Loc, Ctx))
226+ return found;
189227 }
190228
191- // Loc is in this context's range but not in any child's, so this context
192- // must be the inner-most context.
229+ // The location is in this context's range but not in any child's, so this
230+ // context must be the innermost context.
193231 return this ;
194232}
195233
0 commit comments