//===--- ASTScopeLookup.cpp - Swift Object-Oriented AST Scope -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
///
/// This file implements the lookup functionality of the ASTScopeImpl ontology.
///
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTScope.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/STLExtras.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>

using namespace swift;
using namespace namelookup;
using namespace ast_scope;

llvm::SmallVector<const ASTScopeImpl *, 0> ASTScopeImpl::unqualifiedLookup(
    SourceFile *sourceFile, const DeclName name, const SourceLoc loc,
    const DeclContext *const startingContext, DeclConsumer consumer) {
  SmallVector<const ASTScopeImpl *, 0> history;

  const auto *start =
      findStartingScopeForLookup(sourceFile, name, loc, startingContext);
  if (start)
    start->lookup(history, nullptr, nullptr, consumer);
  return history;
}

const ASTScopeImpl *ASTScopeImpl::findStartingScopeForLookup(
    SourceFile *sourceFile, const DeclName name, const SourceLoc loc,
    const DeclContext *const startingContext) {
  // At present, use legacy code in unqualifiedLookup.cpp to handle module-level
  // lookups
  // TODO: implement module scope someday
  if (startingContext->getContextKind() == DeclContextKind::Module)
    return nullptr;

  auto *const fileScope = sourceFile->getScope().impl;
  // Parser may have added decls to source file, since previous lookup
  fileScope->addNewDeclsToScopeTree();
  if (name.isOperator())
    return fileScope; // operators always at file scope

  const auto innermost = fileScope->findInnermostEnclosingScope(loc, nullptr);
  ASTScopeAssert(innermost->getWasExpanded(),
                 "If looking in a scope, it must have been expanded.");

  // The legacy lookup code gets passed both a SourceLoc and a starting context.
  // However, our ultimate intent is for clients to not have to pass in a
  // DeclContext at all, since the SourceLoc should be enough. While we are
  // debugging the new ASTScope lookup code, we can catch bugs by comparing the
  // DeclContext of the ASTScope found from the desired SourceLoc to the
  // DeclContext passed in by the client.

  const auto *startingScope = innermost;
  for (; startingScope &&
         !startingScope->doesContextMatchStartingContext(startingContext);
       startingScope = startingScope->getParent().getPtrOrNull()) {
  }
  // Someday, just use the assertion below. For now, print out lots of info for
  // debugging.
  if (!startingScope) {
    llvm::errs() << "ASTScopeImpl: resorting to startingScope hack, file: "
                 << sourceFile->getFilename() << "\n";
    llvm::errs() << "'";
    name.print(llvm::errs());
    llvm::errs() << "' ";
    llvm::errs() << "loc: ";
    loc.dump(sourceFile->getASTContext().SourceMgr);
    llvm::errs() << "\nstarting context:\n ";
    startingContext->dumpContext();
    //    llvm::errs() << "\ninnermost: ";
    //    innermost->dump();
    //    llvm::errs() << "in: \n";
    //    fileScope->dump();
    llvm::errs() << "\n\n";

    // Might distort things
    //    if (fileScope->crossCheckWithAST())
    //      llvm::errs() << "Tree creation missed some DeclContexts.\n";
  }

  ASTScopeAssert(startingScope, "ASTScopeImpl: could not find startingScope");
  return startingScope;
}

const ASTScopeImpl *
ASTScopeImpl::findInnermostEnclosingScope(SourceLoc loc,
                                          NullablePtr<raw_ostream> os) {
  return findInnermostEnclosingScopeImpl(loc, os, getSourceManager(),
                                         getScopeCreator());
}

const ASTScopeImpl *ASTScopeImpl::findInnermostEnclosingScopeImpl(
    SourceLoc loc, NullablePtr<raw_ostream> os, SourceManager &sourceMgr,
    ScopeCreator &scopeCreator) {
  reexpandIfObsolete(scopeCreator);
  auto child = findChildContaining(loc, sourceMgr);
  if (!child)
    return this;
  return child.get()->findInnermostEnclosingScopeImpl(loc, os, sourceMgr,
                                                      scopeCreator);
}

bool ASTScopeImpl::checkSourceRangeOfThisASTNode() const {
  const auto r = getSourceRangeOfThisASTNode();
  (void)r;
  ASTScopeAssert(!getSourceManager().isBeforeInBuffer(r.End, r.Start),
                 "Range is backwards.");
  return true;
}

NullablePtr<ASTScopeImpl>
ASTScopeImpl::findChildContaining(SourceLoc loc,
                                  SourceManager &sourceMgr) const {
  // Use binary search to find the child that contains this location.
  struct CompareLocs {
    SourceManager &sourceMgr;

    bool operator()(const ASTScopeImpl *scope, SourceLoc loc) {
      ASTScopeAssert(scope->checkSourceRangeOfThisASTNode(), "Bad range.");
      return sourceMgr.isBeforeInBuffer(scope->getSourceRangeOfScope().End,
                                        loc);
    }
    bool operator()(SourceLoc loc, const ASTScopeImpl *scope) {
      ASTScopeAssert(scope->checkSourceRangeOfThisASTNode(), "Bad range.");
      return sourceMgr.isBeforeInBuffer(loc,
                                        scope->getSourceRangeOfScope().End);
    }
  };
  auto *const *child = std::lower_bound(
      getChildren().begin(), getChildren().end(), loc, CompareLocs{sourceMgr});

  if (child != getChildren().end() &&
      sourceMgr.rangeContainsTokenLoc((*child)->getSourceRangeOfScope(), loc))
    return *child;

  return nullptr;
}

#pragma mark doesContextMatchStartingContext
// Match existing UnqualifiedLookupBehavior

bool ASTScopeImpl::doesContextMatchStartingContext(
    const DeclContext *context) const {
  // Why are we not checking the loc for this--because already did binary search
  // on loc to find the start First, try MY DeclContext
  if (auto myDCForL = getDeclContext())
    return myDCForL == context;
  // If I don't have one, ask my parent.
  // (Choose innermost scope with matching loc & context.)
  if (auto p = getParent())
    return p.get()->doesContextMatchStartingContext(context);
  // Topmost scope always has a context, the SourceFile.
  ASTScope_unreachable("topmost scope always has a context, the SourceFile");
}

// For a SubscriptDecl with generic parameters, the call tries to do lookups
// with startingContext equal to either the get or set subscript
// AbstractFunctionDecls. Since the generic parameters are in the
// SubScriptDeclScope, and not the AbstractFunctionDecl scopes (after all how
// could one parameter be in two scopes?), GenericParamScoped intercepts the
// match query here and tests against the accessor DeclContexts.
bool GenericParamScope::doesContextMatchStartingContext(
    const DeclContext *context) const {
  if (auto *asd = dyn_cast<AbstractStorageDecl>(holder)) {
    for (auto accessor : asd->getAllAccessors()) {
      if (up_cast<DeclContext>(accessor) == context)
        return true;
    }
  }
  return false;
}

// SWIFT_ENABLE_TENSORFLOW
bool DifferentiableAttributeScope::doesContextMatchStartingContext(
    const DeclContext *context) const {
  // Need special logic to handle case where `attributedDeclaration` is an
  // `AbstractStorageDecl` (`SubscriptDecl` or `VarDecl`). The initial starting
  // context in `ASTScopeImpl::findStartingScopeForLookup` will be an accessor
  // of the `attributedDeclaration`.
  if (auto *asd = dyn_cast<AbstractStorageDecl>(attributedDeclaration))
    for (auto accessor : asd->getAllAccessors())
      if (up_cast<DeclContext>(accessor) == context)
        return true;
  return false;
}
// SWIFT_ENABLE_TENSORFLOW END

#pragma mark lookup methods that run once per scope

void ASTScopeImpl::lookup(SmallVectorImpl<const ASTScopeImpl *> &history,
                          const NullablePtr<const ASTScopeImpl> limit,
                          NullablePtr<const GenericParamList> lastListSearched,
                          DeclConsumer consumer) const {

  history.push_back(this);

#ifndef NDEBUG
  consumer.startingNextLookupStep();
#endif

  // Certain illegal nestings, e.g. protocol nestled inside a struct,
  // require that lookup stop at the outer scope.
  if (this == limit.getPtrOrNull()) {
#ifndef NDEBUG
    consumer.finishingLookup("limit return");
#endif
    return;
  }

  // Look for generics before members in violation of lexical ordering because
  // you can say "self.name" to get a name shadowed by a generic but you
  // can't do the opposite to get a generic shadowed by a name.
  const auto doneAndListSearched =
      lookInMyGenericParameters(lastListSearched, consumer);
  if (doneAndListSearched.first)
    return;

  if (lookupLocalsOrMembers(history, consumer))
    return;

  const auto *const lookupParent = getLookupParent().getPtrOrNull();
  if (!lookupParent) {
#ifndef NDEBUG
    consumer.finishingLookup("Finished lookup; no parent");
#endif
    return;
  }

  // If there is no limit and this scope induces one, pass that on.
  const NullablePtr<const ASTScopeImpl> limitForParent =
      limit ? limit : getLookupLimit();

  return lookupParent->lookup(history, limitForParent, lastListSearched,
                              consumer);
}

#pragma mark genericParams()

NullablePtr<const GenericParamList> ASTScopeImpl::genericParams() const {
  return nullptr;
}
NullablePtr<const GenericParamList>
AbstractFunctionDeclScope::genericParams() const {
  return decl->getGenericParams();
}
NullablePtr<const GenericParamList> SubscriptDeclScope::genericParams() const {
  return decl->getGenericParams();
}
NullablePtr<const GenericParamList> GenericTypeScope::genericParams() const {
  // For Decls:
  // WAIT, WHAT?! Isn't this covered by the GenericParamScope
  // lookupLocalsOrMembers? No, that's for use of generics in the body. This is
  // for generic restrictions.

  // For Bodies:
  // Sigh... These must be here so that from body, we search generics before
  // members. But they also must be on the Decl scope for lookups starting from
  // generic parameters, where clauses, etc.
  return getGenericContext()->getGenericParams();
}
NullablePtr<const GenericParamList> ExtensionScope::genericParams() const {
  return decl->getGenericParams();
}

#pragma mark lookInMyGenericParameters

std::pair<bool, NullablePtr<const GenericParamList>>
ASTScopeImpl::lookInMyGenericParameters(
    NullablePtr<const GenericParamList> formerListSearched,
    ASTScopeImpl::DeclConsumer consumer) const {
  auto listToSearch = genericParams();
  if (listToSearch == formerListSearched)
    return std::make_pair(false, formerListSearched);

  // For extensions of nested types, must check outer parameters
  for (auto *params = listToSearch.getPtrOrNull(); params;
       params = params->getOuterParameters()) {
    if (lookInGenericParametersOf(params, consumer))
      return std::make_pair(true, listToSearch);
  }
  return std::make_pair(false, listToSearch);
}

bool ASTScopeImpl::lookInGenericParametersOf(
    const NullablePtr<const GenericParamList> paramList,
    ASTScopeImpl::DeclConsumer consumer) {
  if (!paramList)
    return false;
  SmallVector<ValueDecl *, 32> bindings;
  for (auto *param : paramList.get()->getParams())
    bindings.push_back(param);
  if (consumer.consume(bindings, DeclVisibilityKind::GenericParameter))
    return true;
  return false;
}

#pragma mark looking in locals or members - members

bool ASTScopeImpl::lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                                         DeclConsumer) const {
  return false; // many kinds of scopes have none
}

bool GenericTypeOrExtensionScope::lookupLocalsOrMembers(
    ArrayRef<const ASTScopeImpl *> history,
    ASTScopeImpl::DeclConsumer consumer) const {
  // isCascadingUseArg must have already been resolved, for a real lookup
  // but may be \c None for dumping.
  return portion->lookupMembersOf(this, history, consumer);
}

bool Portion::lookupMembersOf(const GenericTypeOrExtensionScope *,
                              ArrayRef<const ASTScopeImpl *>,
                              ASTScopeImpl::DeclConsumer) const {
  return false;
}

bool GenericTypeOrExtensionWhereOrBodyPortion::lookupMembersOf(
    const GenericTypeOrExtensionScope *scope,
    ArrayRef<const ASTScopeImpl *> history,
    ASTScopeImpl::DeclConsumer consumer) const {
  auto nt = scope->getCorrespondingNominalTypeDecl().getPtrOrNull();
  if (!nt)
    return false;
  auto selfDC = computeSelfDC(history);
  return consumer.lookInMembers(selfDC, scope->getDeclContext().get(), nt,
                                [&](Optional<bool> initialIsCascadingUse) {
                                  return ASTScopeImpl::computeIsCascadingUse(
                                             history, initialIsCascadingUse)
                                      .getValueOr(true);
                                });
}

#pragma mark looking in locals or members - locals

bool GenericParamScope::lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                                              DeclConsumer consumer) const {
  auto *param = paramList->getParams()[index];
  return consumer.consume({param}, DeclVisibilityKind::GenericParameter);
}

bool PatternEntryDeclScope::lookupLocalsOrMembers(
    ArrayRef<const ASTScopeImpl *>, DeclConsumer consumer) const {
  if (vis != DeclVisibilityKind::LocalVariable)
    return false; // look in self type will find this later
  return lookupLocalBindingsInPattern(getPattern(), vis, consumer);
}

bool ForEachPatternScope::lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                                                DeclConsumer consumer) const {
  return lookupLocalBindingsInPattern(
      stmt->getPattern(), DeclVisibilityKind::LocalVariable, consumer);
}

bool CatchStmtScope::lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                                           DeclConsumer consumer) const {
  return lookupLocalBindingsInPattern(
      stmt->getErrorPattern(), DeclVisibilityKind::LocalVariable, consumer);
}

bool CaseStmtScope::lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                                          DeclConsumer consumer) const {
  for (auto &item : stmt->getMutableCaseLabelItems())
    if (lookupLocalBindingsInPattern(
            item.getPattern(), DeclVisibilityKind::LocalVariable, consumer))
      return true;
  return false;
}

bool AbstractFunctionBodyScope::lookupLocalsOrMembers(
    ArrayRef<const ASTScopeImpl *>, DeclConsumer consumer) const {
  if (auto *paramList = decl->getParameters()) {
    for (auto *paramDecl : *paramList)
      if (consumer.consume({paramDecl}, DeclVisibilityKind::FunctionParameter))
        return true;
  }
  return false;
}

bool MethodBodyScope::lookupLocalsOrMembers(
    ArrayRef<const ASTScopeImpl *> history, DeclConsumer consumer) const {
  ASTScopeAssert(isAMethod(decl), "Asking for members of a non-method.");
  if (AbstractFunctionBodyScope::lookupLocalsOrMembers(history, consumer))
    return true;
  return consumer.consume({decl->getImplicitSelfDecl()},
                          DeclVisibilityKind::FunctionParameter);
}

bool PureFunctionBodyScope::lookupLocalsOrMembers(
    ArrayRef<const ASTScopeImpl *> history, DeclConsumer consumer) const {
  ASTScopeAssert(
      !isAMethod(decl),
      "Should have called lookupLocalsOrMembers instead of this function.");
  if (AbstractFunctionBodyScope::lookupLocalsOrMembers(history, consumer))
    return true;

  // Consider \c var t: T { (did/will/)get/set { ... t }}
  // Lookup needs to find t, but if the var is inside of a type the baseDC needs
  // to be set. It all works fine, except: if the var is not inside of a type,
  // then t needs to be found as a local binding:
  if (auto *accessor = dyn_cast<AccessorDecl>(decl)) {
    if (auto *storage = accessor->getStorage())
      if (consumer.consume({storage}, DeclVisibilityKind::LocalVariable))
        return true;
  }
  return false;
}

bool SpecializeAttributeScope::lookupLocalsOrMembers(
    ArrayRef<const ASTScopeImpl *>, DeclConsumer consumer) const {
  if (auto *params = whatWasSpecialized->getGenericParams())
    for (auto *param : params->getParams())
      if (consumer.consume({param}, DeclVisibilityKind::GenericParameter))
        return true;
  return false;
}

// SWIFT_ENABLE_TENSORFLOW
bool DifferentiableAttributeScope::lookupLocalsOrMembers(
    ArrayRef<const ASTScopeImpl *>, DeclConsumer consumer) const {
  auto visitAbstractFunctionDecl = [&](AbstractFunctionDecl *afd) {
    if (auto *params = afd->getGenericParams())
      for (auto *param : params->getParams())
        if (consumer.consume({param}, DeclVisibilityKind::GenericParameter))
          return true;
    return false;
  };
  if (auto *afd = dyn_cast<AbstractFunctionDecl>(attributedDeclaration)) {
    return visitAbstractFunctionDecl(afd);
  } else if (auto *asd = dyn_cast<AbstractStorageDecl>(attributedDeclaration)) {
    for (auto *accessor : asd->getAllAccessors())
      if (visitAbstractFunctionDecl(accessor))
        return true;
  }
  return false;
}
// SWIFT_ENABLE_TENSORFLOW END

bool BraceStmtScope::lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
                                           DeclConsumer consumer) const {
  // All types and functions are visible anywhere within a brace statement
  // scope. When ordering matters (i.e. var decl) we will have split the brace
  // statement into nested scopes.
  //
  // Don't stop at the first one, there may be local funcs with same base name
  // and want them all.
  SmallVector<ValueDecl *, 32> localBindings;
  for (auto braceElement : stmt->getElements()) {
    if (auto localBinding = braceElement.dyn_cast<Decl *>()) {
      if (auto *vd = dyn_cast<ValueDecl>(localBinding))
        localBindings.push_back(vd);
    }
  }
  return consumer.consume(localBindings, DeclVisibilityKind::LocalVariable);
}

bool PatternEntryInitializerScope::lookupLocalsOrMembers(
    ArrayRef<const ASTScopeImpl *>, DeclConsumer consumer) const {
  // 'self' is available within the pattern initializer of a 'lazy' variable.
  auto *initContext = cast_or_null<PatternBindingInitializer>(
      decl->getPatternList()[0].getInitContext());
  if (initContext) {
    if (auto *selfParam = initContext->getImplicitSelfDecl()) {
      return consumer.consume({selfParam},
                              DeclVisibilityKind::FunctionParameter);
    }
  }
  return false;
}

bool ClosureParametersScope::lookupLocalsOrMembers(
    ArrayRef<const ASTScopeImpl *>, DeclConsumer consumer) const {
  if (auto *cl = captureList.getPtrOrNull()) {
    CaptureListExpr *mutableCL =
        const_cast<CaptureListExpr *>(captureList.get());
    for (auto &e : mutableCL->getCaptureList()) {
      if (consumer.consume(
              {e.Var},
              DeclVisibilityKind::LocalVariable)) // or FunctionParameter??
        return true;
    }
  }
  for (auto param : *closureExpr->getParameters())
    if (consumer.consume({param}, DeclVisibilityKind::FunctionParameter))
      return true;
  return false;
}

bool ConditionalClausePatternUseScope::lookupLocalsOrMembers(
    ArrayRef<const ASTScopeImpl *>, DeclConsumer consumer) const {
  return lookupLocalBindingsInPattern(
      pattern, DeclVisibilityKind::LocalVariable, consumer);
}

bool ASTScopeImpl::lookupLocalBindingsInPattern(Pattern *p,
                                                DeclVisibilityKind vis,
                                                DeclConsumer consumer) {
  if (!p)
    return false;
  bool isDone = false;
  p->forEachVariable([&](VarDecl *var) {
    if (!isDone)
      isDone = consumer.consume({var}, vis);
  });
  return isDone;
}

#pragma mark computeSelfDC

NullablePtr<DeclContext>
GenericTypeOrExtensionWhereOrBodyPortion::computeSelfDC(
    ArrayRef<const ASTScopeImpl *> history) {
  ASTScopeAssert(history.size() != 0, "includes current scope");
  size_t i = history.size() - 1; // skip last entry (this scope)
  while (i != 0) {
    Optional<NullablePtr<DeclContext>> maybeSelfDC =
        history[--i]->computeSelfDCForParent();
    if (maybeSelfDC)
      return *maybeSelfDC;
  }
  return nullptr;
}

#pragma mark compute isCascadingUse

Optional<bool> ASTScopeImpl::computeIsCascadingUse(
    ArrayRef<const ASTScopeImpl *> history,
    const Optional<bool> initialIsCascadingUse) {
  Optional<bool> isCascadingUse = initialIsCascadingUse;
  for (const auto *scope : history)
    isCascadingUse = scope->resolveIsCascadingUseForThisScope(isCascadingUse);
  return isCascadingUse;
}

#pragma mark getLookupLimit

NullablePtr<const ASTScopeImpl> ASTScopeImpl::getLookupLimit() const {
  return nullptr;
}

NullablePtr<const ASTScopeImpl>
GenericTypeOrExtensionScope::getLookupLimit() const {
  return portion->getLookupLimitFor(this);
}

NullablePtr<const ASTScopeImpl>
Portion::getLookupLimitFor(const GenericTypeOrExtensionScope *) const {
  return nullptr;
}
NullablePtr<const ASTScopeImpl>
GenericTypeOrExtensionWholePortion::getLookupLimitFor(
    const GenericTypeOrExtensionScope *scope) const {
  return scope->getLookupLimitForDecl();
}

NullablePtr<const ASTScopeImpl>
GenericTypeOrExtensionScope::getLookupLimitForDecl() const {
  return nullptr;
}

NullablePtr<const ASTScopeImpl>
NominalTypeScope::getLookupLimitForDecl() const {
  if (isa<ProtocolDecl>(decl)) {
    // ProtocolDecl can only be legally nested in a SourceFile,
    // so any other kind of Decl is illegal
    return parentIfNotChildOfTopScope();
  }
  // AFAICT, a struct, decl, or enum can be nested inside anything
  // but a ProtocolDecl.
  return ancestorWithDeclSatisfying(
      [&](const Decl *const d) { return isa<ProtocolDecl>(d); });
}

NullablePtr<const ASTScopeImpl> ExtensionScope::getLookupLimitForDecl() const {
  // Extensions can only be legally nested in a SourceFile,
  // so any other kind of Decl is illegal
  return parentIfNotChildOfTopScope();
}

NullablePtr<const ASTScopeImpl> ASTScopeImpl::ancestorWithDeclSatisfying(
    function_ref<bool(const Decl *)> predicate) const {
  for (NullablePtr<const ASTScopeImpl> s = getParent(); s;
       s = s.get()->getParent()) {
    if (Decl *d = s.get()->getDeclIfAny().getPtrOrNull()) {
      if (predicate(d))
        return s;
    }
  }
  return nullptr;
}

#pragma mark computeSelfDCForParent

// If the lookup depends on implicit self, selfDC is its context.
// (Names in extensions never depend on self.)
// Lookup can propagate it up from, say a method to the enclosing type body.

// By default, propagate the selfDC up to a NomExt decl, body,
// or where clause
Optional<NullablePtr<DeclContext>>
ASTScopeImpl::computeSelfDCForParent() const {
  return None;
}

// Forget the "self" declaration:
Optional<NullablePtr<DeclContext>>
GenericTypeOrExtensionScope::computeSelfDCForParent() const {
  return NullablePtr<DeclContext>();
}

Optional<NullablePtr<DeclContext>>
PatternEntryInitializerScope::computeSelfDCForParent() const {
  // Pattern binding initializers are only interesting insofar as they
  // affect lookup in an enclosing nominal type or extension thereof.
  if (auto *ic = getPatternEntry().getInitContext()) {
    if (auto *bindingInit = dyn_cast<PatternBindingInitializer>(ic)) {
      // Lazy variable initializer contexts have a 'self' parameter for
      // instance member lookup.
      if (bindingInit->getImplicitSelfDecl()) {
        return NullablePtr<DeclContext>(bindingInit);
      }
    }
  }
  return None;
}

Optional<NullablePtr<DeclContext>>
MethodBodyScope::computeSelfDCForParent() const {
  return NullablePtr<DeclContext>(decl);
}

#pragma mark ifUnknownIsCascadingUseAccordingTo

static bool isCascadingUseAccordingTo(const DeclContext *const dc) {
  return dc->isCascadingContextForLookup(false);
}

static bool ifUnknownIsCascadingUseAccordingTo(Optional<bool> isCascadingUse,
                                               const DeclContext *const dc) {
  return isCascadingUse.getValueOr(isCascadingUseAccordingTo(dc));
}

#pragma mark resolveIsCascadingUseForThisScope

Optional<bool> ASTScopeImpl::resolveIsCascadingUseForThisScope(
    Optional<bool> isCascadingUse) const {
  return isCascadingUse;
}

Optional<bool> GenericParamScope::resolveIsCascadingUseForThisScope(
    Optional<bool> isCascadingUse) const {
  if (auto *dc = getDeclContext().getPtrOrNull())
    return ifUnknownIsCascadingUseAccordingTo(isCascadingUse, dc);
  ASTScope_unreachable("generic what?");
}

Optional<bool> AbstractFunctionDeclScope::resolveIsCascadingUseForThisScope(
    Optional<bool> isCascadingUse) const {
  return decl->isCascadingContextForLookup(false) &&
         isCascadingUse.getValueOr(true);
}

Optional<bool> AbstractFunctionBodyScope::resolveIsCascadingUseForThisScope(
    Optional<bool> isCascadingUse) const {
  return false;
}

Optional<bool> GenericTypeOrExtensionScope::resolveIsCascadingUseForThisScope(
    Optional<bool> isCascadingUse) const {
  // Could override for ExtensionScope and just return true
  return ifUnknownIsCascadingUseAccordingTo(isCascadingUse,
                                            getDeclContext().get());
}

Optional<bool>
DefaultArgumentInitializerScope::resolveIsCascadingUseForThisScope(
    Optional<bool>) const {
  return false;
}

Optional<bool> ClosureParametersScope::resolveIsCascadingUseForThisScope(
    Optional<bool> isCascadingUse) const {
  return ifUnknownIsCascadingUseAccordingTo(isCascadingUse, closureExpr);
}
Optional<bool> ClosureBodyScope::resolveIsCascadingUseForThisScope(
    Optional<bool> isCascadingUse) const {
  return ifUnknownIsCascadingUseAccordingTo(isCascadingUse, closureExpr);
}

Optional<bool> PatternEntryInitializerScope::resolveIsCascadingUseForThisScope(
    Optional<bool> isCascadingUse) const {
  auto *const initContext = getPatternEntry().getInitContext();
  auto *PBI = cast_or_null<PatternBindingInitializer>(initContext);
  auto *isd = PBI ? PBI->getImplicitSelfDecl() : nullptr;

  // 'self' is available within the pattern initializer of a 'lazy' variable.
  if (isd)
    return ifUnknownIsCascadingUseAccordingTo(isCascadingUse, PBI);

  // initializing stored property of a type
  auto *const patternDeclContext = decl->getDeclContext();
  if (patternDeclContext->isTypeContext())
    return isCascadingUseAccordingTo(PBI->getParent());

  // initializing global or local
  if (PBI)
    return ifUnknownIsCascadingUseAccordingTo(isCascadingUse, PBI);

  return isCascadingUse;
}
