Skip to content

Commit 3a16af0

Browse files
committed
Revise ASTScope-bsed lookup
1 parent 2e0bfb7 commit 3a16af0

File tree

1 file changed

+96
-108
lines changed

1 file changed

+96
-108
lines changed

lib/AST/UnqualifiedLookup.cpp

Lines changed: 96 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,12 @@ class UnqualifiedLookupFactory {
227227
private:
228228
bool useASTScopesForExperimentalLookup() const;
229229

230-
void lookInModuleScope(DCAndResolvedIsCascadingUse dcAndIsCascadingUse);
230+
void lookInModuleScopeContext(DCAndResolvedIsCascadingUse dcAndIsCascadingUse);
231231

232232
#pragma mark ASTScope-based-lookup declarations
233233

234234

235-
Optional<DCAndResolvedIsCascadingUse>
235+
void
236236
experimentallyLookInASTScopes(DeclContext *dc, Optional<bool> isCascadingUse);
237237

238238
std::pair<const ASTScope *, bool>
@@ -243,25 +243,36 @@ class UnqualifiedLookupFactory {
243243
nonoperatorScopeForASTScopeLookup(DeclContext *dc,
244244
Optional<bool> isCascadingUse) const;
245245

246-
struct LookInScopeForASTScopeLookupResult {
247-
bool isDone; // Searching outers
246+
struct ASTScopeLookupState {
247+
const ASTScope *scope;
248248
DeclContext *selfDC;
249249
DeclContext *dc;
250250
Optional<bool> isCascadingUse;
251+
252+
ASTScopeLookupState withParentScope() const {
253+
return ASTScopeLookupState{scope->getParent(), selfDC, dc, isCascadingUse};
254+
}
255+
ASTScopeLookupState withNoScope() const {
256+
return ASTScopeLookupState{nullptr, selfDC, dc, isCascadingUse};
257+
}
258+
ASTScopeLookupState withSelfDC(DeclContext *selfDC) const {
259+
return ASTScopeLookupState{scope, selfDC, dc, isCascadingUse};
260+
}
261+
ASTScopeLookupState withDC(DeclContext *dc) const {
262+
return ASTScopeLookupState{scope, selfDC, dc, isCascadingUse};
263+
}
264+
ASTScopeLookupState withResolvedIsCascadingUse(bool isCascadingUse) const {
265+
return ASTScopeLookupState{scope, selfDC, dc, isCascadingUse};
266+
}
251267
};
252268

253269
/// Return status and new selfDC and new DC
254-
Optional<LookInScopeForASTScopeLookupResult>
255-
lookInScopeForASTScopeLookup(const ASTScope *const currentScope,
256-
DeclContext *selfDC, DeclContext *dc,
257-
const Optional<bool> isCascadingUse);
270+
ASTScopeLookupState
271+
lookInScopeForASTScopeLookup(const ASTScopeLookupState);
258272

259273
/// Returns status and selfDC and DC
260-
Optional<LookInScopeForASTScopeLookupResult>
261-
lookIntoDeclarationContextForASTScopeLookup(DeclContext *dc,
262-
DeclContext *selfDC,
263-
DeclContext *wasDC,
264-
Optional<bool> isCascadingUse);
274+
ASTScopeLookupState
275+
lookIntoDeclarationContextForASTScopeLookup(ASTScopeLookupState);
265276
/// Can lookup stop searching for results, assuming hasn't looked for outer
266277
/// results yet?
267278
bool isFirstResultEnough() const;
@@ -273,9 +284,7 @@ class UnqualifiedLookupFactory {
273284

274285
#pragma mark normal (non-ASTScope-based) lookup declarations
275286

276-
/// Return None if lookup done.
277-
Optional<DCAndResolvedIsCascadingUse>
278-
lookInDeclContexts(DeclContext *dc, const Optional <bool> isCascadingUseArg);
287+
void lookInDeclContexts(DeclContext *dc, const Optional <bool> isCascadingUseArg);
279288

280289
/// Return None if lookup done.
281290
Optional<DCAndResolvedIsCascadingUse>
@@ -403,16 +412,16 @@ IndexOfFirstOuterResult(lookupToBeCreated.IndexOfFirstOuterResult)
403412

404413
void UnqualifiedLookupFactory::performUnqualifiedLookup() {
405414
const Optional<bool> isCascadingUseInitial =
406-
options.contains(Flags::KnownPrivate) ? Optional<bool>(false) : None;
407-
// Never perform local lookup for operators.
408-
Optional<DCAndResolvedIsCascadingUse> dcAndIsCascadingUse = useASTScopesForExperimentalLookup()
409-
? experimentallyLookInASTScopes(DC, isCascadingUseInitial)
410-
: lookInDeclContexts(DC, isCascadingUseInitial);
411-
if (dcAndIsCascadingUse.hasValue())
412-
lookInModuleScope(dcAndIsCascadingUse.getValue());
415+
options.contains(Flags::KnownPrivate) ? Optional<bool>(false) : None;
416+
417+
if (useASTScopesForExperimentalLookup()) {
418+
experimentallyLookInASTScopes(DC, isCascadingUseInitial);
419+
return;
420+
}
421+
lookInDeclContexts(DC, isCascadingUseInitial);
413422
}
414423

415-
void UnqualifiedLookupFactory::lookInModuleScope(
424+
void UnqualifiedLookupFactory::lookInModuleScopeContext(
416425
DCAndResolvedIsCascadingUse dcAndIsCascadingUse) {
417426
DeclContext *const DC = dcAndIsCascadingUse.DC;
418427
const bool isCascadingUse = dcAndIsCascadingUse.isCascadingUse;
@@ -447,8 +456,7 @@ bool UnqualifiedLookupFactory::useASTScopesForExperimentalLookup() const {
447456

448457
#pragma mark ASTScope-based-lookup definitions
449458

450-
/// Return None if lookup done
451-
Optional<UnqualifiedLookupFactory::DCAndResolvedIsCascadingUse>
459+
void
452460
UnqualifiedLookupFactory::experimentallyLookInASTScopes(DeclContext *const startDC,
453461
Optional<bool> isCascadingUse) {
454462
const std::pair<const ASTScope *, Optional<bool>>
@@ -457,23 +465,17 @@ UnqualifiedLookupFactory::experimentallyLookInASTScopes(DeclContext *const start
457465
? operatorScopeForASTScopeLookup(startDC, isCascadingUse)
458466
: nonoperatorScopeForASTScopeLookup(startDC, isCascadingUse);
459467
// Walk scopes outward from the innermost scope until we find something.
460-
DeclContext *dc = startDC;
461-
DeclContext *selfDC = nullptr;
462-
Optional<bool> currentIsCascadingUse = lookupScopeAndIsCascadingUse.second;
463-
for (auto currentScope = lookupScopeAndIsCascadingUse.first; currentScope;
464-
currentScope = currentScope->getParent()) {
465-
auto r = lookInScopeForASTScopeLookup(currentScope, selfDC, dc,
466-
currentIsCascadingUse);
467-
if (!r.hasValue())
468-
return None;
469-
selfDC = r.getValue().selfDC;
470-
dc = r.getValue().dc;
471-
currentIsCascadingUse = r.getValue().isCascadingUse;
472-
const bool isDone = r.getValue().isDone;
473-
if (isDone)
474-
return DCAndResolvedIsCascadingUse{dc, currentIsCascadingUse.getValue()};
468+
469+
ASTScopeLookupState state{lookupScopeAndIsCascadingUse.first, nullptr, startDC, lookupScopeAndIsCascadingUse.second};
470+
while ( state.scope) {
471+
state = lookInScopeForASTScopeLookup(state);
472+
if (!state.scope)
473+
break;
474+
state = state.withParentScope();
475475
}
476-
llvm_unreachable("impossible");
476+
if (isFirstResultEnough())
477+
return;
478+
lookInModuleScopeContext(DCAndResolvedIsCascadingUse{state.dc, state.isCascadingUse.getValue()});
477479
}
478480

479481
std::pair<const ASTScope *, bool>
@@ -507,127 +509,115 @@ UnqualifiedLookupFactory::nonoperatorScopeForASTScopeLookup(
507509
return std::make_pair(lookupScope, isCascadingUse);
508510
}
509511

510-
Optional<UnqualifiedLookupFactory::LookInScopeForASTScopeLookupResult>
512+
UnqualifiedLookupFactory::ASTScopeLookupState
511513
UnqualifiedLookupFactory::lookInScopeForASTScopeLookup(
512-
const ASTScope *const currentScope, DeclContext *selfDC, DeclContext *dc,
513-
const Optional<bool> isCascadingUse) {
514+
const ASTScopeLookupState state) {
514515

515516
// Perform local lookup within this scope.
516-
auto localBindings = currentScope->getLocalBindings();
517+
auto localBindings = state.scope->getLocalBindings();
517518
for (auto local : localBindings) {
518-
Consumer.foundDecl(local, getLocalDeclVisibilityKind(currentScope));
519+
Consumer.foundDecl(local, getLocalDeclVisibilityKind(state.scope));
519520
}
520521

521522
recordCompletionOfAScope();
522523
// If we found anything, we're done.
523524
if (isFirstResultEnough())
524-
return None;
525+
return state.withNoScope();
525526

526527
// When we are in the body of a method, get the 'self' declaration.
527-
if (currentScope->getKind() == ASTScopeKind::AbstractFunctionBody &&
528-
currentScope->getAbstractFunctionDecl()
528+
if (state.scope->getKind() == ASTScopeKind::AbstractFunctionBody &&
529+
state.scope->getAbstractFunctionDecl()
529530
->getDeclContext()
530531
->isTypeContext()) {
531-
selfDC = currentScope->getAbstractFunctionDecl();
532-
return LookInScopeForASTScopeLookupResult{false, selfDC, dc,
533-
isCascadingUse};
532+
return state.withSelfDC(state.scope->getAbstractFunctionDecl());
534533
}
535534

536535
// If there is a declaration context associated with this scope, we might
537536
// want to look in it.
538-
if (auto scopeDC = currentScope->getDeclContext())
539-
return lookIntoDeclarationContextForASTScopeLookup(scopeDC, selfDC, dc,
540-
isCascadingUse);
541-
return LookInScopeForASTScopeLookupResult{false, selfDC, dc, isCascadingUse};
537+
return lookIntoDeclarationContextForASTScopeLookup(state);
542538
}
543539

544-
Optional<UnqualifiedLookupFactory::LookInScopeForASTScopeLookupResult>
540+
UnqualifiedLookupFactory::ASTScopeLookupState
545541
UnqualifiedLookupFactory::lookIntoDeclarationContextForASTScopeLookup(
546-
DeclContext *dc, DeclContext *selfDC, DeclContext *wasDC,
547-
Optional<bool> isCascadingUse) {
542+
ASTScopeLookupState stateArg) {
543+
544+
DeclContext *scopeDC = stateArg.scope->getDeclContext();
545+
if (!scopeDC)
546+
return stateArg;
548547

549548
// If we haven't determined whether we have a cascading use, do so now.
550549
const bool isCascadingUseResult = resolveIsCascadingUse(
551-
dc, isCascadingUse, /*onlyCareAboutFunctionBody=*/false);
550+
scopeDC, stateArg.isCascadingUse, /*onlyCareAboutFunctionBody=*/false);
551+
552+
const ASTScopeLookupState defaultReturnState = stateArg.withResolvedIsCascadingUse(isCascadingUseResult);
552553

553554
// Pattern binding initializers are only interesting insofar as they
554555
// affect lookup in an enclosing nominal type or extension thereof.
555-
if (auto *bindingInit = dyn_cast<PatternBindingInitializer>(dc)) {
556+
if (auto *bindingInit = dyn_cast<PatternBindingInitializer>(scopeDC)) {
556557
// Lazy variable initializer contexts have a 'self' parameter for
557558
// instance member lookup.
558559
if (bindingInit->getImplicitSelfDecl())
559-
selfDC = bindingInit;
560+
return defaultReturnState.withSelfDC(bindingInit);
560561

561-
return LookInScopeForASTScopeLookupResult{false, selfDC, wasDC,
562-
isCascadingUseResult};
562+
return defaultReturnState;
563563
}
564564

565565
// Default arguments only have 'static' access to the members of the
566566
// enclosing type, if there is one.
567-
if (isa<DefaultArgumentInitializer>(dc))
568-
return LookInScopeForASTScopeLookupResult{false, selfDC, wasDC,
569-
isCascadingUseResult};
567+
if (isa<DefaultArgumentInitializer>(scopeDC))
568+
return defaultReturnState;
570569

571570
// Functions/initializers/deinitializers are only interesting insofar as
572571
// they affect lookup in an enclosing nominal type or extension thereof.
573-
if (isa<AbstractFunctionDecl>(dc))
574-
return LookInScopeForASTScopeLookupResult{false, selfDC, wasDC,
575-
isCascadingUseResult};
572+
if (isa<AbstractFunctionDecl>(scopeDC))
573+
return defaultReturnState;
576574

577575
// Subscripts have no lookup of their own.
578-
if (isa<SubscriptDecl>(dc))
579-
return LookInScopeForASTScopeLookupResult{false, selfDC, wasDC,
580-
isCascadingUseResult};
576+
if (isa<SubscriptDecl>(scopeDC))
577+
return defaultReturnState;
581578

582579
// Closures have no lookup of their own.
583-
if (isa<AbstractClosureExpr>(dc))
584-
return LookInScopeForASTScopeLookupResult{false, selfDC, wasDC,
585-
isCascadingUseResult};
580+
if (isa<AbstractClosureExpr>(scopeDC))
581+
return defaultReturnState;
586582

587583
// Top-level declarations have no lookup of their own.
588-
if (isa<TopLevelCodeDecl>(dc))
589-
return LookInScopeForASTScopeLookupResult{false, selfDC, wasDC,
590-
isCascadingUseResult};
584+
if (isa<TopLevelCodeDecl>(scopeDC))
585+
return defaultReturnState;
591586

592587
// Typealiases have no lookup of their own.
593-
if (isa<TypeAliasDecl>(dc))
594-
return LookInScopeForASTScopeLookupResult{false, selfDC, wasDC,
595-
isCascadingUseResult};
588+
if (isa<TypeAliasDecl>(scopeDC))
589+
return defaultReturnState;
596590

597591
// Lookup in the source file's scope marks the end.
598-
if (isa<SourceFile>(dc)) {
592+
if (isa<SourceFile>(scopeDC)) {
599593
// FIXME: A bit of a hack.
600-
return LookInScopeForASTScopeLookupResult{true, selfDC, dc,
601-
isCascadingUseResult};
594+
return defaultReturnState.withDC(scopeDC).withNoScope();
602595
}
603596

604597
// We have a nominal type or an extension thereof. Perform lookup into
605598
// the nominal type.
606-
auto nominal = dc->getSelfNominalTypeDecl();
599+
auto nominal = scopeDC->getSelfNominalTypeDecl();
607600
if (!nominal)
608-
return LookInScopeForASTScopeLookupResult{false, selfDC, wasDC,
609-
isCascadingUseResult};
601+
return defaultReturnState;
610602

611603
// Dig out the type we're looking into.
612604
using LookupDecls = SmallVector<NominalTypeDecl *, 2>;
613605
LookupDecls lookupDecls;
614-
populateLookupDeclsFromContext(dc, lookupDecls);
606+
populateLookupDeclsFromContext(scopeDC, lookupDecls);
615607

616-
NLOptions options = baseNLOptions;
608+
617609
// Perform lookup into the type.
618-
if (isCascadingUseResult)
619-
options |= NL_KnownCascadingDependency;
620-
else
621-
options |= NL_KnownNonCascadingDependency;
610+
NLOptions options = baseNLOptions | (
611+
isCascadingUseResult ? NL_KnownCascadingDependency : NL_KnownNonCascadingDependency);
622612

623613
SmallVector<ValueDecl *, 4> lookup;
624-
dc->lookupQualified(lookupDecls, Name, options, lookup);
614+
scopeDC->lookupQualified(lookupDecls, Name, options, lookup);
625615

626616
auto startIndex = Results.size();
627617
for (auto result : lookup) {
628-
auto *baseDC = dc;
629-
if (!isa<TypeDecl>(result) && selfDC)
630-
baseDC = selfDC;
618+
auto *baseDC = scopeDC;
619+
if (!isa<TypeDecl>(result) && defaultReturnState.selfDC)
620+
baseDC = defaultReturnState.selfDC;
631621
Results.push_back(LookupResultEntry(baseDC, result));
632622
}
633623

@@ -650,29 +640,27 @@ UnqualifiedLookupFactory::lookIntoDeclarationContextForASTScopeLookup(
650640

651641
recordCompletionOfAScope();
652642
if (isFirstResultEnough())
653-
return None;
643+
return defaultReturnState.withNoScope();
654644
}
655645
}
656646

657647
// Forget the 'self' declaration.
658-
selfDC = nullptr;
659-
660-
return LookInScopeForASTScopeLookupResult{false, selfDC, dc,
661-
isCascadingUseResult};
648+
return defaultReturnState.withSelfDC(nullptr);
662649
}
663650

664651
#pragma mark context-based lookup declarations
665652

666-
Optional<UnqualifiedLookupFactory::DCAndResolvedIsCascadingUse>
653+
void
667654
UnqualifiedLookupFactory::lookInDeclContexts(DeclContext *dc, const Optional <bool> isCascadingUseArg) {
655+
//#error move final rnt to tails of next two
668656
auto dcAndIsCascadingUse =
669657
Name.isOperator() ? lookupOperatorInDeclContexts(DC, isCascadingUseArg)
670658
: lookupNameInDeclContexts(DC, isCascadingUseArg);
671659
if (!dcAndIsCascadingUse.hasValue())
672-
return None;
660+
return;
673661
if (addLocalVariableResults(dcAndIsCascadingUse.getValue().DC))
674-
return None;
675-
return dcAndIsCascadingUse;
662+
return;
663+
lookInModuleScopeContext(dcAndIsCascadingUse.getValue());
676664
}
677665

678666
Optional<UnqualifiedLookupFactory::DCAndResolvedIsCascadingUse>

0 commit comments

Comments
 (0)