//===--- ASTScopeCreation.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 creation methods of the ASTScopeImpl ontology.
///
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTScope.h"

#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Attr.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/NameLookupRequests.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>
#include <unordered_set>

using namespace swift;
using namespace ast_scope;

/// If true, nest scopes so a variable is out of scope before its declaration
/// Does not handle capture rules for local functions properly.
/// If false don't push uses down into subscopes after decls.
static const bool handleUseBeforeDef = false;

#pragma mark source range utilities
static bool rangeableIsIgnored(const Decl *d) { return d->isImplicit(); }
static bool rangeableIsIgnored(const Expr *d) {
  return false; // implicit expr may contain closures
}
static bool rangeableIsIgnored(const Stmt *d) {
  return false; // ??
}
static bool rangeableIsIgnored(const ASTNode n) {
  return n.is<Decl *>() && n.get<Decl *>()->isImplicit();
}

template <typename Rangeable>
static SourceRange getRangeableSourceRange(const Rangeable *const p) {
  return p->getSourceRange();
}
static SourceRange getRangeableSourceRange(const SpecializeAttr *a) {
  return a->getRange();
}
// SWIFT_ENABLE_TENSORFLOW
static SourceRange getRangeableSourceRange(const DifferentiableAttr *a) {
  return a->getRange();
}
// SWIFT_ENABLE_TENSORFLOW END
static SourceRange getRangeableSourceRange(const ASTNode n) {
  return n.getSourceRange();
}

template <typename Rangeable>
static bool isLocalizable(const Rangeable astElement) {
  return !rangeableIsIgnored(astElement) &&
         getRangeableSourceRange(astElement).isValid();
}

template <typename Rangeable>
static void dumpRangeable(const Rangeable r, llvm::raw_ostream &f) {
  r.dump(f);
}
template <typename Rangeable>
static void dumpRangeable(const Rangeable *r, llvm::raw_ostream &f) {
  r->dump(f);
}
template <typename Rangeable>
static void dumpRangeable(Rangeable *r, llvm::raw_ostream &f) {
  r->dump(f);
}

static void dumpRangeable(const SpecializeAttr *r,
                          llvm::raw_ostream &f) LLVM_ATTRIBUTE_USED;
static void dumpRangeable(const SpecializeAttr *r, llvm::raw_ostream &f) {
  llvm::errs() << "SpecializeAttr\n";
}
static void dumpRangeable(SpecializeAttr *r,
                          llvm::raw_ostream &f) LLVM_ATTRIBUTE_USED;
static void dumpRangeable(SpecializeAttr *r, llvm::raw_ostream &f) {
  llvm::errs() << "SpecializeAttr\n";
}

// SWIFT_ENABLE_TENSORFLOW
static void dumpRangeable(const DifferentiableAttr *a,
                          llvm::raw_ostream &f) LLVM_ATTRIBUTE_USED;
static void dumpRangeable(const DifferentiableAttr *a, llvm::raw_ostream &f) {
  llvm::errs() << "DifferentiableAttr\n";
}
static void dumpRangeable(DifferentiableAttr *a,
                          llvm::raw_ostream &f) LLVM_ATTRIBUTE_USED;
static void dumpRangeable(DifferentiableAttr *a, llvm::raw_ostream &f) {
  llvm::errs() << "DifferentiableAttr\n";
}
// SWIFT_ENABLE_TENSORFLOW END

/// For Debugging
template <typename T>
bool doesRangeableRangeMatch(const T *x, const SourceManager &SM,
                             unsigned start, unsigned end,
                             StringRef file = "") {
  auto const r = getRangeableSourceRange(x);
  if (r.isInvalid())
    return false;
  if (start && SM.getLineNumber(r.Start) != start)
    return false;
  if (end && SM.getLineNumber(r.End) != end)
    return false;
  if (file.empty())
    return true;
  const auto buf = SM.findBufferContainingLoc(r.Start);
  return SM.getIdentifierForBuffer(buf).endswith(file);
}

#pragma mark end of rangeable

static std::vector<ASTNode> asNodeVector(DeclRange dr) {
  std::vector<ASTNode> nodes;
  llvm::transform(dr, std::back_inserter(nodes),
                  [&](Decl *d) { return ASTNode(d); });
  return nodes;
}

namespace swift {
namespace ast_scope {

namespace {
/// Use me with any ASTNode, Expr*, Decl*, or Stmt*
/// I will yield a void* that is the same, even when given an Expr* and a
/// ClosureExpr* because I take the Expr*, figure its real class, then up
/// cast.
/// Useful for duplicate checking.
class UniquePointerCalculator
    : public ASTVisitor<UniquePointerCalculator, void *, void *, void *, void *,
                        void *, void *> {
public:
  template <typename T> const void *visit(const T *x) {
    return const_cast<T *>(x);
  }

  // Call these only from the superclass
  void *visitDecl(Decl *e) { return e; }
  void *visitStmt(Stmt *e) { return e; }
  void *visitExpr(Expr *e) { return e; }
  void *visitPattern(Pattern *e) { return e; }
  void *visitDeclAttribute(DeclAttribute *e) { return e; }

// Provide default implementations for statements as ASTVisitor does for Exprs
#define STMT(CLASS, PARENT)                                                    \
  void *visit##CLASS##Stmt(CLASS##Stmt *S) { return visitStmt(S); }
#include "swift/AST/StmtNodes.def"

// Provide default implementations for patterns as ASTVisitor does for Exprs
#define PATTERN(CLASS, PARENT)                                                 \
  void *visit##CLASS##Pattern(CLASS##Pattern *S) { return visitPattern(S); }
#include "swift/AST/PatternNodes.def"
};

/// A set that does the right pointer calculation for comparing Decls to
/// DeclContexts, and Exprs
class NodeSet {
  ::llvm::DenseSet<const void *> pointers;

public:
  bool contains(const ASTScopeImpl *const s) {
    if (auto *r = s->getReferrent().getPtrOrNull())
      return pointers.count(r);
    return false; // never exclude a non-checkable scope
  }
  bool insert(const ASTScopeImpl *const s) {
    if (auto *r = s->getReferrent().getPtrOrNull())
      return pointers.insert(r).second;
    return true;
  }
  void erase(const ASTScopeImpl *const s) {
    if (auto *r = s->getReferrent().getPtrOrNull())
      pointers.erase(r);
  }
};
} // namespace

#pragma mark ScopeCreator

class ScopeCreator final {
  friend class ASTSourceFileScope;
  /// For allocating scopes.
  ASTContext &ctx;

public:
  ASTSourceFileScope *const sourceFileScope;
  ASTContext &getASTContext() const { return ctx; }

  /// The AST can have duplicate nodes, and we don't want to create scopes for
  /// those.
  NodeSet scopedNodes;

  ScopeCreator(SourceFile *SF)
      : ctx(SF->getASTContext()),
        sourceFileScope(new (ctx) ASTSourceFileScope(SF, this)) {
    ctx.addDestructorCleanup(scopedNodes);
  }

  ScopeCreator(const ScopeCreator &) = delete;  // ensure no copies
  ScopeCreator(const ScopeCreator &&) = delete; // ensure no moves

  /// Given an array of ASTNodes or Decl pointers, add them
  /// Return the resultant insertionPoint
  ASTScopeImpl *
  addSiblingsToScopeTree(ASTScopeImpl *const insertionPoint,
                         ASTScopeImpl *const organicInsertionPoint,
                         ArrayRef<ASTNode> nodesOrDeclsToAdd) {
    auto *ip = insertionPoint;
    for (auto nd : expandIfConfigClausesThenCullAndSortElementsOrMembers(
             nodesOrDeclsToAdd)) {
      if (!shouldThisNodeBeScopedWhenFoundInSourceFileBraceStmtOrType(nd)) {
        // FIXME: Could the range get lost if the node is ever reexpanded?
        ip->widenSourceRangeForIgnoredASTNode(nd);
      } else {
        const unsigned preCount = ip->getChildren().size();
        auto *const newIP =
            addToScopeTreeAndReturnInsertionPoint(nd, ip).getPtrOr(ip);
        if (ip != organicInsertionPoint)
          ip->increaseASTAncestorScopeCount(ip->getChildren().size() -
                                            preCount);
        ip = newIP;
      }
    }
    return ip;
  }

public:
  /// For each of searching, call this unless the insertion point is needed
  void addToScopeTree(ASTNode n, ASTScopeImpl *parent) {
    (void)addToScopeTreeAndReturnInsertionPoint(n, parent);
  }
  /// Return new insertion point if the scope was not a duplicate
  /// For ease of searching, don't call unless insertion point is needed
  NullablePtr<ASTScopeImpl>
  addToScopeTreeAndReturnInsertionPoint(ASTNode, ASTScopeImpl *parent);

  bool isWorthTryingToCreateScopeFor(ASTNode n) const {
    if (!n)
      return false;
    if (n.is<Expr *>())
      return true;
    // Cannot ignore implicit statements because implict return can contain
    // scopes in the expression, such as closures.
    // But must ignore other implicit statements, e.g. brace statments
    // if they can have no children and no stmt source range.
    // Deal with it in visitBraceStmt
    if (n.is<Stmt *>())
      return true;

    auto *const d = n.get<Decl *>();
    // Implicit nodes may not have source information for name lookup.
    if (!isLocalizable(d))
      return false;
    /// In \c Parser::parseDeclVarGetSet fake PBDs are created. Ignore them.
    /// Example:
    /// \code
    /// class SR10903 { static var _: Int { 0 } }
    /// \endcode

    // Commented out for
    // validation-test/compiler_crashers_fixed/27962-swift-rebindselfinconstructorexpr-getcalledconstructor.swift
    // In that test the invalid PBD -> var decl which contains the desired
    // closure scope
    //    if (const auto *PBD = dyn_cast<PatternBindingDecl>(d))
    //      if (!isLocalizable(PBD))
    //        return false;
    /// In
    /// \code
    /// @propertyWrapper
    /// public struct Wrapper<T> {
    ///   public var value: T
    ///
    ///   public init(body: () -> T) {
    ///     self.value = body()
    ///   }
    /// }
    ///
    /// let globalInt = 17
    ///
    /// @Wrapper(body: { globalInt })
    /// public var y: Int
    /// \endcode
    /// I'm seeing a dumped AST include:
    /// (pattern_binding_decl range=[test.swift:13:8 - line:12:29]
    const auto &SM = d->getASTContext().SourceMgr;

    // Once we allow invalid PatternBindingDecls (see
    // isWorthTryingToCreateScopeFor), then
    // IDE/complete_property_delegate_attribute.swift fails because we try to
    // expand a member whose source range is backwards.
    (void)SM;
    ASTScopeAssert(d->getStartLoc().isInvalid() ||
                       !SM.isBeforeInBuffer(d->getEndLoc(), d->getStartLoc()),
                   "end-before-start will break tree search via location");
    return true;
  }

  /// Create a new scope of class ChildScope initialized with a ChildElement,
  /// expandScope it,
  /// add it as a child of the receiver, and return the child and the scope to
  /// receive more decls.
  template <typename Scope, typename... Args>
  ASTScopeImpl *constructExpandAndInsertUncheckable(ASTScopeImpl *parent,
                                                    Args... args) {
    ASTScopeAssert(!Scope(args...).getReferrent(),
                   "Not checking for duplicate ASTNode but class supports it");
    return constructExpandAndInsert<Scope>(parent, args...);
  }

  template <typename Scope, typename... Args>
  NullablePtr<ASTScopeImpl>
  ifUniqueConstructExpandAndInsert(ASTScopeImpl *parent, Args... args) {
    Scope dryRun(args...);
    ASTScopeAssert(
        dryRun.getReferrent(),
        "Checking for duplicate ASTNode but class does not support it");
    if (scopedNodes.insert(&dryRun))
      return constructExpandAndInsert<Scope>(parent, args...);
    return nullptr;
  }

  template <typename Scope, typename... Args>
  ASTScopeImpl *ensureUniqueThenConstructExpandAndInsert(ASTScopeImpl *parent,
                                                         Args... args) {
    if (auto s = ifUniqueConstructExpandAndInsert<Scope>(parent, args...))
      return s.get();
    ASTScope_unreachable("Scope should have been unique");
  }

private:
  template <typename Scope, typename... Args>
  ASTScopeImpl *constructExpandAndInsert(ASTScopeImpl *parent, Args... args) {
    auto *child = new (ctx) Scope(args...);
    parent->addChild(child, ctx);
    if (shouldBeLazy()) {
      if (auto *ip = child->insertionPointForDeferredExpansion().getPtrOrNull())
        return ip;
    }
    ASTScopeImpl *insertionPoint =
        child->expandAndBeCurrentDetectingRecursion(*this);
    ASTScopeAssert(child->verifyThatThisNodeComeAfterItsPriorSibling(),
                   "Ensure search will work");
    return insertionPoint;
  }

public:
  template <typename Scope, typename PortionClass, typename... Args>
  ASTScopeImpl *constructWithPortionExpandAndInsert(ASTScopeImpl *parent,
                                                    Args... args) {
    const Portion *portion = new (ctx) PortionClass();
    return constructExpandAndInsertUncheckable<Scope>(parent, portion, args...);
  }

  template <typename Scope, typename PortionClass, typename... Args>
  NullablePtr<ASTScopeImpl>
  ifUniqueConstructWithPortionExpandAndInsert(ASTScopeImpl *parent,
                                              Args... args) {
    const Portion *portion = new (ctx) PortionClass();
    return ifUniqueConstructExpandAndInsert<Scope>(parent, portion, args...);
  }

  void addExprToScopeTree(Expr *expr, ASTScopeImpl *parent) {
    // Use the ASTWalker to find buried captures and closures
    forEachClosureIn(expr, [&](NullablePtr<CaptureListExpr> captureList,
                               ClosureExpr *closureExpr) {
      ifUniqueConstructExpandAndInsert<WholeClosureScope>(parent, closureExpr,
                                                          captureList);
    });
  }

private:
  /// Find all of the (non-nested) closures (and associated capture lists)
  /// referenced within this expression.
  void forEachClosureIn(
      Expr *expr,
      function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
          foundClosure);

  // A safe way to discover this, without creating a circular request.
  // Cannot call getAttachedPropertyWrappers.
  static bool hasAttachedPropertyWrapper(VarDecl *vd) {
    return AttachedPropertyWrapperScope::getSourceRangeOfVarDecl(vd).isValid();
  }

public:
  /// If the pattern has an attached property wrapper, create a scope for it
  /// so it can be looked up.

  void
  addAnyAttachedPropertyWrappersToScopeTree(PatternBindingDecl *patternBinding,
                                            ASTScopeImpl *parent) {
    patternBinding->getPattern(0)->forEachVariable([&](VarDecl *vd) {
      if (hasAttachedPropertyWrapper(vd))
        constructExpandAndInsertUncheckable<AttachedPropertyWrapperScope>(
            parent, vd);
    });
  }

public:
  /// Create the matryoshka nested generic param scopes (if any)
  /// that are subscopes of the receiver. Return
  /// the furthest descendant.
  /// Last GenericParamsScope includes the where clause
  ASTScopeImpl *addNestedGenericParamScopesToTree(Decl *parameterizedDecl,
                                                  GenericParamList *generics,
                                                  ASTScopeImpl *parent) {
    if (!generics)
      return parent;
    auto *s = parent;
    for (unsigned i : indices(generics->getParams()))
      s = ifUniqueConstructExpandAndInsert<GenericParamScope>(
              s, parameterizedDecl, generics, i)
              .getPtrOr(s);
    return s;
  }

  void
  addChildrenForAllLocalizableAccessorsInSourceOrder(AbstractStorageDecl *asd,
                                                     ASTScopeImpl *parent);

  void
  forEachSpecializeAttrInSourceOrder(Decl *declBeingSpecialized,
                                     function_ref<void(SpecializeAttr *)> fn) {
    std::vector<SpecializeAttr *> sortedSpecializeAttrs;
    for (auto *attr : declBeingSpecialized->getAttrs()) {
      if (auto *specializeAttr = dyn_cast<SpecializeAttr>(attr))
        sortedSpecializeAttrs.push_back(specializeAttr);
    }
    // TODO: rm extra copy
    for (auto *specializeAttr : sortBySourceRange(sortedSpecializeAttrs))
      fn(specializeAttr);
  }

  // SWIFT_ENABLE_TENSORFLOW
  void forEachDifferentiableAttrInSourceOrder(
      Decl *decl, function_ref<void(DifferentiableAttr *)> fn) {
    std::vector<DifferentiableAttr *> sortedDifferentiableAttrs;
    for (auto *attr : decl->getAttrs())
      if (auto *diffAttr = dyn_cast<DifferentiableAttr>(attr))
        // NOTE(TF-835): Skipping implicit `@differentiable` attributes is
        // necessary to avoid verification failure:
        // `ASTScopeImpl::verifyThatChildrenAreContainedWithin`.
        // Perhaps this check is no longer necessary after TF-835: robust
        // `@differentiating` attribute lowering.
        if (!diffAttr->isImplicit())
          sortedDifferentiableAttrs.push_back(diffAttr);
    for (auto *diffAttr : sortBySourceRange(sortedDifferentiableAttrs))
      fn(diffAttr);
  }
  // SWIFT_ENABLE_TENSORFLOW END

  std::vector<ASTNode> expandIfConfigClausesThenCullAndSortElementsOrMembers(
      ArrayRef<ASTNode> input) const {
    auto cleanedupNodes = sortBySourceRange(cull(expandIfConfigClauses(input)));
    // TODO: uncomment when working on not creating two pattern binding decls at
    // same location.
    //    findCollidingPatterns(cleanedupNodes);
    return cleanedupNodes;
  }

public:
  /// When ASTScopes are enabled for code completion,
  /// IfConfigs will pose a challenge because we may need to field lookups into
  /// the inactive clauses, but the AST contains redundancy: the active clause's
  /// elements are present in the members or elements of an IterableTypeDecl or
  /// BraceStmt alongside of the IfConfigDecl. In addition there are two more
  /// complications:
  ///
  /// 1. The active clause's elements may be nested inside an init self
  /// rebinding decl (as in StringObject.self).
  ///
  /// 2. The active clause may be before or after the inactive ones
  ///
  /// So, when encountering an IfConfigDecl, we will expand  the inactive
  /// elements. Also, always sort members or elements so that the child scopes
  /// are in source order (Just one of several reasons we need to sort.)
  ///
  static const bool includeInactiveIfConfigClauses = false;

private:
  static std::vector<ASTNode> expandIfConfigClauses(ArrayRef<ASTNode> input) {
    std::vector<ASTNode> expansion;
    expandIfConfigClausesInto(expansion, input, /*isInAnActiveNode=*/true);
    return expansion;
  }

  static void expandIfConfigClausesInto(std::vector<ASTNode> &expansion,
                                        ArrayRef<ASTNode> input,
                                        const bool isInAnActiveNode) {
    for (auto n : input) {
      if (!n.isDecl(DeclKind::IfConfig)) {
        expansion.push_back(n);
        continue;
      }
      auto *const icd = cast<IfConfigDecl>(n.get<Decl *>());
      for (auto &clause : icd->getClauses()) {
        if (auto *const cond = clause.Cond)
          expansion.push_back(cond);
        if (clause.isActive) {
          // TODO: Move this check into ASTVerifier
          ASTScopeAssert(isInAnActiveNode, "Clause should not be marked active "
                                           "unless it's context is active");
          // get inactive nodes that nest in active clauses
          for (auto n : clause.Elements) {
            if (auto *const d = n.dyn_cast<Decl *>())
              if (auto *const icd = dyn_cast<IfConfigDecl>(d))
                expandIfConfigClausesInto(expansion, {d}, true);
          }
        } else if (includeInactiveIfConfigClauses) {
          expandIfConfigClausesInto(expansion, clause.Elements,
                                    /*isInAnActiveNode=*/false);
        }
      }
    }
  }

  /// Remove VarDecls because we'll find them when we expand the
  /// PatternBindingDecls. Remove EnunCases
  /// because they overlap EnumElements and AST includes the elements in the
  /// members.
  std::vector<ASTNode> cull(ArrayRef<ASTNode> input) const {
    // TODO: Investigate whether to move the real EndLoc tracking of
    // SubscriptDecl up into AbstractStorageDecl. May have to cull more.
    std::vector<ASTNode> culled;
    llvm::copy_if(input, std::back_inserter(culled), [&](ASTNode n) {
      ASTScopeAssert(
          !n.isDecl(DeclKind::Accessor),
          "Should not find accessors in iterable types or brace statements");
      return isLocalizable(n) && !n.isDecl(DeclKind::Var) &&
             !n.isDecl(DeclKind::EnumCase);
    });
    return culled;
  }

  /// TODO: The parser yields two decls at the same source loc with the same
  /// kind. TODO:  me when fixing parser's proclivity to create two
  /// PatternBindingDecls at the same source location, then move this to
  /// ASTVerifier.
  ///
  /// In all cases the first pattern seems to carry the initializer, and the
  /// second, the accessor
  void findCollidingPatterns(ArrayRef<ASTNode> input) const {
    auto dumpPBD = [&](PatternBindingDecl *pbd, const char *which) {
      llvm::errs() << "*** " << which
                   << " pbd isImplicit: " << pbd->isImplicit()
                   << ", #entries: " << pbd->getNumPatternEntries() << " :";
      pbd->getSourceRange().print(llvm::errs(), pbd->getASTContext().SourceMgr,
                                  false);
      llvm::errs() << "\n";
      llvm::errs() << "init: " << pbd->getInit(0) << "\n";
      if (pbd->getInit(0)) {
        llvm::errs() << "SR (init): ";
        pbd->getInit(0)->getSourceRange().print(
            llvm::errs(), pbd->getASTContext().SourceMgr, false);
        llvm::errs() << "\n";
        pbd->getInit(0)->dump(llvm::errs(), 0);
      }
      llvm::errs() << "vars:\n";
      pbd->getPattern(0)->forEachVariable([&](VarDecl *vd) {
        llvm::errs() << "  " << vd->getName()
                     << " implicit: " << vd->isImplicit()
                     << " #accs: " << vd->getAllAccessors().size()
                     << "\nSR (var):";
        vd->getSourceRange().print(llvm::errs(), pbd->getASTContext().SourceMgr,
                                   false);
        llvm::errs() << "\nSR (braces)";
        vd->getBracesRange().print(llvm::errs(), pbd->getASTContext().SourceMgr,
                                   false);
        llvm::errs() << "\n";
        for (auto *a : vd->getAllAccessors()) {
          llvm::errs() << "SR (acc): ";
          a->getSourceRange().print(llvm::errs(),
                                    pbd->getASTContext().SourceMgr, false);
          llvm::errs() << "\n";
          a->dump(llvm::errs(), 0);
        }
      });
    };

    Decl *lastD = nullptr;
    for (auto n : input) {
      auto *d = n.dyn_cast<Decl *>();
      if (!d || !lastD || lastD->getStartLoc() != d->getStartLoc() ||
          lastD->getKind() != d->getKind()) {
        lastD = d;
        continue;
      }
      if (auto *pbd = dyn_cast<PatternBindingDecl>(lastD))
        dumpPBD(pbd, "prev");
      if (auto *pbd = dyn_cast<PatternBindingDecl>(d)) {
        dumpPBD(pbd, "curr");
        ASTScope_unreachable("found colliding pattern binding decls");
      }
      llvm::errs() << "Two same kind decls at same loc: \n";
      lastD->dump(llvm::errs());
      llvm::errs() << "and\n";
      d->dump(llvm::errs());
      ASTScope_unreachable("Two same kind decls; unexpected kinds");
    }
  }

  /// Templated to work on either ASTNodes, Decl*'s, or whatnot.
  template <typename Rangeable>
  std::vector<Rangeable>
  sortBySourceRange(std::vector<Rangeable> toBeSorted) const {
    auto compareNodes = [&](Rangeable n1, Rangeable n2) {
      return isNotAfter(n1, n2);
    };
    std::stable_sort(toBeSorted.begin(), toBeSorted.end(), compareNodes);
    return toBeSorted;
  }

  template <typename Rangeable>
  bool isNotAfter(Rangeable n1, Rangeable n2) const {
    auto cmpLoc = [&](const SourceLoc l1, const SourceLoc l2) {
      return l1 == l2 ? 0 : ctx.SourceMgr.isBeforeInBuffer(l1, l2) ? -1 : 1;
    };
    const auto r1 = getRangeableSourceRange(n1);
    const auto r2 = getRangeableSourceRange(n2);
    const int startOrder = cmpLoc(r1.Start, r2.Start);
    const int endOrder = cmpLoc(r1.End, r2.End);

#ifndef NDEBUG
    if (startOrder * endOrder == -1) {
      llvm::errs() << "*** Start order contradicts end order between: ***\n";
      dumpRangeable(n1, llvm::errs());
      llvm::errs() << "\n*** and: ***\n";
      dumpRangeable(n2, llvm::errs());
    }
#endif
    ASTScopeAssert(startOrder * endOrder != -1,
                   "Start order contradicts end order");
    return startOrder + endOrder < 1;
  }

  static bool isVarDeclInPatternBindingDecl(ASTNode n1, ASTNode n2) {
    if (auto *d1 = n1.dyn_cast<Decl *>())
      if (auto *vd = dyn_cast<VarDecl>(d1))
        if (auto *d2 = n2.dyn_cast<Decl *>())
          if (auto *pbd = dyn_cast<PatternBindingDecl>(d2))
            return vd->getParentPatternBinding() == pbd;
    return false;
  }

public:
  bool shouldThisNodeBeScopedWhenFoundInSourceFileBraceStmtOrType(ASTNode n) {
    // Do not scope VarDecls because
    // they get created directly by the pattern code.
    // Doing otherwise distorts the source range
    // of their parents.
    ASTScopeAssert(!n.isDecl(DeclKind::Accessor),
                   "Should not see accessors here");
    // Can occur in illegal code
    if (auto *const s = n.dyn_cast<Stmt *>()) {
      if (auto *const bs = dyn_cast<BraceStmt>(s))
        ASTScopeAssert(bs->getNumElements() == 0,
                       "Might mess up insertion point");
    }
    return !n.isDecl(DeclKind::Var);
  }

  bool shouldBeLazy() const { return ctx.LangOpts.LazyASTScopes; }

public:
  /// For debugging. Return true if scope tree contains all the decl contexts in
  /// the AST May modify the scope tree in order to update obsolete scopes.
  /// Likely slow.
  bool containsAllDeclContextsFromAST() {
    auto allDeclContexts = findLocalizableDeclContextsInAST();
    llvm::DenseMap<const DeclContext *, const ASTScopeImpl *> bogusDCs;
    sourceFileScope->preOrderDo([&](ASTScopeImpl *scope) {
      scope->expandAndBeCurrentDetectingRecursion(*this);
    });
    sourceFileScope->postOrderDo([&](ASTScopeImpl *scope) {
      if (auto *dc = scope->getDeclContext().getPtrOrNull()) {
        auto iter = allDeclContexts.find(dc);
        if (iter != allDeclContexts.end())
          ++iter->second;
        else
          bogusDCs.insert({dc, scope});
      }
    });

    auto printDecl = [&](const Decl *d) {
      llvm::errs() << "\ngetAsDecl() -> " << d << " ";
      d->getSourceRange().dump(ctx.SourceMgr);
      llvm::errs() << " : ";
      d->dump(llvm::errs());
      llvm::errs() << "\n";
    };
    bool foundOmission = false;
    for (const auto &p : allDeclContexts) {
      if (p.second == 0) {
        if (auto *d = p.first->getAsDecl()) {
          if (isLocalizable(d)) {
            llvm::errs() << "\nASTScope tree omitted DeclContext: " << p.first
                         << " "
                         << ":\n";
            p.first->printContext(llvm::errs());
            printDecl(d);
            foundOmission = true;
          }
        } else {
          // If no decl, no source range, so no scope
        }
      }
    }
    for (const auto dcAndScope : bogusDCs) {
      llvm::errs() << "ASTScope tree confabulated: " << dcAndScope.getFirst()
                   << ":\n";
      dcAndScope.getFirst()->printContext(llvm::errs());
      if (auto *d = dcAndScope.getFirst()->getAsDecl())
        printDecl(d);
      dcAndScope.getSecond()->print(llvm::errs(), 0, false);
    }
    return !foundOmission && bogusDCs.empty();
  }

private:
  /// Return a map of every DeclContext in the AST, and zero in the 2nd element.
  /// For debugging.
  llvm::DenseMap<const DeclContext *, unsigned>
  findLocalizableDeclContextsInAST() const;

public:
  void dump() const { print(llvm::errs()); }

  void print(raw_ostream &out) const {
    out << "(swift::ASTSourceFileScope*) " << sourceFileScope << "\n";
  }

  // Make vanilla new illegal.
  void *operator new(size_t bytes) = delete;

  // Only allow allocation of scopes using the allocator of a particular source
  // file.
  void *operator new(size_t bytes, const ASTContext &ctx,
                     unsigned alignment = alignof(ScopeCreator));
  void *operator new(size_t Bytes, void *Mem) {
    ASTScopeAssert(Mem, "Allocation failed");
    return Mem;
  }
};
} // ast_scope
} // namespace swift

#pragma mark Scope tree creation and extension

ASTScope::ASTScope(SourceFile *SF) : impl(createScopeTree(SF)) {}

void ASTScope::buildFullyExpandedTree() { impl->buildFullyExpandedTree(); }

void ASTScope::
    buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals() {
  impl->buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals();
}

ASTSourceFileScope *ASTScope::createScopeTree(SourceFile *SF) {
  ScopeCreator *scopeCreator = new (SF->getASTContext()) ScopeCreator(SF);
  return scopeCreator->sourceFileScope;
}

void ASTSourceFileScope::buildFullyExpandedTree() {
  expandAndBeCurrentDetectingRecursion(*scopeCreator);
  preOrderChildrenDo([&](ASTScopeImpl *s) {
    s->expandAndBeCurrentDetectingRecursion(*scopeCreator);
  });
}

void ASTSourceFileScope::
    buildEnoughOfTreeForTopLevelExpressionsButDontRequestGenericsOrExtendedNominals() {
      expandAndBeCurrentDetectingRecursion(*scopeCreator);
}


ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
                                       ScopeCreator *scopeCreator)
    : SF(SF), scopeCreator(scopeCreator), insertionPoint(this) {}

#pragma mark NodeAdder

namespace swift {
namespace ast_scope {

class NodeAdder
    : public ASTVisitor<NodeAdder, NullablePtr<ASTScopeImpl>,
                        NullablePtr<ASTScopeImpl>, NullablePtr<ASTScopeImpl>,
                        void, void, void, ASTScopeImpl *, ScopeCreator &> {
public:

#pragma mark ASTNodes that do not create scopes

  // Even ignored Decls and Stmts must extend the source range of a scope:
  // E.g. a braceStmt with some definitions that ends in a statement that
  // accesses such a definition must resolve as being IN the scope.

#define VISIT_AND_IGNORE(What)                                                 \
  NullablePtr<ASTScopeImpl> visit##What(What *w, ASTScopeImpl *p,              \
                                        ScopeCreator &) {                      \
    p->widenSourceRangeForIgnoredASTNode(w);                                   \
    return p;                                                                  \
  }

  VISIT_AND_IGNORE(ImportDecl)
  VISIT_AND_IGNORE(EnumCaseDecl)
  VISIT_AND_IGNORE(PrecedenceGroupDecl)
  VISIT_AND_IGNORE(InfixOperatorDecl)
  VISIT_AND_IGNORE(PrefixOperatorDecl)
  VISIT_AND_IGNORE(PostfixOperatorDecl)
  VISIT_AND_IGNORE(GenericTypeParamDecl)
  VISIT_AND_IGNORE(AssociatedTypeDecl)
  VISIT_AND_IGNORE(ModuleDecl)
  VISIT_AND_IGNORE(ParamDecl)
  VISIT_AND_IGNORE(PoundDiagnosticDecl)
  VISIT_AND_IGNORE(MissingMemberDecl)

  // This declaration is handled from the PatternBindingDecl
  VISIT_AND_IGNORE(VarDecl)

  // These contain nothing to scope.
  VISIT_AND_IGNORE(BreakStmt)
  VISIT_AND_IGNORE(ContinueStmt)
  VISIT_AND_IGNORE(FallthroughStmt)
  VISIT_AND_IGNORE(FailStmt)

#undef VISIT_AND_IGNORE

#pragma mark simple creation ignoring deferred nodes

#define VISIT_AND_CREATE(What, ScopeClass)                                     \
  NullablePtr<ASTScopeImpl> visit##What(What *w, ASTScopeImpl *p,              \
                                        ScopeCreator &scopeCreator) {          \
    return scopeCreator.ifUniqueConstructExpandAndInsert<ScopeClass>(p, w);    \
  }

  VISIT_AND_CREATE(SubscriptDecl, SubscriptDeclScope)
  VISIT_AND_CREATE(IfStmt, IfStmtScope)
  VISIT_AND_CREATE(WhileStmt, WhileStmtScope)
  VISIT_AND_CREATE(RepeatWhileStmt, RepeatWhileScope)
  VISIT_AND_CREATE(DoCatchStmt, DoCatchStmtScope)
  VISIT_AND_CREATE(SwitchStmt, SwitchStmtScope)
  VISIT_AND_CREATE(ForEachStmt, ForEachStmtScope)
  VISIT_AND_CREATE(CatchStmt, CatchStmtScope)
  VISIT_AND_CREATE(CaseStmt, CaseStmtScope)
  VISIT_AND_CREATE(AbstractFunctionDecl, AbstractFunctionDeclScope)

#undef VISIT_AND_CREATE

#pragma mark 2D simple creation (ignoring deferred nodes)

#define VISIT_AND_CREATE_WHOLE_PORTION(What, WhatScope)                        \
  NullablePtr<ASTScopeImpl> visit##What(What *w, ASTScopeImpl *p,              \
                                        ScopeCreator &scopeCreator) {          \
    return scopeCreator.ifUniqueConstructWithPortionExpandAndInsert<           \
        WhatScope, GenericTypeOrExtensionWholePortion>(p, w);                  \
  }

  VISIT_AND_CREATE_WHOLE_PORTION(ExtensionDecl, ExtensionScope)
  VISIT_AND_CREATE_WHOLE_PORTION(StructDecl, NominalTypeScope)
  VISIT_AND_CREATE_WHOLE_PORTION(ClassDecl, NominalTypeScope)
  VISIT_AND_CREATE_WHOLE_PORTION(ProtocolDecl, NominalTypeScope)
  VISIT_AND_CREATE_WHOLE_PORTION(EnumDecl, NominalTypeScope)
  VISIT_AND_CREATE_WHOLE_PORTION(TypeAliasDecl, TypeAliasScope)
  VISIT_AND_CREATE_WHOLE_PORTION(OpaqueTypeDecl, OpaqueTypeScope)
#undef VISIT_AND_CREATE_WHOLE_PORTION

  // This declaration is handled from
  // addChildrenForAllLocalizableAccessorsInSourceOrder
  NullablePtr<ASTScopeImpl> visitAccessorDecl(AccessorDecl *ad, ASTScopeImpl *p,
                                              ScopeCreator &scopeCreator) {
    return visitAbstractFunctionDecl(ad, p, scopeCreator);
  }

#pragma mark simple creation with deferred nodes

  // Each of the following creates a new scope, so that nodes which were parsed
  // after them need to be placed in scopes BELOW them in the tree. So pass down
  // the deferred nodes.
  NullablePtr<ASTScopeImpl> visitGuardStmt(GuardStmt *e, ASTScopeImpl *p,
                                           ScopeCreator &scopeCreator) {
    return scopeCreator.ifUniqueConstructExpandAndInsert<GuardStmtScope>(p, e);
  }
  NullablePtr<ASTScopeImpl> visitDoStmt(DoStmt *ds, ASTScopeImpl *p,
                                        ScopeCreator &scopeCreator) {
    scopeCreator.addToScopeTreeAndReturnInsertionPoint(ds->getBody(), p);
    return p; // Don't put subsequent decls inside the "do"
  }
  NullablePtr<ASTScopeImpl> visitTopLevelCodeDecl(TopLevelCodeDecl *d,
                                                  ASTScopeImpl *p,
                                                  ScopeCreator &scopeCreator) {
    return scopeCreator.ifUniqueConstructExpandAndInsert<TopLevelCodeScope>(p,
                                                                            d);
  }

#pragma mark special-case creation

  ASTScopeImpl *visitSourceFile(SourceFile *, ASTScopeImpl *, ScopeCreator &) {
    ASTScope_unreachable("SourceFiles are orphans.");
  }

  NullablePtr<ASTScopeImpl> visitYieldStmt(YieldStmt *ys, ASTScopeImpl *p,
                                           ScopeCreator &scopeCreator) {
    for (Expr *e : ys->getYields())
      visitExpr(e, p, scopeCreator);
    return p;
  }

  NullablePtr<ASTScopeImpl> visitDeferStmt(DeferStmt *ds, ASTScopeImpl *p,
                                           ScopeCreator &scopeCreator) {
    visitFuncDecl(ds->getTempDecl(), p, scopeCreator);
    return p;
  }

  NullablePtr<ASTScopeImpl> visitBraceStmt(BraceStmt *bs, ASTScopeImpl *p,
                                           ScopeCreator &scopeCreator) {
    auto maybeBraceScope =
        scopeCreator.ifUniqueConstructExpandAndInsert<BraceStmtScope>(p, bs);
    if (auto *s = scopeCreator.getASTContext().Stats)
      ++s->getFrontendCounters().NumBraceStmtASTScopes;
    return maybeBraceScope.getPtrOr(p);
  }

  NullablePtr<ASTScopeImpl>
  visitPatternBindingDecl(PatternBindingDecl *patternBinding,
                          ASTScopeImpl *parentScope,
                          ScopeCreator &scopeCreator) {
    scopeCreator.addAnyAttachedPropertyWrappersToScopeTree(patternBinding,
                                                           parentScope);

    const bool isInTypeDecl = parentScope->isATypeDeclScope();

    const DeclVisibilityKind vis =
        isInTypeDecl ? DeclVisibilityKind::MemberOfCurrentNominal
                     : DeclVisibilityKind::LocalVariable;
    auto *insertionPoint = parentScope;
    for (unsigned i = 0; i < patternBinding->getPatternList().size(); ++i) {
      // TODO: Won't need to do so much work to avoid creating one without
      // a SourceRange once parser is fixed to not create two
      // PatternBindingDecls with same locaiton and getSourceRangeOfThisASTNode
      // for PatternEntryDeclScope is simplified to use the PatternEntry's
      // source range.
      auto &patternEntry = patternBinding->getPatternList()[i];
      if (!patternEntry.getOriginalInit()) {
        bool found = false;
        patternEntry.getPattern()->forEachVariable([&](VarDecl *vd) {
          if (!vd->isImplicit())
            found = true;
          else
            found |= llvm::any_of(vd->getAllAccessors(), [&](AccessorDecl *a) {
              return isLocalizable(a);
            });
        });
        if (!found)
          continue;
      }
      insertionPoint =
          scopeCreator
              .ifUniqueConstructExpandAndInsert<PatternEntryDeclScope>(
                  insertionPoint, patternBinding, i, vis)
              .getPtrOr(insertionPoint);
    }
    // If in a type decl, the type search will find these,
    // but if in a brace stmt, must continue under the last binding.
    return isInTypeDecl ? parentScope : insertionPoint;
  }

  NullablePtr<ASTScopeImpl> visitEnumElementDecl(EnumElementDecl *eed,
                                                 ASTScopeImpl *p,
                                                 ScopeCreator &scopeCreator) {
    scopeCreator.constructExpandAndInsertUncheckable<EnumElementScope>(p, eed);
    return p;
  }

  NullablePtr<ASTScopeImpl> visitIfConfigDecl(IfConfigDecl *icd,
                                              ASTScopeImpl *p,
                                              ScopeCreator &scopeCreator) {
    ASTScope_unreachable(
        "Should be handled inside of "
        "expandIfConfigClausesThenCullAndSortElementsOrMembers");
  }

  NullablePtr<ASTScopeImpl> visitReturnStmt(ReturnStmt *rs, ASTScopeImpl *p,
                                            ScopeCreator &scopeCreator) {
    if (rs->hasResult())
      visitExpr(rs->getResult(), p, scopeCreator);
    return p;
  }

  NullablePtr<ASTScopeImpl> visitThrowStmt(ThrowStmt *ts, ASTScopeImpl *p,
                                           ScopeCreator &scopeCreator) {
    visitExpr(ts->getSubExpr(), p, scopeCreator);
    return p;
  }

  NullablePtr<ASTScopeImpl> visitPoundAssertStmt(PoundAssertStmt *pas,
                                                 ASTScopeImpl *p,
                                                 ScopeCreator &scopeCreator) {
    visitExpr(pas->getCondition(), p, scopeCreator);
    return p;
  }

  NullablePtr<ASTScopeImpl> visitExpr(Expr *expr, ASTScopeImpl *p,
                                      ScopeCreator &scopeCreator) {
    if (expr) {
      p->widenSourceRangeForIgnoredASTNode(expr);
      scopeCreator.addExprToScopeTree(expr, p);
    }
    return p;
  }
};
} // namespace ast_scope
} // namespace swift

// These definitions are way down here so it can call into
// NodeAdder
NullablePtr<ASTScopeImpl>
ScopeCreator::addToScopeTreeAndReturnInsertionPoint(ASTNode n,
                                                    ASTScopeImpl *parent) {
  if (!isWorthTryingToCreateScopeFor(n))
    return parent;
  if (auto *p = n.dyn_cast<Decl *>())
    return NodeAdder().visit(p, parent, *this);
  if (auto *p = n.dyn_cast<Expr *>())
    return NodeAdder().visit(p, parent, *this);
  auto *p = n.get<Stmt *>();
  return NodeAdder().visit(p, parent, *this);
}

void ScopeCreator::addChildrenForAllLocalizableAccessorsInSourceOrder(
    AbstractStorageDecl *asd, ASTScopeImpl *parent) {
  // Accessors are always nested within their abstract storage
  // declaration. The nesting may not be immediate, because subscripts may
  // have intervening scopes for generics.
  AbstractStorageDecl *const enclosingAbstractStorageDecl =
      parent->getEnclosingAbstractStorageDecl().get();

  std::vector<AccessorDecl *> accessorsToScope;
  // Assume we don't have to deal with inactive clauses of IfConfigs here
  llvm::copy_if(asd->getAllAccessors(), std::back_inserter(accessorsToScope),
                [&](AccessorDecl *ad) {
                  return enclosingAbstractStorageDecl == ad->getStorage();
                });

  // SWIFT_ENABLE_TENSORFLOW
  // Create scopes for `@differentiable` attributes.
  forEachDifferentiableAttrInSourceOrder(
      asd, [&](DifferentiableAttr *diffAttr) {
    ifUniqueConstructExpandAndInsert<DifferentiableAttributeScope>(
        parent, diffAttr, asd);
  });
  // SWIFT_ENABLE_TENSORFLOW END

  // Sort in order to include synthesized ones, which are out of order.
  for (auto *accessor : sortBySourceRange(accessorsToScope))
    addToScopeTree(accessor, parent);
}

#pragma mark creation helpers

void ASTScopeImpl::addChild(ASTScopeImpl *child, ASTContext &ctx) {
  // If this is the first time we've added children, notify the ASTContext
  // that there's a SmallVector that needs to be cleaned up.
  // FIXME: If we had access to SmallVector::isSmall(), we could do better.
  if (storedChildren.empty() && !haveAddedCleanup) {
    ctx.addDestructorCleanup(storedChildren);
    haveAddedCleanup = true;
  }
  storedChildren.push_back(child);
  ASTScopeAssert(!child->getParent(), "child should not already have parent");
  child->parent = this;
  clearCachedSourceRangesOfMeAndAncestors();
}

void ASTScopeImpl::removeChildren() {
  clearCachedSourceRangesOfMeAndAncestors();
  storedChildren.clear();
}

void ASTScopeImpl::disownDescendants(ScopeCreator &scopeCreator) {
  for (auto *c : getChildren()) {
    c->disownDescendants(scopeCreator);
    c->emancipate();
    scopeCreator.scopedNodes.erase(c);
  }
  removeChildren();
}

#pragma mark implementations of expansion

ASTScopeImpl *
ASTScopeImpl::expandAndBeCurrentDetectingRecursion(ScopeCreator &scopeCreator) {
  return evaluateOrDefault(scopeCreator.getASTContext().evaluator,
                           ExpandASTScopeRequest{this, &scopeCreator}, nullptr);
}

llvm::Expected<ASTScopeImpl *>
ExpandASTScopeRequest::evaluate(Evaluator &evaluator, ASTScopeImpl *parent,
                                ScopeCreator *scopeCreator) const {
  auto *insertionPoint = parent->expandAndBeCurrent(*scopeCreator);
  ASTScopeAssert(insertionPoint,
                 "Used to return a null pointer if the insertion point would "
                 "not be used, but it breaks the request dependency hashing");
  return insertionPoint;
}

bool ASTScopeImpl::doesExpansionOnlyAddNewDeclsAtEnd() const { return false; }
bool ASTSourceFileScope::doesExpansionOnlyAddNewDeclsAtEnd() const {
  return true;
}

ASTScopeImpl *ASTScopeImpl::expandAndBeCurrent(ScopeCreator &scopeCreator) {

  // We might be reexpanding, so save any scopes that were inserted here from
  // above it in the AST
  auto astAncestorScopes = rescueASTAncestorScopesForReuseFromMeOrDescendants();
  ASTScopeAssert(astAncestorScopes.empty() ||
                     !doesExpansionOnlyAddNewDeclsAtEnd(),
                 "ASTSourceFileScope has no ancestors to be rescued.");

  // If reexpanding, we need to remove descendant decls from the duplication set
  // in order to re-add them as sub-scopes. Since expansion only adds new Decls
  // at end, don't bother with descendants
  if (!doesExpansionOnlyAddNewDeclsAtEnd())
    disownDescendants(scopeCreator);

  auto *insertionPoint = expandSpecifically(scopeCreator);
  if (scopeCreator.shouldBeLazy()) {
    ASTScopeAssert(!insertionPointForDeferredExpansion() ||
                       insertionPointForDeferredExpansion().get() ==
                           insertionPoint,
                   "In order for lookups into lazily-expanded scopes to be "
                   "accurate before expansion, the insertion point before "
                   "expansion must be the same as after expansion.");
  }
  replaceASTAncestorScopes(astAncestorScopes);
  setWasExpanded();
  beCurrent();
  ASTScopeAssert(checkSourceRangeAfterExpansion(scopeCreator.getASTContext()),
                 "Bad range.");
  return insertionPoint;
}

  // Do this whole bit so it's easy to see which type of scope is which

#define CREATES_NEW_INSERTION_POINT(Scope)                                     \
  ASTScopeImpl *Scope::expandSpecifically(ScopeCreator &scopeCreator) {        \
    return expandAScopeThatCreatesANewInsertionPoint(scopeCreator)             \
        .insertionPoint;                                                       \
  }

#define NO_NEW_INSERTION_POINT(Scope)                                          \
  ASTScopeImpl *Scope::expandSpecifically(ScopeCreator &scopeCreator) {        \
    expandAScopeThatDoesNotCreateANewInsertionPoint(scopeCreator);             \
    return getParent().get();                                                  \
  }

// Return this in particular for GenericParamScope so body is scoped under it
#define NO_EXPANSION(Scope)                                                    \
  ASTScopeImpl *Scope::expandSpecifically(ScopeCreator &) { return this; }

CREATES_NEW_INSERTION_POINT(ASTSourceFileScope)
CREATES_NEW_INSERTION_POINT(ParameterListScope)
CREATES_NEW_INSERTION_POINT(ConditionalClauseScope)
CREATES_NEW_INSERTION_POINT(GuardStmtScope)
CREATES_NEW_INSERTION_POINT(PatternEntryDeclScope)
CREATES_NEW_INSERTION_POINT(PatternEntryInitializerScope)
CREATES_NEW_INSERTION_POINT(GenericTypeOrExtensionScope)
CREATES_NEW_INSERTION_POINT(BraceStmtScope)
CREATES_NEW_INSERTION_POINT(TopLevelCodeScope)

NO_NEW_INSERTION_POINT(AbstractFunctionBodyScope)
NO_NEW_INSERTION_POINT(AbstractFunctionDeclScope)
NO_NEW_INSERTION_POINT(AttachedPropertyWrapperScope)
NO_NEW_INSERTION_POINT(EnumElementScope)

NO_NEW_INSERTION_POINT(CaptureListScope)
NO_NEW_INSERTION_POINT(CaseStmtScope)
NO_NEW_INSERTION_POINT(CatchStmtScope)
NO_NEW_INSERTION_POINT(ClosureBodyScope)
NO_NEW_INSERTION_POINT(DefaultArgumentInitializerScope)
NO_NEW_INSERTION_POINT(DoCatchStmtScope)
NO_NEW_INSERTION_POINT(ForEachPatternScope)
NO_NEW_INSERTION_POINT(ForEachStmtScope)
NO_NEW_INSERTION_POINT(IfStmtScope)
NO_NEW_INSERTION_POINT(RepeatWhileScope)
NO_NEW_INSERTION_POINT(SubscriptDeclScope)
NO_NEW_INSERTION_POINT(SwitchStmtScope)
NO_NEW_INSERTION_POINT(VarDeclScope)
NO_NEW_INSERTION_POINT(WhileStmtScope)
NO_NEW_INSERTION_POINT(WholeClosureScope)

NO_EXPANSION(GenericParamScope)
NO_EXPANSION(ClosureParametersScope)
NO_EXPANSION(SpecializeAttributeScope)
// SWIFT_ENABLE_TENSORFLOW
NO_EXPANSION(DifferentiableAttributeScope)
// SWIFT_ENABLE_TENSORFLOW END
NO_EXPANSION(ConditionalClausePatternUseScope)
NO_EXPANSION(LookupParentDiversionScope)

#undef CREATES_NEW_INSERTION_POINT
#undef NO_NEW_INSERTION_POINT

AnnotatedInsertionPoint
ASTSourceFileScope::expandAScopeThatCreatesANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  ASTScopeAssert(SF, "Must already have a SourceFile.");
  ArrayRef<Decl *> decls = SF->Decls;
  // Assume that decls are only added at the end, in source order
  ArrayRef<Decl *> newDecls = decls.slice(numberOfDeclsAlreadySeen);
  std::vector<ASTNode> newNodes(newDecls.begin(), newDecls.end());
  insertionPoint =
      scopeCreator.addSiblingsToScopeTree(insertionPoint, this, newNodes);
  // Too slow to perform all the time:
  //    ASTScopeAssert(scopeCreator->containsAllDeclContextsFromAST(),
  //           "ASTScope tree missed some DeclContexts or made some up");
  return {insertionPoint, "Next time decls are added they go here."};
}

AnnotatedInsertionPoint
ParameterListScope::expandAScopeThatCreatesANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  // Each initializer for a function parameter is its own, sibling, scope.
  // Unlike generic parameters or pattern initializers, it cannot refer to a
  // previous parameter.
  for (ParamDecl *pd : params->getArray()) {
    if (pd->getDefaultValue())
      scopeCreator
          .constructExpandAndInsertUncheckable<DefaultArgumentInitializerScope>(
              this, pd);
  }
  return {this, "body of func goes under me"};
}

AnnotatedInsertionPoint
PatternEntryDeclScope::expandAScopeThatCreatesANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  // Initializers come before VarDecls, e.g. PCMacro/didSet.swift 19
  auto patternEntry = getPatternEntry();
  // Create a child for the initializer, if present.
  // Cannot trust the source range given in the ASTScopeImpl for the end of the
  // initializer (because of InterpolatedLiteralStrings and EditorPlaceHolders),
  // so compute it ourselves.
  // Even if this predicate fails, there may be an initContext but
  // we cannot make a scope for it, since no source range.
  if (patternEntry.getOriginalInit() &&
      isLocalizable(patternEntry.getOriginalInit())) {
    ASTScopeAssert(
        !getSourceManager().isBeforeInBuffer(
            patternEntry.getOriginalInit()->getStartLoc(), decl->getStartLoc()),
        "Original inits are always after the '='");
    scopeCreator
        .constructExpandAndInsertUncheckable<PatternEntryInitializerScope>(
            this, decl, patternEntryIndex, vis);
  }
  // Add accessors for the variables in this pattern.
  forEachVarDeclWithLocalizableAccessors(scopeCreator, [&](VarDecl *var) {
    scopeCreator.ifUniqueConstructExpandAndInsert<VarDeclScope>(this, var);
  });
  ASTScopeAssert(!handleUseBeforeDef,
                 "next line is wrong otherwise; would need a use scope");

  return {getParent().get(), "When not handling use-before-def, succeeding "
                             "code just goes in the same scope as this one"};
}

AnnotatedInsertionPoint
PatternEntryInitializerScope::expandAScopeThatCreatesANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  // Create a child for the initializer expression.
  scopeCreator.addToScopeTree(ASTNode(getPatternEntry().getOriginalInit()),
                              this);
  if (handleUseBeforeDef)
    return {this, "PatternEntryDeclScope::expand.* needs initializer scope to "
                  "get its endpoint in order to push back start of "
                  "PatternEntryUseScope"};

  // null pointer here blows up request printing
  return {getParent().get(), "Unused"};
}

AnnotatedInsertionPoint
ConditionalClauseScope::expandAScopeThatCreatesANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  const StmtConditionElement &sec = getStmtConditionElement();
  switch (sec.getKind()) {
  case StmtConditionElement::CK_Availability:
    return {this, "No introduced variables"};
  case StmtConditionElement::CK_Boolean:
    scopeCreator.addToScopeTree(sec.getBoolean(), this);
    return {this, "No introduced variables"};
  case StmtConditionElement::CK_PatternBinding:
    scopeCreator.addToScopeTree(sec.getInitializer(), this);
    auto *const ccPatternUseScope =
        scopeCreator.constructExpandAndInsertUncheckable<
            ConditionalClausePatternUseScope>(this, sec.getPattern(), endLoc);
    return {ccPatternUseScope,
            "Succeeding code must be in scope of conditional variables"};
  }
  ASTScope_unreachable("Unhandled StmtConditionKind in switch");
}

AnnotatedInsertionPoint
GuardStmtScope::expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &
                                                          scopeCreator) {

  ASTScopeImpl *conditionLookupParent =
      createNestedConditionalClauseScopes(scopeCreator, stmt->getBody());
  // Add a child for the 'guard' body, which always exits.
  // Parent is whole guard stmt scope, NOT the cond scopes
  scopeCreator.addToScopeTree(stmt->getBody(), this);

  auto *const lookupParentDiversionScope =
      scopeCreator
          .constructExpandAndInsertUncheckable<LookupParentDiversionScope>(
              this, conditionLookupParent, stmt->getEndLoc());
  return {lookupParentDiversionScope,
          "Succeeding code must be in scope of guard variables"};
}

AnnotatedInsertionPoint
GenericTypeOrExtensionScope::expandAScopeThatCreatesANewInsertionPoint(
    ScopeCreator & scopeCreator) {
  return {portion->expandScope(this, scopeCreator),
          "<X: Foo, Y: X> is legal, so nest these"};
}

AnnotatedInsertionPoint
BraceStmtScope::expandAScopeThatCreatesANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  // TODO: remove the sort after fixing parser to create brace statement
  // elements in source order
  auto *insertionPoint =
      scopeCreator.addSiblingsToScopeTree(this, this, stmt->getElements());
  if (auto *s = scopeCreator.getASTContext().Stats)
    ++s->getFrontendCounters().NumBraceStmtASTScopeExpansions;
  return {
      insertionPoint,
      "For top-level code decls, need the scope under, say a guard statment."};
}

AnnotatedInsertionPoint
TopLevelCodeScope::expandAScopeThatCreatesANewInsertionPoint(ScopeCreator &
                                                             scopeCreator) {

  if (auto *body =
          scopeCreator
              .addToScopeTreeAndReturnInsertionPoint(decl->getBody(), this)
              .getPtrOrNull())
    return {body, "So next top level code scope and put its decls in its body "
                  "under a guard statement scope (etc) from the last top level "
                  "code scope"};
  return {this, "No body"};
}

#pragma mark expandAScopeThatDoesNotCreateANewInsertionPoint

// Create child scopes for every declaration in a body.

void AbstractFunctionDeclScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  // Create scopes for specialize attributes
  scopeCreator.forEachSpecializeAttrInSourceOrder(
      decl, [&](SpecializeAttr *specializeAttr) {
        scopeCreator.ifUniqueConstructExpandAndInsert<SpecializeAttributeScope>(
            this, specializeAttr, decl);
      });

  // SWIFT_ENABLE_TENSORFLOW
  // Create scopes for `@differentiable` attributes.
  scopeCreator.forEachDifferentiableAttrInSourceOrder(
      decl, [&](DifferentiableAttr *diffAttr) {
        scopeCreator
            .ifUniqueConstructExpandAndInsert<DifferentiableAttributeScope>(
                this, diffAttr, decl);
      });
  // SWIFT_ENABLE_TENSORFLOW END

  // Create scopes for generic and ordinary parameters.
  // For a subscript declaration, the generic and ordinary parameters are in an
  // ancestor scope, so don't make them here.
  ASTScopeImpl *leaf = this;
  if (!isa<AccessorDecl>(decl)) {
    leaf = scopeCreator.addNestedGenericParamScopesToTree(
        decl, decl->getGenericParams(), leaf);
    if (isLocalizable(decl) && getParmsSourceLocOfAFD(decl).isValid()) {
      // swift::createDesignatedInitOverride just clones the parameters, so they
      // end up with a bogus SourceRange, maybe *before* the start of the
      // function.
      if (!decl->isImplicit()) {
        leaf = scopeCreator
                   .constructExpandAndInsertUncheckable<ParameterListScope>(
                       leaf, decl->getParameters(), nullptr);
      }
    }
  }
  // Create scope for the body.
  // We create body scopes when there is no body for source kit to complete
  // erroneous code in bodies. But don't let compiler synthesize one.
  if (decl->getBodySourceRange().isValid() && decl->getBody(false)) {
    if (AbstractFunctionBodyScope::isAMethod(decl))
      scopeCreator.constructExpandAndInsertUncheckable<MethodBodyScope>(leaf,
                                                                        decl);
    else
      scopeCreator.constructExpandAndInsertUncheckable<PureFunctionBodyScope>(
          leaf, decl);
  }
}

void EnumElementScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  if (auto *pl = decl->getParameterList())
    scopeCreator.constructExpandAndInsertUncheckable<ParameterListScope>(
        this, pl, nullptr);
  // The invariant that the raw value expression can never introduce a new scope
  // is checked in Parse.  However, this guarantee is not future-proof.  Compute
  // and add the raw value expression anyways just to be defensive.
  //
  // FIXME: Re-enable this.  It currently crashes for malformed enum cases.
  // scopeCreator.addToScopeTree(decl->getStructuralRawValueExpr(), this);
}

void AbstractFunctionBodyScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  expandBody(scopeCreator);
}

void IfStmtScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  ASTScopeImpl *insertionPoint =
      createNestedConditionalClauseScopes(scopeCreator, stmt->getThenStmt());

  // The 'then' branch
  scopeCreator.addToScopeTree(stmt->getThenStmt(), insertionPoint);

  // Add the 'else' branch, if needed.
  scopeCreator.addToScopeTree(stmt->getElseStmt(), this);
}

void WhileStmtScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  ASTScopeImpl *insertionPoint =
      createNestedConditionalClauseScopes(scopeCreator, stmt->getBody());
  scopeCreator.addToScopeTree(stmt->getBody(), insertionPoint);
}

void RepeatWhileScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  scopeCreator.addToScopeTree(stmt->getBody(), this);
  scopeCreator.addToScopeTree(stmt->getCond(), this);
}

void DoCatchStmtScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  scopeCreator.addToScopeTree(stmt->getBody(), this);

  for (auto catchClause : stmt->getCatches())
    scopeCreator.addToScopeTree(catchClause, this);
}

void SwitchStmtScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  scopeCreator.addToScopeTree(stmt->getSubjectExpr(), this);

  for (auto caseStmt : stmt->getCases()) {
    if (isLocalizable(caseStmt))
      scopeCreator.ifUniqueConstructExpandAndInsert<CaseStmtScope>(this,
                                                                   caseStmt);
  }
}

void ForEachStmtScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  scopeCreator.addToScopeTree(stmt->getSequence(), this);

  // Add a child describing the scope of the pattern.
  // In error cases such as:
  //    let v: C { for b : Int -> S((array: P { }
  // the body is implicit and it would overlap the source range of the expr
  // above.
  if (!stmt->getBody()->isImplicit()) {
    if (isLocalizable(stmt->getBody()))
      scopeCreator.constructExpandAndInsertUncheckable<ForEachPatternScope>(
          this, stmt);
  }
}

void ForEachPatternScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  scopeCreator.addToScopeTree(stmt->getWhere(), this);
  scopeCreator.addToScopeTree(stmt->getBody(), this);
}

void CatchStmtScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  scopeCreator.addToScopeTree(stmt->getGuardExpr(), this);
  scopeCreator.addToScopeTree(stmt->getBody(), this);
}

void CaseStmtScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  for (auto &caseItem : stmt->getMutableCaseLabelItems())
    scopeCreator.addToScopeTree(caseItem.getGuardExpr(), this);

  // Add a child for the case body.
  scopeCreator.addToScopeTree(stmt->getBody(), this);
}

void VarDeclScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  scopeCreator.addChildrenForAllLocalizableAccessorsInSourceOrder(decl, this);
}

void SubscriptDeclScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  auto *sub = decl;
  auto *leaf = scopeCreator.addNestedGenericParamScopesToTree(
      sub, sub->getGenericParams(), this);
  auto *params =
      scopeCreator.constructExpandAndInsertUncheckable<ParameterListScope>(
          leaf, sub->getIndices(), sub->getAccessor(AccessorKind::Get));
  scopeCreator.addChildrenForAllLocalizableAccessorsInSourceOrder(sub, params);
}

void WholeClosureScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  if (auto *cl = captureList.getPtrOrNull())
    scopeCreator.ensureUniqueThenConstructExpandAndInsert<CaptureListScope>(
        this, cl);
  ASTScopeImpl *bodyParent = this;
  if (closureExpr->getInLoc().isValid())
    bodyParent =
        scopeCreator
            .constructExpandAndInsertUncheckable<ClosureParametersScope>(
                this, closureExpr, captureList);
  scopeCreator.constructExpandAndInsertUncheckable<ClosureBodyScope>(
      bodyParent, closureExpr, captureList);
}

void CaptureListScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  // Patterns here are implicit, so need to dig out the intializers
  for (const CaptureListEntry &captureListEntry : expr->getCaptureList()) {
    for (unsigned patternEntryIndex = 0;
         patternEntryIndex < captureListEntry.Init->getNumPatternEntries();
         ++patternEntryIndex) {
      Expr *init = captureListEntry.Init->getInit(patternEntryIndex);
      scopeCreator.addExprToScopeTree(init, this);
    }
  }
}

void ClosureBodyScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
    ScopeCreator &scopeCreator) {
  scopeCreator.addToScopeTree(closureExpr->getBody(), this);
}

void DefaultArgumentInitializerScope::
    expandAScopeThatDoesNotCreateANewInsertionPoint(
        ScopeCreator &scopeCreator) {
  auto *initExpr = decl->getDefaultValue();
  ASTScopeAssert(initExpr,
                 "Default argument initializer must have an initializer.");
  scopeCreator.addToScopeTree(initExpr, this);
}

void AttachedPropertyWrapperScope::
    expandAScopeThatDoesNotCreateANewInsertionPoint(
        ScopeCreator &scopeCreator) {
  for (auto *attr : decl->getAttrs().getAttributes<CustomAttr>()) {
    if (auto *expr = attr->getArg())
      scopeCreator.addToScopeTree(expr, this);
  }
}

#pragma mark expandScope

ASTScopeImpl *GenericTypeOrExtensionWholePortion::expandScope(
    GenericTypeOrExtensionScope *scope, ScopeCreator &scopeCreator) const {
  // Get now in case recursion emancipates scope
  auto *const ip = scope->getParent().get();
  
  // Prevent circular request bugs caused by illegal input and
  // doing lookups that getExtendedNominal in the midst of getExtendedNominal.
  if (scope->shouldHaveABody() && !scope->doesDeclHaveABody())
    return ip;

  auto *deepestScope = scopeCreator.addNestedGenericParamScopesToTree(
      scope->getDecl(), scope->getGenericContext()->getGenericParams(), scope);
  if (scope->getGenericContext()->getTrailingWhereClause())
    scope->createTrailingWhereClauseScope(deepestScope, scopeCreator);
  scope->createBodyScope(deepestScope, scopeCreator);
  return ip;
}

ASTScopeImpl *
IterableTypeBodyPortion::expandScope(GenericTypeOrExtensionScope *scope,
                                     ScopeCreator &scopeCreator) const {
  // Get it now in case of recursion and this one gets emancipated
  auto *const ip = scope->getParent().get();
  scope->expandBody(scopeCreator);
  return ip;
}

ASTScopeImpl *GenericTypeOrExtensionWherePortion::expandScope(
    GenericTypeOrExtensionScope *scope, ScopeCreator &) const {
  return scope->getParent().get();
}

#pragma mark createBodyScope

void IterableTypeScope::countBodies(ScopeCreator &scopeCreator) const {
  if (auto *s = scopeCreator.getASTContext().Stats)
    ++s->getFrontendCounters().NumIterableTypeBodyASTScopes;
}

void ExtensionScope::createBodyScope(ASTScopeImpl *leaf,
                                     ScopeCreator &scopeCreator) {
  scopeCreator.constructWithPortionExpandAndInsert<ExtensionScope,
                                                   IterableTypeBodyPortion>(
      leaf, decl);
  countBodies(scopeCreator);
}
void NominalTypeScope::createBodyScope(ASTScopeImpl *leaf,
                                       ScopeCreator &scopeCreator) {
  scopeCreator.constructWithPortionExpandAndInsert<NominalTypeScope,
                                                   IterableTypeBodyPortion>(
      leaf, decl);
  countBodies(scopeCreator);
}

#pragma mark createTrailingWhereClauseScope

ASTScopeImpl *GenericTypeOrExtensionScope::createTrailingWhereClauseScope(
    ASTScopeImpl *parent, ScopeCreator &scopeCreator) {
  return parent;
}

ASTScopeImpl *
ExtensionScope::createTrailingWhereClauseScope(ASTScopeImpl *parent,
                                               ScopeCreator &scopeCreator) {
  return scopeCreator.constructWithPortionExpandAndInsert<
      ExtensionScope, GenericTypeOrExtensionWherePortion>(parent, decl);
}
ASTScopeImpl *
NominalTypeScope::createTrailingWhereClauseScope(ASTScopeImpl *parent,
                                                 ScopeCreator &scopeCreator) {
  return scopeCreator.constructWithPortionExpandAndInsert<
      NominalTypeScope, GenericTypeOrExtensionWherePortion>(parent, decl);
}
ASTScopeImpl *
TypeAliasScope::createTrailingWhereClauseScope(ASTScopeImpl *parent,
                                               ScopeCreator &scopeCreator) {
  return scopeCreator.constructWithPortionExpandAndInsert<
      TypeAliasScope, GenericTypeOrExtensionWherePortion>(parent, decl);
}

#pragma mark misc

ASTScopeImpl *LabeledConditionalStmtScope::createNestedConditionalClauseScopes(
    ScopeCreator &scopeCreator, const Stmt *const afterConds) {
  auto *stmt = getLabeledConditionalStmt();
  ASTScopeImpl *insertionPoint = this;
  for (unsigned i = 0; i < stmt->getCond().size(); ++i) {
    insertionPoint =
        scopeCreator
            .constructExpandAndInsertUncheckable<ConditionalClauseScope>(
                insertionPoint, stmt, i, afterConds->getStartLoc());
  }
  return insertionPoint;
}

AbstractPatternEntryScope::AbstractPatternEntryScope(
    PatternBindingDecl *declBeingScoped, unsigned entryIndex,
    DeclVisibilityKind vis)
    : decl(declBeingScoped), patternEntryIndex(entryIndex), vis(vis) {
  ASTScopeAssert(entryIndex < declBeingScoped->getPatternList().size(),
                 "out of bounds");
}

void AbstractPatternEntryScope::forEachVarDeclWithLocalizableAccessors(
    ScopeCreator &scopeCreator, function_ref<void(VarDecl *)> foundOne) const {
  getPatternEntry().getPattern()->forEachVariable([&](VarDecl *var) {
    if (llvm::any_of(var->getAllAccessors(),
                     [&](AccessorDecl *a) { return isLocalizable(a); }))
      foundOne(var);
  });
}

bool AbstractPatternEntryScope::isLastEntry() const {
  return patternEntryIndex + 1 == decl->getPatternList().size();
}

// Following must be after uses to ensure templates get instantiated
#pragma mark getEnclosingAbstractStorageDecl

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

NullablePtr<AbstractStorageDecl>
SpecializeAttributeScope::getEnclosingAbstractStorageDecl() const {
  return getParent().get()->getEnclosingAbstractStorageDecl();
}
// SWIFT_ENABLE_TENSORFLOW
NullablePtr<AbstractStorageDecl>
DifferentiableAttributeScope::getEnclosingAbstractStorageDecl() const {
  return getParent().get()->getEnclosingAbstractStorageDecl();
}
// SWIFT_ENABLE_TENSORFLOW END
NullablePtr<AbstractStorageDecl>
AbstractFunctionDeclScope::getEnclosingAbstractStorageDecl() const {
  return getParent().get()->getEnclosingAbstractStorageDecl();
}
NullablePtr<AbstractStorageDecl>
ParameterListScope::getEnclosingAbstractStorageDecl() const {
  return getParent().get()->getEnclosingAbstractStorageDecl();
}
NullablePtr<AbstractStorageDecl>
GenericParamScope::getEnclosingAbstractStorageDecl() const {
  return getParent().get()->getEnclosingAbstractStorageDecl();
}

bool ASTScopeImpl::isATypeDeclScope() const {
  Decl *const pd = getDeclIfAny().getPtrOrNull();
  return pd && (isa<NominalTypeDecl>(pd) || isa<ExtensionDecl>(pd));
}

void ScopeCreator::forEachClosureIn(
    Expr *expr, function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
                    foundClosure) {
  ASTScopeAssert(expr,
                 "If looking for closures, must have an expression to search.");

  /// AST walker that finds top-level closures in an expression.
  class ClosureFinder : public ASTWalker {
    function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
        foundClosure;

  public:
    ClosureFinder(
        function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
            foundClosure)
        : foundClosure(foundClosure) {}

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      if (auto *closure = dyn_cast<ClosureExpr>(E)) {
        foundClosure(nullptr, closure);
        return {false, E};
      }
      if (auto *capture = dyn_cast<CaptureListExpr>(E)) {
        foundClosure(capture, capture->getClosureBody());
        return {false, E};
      }
      return {true, E};
    }
    std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
      if (auto *bs = dyn_cast<BraceStmt>(S)) { // closures hidden in here
        return {true, S};
      }
      return {false, S};
    }
    std::pair<bool, Pattern *> walkToPatternPre(Pattern *P) override {
      return {false, P};
    }
    bool walkToDeclPre(Decl *D) override { return false; }
    bool walkToTypeLocPre(TypeLoc &TL) override { return false; }
    bool walkToTypeReprPre(TypeRepr *T) override { return false; }
    bool walkToParameterListPre(ParameterList *PL) override { return false; }
  };

  expr->walk(ClosureFinder(foundClosure));
}

#pragma mark new operators
void *ASTScopeImpl::operator new(size_t bytes, const ASTContext &ctx,
                                 unsigned alignment) {
  return ctx.Allocate(bytes, alignment);
}

void *Portion::operator new(size_t bytes, const ASTContext &ctx,
                             unsigned alignment) {
  return ctx.Allocate(bytes, alignment);
}
void *ASTScope::operator new(size_t bytes, const ASTContext &ctx,
                             unsigned alignment) {
  return ctx.Allocate(bytes, alignment);
}
void *ScopeCreator::operator new(size_t bytes, const ASTContext &ctx,
                                 unsigned alignment) {
  return ctx.Allocate(bytes, alignment);
}

#pragma mark - expandBody

void AbstractFunctionBodyScope::expandBody(ScopeCreator &scopeCreator) {
  scopeCreator.addToScopeTree(decl->getBody(), this);
}

void GenericTypeOrExtensionScope::expandBody(ScopeCreator &) {}

void IterableTypeScope::expandBody(ScopeCreator &scopeCreator) {
  auto nodes = asNodeVector(getIterableDeclContext().get()->getMembers());
  scopeCreator.addSiblingsToScopeTree(this, this, nodes);
  if (auto *s = scopeCreator.getASTContext().Stats)
    ++s->getFrontendCounters().NumIterableTypeBodyASTScopeExpansions;
}

#pragma mark getScopeCreator
ScopeCreator &ASTScopeImpl::getScopeCreator() {
  return getParent().get()->getScopeCreator();
}

ScopeCreator &ASTSourceFileScope::getScopeCreator() { return *scopeCreator; }

#pragma mark getReferrent

  // These are the scopes whose ASTNodes (etc) might be duplicated in the AST
  // getReferrent is the cookie used to dedup them

#define GET_REFERRENT(Scope, x)                                                \
  NullablePtr<const void> Scope::getReferrent() const {                        \
    return UniquePointerCalculator().visit(x);                                 \
  }

GET_REFERRENT(AbstractFunctionDeclScope, getDecl())
// If the PatternBindingDecl is a dup, detect it for the first
// PatternEntryDeclScope; the others are subscopes.
GET_REFERRENT(PatternEntryDeclScope, getPattern())
GET_REFERRENT(TopLevelCodeScope, getDecl())
GET_REFERRENT(SubscriptDeclScope, getDecl())
GET_REFERRENT(VarDeclScope, getDecl())
GET_REFERRENT(GenericParamScope, paramList->getParams()[index])
GET_REFERRENT(AbstractStmtScope, getStmt())
GET_REFERRENT(CaptureListScope, getExpr())
GET_REFERRENT(WholeClosureScope, getExpr())
GET_REFERRENT(SpecializeAttributeScope, specializeAttr)
// SWIFT_ENABLE_TENSORFLOW
GET_REFERRENT(DifferentiableAttributeScope, differentiableAttr)
// SWIFT_ENABLE_TENSORFLOW END
GET_REFERRENT(GenericTypeOrExtensionScope, portion->getReferrentOfScope(this));

const Decl *
Portion::getReferrentOfScope(const GenericTypeOrExtensionScope *s) const {
  return nullptr;
};

const Decl *GenericTypeOrExtensionWholePortion::getReferrentOfScope(
    const GenericTypeOrExtensionScope *s) const {
  return s->getDecl();
};

#undef GET_REFERRENT

#pragma mark currency
NullablePtr<ASTScopeImpl> ASTScopeImpl::insertionPointForDeferredExpansion() {
  return nullptr;
}

NullablePtr<ASTScopeImpl>
AbstractFunctionBodyScope::insertionPointForDeferredExpansion() {
  return getParent().get();
}

NullablePtr<ASTScopeImpl>
IterableTypeScope::insertionPointForDeferredExpansion() {
  return portion->insertionPointForDeferredExpansion(this);
}

NullablePtr<ASTScopeImpl>
GenericTypeOrExtensionWholePortion::insertionPointForDeferredExpansion(
    IterableTypeScope *s) const {
  return s->getParent().get();
}
NullablePtr<ASTScopeImpl>
GenericTypeOrExtensionWherePortion::insertionPointForDeferredExpansion(
    IterableTypeScope *) const {
  return nullptr;
}
NullablePtr<ASTScopeImpl>
IterableTypeBodyPortion::insertionPointForDeferredExpansion(
    IterableTypeScope *s) const {
  return s->getParent().get();
}

bool ASTScopeImpl::isExpansionNeeded(const ScopeCreator &scopeCreator) const {
  return !isCurrent() ||
         scopeCreator.getASTContext().LangOpts.StressASTScopeLookup;
}

bool ASTScopeImpl::isCurrent() const {
  return getWasExpanded() && isCurrentIfWasExpanded();
}

void ASTScopeImpl::beCurrent() {}
bool ASTScopeImpl::isCurrentIfWasExpanded() const { return true; }

void ASTSourceFileScope::beCurrent() {
  numberOfDeclsAlreadySeen = SF->Decls.size();
}
bool ASTSourceFileScope::isCurrentIfWasExpanded() const {
  return SF->Decls.size() == numberOfDeclsAlreadySeen;
}

void IterableTypeScope::beCurrent() { portion->beCurrent(this); }
bool IterableTypeScope::isCurrentIfWasExpanded() const {
  return portion->isCurrentIfWasExpanded(this);
}

void GenericTypeOrExtensionWholePortion::beCurrent(IterableTypeScope *s) const {
  s->makeWholeCurrent();
}
bool GenericTypeOrExtensionWholePortion::isCurrentIfWasExpanded(
    const IterableTypeScope *s) const {
  return s->isWholeCurrent();
}
void GenericTypeOrExtensionWherePortion::beCurrent(IterableTypeScope *) const {}
bool GenericTypeOrExtensionWherePortion::isCurrentIfWasExpanded(
    const IterableTypeScope *) const {
  return true;
}
void IterableTypeBodyPortion::beCurrent(IterableTypeScope *s) const {
  s->makeBodyCurrent();
}
bool IterableTypeBodyPortion::isCurrentIfWasExpanded(
    const IterableTypeScope *s) const {
  return s->isBodyCurrent();
}

void IterableTypeScope::makeWholeCurrent() {
  ASTScopeAssert(getWasExpanded(), "Should have been expanded");
}
bool IterableTypeScope::isWholeCurrent() const {
  // Whole starts out unexpanded, and is lazily built but will have at least a
  // body scope child
  return getWasExpanded();
}
void IterableTypeScope::makeBodyCurrent() {
  memberCount = getIterableDeclContext().get()->getMemberCount();
}
bool IterableTypeScope::isBodyCurrent() const {
  return memberCount == getIterableDeclContext().get()->getMemberCount();
}

void AbstractFunctionBodyScope::beCurrent() {
  bodyWhenLastExpanded = decl->getBody(false);
}
bool AbstractFunctionBodyScope::isCurrentIfWasExpanded() const {
  return bodyWhenLastExpanded == decl->getBody(false);
}

void TopLevelCodeScope::beCurrent() { bodyWhenLastExpanded = decl->getBody(); }
bool TopLevelCodeScope::isCurrentIfWasExpanded() const {
  return bodyWhenLastExpanded == decl->getBody();
}

// Try to avoid the work of counting
static const bool assumeVarsDoNotGetAdded = true;

static unsigned countVars(const PatternBindingEntry &entry) {
  unsigned varCount = 0;
  entry.getPattern()->forEachVariable([&](VarDecl *) { ++varCount; });
  return varCount;
}

void PatternEntryDeclScope::beCurrent() {
  initWhenLastExpanded = getPatternEntry().getOriginalInit();
  if (assumeVarsDoNotGetAdded && varCountWhenLastExpanded)
    return;
  varCountWhenLastExpanded = countVars(getPatternEntry());
}
bool PatternEntryDeclScope::isCurrentIfWasExpanded() const {
  if (initWhenLastExpanded != getPatternEntry().getOriginalInit())
    return false;
  if (assumeVarsDoNotGetAdded && varCountWhenLastExpanded) {
    ASTScopeAssert(varCountWhenLastExpanded == countVars(getPatternEntry()),
                   "Vars were not supposed to be added to a pattern entry.");
    return true;
  }
  return countVars(getPatternEntry()) == varCountWhenLastExpanded;
}

void WholeClosureScope::beCurrent() {
  bodyWhenLastExpanded = closureExpr->getBody();
}
bool WholeClosureScope::isCurrentIfWasExpanded() const {
  return bodyWhenLastExpanded == closureExpr->getBody();
}

#pragma mark getParentOfASTAncestorScopesToBeRescued
NullablePtr<ASTScopeImpl>
ASTScopeImpl::getParentOfASTAncestorScopesToBeRescued() {
  return this;
}
NullablePtr<ASTScopeImpl>
AbstractFunctionBodyScope::getParentOfASTAncestorScopesToBeRescued() {
  // Reexpansion always creates a new body as the first child
  // That body contains the scopes to be rescued.
  return getChildren().empty() ? nullptr : getChildren().front();
}
NullablePtr<ASTScopeImpl>
TopLevelCodeScope::getParentOfASTAncestorScopesToBeRescued() {
  // Reexpansion always creates a new body as the first child
  // That body contains the scopes to be rescued.
  return getChildren().empty() ? nullptr : getChildren().front();
}

#pragma mark rescuing & reusing
std::vector<ASTScopeImpl *>
ASTScopeImpl::rescueASTAncestorScopesForReuseFromMeOrDescendants() {
  if (auto *p = getParentOfASTAncestorScopesToBeRescued().getPtrOrNull()) {
    return p->rescueASTAncestorScopesForReuseFromMe();
  }
  ASTScopeAssert(
      getASTAncestorScopeCount() == 0,
      "If receives ASTAncestor scopes, must know where to find parent");
  return {};
}

void ASTScopeImpl::replaceASTAncestorScopes(
    ArrayRef<ASTScopeImpl *> scopesToAdd) {
  auto *p = getParentOfASTAncestorScopesToBeRescued().getPtrOrNull();
  if (!p) {
    ASTScopeAssert(scopesToAdd.empty(), "Non-empty body disappeared?!");
    return;
  }
  auto &ctx = getASTContext();
  for (auto *s : scopesToAdd) {
    p->addChild(s, ctx);
    ASTScopeAssert(s->verifyThatThisNodeComeAfterItsPriorSibling(),
                   "Ensure search will work");
  }
  p->increaseASTAncestorScopeCount(scopesToAdd.size());
}

std::vector<ASTScopeImpl *>
ASTScopeImpl::rescueASTAncestorScopesForReuseFromMe() {
  std::vector<ASTScopeImpl *> astAncestorScopes;
  for (unsigned i = getChildren().size() - getASTAncestorScopeCount();
       i < getChildren().size(); ++i)
    astAncestorScopes.push_back(getChildren()[i]);
  // So they don't get disowned and children cleared.
  for (unsigned i = 0; i < getASTAncestorScopeCount(); ++i) {
    storedChildren.back()->emancipate();
    storedChildren.pop_back();
  }
  resetASTAncestorScopeCount();
  return astAncestorScopes;
}

bool AbstractFunctionDeclScope::shouldCreateAccessorScope(
    const AccessorDecl *const ad) {
  return isLocalizable(ad);
}

#pragma mark verification

namespace {
class LocalizableDeclContextCollector : public ASTWalker {

public:
  llvm::DenseMap<const DeclContext *, unsigned> declContexts;

  void record(const DeclContext *dc) {
    if (dc)
      declContexts.insert({dc, 0});
  }

  bool walkToDeclPre(Decl *D) override {
    //    catchForDebugging(D, "DictionaryBridging.swift", 694);
    if (const auto *dc = dyn_cast<DeclContext>(D))
      record(dc);
    if (auto *icd = dyn_cast<IfConfigDecl>(D)) {
      walkToClauses(icd);
      return false;
    }
    if (auto *pd = dyn_cast<ParamDecl>(D))
      record(pd->getDefaultArgumentInitContext());
    else if (auto *pbd = dyn_cast<PatternBindingDecl>(D))
      recordInitializers(pbd);
    else if (auto *vd = dyn_cast<VarDecl>(D))
      for (auto *ad : vd->getAllAccessors())
        ad->walk(*this);
    return ASTWalker::walkToDeclPre(D);
  }

  std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
    if (const auto *ce = dyn_cast<ClosureExpr>(E))
      record(ce);
    return ASTWalker::walkToExprPre(E);
  }

private:
  void walkToClauses(IfConfigDecl *icd) {
    for (auto &clause : icd->getClauses()) {
      // Generate scopes for any closures in the condition
      if (ScopeCreator::includeInactiveIfConfigClauses && clause.isActive) {
        if (clause.Cond)
          clause.Cond->walk(*this);
        for (auto n : clause.Elements)
          n.walk(*this);
      }
    }
  }

  void recordInitializers(PatternBindingDecl *pbd) {
    for (auto entry : pbd->getPatternList())
      record(entry.getInitContext());
  }

  void catchForDebugging(Decl *D, const char *file, const unsigned line) {
    auto &SM = D->getASTContext().SourceMgr;
    auto loc = D->getStartLoc();
    if (!loc.isValid())
      return;
    auto bufID = SM.findBufferContainingLoc(loc);
    auto f = SM.getIdentifierForBuffer(bufID);
    auto lin = SM.getLineNumber(loc);
    if (f.endswith(file) && lin == line)
      if (auto *v = dyn_cast<PatternBindingDecl>(D))
        llvm::errs() << "*** catchForDebugging: " << lin << " ***\n";
  }
};
} // end namespace

llvm::DenseMap<const DeclContext *, unsigned>
ScopeCreator::findLocalizableDeclContextsInAST() const {
  LocalizableDeclContextCollector collector;
  sourceFileScope->SF->walk(collector);
  // Walker omits the top
  collector.record(sourceFileScope->SF);
  return collector.declContexts;
}

bool ASTSourceFileScope::crossCheckWithAST() {
  return scopeCreator->containsAllDeclContextsFromAST();
}

void ast_scope::simple_display(llvm::raw_ostream &out,
                               const ScopeCreator *scopeCreator) {
  scopeCreator->print(out);
}

//----------------------------------------------------------------------------//
// ExpandASTScopeRequest computation.
//----------------------------------------------------------------------------//

bool ExpandASTScopeRequest::isCached() const {
  ASTScopeImpl *scope = std::get<0>(getStorage());
  ScopeCreator *scopeCreator = std::get<1>(getStorage());
  return !scope->isExpansionNeeded(*scopeCreator);
}

Optional<ASTScopeImpl *> ExpandASTScopeRequest::getCachedResult() const {
  return std::get<0>(getStorage());
}
