//===--- MiscDiagnostics.cpp - AST-Level Diagnostics ----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 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 AST-level diagnostics.
//
//===----------------------------------------------------------------------===//

#include "MiscDiagnostics.h"
#include "TypeCheckAvailability.h"
#include "TypeCheckConcurrency.h"
#include "TypeChecker.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/NameLookupRequests.h"
#include "swift/AST/Pattern.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/Statistic.h"
#include "swift/Basic/StringExtras.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/Parser.h"
#include "swift/Sema/ConstraintSystem.h"
#include "swift/Sema/IDETypeChecking.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/SaveAndRestore.h"

#define DEBUG_TYPE "Sema"
using namespace swift;
using namespace constraints;

/// Return true if this expression is an implicit promotion from T to T?.
static Expr *isImplicitPromotionToOptional(Expr *E) {
  if (E->isImplicit())
    if (auto IIOE = dyn_cast<InjectIntoOptionalExpr>(
                                               E->getSemanticsProvidingExpr()))
      return IIOE->getSubExpr();
  return nullptr;
}

/// Diagnose syntactic restrictions of expressions.
///
///   - Module values may only occur as part of qualification.
///   - Metatype names cannot generally be used as values: they need a "T.self"
///     qualification unless used in narrow case (e.g. T() for construction).
///   - '_' may only exist on the LHS of an assignment expression.
///   - warn_unqualified_access values must not be accessed except via qualified
///     lookup.
///   - Partial application of some decls isn't allowed due to implementation
///     limitations.
///   - "&" (aka InOutExpressions) may only exist directly in function call
///     argument lists.
///   - 'self.init' and 'super.init' cannot be wrapped in a larger expression
///     or statement.
///   - Warn about promotions to optional in specific syntactic forms.
///   - Error about collection literals that default to Any collections in
///     invalid positions.
///
static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
                                         bool isExprStmt) {
  class DiagnoseWalker : public ASTWalker {
    SmallPtrSet<Expr*, 4> AlreadyDiagnosedMetatypes;
    SmallPtrSet<DeclRefExpr*, 4> AlreadyDiagnosedBitCasts;

    /// Keep track of the arguments to CallExprs.
    SmallPtrSet<Expr *, 2> CallArgs;

    bool IsExprStmt;

  public:
    ASTContext &Ctx;
    const DeclContext *DC;

    DiagnoseWalker(const DeclContext *DC, bool isExprStmt)
      : IsExprStmt(isExprStmt), Ctx(DC->getASTContext()), DC(DC) {}

    std::pair<bool, Pattern*> walkToPatternPre(Pattern *P) override {
      return { false, P };
    }

    bool walkToDeclPre(Decl *D) override {
      if (auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext()))
        return !closure->isSeparatelyTypeChecked();
      return false;
    }

    bool walkToTypeReprPre(TypeRepr *T) override { return true; }

    bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override {
      return false;
    }

    bool shouldWalkCaptureInitializerExpressions() override { return true; }

    bool shouldWalkIntoTapExpression() override { return false; }

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      // See through implicit conversions of the expression.  We want to be able
      // to associate the parent of this expression with the ultimate callee.
      auto Base = E;
      while (auto Conv = dyn_cast<ImplicitConversionExpr>(Base))
        Base = Conv->getSubExpr();

      if (auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
        // Verify metatype uses.
        if (isa<TypeDecl>(DRE->getDecl())) {
          if (isa<ModuleDecl>(DRE->getDecl()))
            checkUseOfModule(DRE);
          else
            checkUseOfMetaTypeName(Base);
        }

        // Verify warn_unqualified_access uses.
        checkUnqualifiedAccessUse(DRE);
        
        // Verify that special decls are eliminated.
        checkForDeclWithSpecialTypeCheckingSemantics(DRE);
        
        // Verify that `unsafeBitCast` isn't misused.
        checkForSuspiciousBitCasts(DRE, nullptr);
      }
      if (auto *MRE = dyn_cast<MemberRefExpr>(Base)) {
        if (isa<TypeDecl>(MRE->getMember().getDecl()))
          checkUseOfMetaTypeName(Base);
      }
      if (isa<TypeExpr>(Base))
        checkUseOfMetaTypeName(Base);

      if (auto *OLE = dyn_cast<ObjectLiteralExpr>(E)) {
        CallArgs.insert(OLE->getArg());
      }

      if (auto *SE = dyn_cast<SubscriptExpr>(E))
        CallArgs.insert(SE->getIndex());

      if (auto *DSE = dyn_cast<DynamicSubscriptExpr>(E))
        CallArgs.insert(DSE->getIndex());

      if (auto *KPE = dyn_cast<KeyPathExpr>(E)) {
        for (auto Comp : KPE->getComponents()) {
          if (auto *Arg = Comp.getIndexExpr())
            CallArgs.insert(Arg);
        }
      }

      // Check function calls, looking through implicit conversions on the
      // function and inspecting the arguments directly.
      if (auto *Call = dyn_cast<ApplyExpr>(E)) {
        // Record call arguments.
        CallArgs.insert(Call->getArg());

        // Warn about surprising implicit optional promotions.
        checkOptionalPromotions(Call);
        
        // Check the callee, looking through implicit conversions.
        auto base = Call->getFn();
        unsigned uncurryLevel = 0;
        while (auto conv = dyn_cast<ImplicitConversionExpr>(base))
          base = conv->getSubExpr();

        const auto findDynamicMemberRefExpr =
            [](Expr *e) -> DynamicMemberRefExpr* {
          if (auto open = dyn_cast<OpenExistentialExpr>(e)) {
            return dyn_cast<DynamicMemberRefExpr>(open->getSubExpr());
          }
          return nullptr;
        };

        if (auto force = dyn_cast<ForceValueExpr>(base)) {
          if (auto ref = findDynamicMemberRefExpr(force->getSubExpr()))
            base = ref;
        } else if (auto bind = dyn_cast<BindOptionalExpr>(base)) {
          if (auto ref = findDynamicMemberRefExpr(bind->getSubExpr()))
            base = ref;
        }

        while (auto ignoredBase = dyn_cast<DotSyntaxBaseIgnoredExpr>(base))
          base = ignoredBase->getRHS();

        ConcreteDeclRef callee;
        if (auto *calleeDRE = dyn_cast<DeclRefExpr>(base)) {
          checkForSuspiciousBitCasts(calleeDRE, Call);
          callee = calleeDRE->getDeclRef();

        // Otherwise, try to drill down through member calls for the purposes
        // of argument-matching code below.
        } else if (auto selfApply = dyn_cast<SelfApplyExpr>(base)) {
          ++uncurryLevel;
          base = selfApply->getSemanticFn();
          if (auto calleeDRE = dyn_cast<DeclRefExpr>(base))
            callee = calleeDRE->getDeclRef();

        // Otherwise, check for a dynamic member.
        } else if (auto dynamicMRE = dyn_cast<DynamicMemberRefExpr>(base)) {
          ++uncurryLevel;
          callee = dynamicMRE->getMember();
        }

        if (callee) {
          visitArguments(Call, [&](unsigned argIndex, Expr *arg) {
            checkMagicIdentifierMismatch(callee, uncurryLevel, argIndex, arg);

            // InOutExprs can be wrapped in some implicit casts.
            Expr *unwrapped = arg;
            if (auto *IIO = dyn_cast<InjectIntoOptionalExpr>(arg))
              unwrapped = IIO->getSubExpr();

            if (isa<InOutToPointerExpr>(unwrapped) ||
                isa<ArrayToPointerExpr>(unwrapped) ||
                isa<ErasureExpr>(unwrapped)) {
              auto operand =
                cast<ImplicitConversionExpr>(unwrapped)->getSubExpr();
              if (auto *IOE = dyn_cast<InOutExpr>(operand))
                operand = IOE->getSubExpr();

              // Also do some additional work based on how the function uses
              // the argument.
              checkConvertedPointerArgument(callee, uncurryLevel, argIndex,
                                            unwrapped, operand);
            }
          });
        }
      }

      // If we have an assignment expression, scout ahead for acceptable _'s.
      if (auto *AE = dyn_cast<AssignExpr>(E)) {
        auto destExpr = AE->getDest();
        // If the user is assigning the result of a function that returns
        // Void to _ then warn, because that is redundant.
        if (auto DAE = dyn_cast<DiscardAssignmentExpr>(destExpr)) {
          if (auto CE = dyn_cast<CallExpr>(AE->getSrc())) {
            if (CE->getCalledValue() && isa<FuncDecl>(CE->getCalledValue()) &&
                CE->getType()->isVoid()) {
              Ctx.Diags
                  .diagnose(DAE->getLoc(),
                            diag::discard_expr_void_result_redundant)
                  .fixItRemoveChars(DAE->getStartLoc(),
                                    AE->getSrc()->getStartLoc());
            }
          }
        }
      }

      // Diagnose 'self.init' or 'super.init' nested in another expression
      // or closure.
      if (auto *rebindSelfExpr = dyn_cast<RebindSelfInConstructorExpr>(E)) {
        if (!Parent.isNull() || !IsExprStmt || DC->getParent()->isLocalContext()) {
          bool isChainToSuper;
          (void)rebindSelfExpr->getCalledConstructor(isChainToSuper);
          Ctx.Diags.diagnose(E->getLoc(), diag::init_delegation_nested,
                             isChainToSuper, !IsExprStmt);
        }
      }

      // Diagnose single-element tuple expressions.
      if (auto *tupleExpr = dyn_cast<TupleExpr>(E)) {
        if (!CallArgs.count(tupleExpr)) {
          if (tupleExpr->getNumElements() == 1) {
            Ctx.Diags.diagnose(tupleExpr->getElementNameLoc(0),
                               diag::tuple_single_element)
              .fixItRemoveChars(tupleExpr->getElementNameLoc(0),
                                tupleExpr->getElement(0)->getStartLoc());
          }
        }
      }

      // Diagnose tuple expressions with duplicate element label
      if (auto *tupleExpr = dyn_cast<TupleExpr>(E)) {
        // FIXME: Duplicate labels on enum payloads should be diagnosed
        // when declared, not when called.
        bool isEnumCase = false;
        if (auto CE = dyn_cast_or_null<CallExpr>(Parent.getAsExpr())) {
          auto calledValue = CE->getCalledValue();
          if (calledValue) {
            isEnumCase = isa<EnumElementDecl>(calledValue);
          }
        }

        if ((!CallArgs.count(tupleExpr)) || isEnumCase) {
          auto diagnose = false;

          llvm::SmallDenseSet<Identifier> names;
          names.reserve(tupleExpr->getNumElements());

          for (auto name : tupleExpr->getElementNames()) {
            if (name.empty())
              continue;

            if (names.count(name) == 1) {
              diagnose = true;
              break;
            }

            names.insert(name);
          }

          if (diagnose) {
            Ctx.Diags.diagnose(tupleExpr->getLoc(),
                               diag::tuple_duplicate_label);
          }
        }
      }

      return { true, E };
    }

    /// Visit the argument/s represented by either a ParenExpr or TupleExpr,
    /// unshuffling if needed. If any other kind of expression, will pass it
    /// straight back.
    static void argExprVisitArguments(Expr* arg,
                                      llvm::function_ref
                                        <void(unsigned, Expr*)> fn) {
      // The argument is either a ParenExpr or TupleExpr.
      if (auto *TE = dyn_cast<TupleExpr>(arg)) {
        auto elts = TE->getElements();
        for (auto i : indices(elts))
          fn(i, elts[i]);
      } else if (auto *PE = dyn_cast<ParenExpr>(arg)) {
        fn(0, PE->getSubExpr());
      } else {
        fn(0, arg);
      }
    }

    static void visitArguments(ApplyExpr *apply,
                               llvm::function_ref<void(unsigned, Expr*)> fn) {
      auto *arg = apply->getArg();
      argExprVisitArguments(arg, fn);
    }

    static Expr *lookThroughArgument(Expr *arg) {
      while (1) {
        if (auto conv = dyn_cast<ImplicitConversionExpr>(arg))
          arg = conv->getSubExpr();
        else if (auto *PE = dyn_cast<ParenExpr>(arg))
          arg = PE->getSubExpr();
        else
          break;
      }
      return arg;
    }

    void checkConvertedPointerArgument(ConcreteDeclRef callee,
                                       unsigned uncurryLevel,
                                       unsigned argIndex,
                                       Expr *pointerExpr,
                                       Expr *storage) {
      if (!isPointerIdentityArgument(callee, uncurryLevel, argIndex))
        return;

      // Flag that the argument is non-accessing.
      if (auto inout = dyn_cast<InOutToPointerExpr>(pointerExpr)) {
        inout->setNonAccessing(true);
      } else if (auto array = dyn_cast<ArrayToPointerExpr>(pointerExpr)) {
        array->setNonAccessing(true);
      }

      // TODO: warn if taking the address of 'storage' will definitely
      // yield a temporary address.
    }

    /// Is the given call argument, known to be of pointer type, just used
    /// for its pointer identity?
    bool isPointerIdentityArgument(ConcreteDeclRef ref, unsigned uncurryLevel,
                                   unsigned argIndex) {
      // FIXME: derive this from an attribute instead of hacking it based
      // on the target name!
      auto decl = ref.getDecl();

      // Assume that == and != are non-accessing uses.
      if (decl->isOperator()) {
        auto op = decl->getBaseName();
        if (op == "==" || op == "!=")
          return true;
        return false;
      }

      // NSObject.addObserver(_:forKeyPath:options:context:)
      if (uncurryLevel == 1 && argIndex == 3) {
        return decl->getName().isCompoundName("addObserver",
                                              { "", "forKeyPath",
                                                "options", "context" });
      }

      // NSObject.removeObserver(_:forKeyPath:context:)
      if (uncurryLevel == 1 && argIndex == 2) {
        return decl->getName().isCompoundName("removeObserver",
                                              { "", "forKeyPath", "context" });
      }

      return false;
    }

    /// We have a collection literal with a defaulted type, e.g. of [Any].  Emit
    /// an error if it was inferred to this type in an invalid context, which is
    /// one in which the parent expression is not itself a collection literal.
    void checkTypeDefaultedCollectionExpr(CollectionExpr *c) {
      // If the parent is a non-expression, or is not itself a literal, then
      // produce an error with a fixit to add the type as an explicit
      // annotation.
      if (c->getNumElements() == 0)
        Ctx.Diags.diagnose(c->getLoc(), diag::collection_literal_empty)
          .highlight(c->getSourceRange());
      else {
        assert(c->getType()->hasTypeRepr() &&
               "a defaulted type should always be printable");
        Ctx.Diags.diagnose(c->getLoc(), diag::collection_literal_heterogeneous,
                           c->getType())
          .highlight(c->getSourceRange())
          .fixItInsertAfter(c->getEndLoc(), " as " + c->getType()->getString());
      }
    }

    void checkMagicIdentifierMismatch(ConcreteDeclRef callee,
                                      unsigned uncurryLevel,
                                      unsigned argIndex,
                                      Expr *arg) {
      // We only care about args in the arg list.
      if (uncurryLevel != (callee.getDecl()->hasCurriedSelf() ? 1 : 0))
        return;

      // Get underlying params for both callee and caller, if declared.
      auto *calleeParam = getParameterAt(callee.getDecl(), argIndex);
      auto *callerParam = dyn_cast_or_null<ParamDecl>(
          arg->getReferencedDecl(/*stopAtParenExpr=*/true).getDecl()
      );

      // (Otherwise, we don't need to do anything.)
      if (!calleeParam || !callerParam)
        return;

      auto calleeDefaultArg = getMagicIdentifierDefaultArgKind(calleeParam);
      auto callerDefaultArg = getMagicIdentifierDefaultArgKind(callerParam);

      // If one of the parameters doesn't have a default arg, or they're both
      // compatible, everything's fine.
      if (!calleeDefaultArg || !callerDefaultArg ||
          areMagicIdentifiersCompatible(*calleeDefaultArg, *callerDefaultArg))
        return;

      StringRef calleeDefaultArgString =
          MagicIdentifierLiteralExpr::getKindString(*calleeDefaultArg);
      StringRef callerDefaultArgString =
          MagicIdentifierLiteralExpr::getKindString(*callerDefaultArg);

      // Emit main warning
      Ctx.Diags.diagnose(arg->getLoc(), diag::default_magic_identifier_mismatch,
                         callerParam->getName(), callerDefaultArgString,
                         calleeParam->getName(), calleeDefaultArgString);

      // Add "change caller default arg" fixit
      SourceLoc callerDefaultArgLoc =
          callerParam->getStructuralDefaultExpr()->getLoc();
      Ctx.Diags.diagnose(callerDefaultArgLoc,
                         diag::change_caller_default_to_match_callee,
                         callerParam->getName(), calleeDefaultArgString)
        .fixItReplace(callerDefaultArgLoc, calleeDefaultArgString);

      // Add "silence with parens" fixit
      Ctx.Diags.diagnose(arg->getLoc(),
                         diag::silence_default_magic_identifier_mismatch)
        .fixItInsert(arg->getStartLoc(), "(")
        .fixItInsertAfter(arg->getEndLoc(), ")");

      // Point to callee parameter
      Ctx.Diags.diagnose(calleeParam, diag::decl_declared_here,
                         calleeParam->getName());
    }

    Optional<MagicIdentifierLiteralExpr::Kind>
    getMagicIdentifierDefaultArgKind(const ParamDecl *param) {
      switch (param->getDefaultArgumentKind()) {
#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
      case DefaultArgumentKind::NAME: \
        return MagicIdentifierLiteralExpr::Kind::NAME;
#include "swift/AST/MagicIdentifierKinds.def"

      case DefaultArgumentKind::None:
      case DefaultArgumentKind::Normal:
      case DefaultArgumentKind::Inherited:
      case DefaultArgumentKind::NilLiteral:
      case DefaultArgumentKind::EmptyArray:
      case DefaultArgumentKind::EmptyDictionary:
      case DefaultArgumentKind::StoredProperty:
        return None;
      }

      llvm_unreachable("Unhandled DefaultArgumentKind in "
                       "getMagicIdentifierDefaultArgKind");
    }

    static bool
    areMagicIdentifiersCompatible(MagicIdentifierLiteralExpr::Kind a,
                                  MagicIdentifierLiteralExpr::Kind b) {
      if (a == b)
        return true;

      // The rest of this handles special compatibility rules between the
      // `*SpelledAsFile` cases and various other File-related cases.
      //
      // The way we're going to do this is a bit magical. We will arrange the
      // cases in MagicIdentifierLiteralExpr::Kind so that that they sort in
      // this order:
      //
      //     #fileID < Swift 6 #file < #filePath < Swift 5 #file < others
      //
      // Before we continue, let's verify that this holds.

      using Kind = MagicIdentifierLiteralExpr::Kind;

      static_assert(Kind::FileID < Kind::FileIDSpelledAsFile,
                    "#fileID < Swift 6 #file");
      static_assert(Kind::FileIDSpelledAsFile < Kind::FilePath,
                    "Swift 6 #file < #filePath");
      static_assert(Kind::FilePath < Kind::FilePathSpelledAsFile,
                    "#filePath < Swift 5 #file");

      static_assert(Kind::FilePathSpelledAsFile < Kind::Line,
                    "Swift 5 #file < #line");
      static_assert(Kind::FilePathSpelledAsFile < Kind::Column,
                    "Swift 5 #file < #column");
      static_assert(Kind::FilePathSpelledAsFile < Kind::Function,
                    "Swift 5 #file < #function");
      static_assert(Kind::FilePathSpelledAsFile < Kind::DSOHandle,
                    "Swift 5 #file < #dsohandle");

      // The rules are all commutative, so we will take the greater of the two
      // kinds.
      auto maxKind = std::max(a, b);

      // Both Swift 6 #file and Swift 5 #file are greater than all of the cases
      // they're compatible with. So if `maxCase` is one of those two, the other
      // case must have been compatible with it!
      return maxKind == Kind::FileIDSpelledAsFile ||
             maxKind == Kind::FilePathSpelledAsFile;
    }

    void checkUseOfModule(DeclRefExpr *E) {
      // Allow module values as a part of:
      // - ignored base expressions;
      // - expressions that failed to type check.
      if (auto *ParentExpr = Parent.getAsExpr()) {
        if (isa<DotSyntaxBaseIgnoredExpr>(ParentExpr) ||
            isa<UnresolvedDotExpr>(ParentExpr))
          return;
      }

      Ctx.Diags.diagnose(E->getStartLoc(), diag::value_of_module_type);
    }

    // Diagnose metatype values that don't appear as part of a property,
    // method, or constructor reference.
    void checkUseOfMetaTypeName(Expr *E) {
      // If we've already checked this at a higher level, we're done.
      if (!AlreadyDiagnosedMetatypes.insert(E).second)
        return;

      // Allow references to types as a part of:
      // - member references T.foo, T.Type, T.self, etc.
      // - constructor calls T()
      // - Subscripts T[]
      if (auto *ParentExpr = Parent.getAsExpr()) {
        // This is an exhaustive list of the accepted syntactic forms.
        if (isa<ErrorExpr>(ParentExpr) ||
            isa<DotSelfExpr>(ParentExpr) ||               // T.self
            isa<CallExpr>(ParentExpr) ||                  // T()
            isa<MemberRefExpr>(ParentExpr) ||             // T.foo
            isa<UnresolvedMemberExpr>(ParentExpr) ||
            isa<SelfApplyExpr>(ParentExpr) ||             // T.foo()  T()
            isa<UnresolvedDotExpr>(ParentExpr) ||
            isa<DotSyntaxBaseIgnoredExpr>(ParentExpr) ||
            isa<UnresolvedSpecializeExpr>(ParentExpr) ||
            isa<OpenExistentialExpr>(ParentExpr) ||
            isa<SubscriptExpr>(ParentExpr)) {
          return;
        }
      }

      // Is this a protocol metatype?

      Ctx.Diags.diagnose(E->getStartLoc(), diag::value_of_metatype_type);

      // Add fix-it to insert '()', only if this is a metatype of
      // non-existential type and has any initializers.
      bool isExistential = false;
      if (auto metaTy = E->getType()->getAs<MetatypeType>()) {
        auto instanceTy = metaTy->getInstanceType();
        isExistential = instanceTy->isExistentialType();
        if (!isExistential &&
            instanceTy->mayHaveMembers() &&
            !TypeChecker::lookupMember(const_cast<DeclContext *>(DC), instanceTy,
                                       DeclNameRef::createConstructor()).empty()) {
          Ctx.Diags.diagnose(E->getEndLoc(), diag::add_parens_to_type)
            .fixItInsertAfter(E->getEndLoc(), "()");
        }
      }

      // Add fix-it to insert ".self".
      auto diag = Ctx.Diags.diagnose(E->getEndLoc(), diag::add_self_to_type);
      if (E->canAppendPostfixExpression()) {
        diag.fixItInsertAfter(E->getEndLoc(), ".self");
      } else {
        diag.fixItInsert(E->getStartLoc(), "(");
        diag.fixItInsertAfter(E->getEndLoc(), ").self");
      }
    }

    void checkUnqualifiedAccessUse(const DeclRefExpr *DRE) {
      const Decl *D = DRE->getDecl();
      if (!D->getAttrs().hasAttribute<WarnUnqualifiedAccessAttr>())
        return;

      if (auto *parentExpr = Parent.getAsExpr()) {
        if (auto *ignoredBase = dyn_cast<DotSyntaxBaseIgnoredExpr>(parentExpr)){
          if (!ignoredBase->isImplicit())
            return;
        }
        if (auto *calledBase = dyn_cast<DotSyntaxCallExpr>(parentExpr)) {
          if (!calledBase->isImplicit())
            return;
        }
      }

      const auto *VD = cast<ValueDecl>(D);
      const TypeDecl *declParent =
          VD->getDeclContext()->getSelfNominalTypeDecl();
      if (!declParent) {
        // If the declaration has been validated but not fully type-checked,
        // the attribute might be applied to something invalid.
        if (!VD->getDeclContext()->isModuleScopeContext())
          return;
        declParent = VD->getDeclContext()->getParentModule();
      }

      Ctx.Diags.diagnose(DRE->getLoc(), diag::warn_unqualified_access,
                         VD->getBaseIdentifier(),
                         VD->getDescriptiveKind(),
                         declParent->getDescriptiveKind(),
                         declParent->getName());
      Ctx.Diags.diagnose(VD, diag::decl_declared_here, VD->getName());

      if (VD->getDeclContext()->isTypeContext()) {
        Ctx.Diags.diagnose(DRE->getLoc(), diag::fix_unqualified_access_member)
          .fixItInsert(DRE->getStartLoc(), "self.");
      }

      DeclContext *topLevelSubcontext = DC->getModuleScopeContext();
      auto descriptor = UnqualifiedLookupDescriptor(
          DeclNameRef(VD->getBaseName()), topLevelSubcontext, SourceLoc());
      auto lookup = evaluateOrDefault(Ctx.evaluator,
                                      UnqualifiedLookupRequest{descriptor}, {});

      // Group results by module. Pick an arbitrary result from each module.
      llvm::SmallDenseMap<const ModuleDecl*,const ValueDecl*,4> resultsByModule;
      for (auto &result : lookup) {
        const ValueDecl *value = result.getValueDecl();
        resultsByModule.insert(std::make_pair(value->getModuleContext(),value));
      }

      // Sort by module name.
      using ModuleValuePair = std::pair<const ModuleDecl *, const ValueDecl *>;
      SmallVector<ModuleValuePair, 4> sortedResults{
        resultsByModule.begin(), resultsByModule.end()
      };
      llvm::array_pod_sort(sortedResults.begin(), sortedResults.end(),
                           [](const ModuleValuePair *lhs,
                              const ModuleValuePair *rhs) {
        return lhs->first->getName().compare(rhs->first->getName());
      });

      auto topLevelDiag = diag::fix_unqualified_access_top_level;
      if (sortedResults.size() > 1)
        topLevelDiag = diag::fix_unqualified_access_top_level_multi;

      for (const ModuleValuePair &pair : sortedResults) {
        DescriptiveDeclKind k = pair.second->getDescriptiveKind();

        SmallString<32> namePlusDot = pair.first->getName().str();
        namePlusDot.push_back('.');

        Ctx.Diags.diagnose(DRE->getLoc(), topLevelDiag,
                           namePlusDot, k, pair.first->getName())
          .fixItInsert(DRE->getStartLoc(), namePlusDot);
      }
    }
    
    void checkForDeclWithSpecialTypeCheckingSemantics(const DeclRefExpr *DRE) {
      // Referencing type(of:) and other decls with special type-checking
      // behavior as functions is not implemented. Maybe we could wrap up the
      // special-case behavior in a closure someday...
      if (TypeChecker::getDeclTypeCheckingSemantics(DRE->getDecl())
            != DeclTypeCheckingSemantics::Normal) {
        Ctx.Diags.diagnose(DRE->getLoc(), diag::unsupported_special_decl_ref,
                           DRE->getDecl()->getBaseIdentifier());
      }
    }
    
    enum BitcastableNumberKind {
      BNK_None = 0,
      BNK_Int8,
      BNK_Int16,
      BNK_Int32,
      BNK_Int64,
      BNK_Int,
      BNK_UInt8,
      BNK_UInt16,
      BNK_UInt32,
      BNK_UInt64,
      BNK_UInt,
      BNK_Float,
      BNK_Double,
    };
    BitcastableNumberKind getBitcastableNumberKind(Type t) const {
      auto decl = t->getNominalOrBoundGenericNominal();
#define MATCH_DECL(type) \
      if (decl == Ctx.get##type##Decl()) \
        return BNK_##type;
      MATCH_DECL(Int8)
      MATCH_DECL(Int16)
      MATCH_DECL(Int32)
      MATCH_DECL(Int64)
      MATCH_DECL(Int)
      MATCH_DECL(UInt8)
      MATCH_DECL(UInt16)
      MATCH_DECL(UInt32)
      MATCH_DECL(UInt64)
      MATCH_DECL(UInt)
      MATCH_DECL(Float)
      MATCH_DECL(Double)
#undef MATCH_DECL
      
      return BNK_None;
    }
    
    static constexpr unsigned BNKPair(BitcastableNumberKind a,
                                      BitcastableNumberKind b) {
      return (a << 8) | b;
    }
    
    void checkForSuspiciousBitCasts(DeclRefExpr *DRE,
                                    Expr *Parent = nullptr) {
      if (DRE->getDecl() != Ctx.getUnsafeBitCast())
        return;
      
      if (DRE->getDeclRef().getSubstitutions().empty())
        return;
      
      // Don't check the same use of unsafeBitCast twice.
      if (!AlreadyDiagnosedBitCasts.insert(DRE).second)
        return;

      auto subMap = DRE->getDeclRef().getSubstitutions();
      auto fromTy = subMap.getReplacementTypes()[0];
      auto toTy = subMap.getReplacementTypes()[1];

      // Warn about `unsafeBitCast` formulations that are undefined behavior
      // or have better-defined alternative APIs that can be used instead.
      
      // If we have a parent ApplyExpr that calls bitcast, extract the argument
      // for fixits.
      Expr *subExpr = nullptr;
      CharSourceRange removeBeforeRange, removeAfterRange;
      if (auto apply = dyn_cast_or_null<ApplyExpr>(Parent)) {
        if (auto args = dyn_cast<TupleExpr>(apply->getArg())) {
          subExpr = args->getElement(0);
          // Determine the fixit range from the start of the application to
          // the first argument, `unsafeBitCast(`
          removeBeforeRange = CharSourceRange(Ctx.SourceMgr, DRE->getLoc(),
                                              subExpr->getStartLoc());
          // Determine the fixit range from the end of the first argument to
          // the end of the application, `, to: T.self)`
          removeAfterRange = CharSourceRange(Ctx.SourceMgr,
                         Lexer::getLocForEndOfToken(Ctx.SourceMgr,
                                                    subExpr->getEndLoc()),
                         Lexer::getLocForEndOfToken(Ctx.SourceMgr,
                                                    apply->getEndLoc()));          
        }
      }
  
      // Casting to the same type or a superclass is a no-op.
      if (toTy->isEqual(fromTy) ||
          toTy->isExactSuperclassOf(fromTy)) {
        auto d = Ctx.Diags.diagnose(DRE->getLoc(), diag::bitcasting_is_no_op,
                                    fromTy, toTy);
        if (subExpr) {
          d.fixItRemoveChars(removeBeforeRange.getStart(),
                             removeBeforeRange.getEnd())
           .fixItRemoveChars(removeAfterRange.getStart(),
                             removeAfterRange.getEnd());
        }
        return;
      }
      
     if (auto fromFnTy = fromTy->getAs<FunctionType>()) {
        if (auto toFnTy = toTy->getAs<FunctionType>()) {
          // Casting a nonescaping function to escaping is UB.
          // `withoutActuallyEscaping` ought to be used instead.
          if (fromFnTy->isNoEscape() && !toFnTy->isNoEscape()) {
            Ctx.Diags.diagnose(DRE->getLoc(), diag::bitcasting_away_noescape,
                               fromTy, toTy);
          }
          // Changing function representation (say, to try to force a
          // @convention(c) function pointer to exist) is also unlikely to work.
          if (fromFnTy->getRepresentation() != toFnTy->getRepresentation()) {
            Ctx.Diags.diagnose(DRE->getLoc(),
                               diag::bitcasting_to_change_function_rep, fromTy,
                               toTy);
          }
          return;
        }
      }
      
      // Unchecked casting to a subclass is better done by unsafeDowncast.
      if (fromTy->isBindableToSuperclassOf(toTy)) {
        Ctx.Diags.diagnose(DRE->getLoc(), diag::bitcasting_to_downcast,
                           fromTy, toTy)
          .fixItReplace(DRE->getNameLoc().getBaseNameLoc(),
                        "unsafeDowncast");
        return;
      }

      // Casting among pointer types should use the Unsafe*Pointer APIs for
      // rebinding typed memory or accessing raw memory instead.
      PointerTypeKind fromPTK, toPTK;
      Type fromPointee = fromTy->getAnyPointerElementType(fromPTK);
      Type toPointee = toTy->getAnyPointerElementType(toPTK);
      if (fromPointee && toPointee) {
        // Casting to a pointer to the same type or UnsafeRawPointer can use
        // normal initializers on the destination type.
        if (toPointee->isEqual(fromPointee)
            || isRawPointerKind(toPTK)) {
          auto d = Ctx.Diags.diagnose(DRE->getLoc(),
                              diag::bitcasting_to_change_pointer_kind,
                              fromTy, toTy,
                              toTy->getStructOrBoundGenericStruct()->getName());
          if (subExpr) {
            StringRef before, after;
            switch (toPTK) {
            case PTK_UnsafePointer:
              // UnsafePointer(mutablePointer)
              before = "UnsafePointer(";
              after = ")";
              break;
            case PTK_UnsafeMutablePointer:
            case PTK_AutoreleasingUnsafeMutablePointer:
              before = "UnsafeMutablePointer(mutating: ";
              after = ")";
              break;
              
            case PTK_UnsafeRawPointer:
              // UnsafeRawPointer(pointer)
              before = "UnsafeRawPointer(";
              after = ")";
              break;
              
            case PTK_UnsafeMutableRawPointer:
              // UnsafeMutableRawPointer(mutating: rawPointer)
              before = fromPTK == PTK_UnsafeMutablePointer
                ? "UnsafeMutableRawPointer("
                : "UnsafeMutableRawPointer(mutating: ";
              after = ")";
              break;
            }
            d.fixItReplaceChars(removeBeforeRange.getStart(),
                                removeBeforeRange.getEnd(),
                                before)
             .fixItReplaceChars(removeAfterRange.getStart(),
                                removeAfterRange.getEnd(),
                                after);
          }
          return;
        }
        
        // Casting to a different typed pointer type should use
        // withMemoryRebound.
        if (!isRawPointerKind(fromPTK) && !isRawPointerKind(toPTK)) {
          Ctx.Diags.diagnose(DRE->getLoc(),
                             diag::bitcasting_to_change_pointee_type,
                             fromTy, toTy);
          return;
        }
        
        // Casting a raw pointer to a typed pointer should bind the memory
        // (or assume it's already bound).
        assert(isRawPointerKind(fromPTK) && !isRawPointerKind(toPTK)
               && "unhandled cast combo?!");
        Ctx.Diags.diagnose(DRE->getLoc(),
                           diag::bitcasting_to_give_type_to_raw_pointer,
                           fromTy, toTy);
        if (subExpr) {
          SmallString<64> fixitBuf;
          {
            llvm::raw_svector_ostream os(fixitBuf);
            os << ".assumingMemoryBound(to: ";
            toPointee->print(os);
            os << ".self)";
          }
          Ctx.Diags.diagnose(DRE->getLoc(),
                             diag::bitcast_assume_memory_rebound,
                             toPointee)
            .fixItRemoveChars(removeBeforeRange.getStart(),
                              removeBeforeRange.getEnd())
            .fixItReplaceChars(removeAfterRange.getStart(),
                               removeAfterRange.getEnd(),
                               fixitBuf);
          fixitBuf.clear();
          {
            llvm::raw_svector_ostream os(fixitBuf);
            os << ".bindMemory(to: ";
            toPointee->print(os);
            os << ".self, capacity: <""#capacity#"">)";
          }
          Ctx.Diags.diagnose(DRE->getLoc(),
                             diag::bitcast_bind_memory,
                             toPointee)
            .fixItRemoveChars(removeBeforeRange.getStart(),
                              removeBeforeRange.getEnd())
            .fixItReplaceChars(removeAfterRange.getStart(),
                               removeAfterRange.getEnd(),
                               fixitBuf);
        }
        return;
      }
      
      StringRef replaceBefore, replaceAfter;
      Optional<Diag<Type, Type>> diagID;
      SmallString<64> replaceBeforeBuf;

      // Bitcasting among numeric types should use `bitPattern:` initializers.
      auto fromBNK = getBitcastableNumberKind(fromTy);
      auto toBNK = getBitcastableNumberKind(toTy);
      if (fromBNK && toBNK) {
        switch (BNKPair(fromBNK, toBNK)) {
        // Combos that can be bitPattern-ed with a constructor
        case BNKPair(BNK_Int8, BNK_UInt8):
        case BNKPair(BNK_UInt8, BNK_Int8):
        case BNKPair(BNK_Int16, BNK_UInt16):
        case BNKPair(BNK_UInt16, BNK_Int16):
        case BNKPair(BNK_Int32, BNK_UInt32):
        case BNKPair(BNK_UInt32, BNK_Int32):
        case BNKPair(BNK_Int64, BNK_UInt64):
        case BNKPair(BNK_UInt64, BNK_Int64):
        case BNKPair(BNK_Int, BNK_UInt):
        case BNKPair(BNK_UInt, BNK_Int):
        case BNKPair(BNK_UInt32, BNK_Float):
        case BNKPair(BNK_UInt64, BNK_Double):
          diagID = diag::bitcasting_for_number_bit_pattern_init;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(bitPattern: ";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = ")";
          break;
        
        // Combos that can be bitPattern-ed with a constructor and sign flip
        case BNKPair(BNK_Int32, BNK_Float):
        case BNKPair(BNK_Int64, BNK_Double):
          diagID = diag::bitcasting_for_number_bit_pattern_init;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(bitPattern: ";
            if (fromBNK == BNK_Int32)
              os << "UInt32(bitPattern: ";
            else
              os << "UInt64(bitPattern: ";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = "))";
          break;
        
        // Combos that can be bitPattern-ed with a property
        case BNKPair(BNK_Float, BNK_UInt32):
        case BNKPair(BNK_Double, BNK_UInt64):
          diagID = diag::bitcasting_for_number_bit_pattern_property;
          replaceAfter = ".bitPattern";
          break;
        
        // Combos that can be bitPattern-ed with a property and sign flip
        case BNKPair(BNK_Float, BNK_Int32):
        case BNKPair(BNK_Double, BNK_Int64):
          diagID = diag::bitcasting_for_number_bit_pattern_property;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(bitPattern: ";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = ")";
          break;

        // Combos that can be bitPattern-ed with a constructor once (U)Int is
        // converted to a sized type.
        case BNKPair(BNK_UInt, BNK_Float):
        case BNKPair(BNK_Int, BNK_UInt32):
        case BNKPair(BNK_UInt, BNK_Int32):
        case BNKPair(BNK_Int, BNK_UInt64):
        case BNKPair(BNK_UInt, BNK_Int64):
        case BNKPair(BNK_UInt, BNK_Double):
          diagID = diag::bitcasting_for_number_bit_pattern_init;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(bitPattern: ";
            
            if (fromBNK == BNK_Int)
              os << "Int";
            else
              os << "UInt";
            
            if (toBNK == BNK_Float
                || toBNK == BNK_Int32
                || toBNK == BNK_UInt32)
              os << "32(";
            else
              os << "64(";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = "))";
          break;

        case BNKPair(BNK_Int, BNK_Float):
        case BNKPair(BNK_Int, BNK_Double):
          diagID = diag::bitcasting_for_number_bit_pattern_init;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(bitPattern: UInt";
            
            if (toBNK == BNK_Float
                || toBNK == BNK_Int32
                || toBNK == BNK_UInt32)
              os << "32(bitPattern: Int32(";
            else
              os << "64(bitPattern: Int64(";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = ")))";
          break;
    
        // Combos that can be bitPattern-ed then converted from a sized type
        // to (U)Int.
        case BNKPair(BNK_Int32, BNK_UInt):
        case BNKPair(BNK_UInt32, BNK_Int):
        case BNKPair(BNK_Int64, BNK_UInt):
        case BNKPair(BNK_UInt64, BNK_Int):
          diagID = diag::bitcasting_for_number_bit_pattern_init;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(";
            if (toBNK == BNK_UInt)
              os << "UInt";
            else
              os << "Int";
            if (fromBNK == BNK_Int32 || fromBNK == BNK_UInt32)
              os << "32(bitPattern: ";
            else
              os << "64(bitPattern: ";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = "))";
          break;
        
        case BNKPair(BNK_Float, BNK_UInt):
        case BNKPair(BNK_Double, BNK_UInt):
          diagID = diag::bitcasting_for_number_bit_pattern_property;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = ".bitPattern)";
          break;
          
        case BNKPair(BNK_Float, BNK_Int):
        case BNKPair(BNK_Double, BNK_Int):
          diagID = diag::bitcasting_for_number_bit_pattern_property;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(bitPattern: UInt(";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = ".bitPattern))";
          break;
        
        // Combos that should be done with a value-preserving initializer.
        case BNKPair(BNK_Int, BNK_Int32):
        case BNKPair(BNK_Int, BNK_Int64):
        case BNKPair(BNK_UInt, BNK_UInt32):
        case BNKPair(BNK_UInt, BNK_UInt64):
        case BNKPair(BNK_Int32, BNK_Int):
        case BNKPair(BNK_Int64, BNK_Int):
        case BNKPair(BNK_UInt32, BNK_UInt):
        case BNKPair(BNK_UInt64, BNK_UInt):
          diagID = diag::bitcasting_to_change_from_unsized_to_sized_int;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << '(';
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = ")";
          break;
        
        default:
          // Leave other combos alone.
          break;
        }
      }
      
      // Casting a pointer to an int or back should also use bitPattern
      // initializers.
      if (fromPointee && toBNK) {
        switch (toBNK) {
        case BNK_UInt:
        case BNK_Int:
          diagID = diag::bitcasting_for_number_bit_pattern_init;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(bitPattern: ";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = ")";
          break;
          
        case BNK_UInt64:
        case BNK_UInt32:
        case BNK_Int64:
        case BNK_Int32:
          diagID = diag::bitcasting_for_number_bit_pattern_init;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << '(';
            if (toBNK == BNK_UInt32 || toBNK == BNK_UInt64)
              os << "UInt(bitPattern: ";
            else
              os << "Int(bitPattern: ";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = "))";
          break;
        
        default:
          break;
        }
      }
      if (fromBNK && toPointee) {
        switch (fromBNK) {
        case BNK_UInt:
        case BNK_Int:
          diagID = diag::bitcasting_for_number_bit_pattern_init;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(bitPattern: ";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = ")";
          break;
          
        case BNK_UInt64:
        case BNK_UInt32:
        case BNK_Int64:
        case BNK_Int32:
          diagID = diag::bitcasting_for_number_bit_pattern_init;
          {
            llvm::raw_svector_ostream os(replaceBeforeBuf);
            toTy->print(os);
            os << "(bitPattern: ";
            if (fromBNK == BNK_Int32 || fromBNK == BNK_Int64)
              os << "Int(";
            else
              os << "UInt(";
          }
          replaceBefore = replaceBeforeBuf;
          replaceAfter = "))";
          break;

        default:
          break;
        }
      }
      
      if (diagID) {
        auto d = Ctx.Diags.diagnose(DRE->getLoc(), *diagID, fromTy, toTy);
        if (subExpr) {
          d.fixItReplaceChars(removeBeforeRange.getStart(),
                              removeBeforeRange.getEnd(),
                              replaceBefore);
          d.fixItReplaceChars(removeAfterRange.getStart(),
                              removeAfterRange.getEnd(),
                              replaceAfter);
        }
      }

    }
    
    /// Return true if this is a 'nil' literal.  This looks
    /// like this if the type is Optional<T>:
    ///
    ///   (dot_syntax_call_expr implicit type='Int?'
    ///     (declref_expr implicit decl=Optional.none)
    ///     (type_expr type=Int?))
    ///
    /// Or like this if it is any other ExpressibleByNilLiteral type:
    ///
    ///   (nil_literal_expr)
    ///
    bool isTypeCheckedOptionalNil(Expr *E) {
      if (dyn_cast<NilLiteralExpr>(E)) return true;

      auto CE = dyn_cast<ApplyExpr>(E->getSemanticsProvidingExpr());
      if (!CE || !CE->isImplicit())
        return false;

      // First case -- Optional.none
      if (auto DRE = dyn_cast<DeclRefExpr>(CE->getSemanticFn()))
        return DRE->getDecl() == Ctx.getOptionalNoneDecl();

      return false;
    }


    /// Warn about surprising implicit optional promotions involving operands to
    /// calls.  Specifically, we warn about these expressions when the 'x'
    /// operand is implicitly promoted to optional:
    ///
    ///       x ?? y
    ///       x == nil    // also !=
    ///
    void checkOptionalPromotions(ApplyExpr *call) {
      // We only care about binary expressions.
      if (!isa<BinaryExpr>(call)) return;

      // Dig out the function we're calling.
      auto fnExpr = call->getSemanticFn();
      if (auto dotSyntax = dyn_cast<DotSyntaxCallExpr>(fnExpr))
        fnExpr = dotSyntax->getSemanticFn();

      auto DRE = dyn_cast<DeclRefExpr>(fnExpr);
      auto args = dyn_cast<TupleExpr>(call->getArg());
      if (!DRE || !DRE->getDecl()->isOperator() ||
          !args || args->getNumElements() != 2)
        return;
      
      auto lhs = args->getElement(0);
      auto rhs = args->getElement(1);
      auto calleeName = DRE->getDecl()->getBaseName();

      Expr *subExpr = nullptr;
      if (calleeName == "??" &&
          (subExpr = isImplicitPromotionToOptional(lhs))) {
        Ctx.Diags.diagnose(DRE->getLoc(), diag::use_of_qq_on_non_optional_value,
                           subExpr->getType())
          .highlight(lhs->getSourceRange())
          .fixItRemove(SourceRange(DRE->getLoc(), rhs->getEndLoc()));
        return;
      }
      
      if (calleeName == "==" || calleeName == "!=" ||
          calleeName == "===" || calleeName == "!==") {
        if (((subExpr = isImplicitPromotionToOptional(lhs)) &&
             isTypeCheckedOptionalNil(rhs)) ||
            (isTypeCheckedOptionalNil(lhs) &&
             (subExpr = isImplicitPromotionToOptional(rhs)))) {
          bool isTrue = calleeName == "!=" || calleeName == "!==";
              
          Ctx.Diags.diagnose(DRE->getLoc(), diag::nonoptional_compare_to_nil,
                             subExpr->getType(), isTrue)
            .highlight(lhs->getSourceRange())
            .highlight(rhs->getSourceRange());
          return;
        }
      }
    }
  };

  DiagnoseWalker Walker(DC, isExprStmt);
  const_cast<Expr *>(E)->walk(Walker);

  // Diagnose uses of collection literals with defaulted types at the top
  // level.
  if (auto collection
        = dyn_cast<CollectionExpr>(E->getSemanticsProvidingExpr())) {
    if (collection->isTypeDefaulted()) {
      Walker.checkTypeDefaultedCollectionExpr(
        const_cast<CollectionExpr *>(collection));
    }
  }
}


/// Diagnose recursive use of properties within their own accessors
static void diagRecursivePropertyAccess(const Expr *E, const DeclContext *DC) {
  auto fn = dyn_cast<AccessorDecl>(DC);
  if (!fn)
    return;

  auto var = dyn_cast<VarDecl>(fn->getStorage());
  if (!var)  // Ignore subscripts
    return;

  class DiagnoseWalker : public ASTWalker {
    ASTContext &Ctx;
    VarDecl *Var;
    const AccessorDecl *Accessor;

  public:
    explicit DiagnoseWalker(VarDecl *var, const AccessorDecl *Accessor)
      : Ctx(var->getASTContext()), Var(var), Accessor(Accessor) {}

    /// Return true if this is an implicit reference to self.
    static bool isImplicitSelfUse(Expr *E) {
      auto *DRE = dyn_cast<DeclRefExpr>(E);
      return DRE && DRE->isImplicit() && isa<VarDecl>(DRE->getDecl()) &&
             cast<VarDecl>(DRE->getDecl())->isSelfParameter();
    }

    bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override {
      return false;
    }

    bool shouldWalkCaptureInitializerExpressions() override { return true; }

    bool shouldWalkIntoTapExpression() override { return false; }

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      Expr *subExpr;
      bool isStore = false;

      if (auto *AE = dyn_cast<AssignExpr>(E)) {
        subExpr = AE->getDest();
        
        // If we couldn't flatten this expression, don't explode.
        if (!subExpr)
          return { true, E };

        isStore = true;
      } else if (auto *IOE = dyn_cast<InOutExpr>(E)) {
        subExpr = IOE->getSubExpr();
        isStore = true;
      } else {
        subExpr = E;
      }

      if (auto *BOE = dyn_cast<BindOptionalExpr>(subExpr))
        subExpr = BOE;

      if (auto *DRE = dyn_cast<DeclRefExpr>(subExpr)) {
        if (DRE->getDecl() == Var) {
          // Handle local and top-level computed variables.
          if (DRE->getAccessSemantics() == AccessSemantics::Ordinary) {
            bool shouldDiagnose = false;
            // Warn about any property access in the getter.
            if (Accessor->isGetter())
              shouldDiagnose = !isStore;
            // Warn about stores in the setter, but allow loads.
            if (Accessor->isSetter())
              shouldDiagnose = isStore;

            // But silence the warning if the base was explicitly qualified.
            auto parentAsExpr = Parent.getAsExpr();
            if (parentAsExpr && isa<DotSyntaxBaseIgnoredExpr>(parentAsExpr))
              shouldDiagnose = false;

            if (shouldDiagnose) {
              Ctx.Diags.diagnose(subExpr->getLoc(),
                                 diag::recursive_accessor_reference,
                                 Var->getName(), Accessor->isSetter());
            }
          }
          
          // If this is a direct store in a "willSet", we reject this because
          // it is about to get overwritten.
          if (isStore &&
              DRE->getAccessSemantics() == AccessSemantics::DirectToStorage &&
              Accessor->getAccessorKind() == AccessorKind::WillSet) {
            Ctx.Diags.diagnose(E->getLoc(), diag::store_in_willset,
                               Var->getName());
          }
        }


      } else if (auto *MRE = dyn_cast<MemberRefExpr>(subExpr)) {
        // Handle instance and type computed variables.
        // Find MemberRefExprs that have an implicit "self" base.
        if (MRE->getMember().getDecl() == Var &&
            isa<DeclRefExpr>(MRE->getBase()) &&
            isImplicitSelfUse(MRE->getBase())) {
          
          if (MRE->getAccessSemantics() == AccessSemantics::Ordinary) {
            bool shouldDiagnose = false;
            // Warn about any property access in the getter.
            if (Accessor->isGetter())
              shouldDiagnose = !isStore;
            // Warn about stores in the setter, but allow loads.
            if (Accessor->isSetter())
              shouldDiagnose = isStore;

            if (shouldDiagnose) {
              Ctx.Diags.diagnose(subExpr->getLoc(),
                                 diag::recursive_accessor_reference,
                                 Var->getName(), Accessor->isSetter());
              Ctx.Diags.diagnose(subExpr->getLoc(),
                                 diag::recursive_accessor_reference_silence)
              .fixItInsert(subExpr->getStartLoc(), "self.");
            }
          }

          // If this is a direct store in a "willSet", we reject this because
          // it is about to get overwritten.
          if (isStore &&
              MRE->getAccessSemantics() == AccessSemantics::DirectToStorage &&
              Accessor->getAccessorKind() == AccessorKind::WillSet) {
            Ctx.Diags.diagnose(subExpr->getLoc(), diag::store_in_willset,
                               Var->getName());
          }
        }

      }

      return { true, E };
    }
  };

  DiagnoseWalker walker(var, fn);
  const_cast<Expr *>(E)->walk(walker);
}

/// Look for any property references in closures that lack a 'self.' qualifier.
/// Within a closure, we require that the source code contain 'self.' explicitly
/// (or that the closure explicitly capture 'self' in the capture list) because
/// 'self' is captured, not the property value.  This is a common source of
/// confusion, so we force an explicit self.
static void diagnoseImplicitSelfUseInClosure(const Expr *E,
                                             const DeclContext *DC) {
  class DiagnoseWalker : public ASTWalker {
    ASTContext &Ctx;
    SmallVector<AbstractClosureExpr *, 4> Closures;
  public:
    explicit DiagnoseWalker(ASTContext &ctx, AbstractClosureExpr *ACE)
        : Ctx(ctx), Closures() {
          if (ACE)
            Closures.push_back(ACE);
        }

    /// Return true if this is an implicit reference to self which is required
    /// to be explicit in an escaping closure. Metatype references and value
    /// type references are excluded.
    static bool isImplicitSelfParamUseLikelyToCauseCycle(Expr *E) {
      auto *DRE = dyn_cast<DeclRefExpr>(E);

      if (!DRE || !DRE->isImplicit() || !isa<VarDecl>(DRE->getDecl()) ||
          !cast<VarDecl>(DRE->getDecl())->isSelfParameter())
        return false;

      // Defensive check for type. If the expression doesn't have type here, it
      // should have been diagnosed somewhere else.
      Type ty = DRE->getType();
      assert(ty && "Implicit self parameter ref without type");
      if (!ty)
        return false;

      // Metatype self captures don't extend the lifetime of an object.
      if (ty->is<MetatypeType>())
        return false;

      // If self does not have reference semantics, it is very unlikely that
      // capturing it will create a reference cycle.
      if (!ty->hasReferenceSemantics())
        return false;

      return true;
    }

    /// Return true if this is a closure expression that will require explicit
    /// use or capture of "self." for qualification of member references.
    static bool isClosureRequiringSelfQualification(
                  const AbstractClosureExpr *CE) {
      // If the closure's type was inferred to be noescape, then it doesn't
      // need qualification.
      if (AnyFunctionRef(const_cast<AbstractClosureExpr *>(CE))
               .isKnownNoEscape())
        return false;

      if (auto autoclosure = dyn_cast<AutoClosureExpr>(CE)) {
        if (autoclosure->getThunkKind() == AutoClosureExpr::Kind::AsyncLet)
          return false;
      }

      return true;
    }


    // Don't walk into nested decls.
    bool walkToDeclPre(Decl *D) override {
      if (auto *closure = dyn_cast<ClosureExpr>(D->getDeclContext()))
        return !closure->isSeparatelyTypeChecked();
      return false;
    }

    bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override {
      return false;
    }

    bool shouldWalkCaptureInitializerExpressions() override { return true; }

    bool shouldWalkIntoTapExpression() override { return false; }

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      if (auto *CE = dyn_cast<AbstractClosureExpr>(E)) {
        // If this is a potentially-escaping closure expression, start looking
        // for references to self if we aren't already.
        if (isClosureRequiringSelfQualification(CE))
          Closures.push_back(CE);
      }

      // If we aren't in a closure, no diagnostics will be produced.
      if (Closures.size() == 0)
        return { true, E };

      auto &Diags = Ctx.Diags;
      
      // Diagnostics should correct the innermost closure
      auto *ACE = Closures[Closures.size() - 1];
      assert(ACE);
      
      SourceLoc memberLoc = SourceLoc();
      if (auto *MRE = dyn_cast<MemberRefExpr>(E))
        if (isImplicitSelfParamUseLikelyToCauseCycle(MRE->getBase())) {
          auto baseName = MRE->getMember().getDecl()->getBaseName();
          memberLoc = MRE->getLoc();
          Diags.diagnose(memberLoc,
                         diag::property_use_in_closure_without_explicit_self,
                         baseName.getIdentifier());
        }

      // Handle method calls with a specific diagnostic + fixit.
      if (auto *DSCE = dyn_cast<DotSyntaxCallExpr>(E))
        if (isImplicitSelfParamUseLikelyToCauseCycle(DSCE->getBase()) &&
            isa<DeclRefExpr>(DSCE->getFn())) {
          auto MethodExpr = cast<DeclRefExpr>(DSCE->getFn());
          memberLoc = DSCE->getLoc();
          Diags.diagnose(DSCE->getLoc(),
                         diag::method_call_in_closure_without_explicit_self,
                         MethodExpr->getDecl()->getBaseIdentifier());
        }

      if (memberLoc.isValid()) {
        emitFixIts(Diags, memberLoc, ACE);
        return { false, E };
      }
      
      // Catch any other implicit uses of self with a generic diagnostic.
      if (isImplicitSelfParamUseLikelyToCauseCycle(E))
        Diags.diagnose(E->getLoc(), diag::implicit_use_of_self_in_closure);

      return { true, E };
    }
    
    Expr *walkToExprPost(Expr *E) override {
      if (auto *CE = dyn_cast<AbstractClosureExpr>(E)) {
        if (isClosureRequiringSelfQualification(CE)) {
          assert(Closures.size() > 0);
          Closures.pop_back();
        }
      }
      
      return E;
    }

    /// Emit any fix-its for this error.
    void emitFixIts(DiagnosticEngine &Diags,
                    SourceLoc memberLoc,
                    const AbstractClosureExpr *ACE) {
      // This error can be fixed by either capturing self explicitly (if in an
      // explicit closure), or referencing self explicitly.
      if (auto *CE = dyn_cast<const ClosureExpr>(ACE)) {
        if (diagnoseAlmostMatchingCaptures(Diags, memberLoc, CE)) {
          // Bail on the rest of the diagnostics. Offering the option to
          // capture 'self' explicitly will result in an error, and using
          // 'self.' explicitly will be accessing something other than the
          // self param.
          // FIXME: We could offer a special fixit in the [weak self] case to insert 'self?.'...
          return;
        }
        emitFixItsForExplicitClosure(Diags, memberLoc, CE);
      } else {
        // If this wasn't an explicit closure, just offer the fix-it to
        // reference self explicitly.
        Diags.diagnose(memberLoc, diag::note_reference_self_explicitly)
          .fixItInsert(memberLoc, "self.");
      }
    }
    
    /// Diagnose any captures which might have been an attempt to capture
    /// \c self strongly, but do not actually enable implicit \c self. Returns
    /// whether there were any such captures to diagnose.
    bool diagnoseAlmostMatchingCaptures(DiagnosticEngine &Diags,
                                        SourceLoc memberLoc,
                                        const ClosureExpr *closureExpr) {
      // If we've already captured something with the name "self" other than
      // the actual self param, offer special diagnostics.
      if (auto *VD = closureExpr->getCapturedSelfDecl()) {
        // Either this is a weak capture of self...
        if (VD->getType()->is<WeakStorageType>()) {
          Diags.diagnose(VD->getLoc(), diag::note_self_captured_weakly);
        // ...or something completely different.
        } else {
          Diags.diagnose(VD->getLoc(), diag::note_other_self_capture);
        }
        
        return true;
      }
      return false;
    }

    /// Emit fix-its for invalid use of implicit \c self in an explicit closure.
    /// The error can be solved by capturing self explicitly,
    /// or by using \c self. explicitly.
    void emitFixItsForExplicitClosure(DiagnosticEngine &Diags,
                                      SourceLoc memberLoc,
                                      const ClosureExpr *closureExpr) {
      Diags.diagnose(memberLoc, diag::note_reference_self_explicitly)
        .fixItInsert(memberLoc, "self.");
      auto diag = Diags.diagnose(closureExpr->getLoc(),
                                 diag::note_capture_self_explicitly);
      // There are four different potential fix-its to offer based on the
      // closure signature:
      //   1. There is an existing capture list which already has some
      //      entries. We need to insert 'self' into the capture list along
      //      with a separating comma.
      //   2. There is an existing capture list, but it is empty (jusr '[]').
      //      We can just insert 'self'.
      //   3. Arguments or types are already specified in the signature,
      //      but there is no existing capture list. We will need to insert
      //      the capture list, but 'in' will already be present.
      //   4. The signature empty so far. We must insert the full capture
      //      list as well as 'in'.
      const auto brackets = closureExpr->getBracketRange();
      if (brackets.isValid()) {
        emitInsertSelfIntoCaptureListFixIt(brackets, diag);
      }
      else {
        emitInsertNewCaptureListFixIt(closureExpr, diag);
      }
    }

    /// Emit a fix-it for inserting \c self into in existing capture list, along
    /// with a trailing comma if needed. The fix-it will be attached to the
    /// provided diagnostic \c diag.
    void emitInsertSelfIntoCaptureListFixIt(SourceRange brackets,
                                            InFlightDiagnostic &diag) {
      // Look for any non-comment token. If there's anything before the
      // closing bracket, we assume that it is a valid capture list entry and
      // insert 'self,'. If it wasn't a valid entry, then we will at least not
      // be introducing any new errors/warnings...
      const auto locAfterBracket = brackets.Start.getAdvancedLoc(1);
      const auto nextAfterBracket =
          Lexer::getTokenAtLocation(Ctx.SourceMgr, locAfterBracket,
                                    CommentRetentionMode::None);
      if (nextAfterBracket.getLoc() != brackets.End)
        diag.fixItInsertAfter(brackets.Start, "self, ");
      else
        diag.fixItInsertAfter(brackets.Start, "self");
    }

    /// Emit a fix-it for inserting a capture list into a closure that does not
    /// already have one, along with a trailing \c in if necessary. The fix-it
    /// will be attached to the provided diagnostic \c diag.
    void emitInsertNewCaptureListFixIt(const ClosureExpr *closureExpr,
                                       InFlightDiagnostic &diag) {
      if (closureExpr->getInLoc().isValid()) {
        diag.fixItInsertAfter(closureExpr->getLoc(), " [self]");
        return;
      }

      // If there's a (non-comment) token immediately following the
      // opening brace of the closure, we may need to pad the fix-it
      // with a space.
      const auto nextLoc = closureExpr->getLoc().getAdvancedLoc(1);
      const auto next =
      Lexer::getTokenAtLocation(Ctx.SourceMgr, nextLoc,
                                CommentRetentionMode::None);
      std::string trailing = next.getLoc() == nextLoc ? " " : "";

      diag.fixItInsertAfter(closureExpr->getLoc(), " [self] in" + trailing);
    }
  };

  AbstractClosureExpr *ACE = nullptr;
  if (DC->isLocalContext()) {
    while (DC->getParent()->isLocalContext() && !ACE) {
      if (auto *closure = dyn_cast<AbstractClosureExpr>(DC))
        if (DiagnoseWalker::isClosureRequiringSelfQualification(closure))
          ACE = const_cast<AbstractClosureExpr *>(closure);
      DC = DC->getParent();
    }
  }
  auto &ctx = DC->getASTContext();
  const_cast<Expr *>(E)->walk(DiagnoseWalker(ctx, ACE));
}

bool TypeChecker::getDefaultGenericArgumentsString(
    SmallVectorImpl<char> &buf,
    const swift::GenericTypeDecl *typeDecl,
    llvm::function_ref<Type(const GenericTypeParamDecl *)> getPreferredType) {
  llvm::raw_svector_ostream genericParamText{buf};
  genericParamText << "<";

  auto printGenericParamSummary =
      [&](GenericTypeParamType *genericParamTy) {
    const GenericTypeParamDecl *genericParam = genericParamTy->getDecl();
    if (Type result = getPreferredType(genericParam)) {
      result.print(genericParamText);
      return;
    }

    auto contextTy = typeDecl->mapTypeIntoContext(genericParamTy);
    if (auto archetypeTy = contextTy->getAs<ArchetypeType>()) {
      SmallVector<Type, 2> members;

      bool hasExplicitAnyObject = archetypeTy->requiresClass();
      if (auto superclass = archetypeTy->getSuperclass()) {
        hasExplicitAnyObject = false;
        members.push_back(superclass);
      }

      for (auto proto : archetypeTy->getConformsTo()) {
        members.push_back(proto->getDeclaredInterfaceType());
        if (proto->requiresClass())
          hasExplicitAnyObject = false;
      }

      if (hasExplicitAnyObject)
        members.push_back(typeDecl->getASTContext().getAnyObjectType());

      auto type = ProtocolCompositionType::get(typeDecl->getASTContext(),
                                               members, hasExplicitAnyObject);

      if (type->isObjCExistentialType() || type->isAny()) {
        genericParamText << type;
        return;
      }

      genericParamText << "<#" << genericParam->getName() << ": ";
      genericParamText << type << "#>";
      return;
    }

    genericParamText << contextTy;
  };

  // FIXME: We can potentially be in the middle of creating a generic signature
  // if we get here.  Break this cycle.
  if (typeDecl->hasComputedGenericSignature()) {
    llvm::interleave(typeDecl->getInnermostGenericParamTypes(),
                     printGenericParamSummary,
                     [&] { genericParamText << ", "; });
  }
  
  genericParamText << ">";
  return true;
}

/// Diagnose an argument labeling issue, returning true if we successfully
/// diagnosed the issue.
bool swift::diagnoseArgumentLabelError(ASTContext &ctx,
                                       Expr *expr,
                                       ArrayRef<Identifier> newNames,
                                       bool isSubscript,
                                       InFlightDiagnostic *existingDiag) {
  Optional<InFlightDiagnostic> diagOpt;
  auto getDiag = [&]() -> InFlightDiagnostic & {
    if (existingDiag)
      return *existingDiag;
    return *diagOpt;
  };

  auto &diags = ctx.Diags;

  OriginalArgumentList argList = getOriginalArgumentList(expr);

  // Figure out how many extraneous, missing, and wrong labels are in
  // the call.
  unsigned numExtra = 0, numMissing = 0, numWrong = 0;
  unsigned n = std::max(argList.args.size(), newNames.size());

  llvm::SmallString<16> missingBuffer;
  llvm::SmallString<16> extraBuffer;
  for (unsigned i = 0; i != n; ++i) {
    Identifier oldName;
    if (i < argList.args.size())
      oldName = argList.labels[i];
    Identifier newName;
    if (i < newNames.size())
      newName = newNames[i];

    if (oldName == newName ||
        (argList.hasTrailingClosure && i == argList.args.size()-1 &&
         (numMissing > 0 || numExtra > 0 || numWrong > 0)))
      continue;

    if (oldName.empty()) {
      ++numMissing;
      missingBuffer += newName.str();
      missingBuffer += ":";
    } else if (newName.empty()) {
      ++numExtra;
      extraBuffer += oldName.str();
      extraBuffer += ':';
    } else
      ++numWrong;
  }

  // Emit the diagnostic.
  assert(numMissing > 0 || numExtra > 0 || numWrong > 0);
  llvm::SmallString<16> haveBuffer; // note: diagOpt has references to this
  llvm::SmallString<16> expectedBuffer; // note: diagOpt has references to this

  // If we had any wrong labels, or we have both missing and extra labels,
  // emit the catch-all "wrong labels" diagnostic.
  if (!existingDiag) {
    bool plural = (numMissing + numExtra + numWrong) > 1;
    if (numWrong > 0 || (numMissing > 0 && numExtra > 0)) {
      for (unsigned i = 0, n = argList.args.size(); i != n; ++i) {
        auto haveName = argList.labels[i];
        if (haveName.empty())
          haveBuffer += '_';
        else
          haveBuffer += haveName.str();
        haveBuffer += ':';
      }

      for (auto expected : newNames) {
        if (expected.empty())
          expectedBuffer += '_';
        else
          expectedBuffer += expected.str();
        expectedBuffer += ':';
      }

      StringRef haveStr = haveBuffer;
      StringRef expectedStr = expectedBuffer;
      diagOpt.emplace(diags.diagnose(expr->getLoc(),
                                     diag::wrong_argument_labels,
                                     plural, haveStr, expectedStr,
                                     isSubscript));
    } else if (numMissing > 0) {
      StringRef missingStr = missingBuffer;
      diagOpt.emplace(diags.diagnose(expr->getLoc(),
                                     diag::missing_argument_labels,
                                     plural, missingStr, isSubscript));
    } else {
      assert(numExtra > 0);
      StringRef extraStr = extraBuffer;
      diagOpt.emplace(diags.diagnose(expr->getLoc(),
                                     diag::extra_argument_labels,
                                     plural, extraStr, isSubscript));
    }
  }

  // Emit Fix-Its to correct the names.
  auto &diag = getDiag();
  for (unsigned i = 0, n = argList.args.size(); i != n; ++i) {
    Identifier oldName = argList.labels[i];
    Identifier newName;
    if (i < newNames.size())
      newName = newNames[i];

    if (oldName == newName || (i == n-1 && argList.hasTrailingClosure))
      continue;

    if (newName.empty()) {
      // Delete the old name.
      diag.fixItRemoveChars(argList.labelLocs[i],
                            argList.args[i]->getStartLoc());
      continue;
    }

    bool newNameIsReserved = !canBeArgumentLabel(newName.str());
    llvm::SmallString<16> newStr;
    if (newNameIsReserved)
      newStr += "`";
    newStr += newName.str();
    if (newNameIsReserved)
      newStr += "`";

    if (oldName.empty()) {
      // Insert the name.
      newStr += ": ";
      diag.fixItInsert(argList.args[i]->getStartLoc(), newStr);
      continue;
    }

    // Change the name.
    diag.fixItReplace(argList.labelLocs[i], newStr);
  }

  // If the diagnostic is local, flush it before returning.
  // This makes sure it's emitted before the message text buffers are destroyed.
  diagOpt.reset();
  return true;
}

static const Expr *lookThroughExprsToImmediateDeallocation(const Expr *E) {
  // Look through various expressions that don't affect the fact that the user
  // will be assigning a class instance that will be immediately deallocated.
  while (true) {
    E = E->getValueProvidingExpr();

    // We don't currently deal with tuple destructuring.
    if (isa<DestructureTupleExpr>(E))
      return E;

    // If we have a TupleElementExpr with a child TupleExpr, dig into that
    // element.
    if (auto *TEE = dyn_cast<TupleElementExpr>(E)) {
      auto *subExpr = lookThroughExprsToImmediateDeallocation(TEE->getBase());
      if (auto *TE = dyn_cast<TupleExpr>(subExpr)) {
        auto *element = TE->getElements()[TEE->getFieldNumber()];
        return lookThroughExprsToImmediateDeallocation(element);
      }
      return subExpr;
    }

    if (auto *ICE = dyn_cast<ImplicitConversionExpr>(E)) {
      E = ICE->getSubExpr();
      continue;
    }
    if (auto *CE = dyn_cast<CoerceExpr>(E)) {
      E = CE->getSubExpr();
      continue;
    }
    if (auto *OEE = dyn_cast<OpenExistentialExpr>(E)) {
      E = OEE->getSubExpr();
      continue;
    }

    // Look through optional evaluations, we still want to diagnose on
    // things like initializers called through optional chaining and the
    // unwrapping of failable initializers.
    if (auto *OEE = dyn_cast<OptionalEvaluationExpr>(E)) {
      E = OEE->getSubExpr();
      continue;
    }
    if (auto *OBE = dyn_cast<BindOptionalExpr>(E)) {
      E = OBE->getSubExpr();
      continue;
    }
    if (auto *FOE = dyn_cast<ForceValueExpr>(E)) {
      E = FOE->getSubExpr();
      continue;
    }

    if (auto *ATE = dyn_cast<AnyTryExpr>(E)) {
      E = ATE->getSubExpr();
      continue;
    }
    if (auto *DSBIE = dyn_cast<DotSyntaxBaseIgnoredExpr>(E)) {
      E = DSBIE->getRHS();
      continue;
    }
    return E;
  }
}

static void diagnoseUnownedImmediateDeallocationImpl(ASTContext &ctx,
                                                     const VarDecl *varDecl,
                                                     const Expr *initExpr,
                                                     SourceLoc diagLoc,
                                                     SourceRange diagRange) {
  auto *ownershipAttr =
      varDecl->getAttrs().getAttribute<ReferenceOwnershipAttr>();
  if (!ownershipAttr || ownershipAttr->isInvalid())
    return;

  // Only diagnose for non-owning ownerships such as 'weak' and 'unowned'.
  // Zero is the default/strong ownership strength.
  if (ReferenceOwnership::Strong == ownershipAttr->get() ||
      isLessStrongThan(ReferenceOwnership::Strong, ownershipAttr->get()))
    return;

  // Try to find a call to a constructor.
  initExpr = lookThroughExprsToImmediateDeallocation(initExpr);
  auto *CE = dyn_cast<CallExpr>(initExpr);
  if (!CE)
    return;

  auto *CRCE = dyn_cast<ConstructorRefCallExpr>(CE->getFn());
  if (!CRCE)
    return;

  auto *DRE = dyn_cast<DeclRefExpr>(CRCE->getFn());
  if (!DRE)
    return;

  auto *constructorDecl = dyn_cast<ConstructorDecl>(DRE->getDecl());
  if (!constructorDecl)
    return;

  // Make sure the constructor constructs an instance that allows ownership.
  // This is to ensure we don't diagnose on constructors such as
  // Optional.init(nilLiteral:).
  auto selfType = constructorDecl->getDeclContext()->getSelfTypeInContext();
  if (!selfType->allowsOwnership())
    return;

  // This must stay in sync with
  // diag::unowned_assignment_immediate_deallocation.
  enum {
    SK_Variable = 0,
    SK_Property
  } storageKind = SK_Variable;

  if (varDecl->getDeclContext()->isTypeContext())
    storageKind = SK_Property;

  ctx.Diags.diagnose(diagLoc, diag::unowned_assignment_immediate_deallocation,
                     varDecl->getName(), ownershipAttr->get(),
                     unsigned(storageKind))
    .highlight(diagRange);

  ctx.Diags.diagnose(diagLoc, diag::unowned_assignment_requires_strong)
    .highlight(diagRange);

  ctx.Diags.diagnose(varDecl, diag::decl_declared_here, varDecl->getName());
}

void swift::diagnoseUnownedImmediateDeallocation(ASTContext &ctx,
                                                 const AssignExpr *assignExpr) {
  auto *destExpr = assignExpr->getDest()->getValueProvidingExpr();
  auto *initExpr = assignExpr->getSrc();

  // Try to find a referenced VarDecl.
  const VarDecl *VD = nullptr;
  if (auto *DRE = dyn_cast<DeclRefExpr>(destExpr)) {
    VD = dyn_cast<VarDecl>(DRE->getDecl());
  } else if (auto *MRE = dyn_cast<MemberRefExpr>(destExpr)) {
    VD = dyn_cast<VarDecl>(MRE->getMember().getDecl());
  }

  if (VD)
    diagnoseUnownedImmediateDeallocationImpl(ctx, VD, initExpr,
                                             assignExpr->getLoc(),
                                             initExpr->getSourceRange());
}

void swift::diagnoseUnownedImmediateDeallocation(ASTContext &ctx,
                                                 const Pattern *pattern,
                                                 SourceLoc equalLoc,
                                                 const Expr *initExpr) {
  pattern = pattern->getSemanticsProvidingPattern();

  if (auto *TP = dyn_cast<TuplePattern>(pattern)) {
    initExpr = lookThroughExprsToImmediateDeallocation(initExpr);

    // If we've found a matching tuple initializer with the same number of
    // elements as our pattern, diagnose each element individually.
    auto TE = dyn_cast<TupleExpr>(initExpr);
    if (TE && TE->getNumElements() == TP->getNumElements()) {
      for (unsigned i = 0, e = TP->getNumElements(); i != e; ++i) {
        const TuplePatternElt &elt = TP->getElement(i);
        const Pattern *subPattern = elt.getPattern();
        Expr *subInitExpr = TE->getElement(i);

        diagnoseUnownedImmediateDeallocation(ctx, subPattern, equalLoc,
                                             subInitExpr);
      }
    }
  } else if (auto *NP = dyn_cast<NamedPattern>(pattern)) {
    diagnoseUnownedImmediateDeallocationImpl(ctx, NP->getDecl(), initExpr,
                                             equalLoc,
                                             initExpr->getSourceRange());
  }
}

namespace {
enum NoteKind_t {
  FixItReplace,
  FixItInsert,
};

static bool fixItOverrideDeclarationTypesImpl(
    ValueDecl *decl, const ValueDecl *base,
    SmallVectorImpl<std::tuple<NoteKind_t, SourceRange, std::string>> &notes) {
  // For now, just rewrite cases where the base uses a value type and the
  // override uses a reference type, and the value type is bridged to the
  // reference type. This is a way to migrate code that makes use of types
  // that previously were not bridged to value types.
  auto checkValueReferenceType =
      [&](Type overrideTy, ParamDecl::Specifier overrideSpec,
          Type baseTy, ParamDecl::Specifier baseSpec,
          SourceRange typeRange) -> bool {
    if (typeRange.isInvalid())
      return false;

    auto normalizeType = [](Type &ty, ParamDecl::Specifier spec) -> Type {
      Type normalizedTy = ty;
      if (Type unwrappedTy = normalizedTy->getOptionalObjectType())
        normalizedTy = unwrappedTy;
      if (spec == ParamDecl::Specifier::InOut)
        ty = InOutType::get(ty);
      return normalizedTy;
    };

    // Is the base type bridged?
    Type normalizedBaseTy = normalizeType(baseTy, baseSpec);
    const DeclContext *DC = decl->getDeclContext();

    ASTContext &ctx = decl->getASTContext();

    // ...and just knowing that it's bridged isn't good enough if we don't
    // know what it's bridged /to/. Also, don't do this check for trivial
    // bridging---that doesn't count.
    Type bridged;
    if (normalizedBaseTy->isAny()) {
      bridged = ctx.getAnyObjectType();
    } else {
      bridged = ctx.getBridgedToObjC(DC, normalizedBaseTy);
    }
    if (!bridged || bridged->isEqual(normalizedBaseTy))
      return false;

    // ...and is it bridged to the overridden type?
    Type normalizedOverrideTy = normalizeType(overrideTy, overrideSpec);
    if (!bridged->isEqual(normalizedOverrideTy)) {
      // If both are nominal types, check again, ignoring generic arguments.
      auto *overrideNominal = normalizedOverrideTy->getAnyNominal();
      if (!overrideNominal || bridged->getAnyNominal() != overrideNominal) {
        return false;
      }
    }

    Type newOverrideTy = baseTy;

    // Preserve optionality if we're dealing with a simple type.
    if (Type unwrappedTy = newOverrideTy->getOptionalObjectType())
      newOverrideTy = unwrappedTy;
    if (overrideTy->getOptionalObjectType())
      newOverrideTy = OptionalType::get(newOverrideTy);

    SmallString<32> baseTypeBuf;
    llvm::raw_svector_ostream baseTypeStr(baseTypeBuf);
    PrintOptions options;
    options.SynthesizeSugarOnTypes = true;

    newOverrideTy->print(baseTypeStr, options);
    notes.emplace_back(FixItReplace, typeRange, baseTypeStr.str().str());
    return true;
  };

  // Check if overriding fails because we lack @escaping attribute on the function
  // type repr.
  auto checkTypeMissingEscaping = [&](Type overrideTy, Type baseTy,
                                      SourceRange typeRange) -> bool {
    // Fix-it needs position to apply.
    if (typeRange.isInvalid())
      return false;
    auto overrideFnTy = overrideTy->getAs<AnyFunctionType>();
    auto baseFnTy = baseTy->getAs<AnyFunctionType>();

    // Both types should be function.
    if (overrideFnTy && baseFnTy &&
        // The overriding function type should be no escaping.
        overrideFnTy->getExtInfo().isNoEscape() &&
        // The overridden function type should be escaping.
        !baseFnTy->getExtInfo().isNoEscape()) {
      notes.emplace_back(FixItInsert, typeRange, "@escaping ");
      return true;
    }
    return false;
  };

  auto checkType = [&](Type overrideTy, ParamDecl::Specifier overrideSpec,
                       Type baseTy, ParamDecl::Specifier baseSpec,
                       SourceRange typeRange) -> bool {
    return checkValueReferenceType(overrideTy, overrideSpec,
                                   baseTy, baseSpec, typeRange) ||
      checkTypeMissingEscaping(overrideTy, baseTy, typeRange);
  };

  if (auto *param = dyn_cast<ParamDecl>(decl)) {
    SourceRange typeRange = param->getTypeSourceRangeForDiagnostics();
    auto *baseParam = cast<ParamDecl>(base);
    return checkType(param->getInterfaceType(), param->getSpecifier(),
                     baseParam->getInterfaceType(), baseParam->getSpecifier(),
                     typeRange);
  }

  if (auto *var = dyn_cast<VarDecl>(decl)) {
    SourceRange typeRange = var->getTypeSourceRangeForDiagnostics();
    auto *baseVar = cast<VarDecl>(base);
    return checkType(var->getInterfaceType(), ParamDecl::Specifier::Default,
                     baseVar->getInterfaceType(), ParamDecl::Specifier::Default,
                     typeRange);
  }

  if (auto *fn = dyn_cast<AbstractFunctionDecl>(decl)) {
    auto *baseFn = cast<AbstractFunctionDecl>(base);
    bool fixedAny = false;
    if (fn->getParameters()->size() ==
        baseFn->getParameters()->size()) {
      for_each(*fn->getParameters(),
               *baseFn->getParameters(),
               [&](ParamDecl *param, const ParamDecl *baseParam) {
        fixedAny |= fixItOverrideDeclarationTypesImpl(param, baseParam, notes);
      });
    }
    if (auto *method = dyn_cast<FuncDecl>(decl)) {
      auto resultType = method->mapTypeIntoContext(
          method->getResultInterfaceType());

      auto *baseMethod = cast<FuncDecl>(base);
      auto baseResultType = baseMethod->mapTypeIntoContext(
          baseMethod->getResultInterfaceType());

      fixedAny |= checkType(resultType, ParamDecl::Specifier::Default,
                            baseResultType, ParamDecl::Specifier::Default,
                            method->getResultTypeSourceRange());
    }
    return fixedAny;
  }

  if (auto *subscript = dyn_cast<SubscriptDecl>(decl)) {
    auto *baseSubscript = cast<SubscriptDecl>(base);
    bool fixedAny = false;
    if (subscript->getIndices()->size() ==
        baseSubscript->getIndices()->size()) {
      for_each(*subscript->getIndices(),
               *baseSubscript->getIndices(),
               [&](ParamDecl *param, const ParamDecl *baseParam) {
        fixedAny |= fixItOverrideDeclarationTypesImpl(param, baseParam, notes);
      });
    }

    auto resultType = subscript->getDeclContext()->mapTypeIntoContext(
        subscript->getElementInterfaceType());
    auto baseResultType = baseSubscript->getDeclContext()->mapTypeIntoContext(
        baseSubscript->getElementInterfaceType());
    fixedAny |= checkType(resultType, ParamDecl::Specifier::Default,
                          baseResultType, ParamDecl::Specifier::Default,
                          subscript->getElementTypeSourceRange());
    return fixedAny;
  }

  llvm_unreachable("unknown overridable member");
}
};

bool swift::computeFixitsForOverridenDeclaration(
    ValueDecl *decl, const ValueDecl *base,
    llvm::function_ref<Optional<InFlightDiagnostic>(bool)> diag) {
  SmallVector<std::tuple<NoteKind_t, SourceRange, std::string>, 4> Notes;
  bool hasNotes = ::fixItOverrideDeclarationTypesImpl(decl, base, Notes);

  Optional<InFlightDiagnostic> diagnostic = diag(hasNotes);
  if (!diagnostic) return hasNotes;

  for (const auto &note : Notes) {
    if (std::get<0>(note) == FixItReplace) {
      diagnostic->fixItReplace(std::get<1>(note), std::get<2>(note));
    } else {
      diagnostic->fixItInsert(std::get<1>(note).Start, std::get<2>(note));
    }
  }
  return hasNotes;
}

//===----------------------------------------------------------------------===//
// Per func/init diagnostics
//===----------------------------------------------------------------------===//

namespace {

class VarDeclUsageChecker : public ASTWalker {
  DeclContext *DC;

  DiagnosticEngine &Diags;
  // Keep track of some information about a variable.
  enum {
    RK_Defined     = 1,      ///< Whether it was ever defined in this scope.
    RK_Read        = 2,      ///< Whether it was ever read.
    RK_Written     = 4,      ///< Whether it was ever written or passed inout.
    
    RK_CaptureList = 8       ///< Var is an entry in a capture list.
  };
  
  /// These are all of the variables that we are tracking.  VarDecls get added
  /// to this when the declaration is seen.  We use a MapVector to keep the
  /// diagnostics emission in deterministic order.
  llvm::SmallMapVector<VarDecl*, unsigned, 32> VarDecls;

  /// This is a mapping from an OpaqueValue to the expression that initialized
  /// it.
  llvm::SmallDenseMap<OpaqueValueExpr *, Expr *> OpaqueValueMap;

  /// The first reference to the given property.
  llvm::SmallDenseMap<VarDecl *, Expr *> AssociatedGetterRefExpr;

  /// This is a mapping from VarDecls to the if/while/guard statement that they
  /// occur in, when they are in a pattern in a StmtCondition.
  llvm::SmallDenseMap<VarDecl*, LabeledConditionalStmt*> StmtConditionForVD;

#ifndef NDEBUG
  llvm::SmallPtrSet<Expr*, 32> AllExprsSeen;
#endif
  
  bool sawError = false;
  
  VarDeclUsageChecker(const VarDeclUsageChecker &) = delete;
  void operator=(const VarDeclUsageChecker &) = delete;

public:
  VarDeclUsageChecker(DeclContext *DC,
                      DiagnosticEngine &Diags) : DC(DC), Diags(Diags) {}

  // After we have scanned the entire region, diagnose variables that could be
  // declared with a narrower usage kind.
  ~VarDeclUsageChecker() override;

  /// Check to see if the specified VarDecl is part of a larger
  /// PatternBindingDecl, where some other bound variable was mutated.  In this
  /// case we don't want to generate a "variable never mutated" warning, because
  /// it would require splitting up the destructuring of the tuple, which is
  ///  more code turmoil than the warning is worth.
  bool isVarDeclPartOfPBDThatHadSomeMutation(VarDecl *VD) {
    auto *PBD = VD->getParentPatternBinding();
    if (!PBD) return false;

    bool sawMutation = false;
    for (auto idx : range(PBD->getNumPatternEntries())) {
      PBD->getPattern(idx)->forEachVariable([&](VarDecl *VD) {
        auto it = VarDecls.find(VD);
        sawMutation |= it != VarDecls.end() && (it->second & RK_Written);
      });
    }
    return sawMutation;
  }

  bool shouldTrackVarDecl(VarDecl *VD) {
    // If the variable is implicit, ignore it.
    if (VD->isImplicit() || VD->getLoc().isInvalid())
      return false;
    
    // If the variable is computed, ignore it.
    if (!VD->hasStorage())
      return false;
    
    // If the variable was invalid, ignore it and notice that the code is
    // malformed.
    if (VD->isInvalid()) {
      sawError = true;
      return false;
    }
    
    // If the variable is already unnamed, ignore it.
    if (!VD->hasName() || VD->getName().str() == "_")
      return false;

    return true;
  }

  void addMark(Decl *D, unsigned Flag) {
    auto *vd = dyn_cast<VarDecl>(D);
    if (!vd) return;

    VarDecls[vd] |= Flag;
  }
  
  void markBaseOfStorageUse(Expr *E, ConcreteDeclRef decl, unsigned flags);
  void markBaseOfStorageUse(Expr *E, bool isMutating);
  
  void markStoredOrInOutExpr(Expr *E, unsigned Flags);
  
  // We generally walk into declarations, other than types and nested functions.
  // FIXME: peek into capture lists of nested functions.
  bool walkToDeclPre(Decl *D) override {
    if (isa<TypeDecl>(D))
      return false;
      
    // The body of #if clauses are not walked into, we need custom processing
    // for them.
    if (auto *ICD = dyn_cast<IfConfigDecl>(D))
      handleIfConfig(ICD);
      
    // If this is a VarDecl, then add it to our list of things to track.
    if (auto *vd = dyn_cast<VarDecl>(D)) {
      if (shouldTrackVarDecl(vd)) {
        // Inline constructor.
        auto defaultFlags = [&]() -> unsigned {
          // If this VarDecl is nested inside of a CaptureListExpr, remember
          // that fact for better diagnostics.
          auto parentAsExpr = Parent.getAsExpr();
          if (parentAsExpr && isa<CaptureListExpr>(parentAsExpr))
            return RK_CaptureList | RK_Defined;
          // Otherwise, return none.
          return RK_Defined;
        }();

        if (!vd->isImplicit()) {
          if (auto *childVd =
                  vd->getCorrespondingCaseBodyVariable().getPtrOrNull()) {
            // Child vars are never in capture lists.
            assert(defaultFlags == RK_Defined);
            VarDecls[childVd] |= RK_Defined;
          }
        }
        VarDecls[vd] |= defaultFlags;
      }
    }

    // Don't walk into implicit accessors, since eg. an observer's setter
    // references the variable, but we don't want to consider it as a real
    // "use".
    if (isa<AccessorDecl>(D) && D->isImplicit())
      return false;

    if (auto *afd = dyn_cast<AbstractFunctionDecl>(D)) {
      // If this AFD is a setter, track the parameter and the getter for
      // the containing property so if newValue isn't used but the getter is used
      // an error can be reported.
      if (auto FD = dyn_cast<AccessorDecl>(afd)) {
        if (FD->getAccessorKind() == AccessorKind::Set) {
          if (isa<VarDecl>(FD->getStorage())) {
            auto arguments = FD->getParameters();
            VarDecls[arguments->get(0)] = RK_Defined;
          }
        }
      }

      if (afd->isBodyTypeChecked())
        return true;

      // Don't walk into a body that has not yet been type checked. This should
      // only occur for top-level code.
      VarDecls.clear();
      return false;
    }

    if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
      // If this is a TopLevelCodeDecl, scan for global variables
      auto *body = TLCD->getBody();
      for (auto node : body->getElements()) {
        if (node.is<Decl *>()) {
          // Flag all variables in a PatternBindingDecl
          Decl *D = node.get<Decl *>();
          auto *PBD = dyn_cast<PatternBindingDecl>(D);
          if (!PBD) continue;
          for (auto idx : range(PBD->getNumPatternEntries())) {
            PBD->getPattern(idx)->forEachVariable([&](VarDecl *VD) {
              VarDecls[VD] = RK_Read|RK_Written|RK_Defined;
            });
          }
        } else if (node.is<Stmt *>()) {
          // Flag all variables in guard statements
          Stmt *S = node.get<Stmt *>();
          auto *GS = dyn_cast<GuardStmt>(S);
          if (!GS) continue;
          for (StmtConditionElement SCE : GS->getCond()) {
            if (auto pattern = SCE.getPatternOrNull()) {
              pattern->forEachVariable([&](VarDecl *VD) {
                VarDecls[VD] = RK_Read|RK_Written|RK_Defined;
              });
            }
          }
        }
      }
    }

    // Note that we ignore the initialization behavior of PatternBindingDecls,
    // but we do want to walk into them, because we want to see any uses or
    // other things going on in the initializer expressions.
    return true;
  }

  /// The heavy lifting happens when visiting expressions.
  std::pair<bool, Expr *> walkToExprPre(Expr *E) override;

  /// handle #if directives.
  void handleIfConfig(IfConfigDecl *ICD);

  /// Custom handling for statements.
  std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
    // Keep track of an association between vardecls and the StmtCondition that
    // they are bound in for IfStmt, GuardStmt, WhileStmt, etc.
    if (auto LCS = dyn_cast<LabeledConditionalStmt>(S)) {
      for (auto &cond : LCS->getCond())
        if (auto pat = cond.getPatternOrNull()) {
          pat->forEachVariable([&](VarDecl *VD) {
            StmtConditionForVD[VD] = LCS;
          });
        }
    }
    
    // A fallthrough dest case's bound variable means the source case's
    // var of the same name is read.
    if (auto *fallthroughStmt = dyn_cast<FallthroughStmt>(S)) {
      if (auto *sourceCase = fallthroughStmt->getFallthroughSource()) {
        SmallVector<VarDecl *, 4> sourceVars;
        auto sourcePattern = sourceCase->getCaseLabelItems()[0].getPattern();
        sourcePattern->collectVariables(sourceVars);
        
        auto destCase = fallthroughStmt->getFallthroughDest();
        auto destPattern = destCase->getCaseLabelItems()[0].getPattern();
        destPattern->forEachVariable([&](VarDecl *V) {
          if (!V->hasName())
            return;
          for (auto *var : sourceVars) {
            if (var->hasName() && var->getName() == V->getName()) {
              VarDecls[var] |= RK_Read;
              break;
            }
          }
        });
      }
    }

    // Make sure that we setup our case body variables.
    if (auto *caseStmt = dyn_cast<CaseStmt>(S)) {
      for (auto *vd : caseStmt->getCaseBodyVariablesOrEmptyArray()) {
        VarDecls[vd] |= RK_Defined;
      }
    }

    return { true, S };
  }
};
  
/// An AST walker that determines the underlying type of an opaque return decl
/// from its associated function body.
class OpaqueUnderlyingTypeChecker : public ASTWalker {
  ASTContext &Ctx;
  AbstractFunctionDecl *Implementation;
  OpaqueTypeDecl *OpaqueDecl;
  BraceStmt *Body;
  SmallVector<std::pair<Expr*, Type>, 4> Candidates;

  bool HasInvalidReturn = false;

public:
  OpaqueUnderlyingTypeChecker(AbstractFunctionDecl *Implementation,
                              OpaqueTypeDecl *OpaqueDecl,
                              BraceStmt *Body)
    : Ctx(Implementation->getASTContext()),
      Implementation(Implementation),
      OpaqueDecl(OpaqueDecl),
      Body(Body)
  {
    
  }
  
  void check() {
    Body->walk(*this);

    // If given function has any invalid returns in the body
    // let's not try to validate the types, since it wouldn't
    // be accurate.
    if (HasInvalidReturn)
      return;

    // If there are no candidates, then the body has no return statements, and
    // we have nothing to infer the underlying type from.
    if (Candidates.empty()) {
      Implementation->diagnose(diag::opaque_type_no_underlying_type_candidates);
      return;
    }
    
    // Check whether all of the underlying type candidates match up.
    auto opaqueTypeInContext =
      Implementation->mapTypeIntoContext(OpaqueDecl->getDeclaredInterfaceType());
    Type underlyingType = Candidates.front().second;
    
    bool mismatch = false;
    for (auto otherCandidate : llvm::makeArrayRef(Candidates).slice(1)) {
      // Disregard tautological candidates.
      if (otherCandidate.second->isEqual(opaqueTypeInContext))
        continue;
        
      if (!underlyingType->isEqual(otherCandidate.second)) {
        mismatch = true;
        break;
      }
    }
    
    if (mismatch) {
      Implementation->diagnose(
          diag::opaque_type_mismatched_underlying_type_candidates);
      for (auto candidate : Candidates) {
        Ctx.Diags.diagnose(candidate.first->getLoc(),
                           diag::opaque_type_underlying_type_candidate_here,
                           candidate.second);
      }
      return;
    }
    
    // The underlying type can't be defined recursively
    // in terms of the opaque type itself.
    auto isSelfReferencing = underlyingType.findIf([&](Type t) -> bool {
      return t->isEqual(opaqueTypeInContext);
    });
    
    if (isSelfReferencing) {
      Ctx.Diags.diagnose(Candidates.front().first->getLoc(),
                         diag::opaque_type_self_referential_underlying_type,
                         underlyingType);
      return;
    }
    
    // If we have one successful candidate, then save it as the underlying type
    // of the opaque decl.
    // Form a substitution map that defines it in terms of the other context
    // generic parameters.
    underlyingType = underlyingType->mapTypeOutOfContext();
    auto underlyingSubs = SubstitutionMap::get(
      OpaqueDecl->getOpaqueInterfaceGenericSignature(),
      [&](SubstitutableType *t) -> Type {
        if (t->isEqual(OpaqueDecl->getUnderlyingInterfaceType())) {
          return underlyingType;
        }
        return Type(t);
      },
      LookUpConformanceInModule(OpaqueDecl->getModuleContext()));
    
    OpaqueDecl->setUnderlyingTypeSubstitutions(underlyingSubs);
  }
  
  std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
    if (auto underlyingToOpaque = dyn_cast<UnderlyingToOpaqueExpr>(E)) {
      assert(E->getType()->isEqual(
       Implementation->mapTypeIntoContext(OpaqueDecl->getDeclaredInterfaceType()))
             && "unexpected opaque type in function body");
      
      Candidates.push_back(std::make_pair(underlyingToOpaque->getSubExpr(),
                                  underlyingToOpaque->getSubExpr()->getType()));
    }
    return std::make_pair(false, E);
  }

  std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
    if (auto *RS = dyn_cast<ReturnStmt>(S)) {
      if (RS->hasResult()) {
        auto resultTy = RS->getResult()->getType();
        // If expression associated with return statement doesn't have
        // a type or type has an error, checking opaque types is going
        // to produce incorrect diagnostics.
        HasInvalidReturn |= resultTy.isNull() || resultTy->hasError();
      }
    }

    return {true, S};
  }
  
  // Don't descend into nested decls.
  bool walkToDeclPre(Decl *D) override {
    return false;
  }
};

} // end anonymous namespace

// After we have scanned the entire region, diagnose variables that could be
// declared with a narrower usage kind.
VarDeclUsageChecker::~VarDeclUsageChecker() {
  // If we saw an ErrorExpr somewhere in the body, then we have a malformed AST
  // and we know stuff got dropped.  Instead of producing these diagnostics,
  // lets let the bigger issues get resolved first.
  if (sawError)
    return;

  for (auto p : VarDecls) {
    VarDecl *var;
    unsigned access;
    std::tie(var, access) = p;

    // If the variable was not defined in this scope, we can safely ignore it.
    if (!(access & RK_Defined))
      continue;

    if (auto *caseStmt =
            dyn_cast_or_null<CaseStmt>(var->getRecursiveParentPatternStmt())) {
      // Only diagnose VarDecls from the first CaseLabelItem in CaseStmts, as
      // the remaining items must match it anyway.
      auto caseItems = caseStmt->getCaseLabelItems();
      assert(!caseItems.empty() &&
             "If we have any case stmt var decls, we should have a case item");
      if (!caseItems.front().getPattern()->containsVarDecl(var))
        continue;

      auto *childVar = var->getCorrespondingCaseBodyVariable().get();
      access |= VarDecls[childVar];
    }

    // If the setter parameter is not used, but the property is read, report
    // a warning. Otherwise, parameters should not generate usage warnings. It
    // is common to name a parameter and not use it (e.g. because you are an
    // override or want the named keyword, etc).  Warning to rewrite it to _ is
    // more annoying than it is useful.
    if (auto param = dyn_cast<ParamDecl>(var)) {
      auto FD = dyn_cast<AccessorDecl>(param->getDeclContext());
      if (FD && FD->getAccessorKind() == AccessorKind::Set) {
        auto VD = dyn_cast<VarDecl>(FD->getStorage());
        if ((access & RK_Read) == 0) {
          auto found = AssociatedGetterRefExpr.find(VD);
          if (found != AssociatedGetterRefExpr.end()) {
            auto *DRE = found->second;
            Diags.diagnose(DRE->getLoc(), diag::unused_setter_parameter,
                           var->getName());
            Diags.diagnose(DRE->getLoc(), diag::fixit_for_unused_setter_parameter,
                           var->getName())
              .fixItReplace(DRE->getSourceRange(), var->getName().str());
          }
        }
      }
      continue;
    }

    // If this is a 'let' value, any stores to it are actually initializations,
    // not mutations.
    auto isWrittenLet = false;
    if (var->isLet()) {
      isWrittenLet = (access & RK_Written) != 0;
      access &= ~RK_Written;
    }
    
    // If this variable has WeakStorageType, then it can be mutated in ways we
    // don't know.
    if (var->getType()->is<WeakStorageType>())
      access |= RK_Written;
    
    // Diagnose variables that were never used (other than their
    // initialization).
    //
    if ((access & (RK_Read|RK_Written)) == 0) {
      // If this is a member in a capture list, just say it is unused.  We could
      // produce a fixit hint with a parent map, but this is a lot of effort for
      // a narrow case.
      if (access & RK_CaptureList) {
        Diags.diagnose(var->getLoc(), diag::capture_never_used,
                       var->getName());
        continue;
      }
      
      // If the source of the VarDecl is a trivial PatternBinding with only a
      // single binding, rewrite the whole thing into an assignment.
      //    let x = foo()
      //  ->
      //    _ = foo()
      if (auto *pbd = var->getParentPatternBinding()) {
        if (pbd->getSingleVar() == var && pbd->getInit(0) != nullptr &&
            !isa<TypedPattern>(pbd->getPattern(0))) {
          unsigned varKind = var->isLet();
          SourceRange replaceRange(
              pbd->getStartLoc(),
              pbd->getPattern(0)->getEndLoc());
          Diags.diagnose(var->getLoc(), diag::pbd_never_used,
                         var->getName(), varKind)
            .fixItReplace(replaceRange, "_");
          continue;
        }
      }

      // If the variable is defined in a pattern in an if/while/guard statement,
      // see if we can produce a tuned fixit.  When we have something like:
      //
      //    if let x = <expr> {
      //
      // we prefer to rewrite it to:
      //
      //    if <expr> != nil {
      //
      if (auto SC = StmtConditionForVD[var]) {
        // We only handle the "if let" case right now, since it is vastly the
        // most common situation that people run into.
        if (SC->getCond().size() == 1) {
          auto pattern = SC->getCond()[0].getPattern();
          if (auto OSP = dyn_cast<OptionalSomePattern>(pattern))
            if (auto LP = dyn_cast<BindingPattern>(OSP->getSubPattern()))
              if (isa<NamedPattern>(LP->getSubPattern())) {
                auto initExpr = SC->getCond()[0].getInitializer();
                if (initExpr->getStartLoc().isValid()) {
                  unsigned noParens = initExpr->canAppendPostfixExpression();
                  
                  // If the subexpr is an "as?" cast, we can rewrite it to
                  // be an "is" test.
                  bool isIsTest = false;
                  if (isa<ConditionalCheckedCastExpr>(initExpr) &&
                      !initExpr->isImplicit()) {
                    noParens = isIsTest = true;
                  }
                  
                  auto diagIF = Diags.diagnose(var->getLoc(),
                                               diag::pbd_never_used_stmtcond,
                                            var->getName());
                  auto introducerLoc = SC->getCond()[0].getIntroducerLoc();
                  diagIF.fixItReplaceChars(introducerLoc,
                                           initExpr->getStartLoc(),
                                           &"("[noParens]);
                  
                  if (isIsTest) {
                    // If this was an "x as? T" check, rewrite it to "x is T".
                    auto CCE = cast<ConditionalCheckedCastExpr>(initExpr);
                    diagIF.fixItReplace(SourceRange(CCE->getLoc(),
                                                    CCE->getQuestionLoc()),
                                        "is");
                  } else {
                    diagIF.fixItInsertAfter(initExpr->getEndLoc(),
                                            &") != nil"[noParens]);
                  }
                  continue;
                }
              }
        }
      }

      // If the variable is defined in a pattern that isn't one of the usual
      // conditional statements, try to detect and rewrite "simple" binding
      // patterns:
      //    case .pattern(let x):
      //  ->
      //    case .pattern(_):
      if (auto *pattern = var->getParentPattern()) {
        BindingPattern *foundVP = nullptr;
        pattern->forEachNode([&](Pattern *P) {
          if (auto *VP = dyn_cast<BindingPattern>(P))
            if (VP->getSingleVar() == var)
              foundVP = VP;
        });

        if (foundVP) {
          unsigned varKind = var->isLet();
          Diags
              .diagnose(var->getLoc(), diag::variable_never_used,
                        var->getName(), varKind)
              .fixItReplace(foundVP->getSourceRange(), "_");
          continue;
        }
      }
      
      // Otherwise, this is something more complex, perhaps
      //    let (a,b) = foo()
      if (isWrittenLet) {
        Diags.diagnose(var->getLoc(),
                       diag::immutable_value_never_used_but_assigned,
                       var->getName());
      } else {
        unsigned varKind = var->isLet();
        // Just rewrite the one variable with a _.
        Diags.diagnose(var->getLoc(), diag::variable_never_used,
                       var->getName(), varKind)
          .fixItReplace(var->getLoc(), "_");
      }
      continue;
    }
    
    // If this is a mutable 'var', and it was never written to, suggest
    // upgrading to 'let'.
    if (!var->isLet() && (access & RK_Written) == 0 &&
        // Don't warn if we have something like "let (x,y) = ..." and 'y' was
        // never mutated, but 'x' was.
        !isVarDeclPartOfPBDThatHadSomeMutation(var)) {
      SourceLoc FixItLoc;

      // Try to find the location of the 'var' so we can produce a fixit.  If
      // this is a simple PatternBinding, use its location.
      if (auto *PBD = var->getParentPatternBinding()) {
        if (PBD->getSingleVar() == var)
          FixItLoc = PBD->getLoc();
      } else if (auto *pattern = var->getParentPattern()) {
        BindingPattern *foundVP = nullptr;
        pattern->forEachNode([&](Pattern *P) {
          if (auto *VP = dyn_cast<BindingPattern>(P))
            if (VP->getSingleVar() == var)
              foundVP = VP;
        });

        if (foundVP && !foundVP->isLet())
          FixItLoc = foundVP->getLoc();
      }

      // If this is a parameter explicitly marked 'var', remove it.
      if (FixItLoc.isInvalid()) {
        Diags.diagnose(var->getLoc(), diag::variable_never_mutated,
                       var->getName(), true);
      }
      else {
        bool suggestLet = true;
        if (auto *stmt = var->getRecursiveParentPatternStmt()) {
          // Don't try to suggest 'var' -> 'let' conversion
          // in case of 'for' loop because it's an implicitly
          // immutable context.
          suggestLet = !isa<ForEachStmt>(stmt);
        }

        auto diag = Diags.diagnose(var->getLoc(), diag::variable_never_mutated,
                                   var->getName(), suggestLet);

        if (suggestLet)
          diag.fixItReplace(FixItLoc, "let");
        else
          diag.fixItRemove(FixItLoc);

        continue;
      }
    }
    
    // If this is a variable that was only written to, emit a warning.
    if ((access & RK_Read) == 0) {
      Diags.diagnose(var->getLoc(), diag::variable_never_read, var->getName());
      continue;
    }
  }
}

/// Handle a use of "x.y" or "x[0]" where 'base' is the expression for x and
/// 'decl' is the property or subscript.
///
/// TODO: Rip this out and just rely on LValueAccessKind.
void VarDeclUsageChecker::markBaseOfStorageUse(Expr *base, ConcreteDeclRef decl,
                                               unsigned flags) {
  // If the base is an rvalue, then we know that this is a non-mutating access.
  // Note that we can have mutating accesses even when the base has class or
  // metatype type due to protocols and protocol extensions.
  if (!base->getType()->hasLValueType() &&
      !base->isSemanticallyInOutExpr()) {
    base->walk(*this);
    return;
  }

  // Compute whether this access is to a mutating member.
  auto *ASD = dyn_cast_or_null<AbstractStorageDecl>(decl.getDecl());
  bool isMutating = false;
  if (!ASD) {
    // If there's no abstract storage declaration (which should hopefully
    // only happen with invalid code), treat the base access as mutating if
    // the subobject is being mutated and the base type is not a class
    // or metatype.
    if (flags & RK_Written) {
      Type type = base->getType()->getRValueType()->getInOutObjectType();
      if (!type->isAnyClassReferenceType() && !type->is<AnyMetatypeType>())
        isMutating = true;
    }
  } else {
    // Otherwise, consider whether the accessors are mutating.
    if (flags & RK_Read)
      isMutating |= ASD->isGetterMutating();
    if (flags & RK_Written)
      isMutating |= ASD->isSettable(nullptr) && ASD->isSetterMutating();
  }

  markBaseOfStorageUse(base, isMutating);
}

void VarDeclUsageChecker::markBaseOfStorageUse(Expr *base, bool isMutating) {
  // CSApply sometimes wraps the base in an InOutExpr just because the
  // base is an l-value; look through that so we can get more precise
  // checking.
  if (auto *ioe = dyn_cast<InOutExpr>(base))
    base = ioe->getSubExpr();

  if (!isMutating) {
    base->walk(*this);
    return;
  }

  // Otherwise this is a read and write of the base.
  return markStoredOrInOutExpr(base, RK_Written|RK_Read);
}


void VarDeclUsageChecker::markStoredOrInOutExpr(Expr *E, unsigned Flags) {
  // Sema leaves some subexpressions null, which seems really unfortunate.  It
  // should replace them with ErrorExpr.
  if (E == nullptr || !E->getType() || E->getType()->hasError()) {
    sawError = true;
    return;
  }
  
  // Ignore parens and other easy cases.
  E = E->getSemanticsProvidingExpr();
  
  // If we found a decl that is being assigned to, then mark it.
  if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
    addMark(DRE->getDecl(), Flags);
    return;
  }
  
  if (auto *TE = dyn_cast<TupleExpr>(E)) {
    for (auto &elt : TE->getElements())
      markStoredOrInOutExpr(elt, Flags);
    return;
  }
  
  // If this is an assignment into a mutating subscript lvalue expr, then we
  // are mutating the base expression.  We also need to visit the index
  // expressions as loads though.
  if (auto *SE = dyn_cast<SubscriptExpr>(E)) {
    // The index of the subscript is evaluated as an rvalue.
    SE->getIndex()->walk(*this);
    markBaseOfStorageUse(SE->getBase(), SE->getDecl(), Flags);
    return;
  }
  
  // Likewise for key path applications. An application of a WritableKeyPath
  // reads and writes its base; an application of a ReferenceWritableKeyPath
  // only reads its base; the other KeyPath types cannot be written at all.
  if (auto *KPA = dyn_cast<KeyPathApplicationExpr>(E)) {
    auto &C = KPA->getType()->getASTContext();
    KPA->getKeyPath()->walk(*this);

    bool isMutating =
      (Flags & RK_Written) &&
      KPA->getKeyPath()->getType()->getAnyNominal()
        == C.getWritableKeyPathDecl();
    markBaseOfStorageUse(KPA->getBase(), isMutating);
    return;
  }
  
  if (auto *ioe = dyn_cast<InOutExpr>(E))
    return markStoredOrInOutExpr(ioe->getSubExpr(), RK_Written|RK_Read);
  
  if (auto *MRE = dyn_cast<MemberRefExpr>(E)) {
    markBaseOfStorageUse(MRE->getBase(), MRE->getMember(), Flags);
    return;
  }

  if (auto *TEE = dyn_cast<TupleElementExpr>(E))
    return markStoredOrInOutExpr(TEE->getBase(), Flags);
  
  if (auto *FVE = dyn_cast<ForceValueExpr>(E))
    return markStoredOrInOutExpr(FVE->getSubExpr(), Flags);

  if (auto *BOE = dyn_cast<BindOptionalExpr>(E))
    return markStoredOrInOutExpr(BOE->getSubExpr(), Flags);

  // Bind existential expressions.
  if (auto *OEE = dyn_cast<OpenExistentialExpr>(E)) {
    OpaqueValueMap[OEE->getOpaqueValue()] = OEE->getExistentialValue();
    return markStoredOrInOutExpr(OEE->getSubExpr(), Flags);
  }
  
  // If this is an OpaqueValueExpr that we've seen a mapping for, jump to the
  // mapped value.
  if (auto *OVE = dyn_cast<OpaqueValueExpr>(E))
    if (auto *expr = OpaqueValueMap[OVE])
      return markStoredOrInOutExpr(expr, Flags);

  // If we don't know what kind of expression this is, assume it's a reference
  // and mark it as a read.
  E->walk(*this);
}

/// The heavy lifting happens when visiting expressions.
std::pair<bool, Expr *> VarDeclUsageChecker::walkToExprPre(Expr *E) {
  STATISTIC(VarDeclUsageCheckerExprVisits,
            "# of times VarDeclUsageChecker::walkToExprPre is called");
  ++VarDeclUsageCheckerExprVisits;

  // Sema leaves some subexpressions null, which seems really unfortunate.  It
  // should replace them with ErrorExpr.
  if (E == nullptr || !E->getType() || E->getType()->hasError()) {
    sawError = true;
    return { false, E };
  }

  assert(AllExprsSeen.insert(E).second && "duplicate traversal");

  // If this is a DeclRefExpr found in a random place, it is a load of the
  // vardecl.
  if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
    addMark(DRE->getDecl(), RK_Read);

    // If the Expression is a read of a getter, track for diagnostics
    if (auto VD = dyn_cast<VarDecl>(DRE->getDecl())) {
      AssociatedGetterRefExpr.insert(std::make_pair(VD, DRE));
    }
  }
  // If the Expression is a member reference, see if it is a read of the getter
  // to track for diagnostics.
  if (auto *MRE = dyn_cast<MemberRefExpr>(E)) {
    if (auto VD = dyn_cast<VarDecl>(MRE->getMember().getDecl())) {
      AssociatedGetterRefExpr.insert(std::make_pair(VD, MRE));
      markBaseOfStorageUse(MRE->getBase(), MRE->getMember(), RK_Read);
      return { false, E };
    }
  }
  if (auto SE = dyn_cast<SubscriptExpr>(E)) {
    SE->getIndex()->walk(*this);
    markBaseOfStorageUse(SE->getBase(), SE->getDecl(), RK_Read);
    return { false, E };
  }

  // If this is an AssignExpr, see if we're mutating something that we know
  // about.
  if (auto *assign = dyn_cast<AssignExpr>(E)) {
    markStoredOrInOutExpr(assign->getDest(), RK_Written);
    
    // Don't walk into the LHS of the assignment, only the RHS.
    assign->getSrc()->walk(*this);
    return { false, E };
  }
  
  // '&x' is a read and write of 'x'.
  if (auto *io = dyn_cast<InOutExpr>(E)) {
    markStoredOrInOutExpr(io->getSubExpr(), RK_Read|RK_Written);
    // Don't bother walking into this.
    return { false, E };
  }
  
  // If we see an OpenExistentialExpr, remember the mapping for its OpaqueValue
  // and only walk the subexpr.
  if (auto *oee = dyn_cast<OpenExistentialExpr>(E)) {
    OpaqueValueMap[oee->getOpaqueValue()] = oee->getExistentialValue();
    oee->getSubExpr()->walk(*this);
    return { false, E };
  }

  // Visit bindings.
  if (auto ove = dyn_cast<OpaqueValueExpr>(E)) {
    if (auto mapping = OpaqueValueMap.lookup(ove))
      mapping->walk(*this);
    return { false, E };
  }
  
  // If we saw an ErrorExpr, take note of this.
  if (isa<ErrorExpr>(E))
    sawError = true;
  
  return { true, E };
}

/// handle #if directives.  All of the active clauses are already walked by the
/// AST walker, but we also want to handle the inactive ones to avoid false
/// positives.
void VarDeclUsageChecker::handleIfConfig(IfConfigDecl *ICD) {
  struct ConservativeDeclMarker : public ASTWalker {
    VarDeclUsageChecker &VDUC;
    SourceFile *SF;

    ConservativeDeclMarker(VarDeclUsageChecker &VDUC)
      : VDUC(VDUC), SF(VDUC.DC->getParentSourceFile()) {}

    Expr *walkToExprPost(Expr *E) override {
      // If we see a bound reference to a decl in an inactive #if block, then
      // conservatively mark it read and written.  This will silence "variable
      // unused" and "could be marked let" warnings for it.
      if (auto *DRE = dyn_cast<DeclRefExpr>(E))
        VDUC.addMark(DRE->getDecl(), RK_Read|RK_Written);
      else if (auto *declRef = dyn_cast<UnresolvedDeclRefExpr>(E)) {
        auto name = declRef->getName();
        auto loc = declRef->getLoc();
        if (name.isSimpleName() && loc.isValid()) {
          auto *varDecl = dyn_cast_or_null<VarDecl>(
            ASTScope::lookupSingleLocalDecl(SF, name.getFullName(), loc));
          if (varDecl)
            VDUC.addMark(varDecl, RK_Read|RK_Written);
        }
      }
      return E;
    }
  };

  for (auto &clause : ICD->getClauses()) {
    // Active clauses are handled by the normal AST walk.
    if (clause.isActive) continue;

    for (auto elt : clause.Elements)
      elt.walk(ConservativeDeclMarker(*this));
  }
}

/// Apply the warnings managed by VarDeclUsageChecker to the top level
/// code declarations that haven't been checked yet.
void swift::
performTopLevelDeclDiagnostics(TopLevelCodeDecl *TLCD) {
  auto &ctx = TLCD->getDeclContext()->getASTContext();
  VarDeclUsageChecker checker(TLCD, ctx.Diags);
  TLCD->walk(checker);
}

/// Perform diagnostics for func/init/deinit declarations.
void swift::performAbstractFuncDeclDiagnostics(AbstractFunctionDecl *AFD) {
  // Don't produce these diagnostics for implicitly generated code.
  if (AFD->getLoc().isInvalid() || AFD->isImplicit() || AFD->isInvalid())
    return;
  
  // Check for unused variables, as well as variables that are could be
  // declared as constants. Skip local functions though, since they will
  // be checked as part of their parent function or TopLevelCodeDecl.
  if (!AFD->getDeclContext()->isLocalContext()) {
    auto &ctx = AFD->getDeclContext()->getASTContext();
    VarDeclUsageChecker checker(AFD, ctx.Diags);
    AFD->walk(checker);
  }

  auto *body = AFD->getBody();

  // If the function has an opaque return type, check the return expressions
  // to determine the underlying type.
  if (auto opaqueResultTy = AFD->getOpaqueResultTypeDecl()) {
    OpaqueUnderlyingTypeChecker(AFD, opaqueResultTy, body).check();
  } else if (auto accessor = dyn_cast<AccessorDecl>(AFD)) {
    if (accessor->isGetter()) {
      if (auto opaqueResultTy
                          = accessor->getStorage()->getOpaqueResultTypeDecl()) {
        OpaqueUnderlyingTypeChecker(AFD, opaqueResultTy, body).check();
      }
    }
  }
}

// Perform MiscDiagnostics on Switch Statements.
static void checkSwitch(ASTContext &ctx, const SwitchStmt *stmt) {
  // We want to warn about "case .Foo, .Bar where 1 != 100:" since the where
  // clause only applies to the second case, and this is surprising.
  for (auto cs : stmt->getCases()) {
    TypeChecker::checkUnsupportedProtocolType(ctx, cs);

    // The case statement can have multiple case items, each can have a where.
    // If we find a "where", and there is a preceding item without a where, and
    // if they are on the same source line, then warn.
    auto items = cs->getCaseLabelItems();
    
    // Don't do any work for the vastly most common case.
    if (items.size() == 1) continue;
    
    // Ignore the first item, since it can't have preceding ones.
    for (unsigned i = 1, e = items.size(); i != e; ++i) {
      // Must have a where clause.
      auto where = items[i].getGuardExpr();
      if (!where)
        continue;
      
      // Preceding item must not.
      if (items[i-1].getGuardExpr())
        continue;
      
      // Must be on the same source line.
      auto prevLoc = items[i-1].getStartLoc();
      auto thisLoc = items[i].getStartLoc();
      if (prevLoc.isInvalid() || thisLoc.isInvalid())
        continue;
      
      auto &SM = ctx.SourceMgr;
      auto prevLineCol = SM.getLineAndColumnInBuffer(prevLoc);
      if (SM.getLineAndColumnInBuffer(thisLoc).first != prevLineCol.first)
        continue;

      ctx.Diags.diagnose(items[i].getWhereLoc(), diag::where_on_one_item)
        .highlight(items[i].getPattern()->getSourceRange())
        .highlight(where->getSourceRange());
      
      // Whitespace it out to the same column as the previous item.
      std::string whitespace(prevLineCol.second-1, ' ');
      ctx.Diags.diagnose(thisLoc, diag::add_where_newline)
        .fixItInsert(thisLoc, "\n"+whitespace);

      auto whereRange = SourceRange(items[i].getWhereLoc(),
                                    where->getEndLoc());
      auto charRange = Lexer::getCharSourceRangeFromSourceRange(SM, whereRange);
      auto whereText = SM.extractText(charRange);
      ctx.Diags.diagnose(prevLoc, diag::duplicate_where)
        .fixItInsertAfter(items[i-1].getEndLoc(), " " + whereText.str())
        .highlight(items[i-1].getSourceRange());
    }
  }
}

void swift::fixItEncloseTrailingClosure(ASTContext &ctx,
                                        InFlightDiagnostic &diag,
                                        const CallExpr *call,
                                        Identifier closureLabel) {
  auto argsExpr = call->getArg();

  SmallString<32> replacement;
  SourceLoc lastLoc;
  SourceRange closureRange;

  auto argList = getOriginalArgumentList(argsExpr);

  assert(argList.args.size() >= 1 && "must have at least one argument");

  if (argList.args.size() == 1) {
    closureRange = argList.args[0]->getSourceRange();
    lastLoc = argList.lParenLoc; // e.g funcName() { 1 }
    if (!lastLoc.isValid()) {
      // Bare trailing closure: e.g. funcName { 1 }
      replacement = "(";
      lastLoc = call->getFn()->getEndLoc();
    }
  } else {
    // Tuple + trailing closure: e.g. funcName(x: 1) { 1 }
    auto numElements = argList.args.size();
    closureRange = argList.args[numElements - 1]->getSourceRange();
    lastLoc = argList.args[numElements - 2]->getEndLoc();
    replacement = ", ";
  }

  // Add argument label of the closure.
  if (!closureLabel.empty()) {
    replacement += closureLabel.str();
    replacement += ": ";
  }

  lastLoc = Lexer::getLocForEndOfToken(ctx.SourceMgr, lastLoc);
  diag
    .fixItReplaceChars(lastLoc, closureRange.Start, replacement)
    .fixItInsertAfter(closureRange.End, ")");
}

// Perform checkStmtConditionTrailingClosure for single expression.
static void checkStmtConditionTrailingClosure(ASTContext &ctx, const Expr *E) {
  if (E == nullptr || isa<ErrorExpr>(E)) return;

  // Walk into expressions which might have invalid trailing closures
  class DiagnoseWalker : public ASTWalker {
    ASTContext &Ctx;

    void diagnoseIt(const CallExpr *E) {
      if (!E->hasTrailingClosure()) return;

      auto argsExpr = E->getArg();
      auto argsTy = argsExpr->getType();
      // Ignore invalid argument type. Some diagnostics are already emitted.
      if (!argsTy || argsTy->hasError()) return;

      SourceLoc closureLoc;
      if (auto PE = dyn_cast<ParenExpr>(argsExpr))
        closureLoc = PE->getSubExpr()->getStartLoc();
      else if (auto TE = dyn_cast<TupleExpr>(argsExpr))
        closureLoc = TE->getElements().back()->getStartLoc();

      Identifier closureLabel;
      if (auto TT = argsTy->getAs<TupleType>()) {
        assert(TT->getNumElements() != 0 && "Unexpected empty TupleType");
        closureLabel = TT->getElement(TT->getNumElements() - 1).getName();
      }

      auto diag = Ctx.Diags.diagnose(closureLoc,
                                     diag::trailing_closure_requires_parens);
      fixItEncloseTrailingClosure(Ctx, diag, E, closureLabel);
    }

  public:
    DiagnoseWalker(ASTContext &ctx) : Ctx(ctx) { }

    bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override {
      return false;
    }

    bool shouldWalkCaptureInitializerExpressions() override { return true; }

    bool shouldWalkIntoTapExpression() override { return false; }

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      switch (E->getKind()) {
      case ExprKind::Paren:
      case ExprKind::Tuple:
      case ExprKind::Array:
      case ExprKind::Dictionary:
      case ExprKind::InterpolatedStringLiteral:
        // If a trailing closure appears as a child of one of these types of
        // expression, don't diagnose it as there is no ambiguity.
        return {E->isImplicit(), E};
      case ExprKind::Call:
        diagnoseIt(cast<CallExpr>(E));
        break;
      default:
        break;
      }
      return {true, E};
    }
  };

  DiagnoseWalker Walker(ctx);
  const_cast<Expr *>(E)->walk(Walker);
}

/// Diagnose trailing closure in statement-conditions.
///
/// Conditional statements, including 'for' or `switch` doesn't allow ambiguous
/// trailing closures in these conditions part. Even if the parser can recover
/// them, we force them to disambiguate.
//
/// E.g.:
///   if let _ = arr?.map {$0+1} { ... }
///   for _ in numbers.filter {$0 > 4} { ... }
static void checkStmtConditionTrailingClosure(ASTContext &ctx, const Stmt *S) {
  if (auto LCS = dyn_cast<LabeledConditionalStmt>(S)) {
    for (auto elt : LCS->getCond()) {

      if (elt.getKind() == StmtConditionElement::CK_PatternBinding) {
        checkStmtConditionTrailingClosure(ctx, elt.getInitializer());
        if (auto *exprPattern = dyn_cast<ExprPattern>(elt.getPattern())) {
          checkStmtConditionTrailingClosure(ctx, exprPattern->getMatchExpr());
        }
      } else if (elt.getKind() == StmtConditionElement::CK_Boolean)
        checkStmtConditionTrailingClosure(ctx, elt.getBoolean());
      // No trailing closure for CK_Availability: e.g. `if #available() {}`.
    }
  } else if (auto SS = dyn_cast<SwitchStmt>(S)) {
    checkStmtConditionTrailingClosure(ctx, SS->getSubjectExpr());
  } else if (auto FES = dyn_cast<ForEachStmt>(S)) {
    checkStmtConditionTrailingClosure(ctx, FES->getSequence());
    checkStmtConditionTrailingClosure(ctx, FES->getWhere());
  } else if (auto DCS = dyn_cast<DoCatchStmt>(S)) {
    for (auto CS : DCS->getCatches())
      for (auto &LabelItem : CS->getCaseLabelItems())
        checkStmtConditionTrailingClosure(ctx, LabelItem.getGuardExpr());
  }
}

static Optional<ObjCSelector>
parseObjCSelector(ASTContext &ctx, StringRef string) {
  // Find the first colon.
  auto colonPos = string.find(':');

  // If there is no colon, we have a nullary selector.
  if (colonPos == StringRef::npos) {
    if (string.empty() || !Lexer::isIdentifier(string)) return None;
    return ObjCSelector(ctx, 0, { ctx.getIdentifier(string) });
  }

  SmallVector<Identifier, 2> pieces;
  do {
    // Check whether we have a valid selector piece.
    auto piece = string.substr(0, colonPos);
    if (piece.empty()) {
      pieces.push_back(Identifier());
    } else {
      if (!Lexer::isIdentifier(piece)) return None;
      pieces.push_back(ctx.getIdentifier(piece));
    }

    // Move to the next piece.
    string = string.substr(colonPos+1);
    colonPos = string.find(':');
  } while (colonPos != StringRef::npos);

  // If anything remains of the string, it's not a selector.
  if (!string.empty()) return None;

  return ObjCSelector(ctx, pieces.size(), pieces);
}


namespace {

class ObjCSelectorWalker : public ASTWalker {
  ASTContext &Ctx;
  const DeclContext *DC;
  Type SelectorTy;

  /// Determine whether a reference to the given method via its
  /// enclosing class/protocol is ambiguous (and, therefore, needs to
  /// be disambiguated with a coercion).
  bool isSelectorReferenceAmbiguous(AbstractFunctionDecl *method) {
    // Determine the name we would search for. If there are no
    // argument names, our lookup will be based solely on the base
    // name.
    DeclName lookupName = method->getName();
    if (lookupName.getArgumentNames().empty())
      lookupName = lookupName.getBaseName();

    // Look for members with the given name.
    auto nominal = method->getDeclContext()->getSelfNominalTypeDecl();
    auto result = TypeChecker::lookupMember(
        const_cast<DeclContext *>(DC), nominal->getDeclaredInterfaceType(),
        DeclNameRef(lookupName), defaultMemberLookupOptions);

    // If we didn't find multiple methods, there is no ambiguity.
    if (result.size() < 2) return false;

    // If we found more than two methods, it's ambiguous.
    if (result.size() > 2) return true;

    // Dig out the methods.
    auto firstMethod = dyn_cast<FuncDecl>(result[0].getValueDecl());
    auto secondMethod = dyn_cast<FuncDecl>(result[1].getValueDecl());
    if (!firstMethod || !secondMethod) return true;

    // If one is a static/class method and the other is not...
    if (firstMethod->isStatic() == secondMethod->isStatic()) return true;

    // ... overload resolution will prefer the static method. Check
    // that it has the correct selector. We don't even care that it's
    // the same method we're asking for, just that it has the right
    // selector.
    FuncDecl *staticMethod =
      firstMethod->isStatic() ? firstMethod : secondMethod;
    return staticMethod->getObjCSelector() != method->getObjCSelector();
  }

public:
  ObjCSelectorWalker(const DeclContext *dc, Type selectorTy)
    : Ctx(dc->getASTContext()), DC(dc), SelectorTy(selectorTy) { }

  bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override {
    return false;
  }

  bool shouldWalkCaptureInitializerExpressions() override { return true; }

  bool shouldWalkIntoTapExpression() override { return false; }

  std::pair<bool, Expr *> walkToExprPre(Expr *expr) override {
    auto *stringLiteral = dyn_cast<StringLiteralExpr>(expr);
    bool fromStringLiteral = false;
    bool hadParens = false;
    if (stringLiteral) {
      // Is this a string literal that has type 'Selector'.
      if (!stringLiteral->getType() ||
          !stringLiteral->getType()->isEqual(SelectorTy))
        return { true, expr };

      fromStringLiteral = true;

      // FIXME: hadParens
    } else {
      // Is this an initialization of 'Selector'?
      auto call = dyn_cast<CallExpr>(expr);
      if (!call) return { true, expr };

      // That produce Selectors.
      if (!call->getType() || !call->getType()->isEqual(SelectorTy))
        return { true, expr };

      // Via a constructor.
      ConstructorDecl *ctor = nullptr;
      if (auto ctorRefCall = dyn_cast<ConstructorRefCallExpr>(call->getFn())) {
        if (auto ctorRef = dyn_cast<DeclRefExpr>(ctorRefCall->getFn()))
          ctor = dyn_cast<ConstructorDecl>(ctorRef->getDecl());
        else if (auto otherCtorRef =
                   dyn_cast<OtherConstructorDeclRefExpr>(ctorRefCall->getFn()))
          ctor = otherCtorRef->getDecl();
      }

      if (!ctor) return { true, expr };

      // Make sure the constructor is within Selector.
      auto ctorContextType = ctor->getDeclContext()
          ->getSelfNominalTypeDecl()
          ->getDeclaredType();
      if (!ctorContextType || !ctorContextType->isEqual(SelectorTy))
        return { true, expr };

      auto argNames = ctor->getName().getArgumentNames();
      if (argNames.size() != 1) return { true, expr };

      // Is this the init(stringLiteral:) initializer or init(_:) initializer?
      if (argNames[0] == Ctx.Id_stringLiteral)
        fromStringLiteral = true;
      else if (!argNames[0].empty())
        return { true, expr };

      Expr *arg = call->getArg();

      if (auto paren = dyn_cast<ParenExpr>(arg))
        arg = paren->getSubExpr();
      else if (auto tuple = dyn_cast<TupleExpr>(arg))
        arg = tuple->getElement(0);
      else
        return { true, expr };

      // Track whether we had parentheses around the string literal.
      if (auto paren = dyn_cast<ParenExpr>(arg)) {
        hadParens = true;
        arg = paren->getSubExpr();
      }

      // Check whether we have a string literal.
      stringLiteral = dyn_cast<StringLiteralExpr>(arg);
      if (!stringLiteral) return { true, expr };
    }

    /// Retrieve the parent expression that coerces to Selector, if
    /// there is one.
    auto getParentCoercion = [&]() -> CoerceExpr * {
      auto parentExpr = Parent.getAsExpr();
      if (!parentExpr) return nullptr;

      auto coerce = dyn_cast<CoerceExpr>(parentExpr);
      if (!coerce) return nullptr;

      if (coerce->getType() && coerce->getType()->isEqual(SelectorTy))
        return coerce;

      return nullptr;
    };

    // Local function that adds the constructor syntax around string
    // literals implicitly treated as a Selector.
    auto addSelectorConstruction = [&](InFlightDiagnostic &diag) {
      if (!fromStringLiteral) return;

      // Introduce the beginning part of the Selector construction.
      diag.fixItInsert(stringLiteral->getLoc(), "Selector(");

      if (auto coerce = getParentCoercion()) {
        // If the string literal was coerced to Selector, replace the
        // coercion with the ")".
        SourceLoc endLoc = Lexer::getLocForEndOfToken(Ctx.SourceMgr,
                                                      expr->getEndLoc());
        diag.fixItReplace(SourceRange(endLoc, coerce->getEndLoc()), ")");
      } else {
        // Otherwise, just insert the closing ")".
        diag.fixItInsertAfter(stringLiteral->getEndLoc(), ")");
      }
    };

    // Try to parse the string literal as an Objective-C selector, and complain
    // if it isn't one.
    auto selector = parseObjCSelector(Ctx, stringLiteral->getValue());
    if (!selector) {
      auto diag = Ctx.Diags.diagnose(stringLiteral->getLoc(),
                                     diag::selector_literal_invalid);
      diag.highlight(stringLiteral->getSourceRange());
      addSelectorConstruction(diag);
      return { true, expr };
    }

    // Look for methods with this selector.
    SmallVector<AbstractFunctionDecl *, 8> allMethods;
    DC->lookupAllObjCMethods(*selector, allMethods);

    // If we didn't find any methods, complain.
    if (allMethods.empty()) {
      // If this was Selector(("selector-name")), suppress, the
      // diagnostic.
      if (!fromStringLiteral && hadParens)
        return { true, expr };

      {
        auto diag = Ctx.Diags.diagnose(stringLiteral->getLoc(),
                                       diag::selector_literal_undeclared,
                                       *selector);
        addSelectorConstruction(diag);
      }

      // If the result was from a Selector("selector-name"), add a
      // separate note that suggests wrapping the selector in
      // parentheses to silence the warning.
      if (!fromStringLiteral) {
        Ctx.Diags.diagnose(stringLiteral->getLoc(),
                           diag::selector_construction_suppress_warning)
          .fixItInsert(stringLiteral->getStartLoc(), "(")
          .fixItInsertAfter(stringLiteral->getEndLoc(), ")");
      }

      return { true, expr };
    }

    // Find the "best" method that has this selector, so we can report
    // that.
    AbstractFunctionDecl *bestMethod = nullptr;
    for (auto method : allMethods) {
      // If this is the first method, use it.
      if (!bestMethod) {
        bestMethod = method;
        continue;
      }

      // If referencing the best method would produce an ambiguity and
      // referencing the new method would not, we have a new "best".
      if (isSelectorReferenceAmbiguous(bestMethod) &&
          !isSelectorReferenceAmbiguous(method)) {
        bestMethod = method;
        continue;
      }

      // If this method is within a protocol...
      if (auto proto = method->getDeclContext()->getSelfProtocolDecl()) {
        // If the best so far is not from a protocol, or is from a
        // protocol that inherits this protocol, we have a new best.
        auto bestProto = bestMethod->getDeclContext()->getSelfProtocolDecl();
        if (!bestProto || bestProto->inheritsFrom(proto))
          bestMethod = method;
        continue;
      }

      // This method is from a class.
      auto classDecl = method->getDeclContext()->getSelfClassDecl();

      // If the best method was from a protocol, keep it.
      auto bestClassDecl = bestMethod->getDeclContext()->getSelfClassDecl();
      if (!bestClassDecl) continue;

      // If the best method was from a subclass of the place where
      // this method was declared, we have a new best.
      if (classDecl->isSuperclassOf(bestClassDecl)) {
        bestMethod = method;
      }
    }

    // If we have a best method, reference it.
    if (bestMethod) {
      // Form the replacement #selector expression.
      SmallString<32> replacement;
      {
        llvm::raw_svector_ostream out(replacement);
        auto nominal = bestMethod->getDeclContext()->getSelfNominalTypeDecl();
        out << "#selector(";

        DeclName name;
        auto bestAccessor = dyn_cast<AccessorDecl>(bestMethod);
        if (bestAccessor) {
          switch (bestAccessor->getAccessorKind()) {
          case AccessorKind::Get:
            out << "getter: ";
            name = bestAccessor->getStorage()->getName();
            break;

          case AccessorKind::Set:
          case AccessorKind::WillSet:
          case AccessorKind::DidSet:
            out << "setter: ";
            name = bestAccessor->getStorage()->getName();
            break;

          case AccessorKind::Address:
          case AccessorKind::MutableAddress:
          case AccessorKind::Read:
          case AccessorKind::Modify:
            llvm_unreachable("cannot be @objc");
          }
        } else {
          name = bestMethod->getName();
        }

        auto typeName = nominal->getName().str();
        // If we're inside a type Foo (or an extension of it) and the suggestion
        // is going to be #selector(Foo.bar) (or #selector(SuperclassOfFoo.bar),
        // then suggest the more natural #selector(self.bar) instead.
        if (auto containingTypeContext = DC->getInnermostTypeContext()) {
          auto methodNominalType = nominal->getDeclaredType();
          auto outerNomType = containingTypeContext->getSelfNominalTypeDecl()
                                                   ->getDeclaredType();
          if (methodNominalType->isEqual(outerNomType) ||
              methodNominalType->isExactSuperclassOf(outerNomType))
            typeName = "self";
        }

        out << typeName << "." << name.getBaseName();
        auto argNames = name.getArgumentNames();

        // Only print the parentheses if there are some argument
        // names, because "()" would indicate a call.
        if (!argNames.empty()) {
          out << "(";
          for (auto argName : argNames) {
            if (argName.empty()) out << "_";
            else out << argName.str();
            out << ":";
          }
          out << ")";
        }

        // If there will be an ambiguity when referring to the method,
        // introduce a coercion to resolve it to the method we found.
        if (!bestAccessor && isSelectorReferenceAmbiguous(bestMethod)) {
          if (auto fnType =
                bestMethod->getInterfaceType()->getAs<FunctionType>()) {
            // For static/class members, drop the metatype argument.
            if (bestMethod->isStatic())
              fnType = fnType->getResult()->getAs<FunctionType>();

            // Coerce to this type.
            assert(fnType->hasTypeRepr() &&
                   "Objective-C methods should always have printable types");
            out << " as ";
            fnType->print(out);
          }
        }

        out << ")";
      }

      // Emit the diagnostic.
      SourceRange replacementRange = expr->getSourceRange();
      if (auto coerce = getParentCoercion())
        replacementRange.End = coerce->getEndLoc();

      Ctx.Diags
          .diagnose(expr->getLoc(),
                    fromStringLiteral
                        ? diag::selector_literal_deprecated_suggest
                        : diag::selector_construction_suggest)
          .fixItReplace(replacementRange, replacement);
      return { true, expr };
    }

    // If we couldn't pick a method to use for #selector, just wrap
    // the string literal in Selector(...).
    if (fromStringLiteral) {
      auto diag = Ctx.Diags.diagnose(stringLiteral->getLoc(),
                                     diag::selector_literal_deprecated);
      addSelectorConstruction(diag);
      return { true, expr };
    }

    return { true, expr };
  }

};
} // end anonymous namespace

static void diagDeprecatedObjCSelectors(const DeclContext *dc,
                                        const Expr *expr) {
  auto selectorTy = dc->getASTContext().getSelectorType();
  if (!selectorTy) return;

  const_cast<Expr *>(expr)->walk(ObjCSelectorWalker(dc, selectorTy));
}

/// Skip over syntactic patterns that aren't typed patterns.
static Pattern *skipNonTypeSyntacticPatterns(Pattern *pattern) {
  if (auto *pp = dyn_cast<ParenPattern>(pattern))
    return skipNonTypeSyntacticPatterns(pp->getSubPattern());
  if (auto *vp = dyn_cast<BindingPattern>(pattern))
    return skipNonTypeSyntacticPatterns(vp->getSubPattern());
  return pattern;
}

/// Diagnose things like this, where 'i' is an Int, not an Int?
///     if let x: Int = i {
static void
checkImplicitPromotionsInCondition(const StmtConditionElement &cond,
                                   ASTContext &ctx) {
  auto *p = cond.getPatternOrNull();
  if (!p) return;
  
  if (auto *subExpr = isImplicitPromotionToOptional(cond.getInitializer())) {
    // If the subexpression was actually optional, then the pattern must be
    // checking for a type, which forced it to be promoted to a double optional
    // type.
    if (auto ooType = subExpr->getType()->getOptionalObjectType()) {
      if (auto OSP = dyn_cast<OptionalSomePattern>(p)) {
        // Check for 'if let' to produce a tuned diagnostic.
        if (auto *TP = dyn_cast<TypedPattern>(OSP->getSubPattern())) {
          ctx.Diags.diagnose(cond.getIntroducerLoc(),
                             diag::optional_check_promotion,
                             subExpr->getType())
            .highlight(subExpr->getSourceRange())
            .fixItReplace(TP->getTypeRepr()->getSourceRange(),
                          ooType->getString());
          return;
        }
      }
      ctx.Diags.diagnose(cond.getIntroducerLoc(),
                         diag::optional_pattern_match_promotion,
                         subExpr->getType(), cond.getInitializer()->getType())
        .highlight(subExpr->getSourceRange());
      return;
    }

    // Check for 'if let' to produce a tuned diagnostic.
    if (isa<OptionalSomePattern>(skipNonTypeSyntacticPatterns(p))) {
      ctx.Diags.diagnose(
          cond.getIntroducerLoc(),
          p->isImplicit()
            ? diag::condition_optional_element_pattern_not_valid_type
            : diag::optional_element_pattern_not_valid_type,
         subExpr->getType())
            .highlight(subExpr->getSourceRange());
      return;
    }

    ctx.Diags.diagnose(cond.getIntroducerLoc(),
                       diag::optional_check_nonoptional,
                       subExpr->getType())
      .highlight(subExpr->getSourceRange());
  }
}

static void diagnoseUnintendedOptionalBehavior(const Expr *E,
                                               const DeclContext *DC) {
  if (!E || isa<ErrorExpr>(E) || !E->getType())
    return;

  class UnintendedOptionalBehaviorWalker : public ASTWalker {
    ASTContext &Ctx;
    SmallPtrSet<Expr *, 16> IgnoredExprs;

    class OptionalToAnyCoercion {
    public:
      Type DestType;
      CoerceExpr *ParentCoercion;

      bool shouldSuppressDiagnostic() {
        // If we have a parent CoerceExpr that has the same type as our
        // Optional-to-Any coercion, don't emit a diagnostic.
        return ParentCoercion && ParentCoercion->getType()->isEqual(DestType);
      }
    };

    /// Returns true iff a coercion from srcType to destType is an
    /// Optional-to-Any coercion.
    bool isOptionalToAnyCoercion(Type srcType, Type destType) {
      size_t difference = 0;
      return isOptionalToAnyCoercion(srcType, destType, difference);
    }

    /// Returns true iff a coercion from srcType to destType is an
    /// Optional-to-Any coercion. On returning true, the value of 'difference'
    /// will be the difference in the levels of optionality.
    bool isOptionalToAnyCoercion(Type srcType, Type destType,
                                 size_t &difference) {
      SmallVector<Type, 4> destOptionals;
      auto destValueType =
        destType->lookThroughAllOptionalTypes(destOptionals);

      if (!destValueType->isAny())
        return false;

      SmallVector<Type, 4> srcOptionals;
      srcType->lookThroughAllOptionalTypes(srcOptionals);

      if (srcOptionals.size() > destOptionals.size()) {
        difference = srcOptionals.size() - destOptionals.size();
        return true;
      } else {
        return false;
      }
    }

    /// Returns true iff the collection upcast coercion is an Optional-to-Any
    /// coercion.
    bool isOptionalToAnyCoercion(CollectionUpcastConversionExpr::ConversionPair
                                   conversion) {
      if (!conversion.OrigValue || !conversion.Conversion)
        return false;

      auto srcType = conversion.OrigValue->getType();
      auto destType = conversion.Conversion->getType();
      return isOptionalToAnyCoercion(srcType, destType);
    }

    /// Looks through OptionalEvaluationExprs and InjectIntoOptionalExprs to
    /// find a child ErasureExpr, returning nullptr if no such child is found.
    /// Any intermediate OptionalEvaluationExprs will be marked as ignored.
    ErasureExpr *findErasureExprThroughOptionalInjections(Expr *E) {
      while (true) {
        if (auto *next = dyn_cast<OptionalEvaluationExpr>(E)) {
          // We don't want to re-visit any intermediate optional evaluations.
          IgnoredExprs.insert(next);
          E = next->getSubExpr();
        } else if (auto *next = dyn_cast<InjectIntoOptionalExpr>(E)) {
          E = next->getSubExpr();
        } else {
          break;
        }
      }
      return dyn_cast<ErasureExpr>(E);
    }

    void emitSilenceOptionalAnyWarningWithCoercion(Expr *E, Type destType) {
      assert(destType->hasTypeRepr() &&
             "coercion to Any should always be printable");

      SmallString<16> coercionString;
      coercionString += " as ";
      coercionString += destType->getWithoutParens()->getString();

      Ctx.Diags.diagnose(E->getLoc(), diag::silence_optional_to_any,
                         destType, coercionString.substr(1))
        .highlight(E->getSourceRange())
        .fixItInsertAfter(E->getEndLoc(), coercionString);
    }

    static bool hasImplicitlyUnwrappedResult(Expr *E) {
      auto *decl = getDeclForImplicitlyUnwrappedExpr(E);

      return decl && decl->isImplicitlyUnwrappedOptional();
    }

    static ValueDecl *getDeclForImplicitlyUnwrappedExpr(Expr *E) {
      E = E->getValueProvidingExpr();

      // Look through implicit conversions like loads, derived-to-base
      // conversion, etc.
      if (auto *ICE = dyn_cast<ImplicitConversionExpr>(E)) {
        E = ICE->getSubExpr();
      }

      if (auto *subscript = dyn_cast<SubscriptExpr>(E)) {
        if (subscript->hasDecl())
          return subscript->getDecl().getDecl();
        return nullptr;
      }

      if (auto *memberRef = dyn_cast<MemberRefExpr>(E))
        return memberRef->getMember().getDecl();

      if (auto *declRef = dyn_cast<DeclRefExpr>(E))
        return declRef->getDecl();

      if (auto *apply = dyn_cast<ApplyExpr>(E)) {
        auto *decl = apply->getCalledValue();
        if (decl && isa<AbstractFunctionDecl>(decl))
          return decl;
      }
      return nullptr;
    }

    void visitErasureExpr(ErasureExpr *E, OptionalToAnyCoercion coercion) {
      if (coercion.shouldSuppressDiagnostic())
        return;

      auto subExpr = E->getSubExpr();

      // Look through any BindOptionalExprs, as the coercion may have started
      // from a higher level of optionality.
      while (auto *bindExpr = dyn_cast<BindOptionalExpr>(subExpr))
        subExpr = bindExpr->getSubExpr();

      // Do not warn on coercions from implicitly unwrapped optionals
      // for Swift versions less than 5.
      if (!Ctx.isSwiftVersionAtLeast(5) &&
          hasImplicitlyUnwrappedResult(subExpr))
        return;

      // We're taking the source type from the child of any BindOptionalExprs,
      // and the destination from the parent of any
      // (InjectIntoOptional/OptionalEvaluation)Exprs in order to take into
      // account any bindings that need to be done for nested Optional-to-Any
      // coercions, e.g Int??? to Any?.
      auto srcType = subExpr->getType();
      auto destType = coercion.DestType;

      size_t optionalityDifference = 0;
      if (!isOptionalToAnyCoercion(srcType, destType, optionalityDifference))
        return;
      
      // If we're implicitly unwrapping from IUO to Any then emit a custom
      // diagnostic
      if (hasImplicitlyUnwrappedResult(subExpr)) {
        if (auto decl = getDeclForImplicitlyUnwrappedExpr(subExpr)) {
          Ctx.Diags.diagnose(subExpr->getStartLoc(), diag::iuo_to_any_coercion,
                             /* from */ srcType, /* to */ destType)
              .highlight(subExpr->getSourceRange());

          auto noteDiag = isa<FuncDecl>(decl)
                              ? diag::iuo_to_any_coercion_note_func_result
                              : diag::iuo_to_any_coercion_note;

          Ctx.Diags.diagnose(decl->getLoc(), noteDiag,
                             decl->getDescriptiveKind(), decl->getName());
        }
      } else {
        Ctx.Diags.diagnose(subExpr->getStartLoc(),
                           diag::optional_to_any_coercion,
                           /* from */ srcType, /* to */ destType)
            .highlight(subExpr->getSourceRange());
      }
      
      if (optionalityDifference == 1) {
        Ctx.Diags.diagnose(subExpr->getLoc(), diag::default_optional_to_any)
            .highlight(subExpr->getSourceRange())
            .fixItInsertAfter(subExpr->getEndLoc(), " ?? <#default value#>");
      }

      SmallString<4> forceUnwrapString;
      for (size_t i = 0; i < optionalityDifference; ++i)
        forceUnwrapString += "!";

      Ctx.Diags.diagnose(subExpr->getLoc(), diag::force_optional_to_any)
        .highlight(subExpr->getSourceRange())
        .fixItInsertAfter(subExpr->getEndLoc(), forceUnwrapString);

      emitSilenceOptionalAnyWarningWithCoercion(subExpr, destType);
    }

    void visitCollectionUpcastExpr(CollectionUpcastConversionExpr *E,
                                   OptionalToAnyCoercion coercion) {
      // We only need to consider the valueConversion, as the Key type of a
      // Dictionary cannot be implicitly coerced to Any.
      auto valueConversion = E->getValueConversion();

      // We're handling the coercion of the entire collection, so we don't need
      // to re-visit a nested ErasureExpr for the value.
      if (auto conversionExpr = valueConversion.Conversion)
        if (auto *erasureExpr =
              findErasureExprThroughOptionalInjections(conversionExpr))
          IgnoredExprs.insert(erasureExpr);

      if (coercion.shouldSuppressDiagnostic() ||
          !isOptionalToAnyCoercion(valueConversion))
        return;

      auto subExpr = E->getSubExpr();

      Ctx.Diags.diagnose(subExpr->getStartLoc(), diag::optional_to_any_coercion,
                         /* from */ subExpr->getType(), /* to */ E->getType())
        .highlight(subExpr->getSourceRange());

      emitSilenceOptionalAnyWarningWithCoercion(subExpr, E->getType());
    }

    void visitPossibleOptionalToAnyExpr(Expr *E,
                                        OptionalToAnyCoercion coercion) {
      if (auto *upcastExpr =
          dyn_cast<CollectionUpcastConversionExpr>(E)) {
        visitCollectionUpcastExpr(upcastExpr, coercion);
      } else if (auto *erasureExpr = dyn_cast<ErasureExpr>(E)) {
        visitErasureExpr(erasureExpr, coercion);
      } else if (auto *optionalEvalExpr = dyn_cast<OptionalEvaluationExpr>(E)) {
        // The ErasureExpr could be nested within optional injections and
        // bindings, such as is the case for e.g Int??? to Any?. Try and find
        // and visit it directly, making sure we don't re-visit it later.
        auto subExpr = optionalEvalExpr->getSubExpr();
        if (auto *erasureExpr =
              findErasureExprThroughOptionalInjections(subExpr)) {
          visitErasureExpr(erasureExpr, coercion);
          IgnoredExprs.insert(erasureExpr);
        }
      }
    }

    enum class UnintendedInterpolationKind: bool {
      Optional,
      Function
    };

    void visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E) {
      E->forEachSegment(Ctx,
          [&](bool isInterpolation, CallExpr *segment) -> void {
        if (isInterpolation) {
          diagnoseIfUnintendedInterpolation(segment,
                              UnintendedInterpolationKind::Optional);
          diagnoseIfUnintendedInterpolation(segment,
                              UnintendedInterpolationKind::Function);
        }
      });
    }

    void diagnoseIfUnintendedInterpolation(CallExpr *segment,
                                           UnintendedInterpolationKind kind) {
      if (interpolationWouldBeUnintended(segment->getCalledValue(), kind))
        if (auto firstArg =
              getFirstArgIfUnintendedInterpolation(segment->getArg(), kind))
          diagnoseUnintendedInterpolation(firstArg, kind);
    }

    bool interpolationWouldBeUnintended(ConcreteDeclRef appendMethod,
                                        UnintendedInterpolationKind kind) {
      ValueDecl * fnDecl = appendMethod.getDecl();

      // If things aren't set up right, just hope for the best.
      if (!fnDecl || fnDecl->isInvalid())
        return false;

      // If the decl expects an optional, that's fine.
      auto uncurriedType = fnDecl->getInterfaceType()->getAs<AnyFunctionType>();
      auto curriedType = uncurriedType->getResult()->getAs<AnyFunctionType>();

      // I don't know why you'd use a zero-arg interpolator, but it obviously 
      // doesn't interpolate an optional.
      if (curriedType->getNumParams() == 0)
        return false;

      // If the first parameter explicitly accepts the type, this method 
      // presumably doesn't want us to warn about optional use.
      auto firstParamType =
        curriedType->getParams().front().getPlainType()->getRValueType();
      if (kind == UnintendedInterpolationKind::Optional) {
        if (firstParamType->getOptionalObjectType())
          return false;
      } else {
        if (firstParamType->is<AnyFunctionType>())
          return false;
      }

      return true;
    }

    Expr *
    getFirstArgIfUnintendedInterpolation(Expr *args,
                                         UnintendedInterpolationKind kind) {
      // Just check the first argument, which is usually the value 
      // being interpolated.
      Expr *firstArg;
      if (auto parenExpr = dyn_cast_or_null<ParenExpr>(args)) {
        firstArg = parenExpr->getSubExpr();
      } else if (auto tupleExpr = dyn_cast_or_null<TupleExpr>(args)) {
        if (tupleExpr->getNumElements())
          firstArg = tupleExpr->getElement(0);
        else
          return nullptr;
      }
      else {
        firstArg = args;
      }

      // Allow explicit casts.
      if (isa<ExplicitCastExpr>(firstArg->getSemanticsProvidingExpr()))
        return nullptr;

      // If we don't have a type, assume the best.
      if (!firstArg->getType() || firstArg->getType()->hasError())
        return nullptr;

      // Bail out if we don't have an optional.
      if (kind == UnintendedInterpolationKind::Optional) {
        if (!firstArg->getType()->getRValueType()->getOptionalObjectType())
          return nullptr;
      }
      else if (kind == UnintendedInterpolationKind::Function) {
        if (!firstArg->getType()->getRValueType()->is<AnyFunctionType>())
          return nullptr;
      }

      return firstArg;
    }

    void diagnoseUnintendedInterpolation(Expr * arg, UnintendedInterpolationKind kind) {
      Ctx.Diags
          .diagnose(arg->getStartLoc(),
                    diag::debug_description_in_string_interpolation_segment,
                    (bool)kind)
          .highlight(arg->getSourceRange());

      // Suggest 'String(describing: <expr>)'.
      auto argStart = arg->getStartLoc();
      Ctx.Diags
          .diagnose(
              arg->getLoc(),
              diag::silence_debug_description_in_interpolation_segment_call)
          .highlight(arg->getSourceRange())
          .fixItInsert(argStart, "String(describing: ")
          .fixItInsertAfter(arg->getEndLoc(), ")");

      if (kind == UnintendedInterpolationKind::Optional) {
        // Suggest inserting a default value.
        Ctx.Diags.diagnose(arg->getLoc(), diag::default_optional_to_any)
          .highlight(arg->getSourceRange())
          .fixItInsertAfter(arg->getEndLoc(), " ?? <#default value#>");
      }
    }

    bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override {
      return false;
    }

    bool shouldWalkCaptureInitializerExpressions() override { return true; }

    bool shouldWalkIntoTapExpression() override { return false; }

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      if (!E || isa<ErrorExpr>(E) || !E->getType())
        return { false, E };

      if (IgnoredExprs.count(E))
        return { true, E };

      if (auto *literal = dyn_cast<InterpolatedStringLiteralExpr>(E)) {
        visitInterpolatedStringLiteralExpr(literal);
      } else if (auto *coercion = dyn_cast<CoerceExpr>(E)) {
        // If we come across a CoerceExpr, visit its subExpr with the coercion
        // as the parent, making sure we don't re-visit the subExpr later.
        auto subExpr = coercion->getSubExpr();
        visitPossibleOptionalToAnyExpr(subExpr,
                                       { subExpr->getType(), coercion });
        IgnoredExprs.insert(subExpr);
      } else {
        visitPossibleOptionalToAnyExpr(E, { E->getType(), nullptr });
      }
      return { true, E };
    }

  public:
    UnintendedOptionalBehaviorWalker(ASTContext &ctx) : Ctx(ctx) { }
  };

  UnintendedOptionalBehaviorWalker Walker(DC->getASTContext());
  const_cast<Expr *>(E)->walk(Walker);
}

static void diagnoseDeprecatedWritableKeyPath(const Expr *E,
                                              const DeclContext *DC) {
  if (!E || isa<ErrorExpr>(E) || !E->getType())
    return;

  class DeprecatedWritableKeyPathWalker : public ASTWalker {
    ASTContext &Ctx;
    const DeclContext *DC;

    void visitKeyPathApplicationExpr(KeyPathApplicationExpr *E) {
      bool isWrite = false;
      if (auto *P = Parent.getAsExpr())
        if (auto *AE = dyn_cast<AssignExpr>(P))
          if (AE->getDest() == E)
            isWrite = true;

      if (!isWrite)
        return;

      if (auto *keyPathExpr = dyn_cast<KeyPathExpr>(E->getKeyPath())) {
        auto *decl = keyPathExpr->getType()->getNominalOrBoundGenericNominal();
        if (decl != Ctx.getWritableKeyPathDecl() &&
            decl != Ctx.getReferenceWritableKeyPathDecl())
          return;

        assert(keyPathExpr->getComponents().size() > 0);
        auto &component = keyPathExpr->getComponents().back();
        if (component.getKind() == KeyPathExpr::Component::Kind::Property) {
          auto *storage =
            cast<AbstractStorageDecl>(component.getDeclRef().getDecl());
          if (!storage->isSettable(nullptr) ||
              !storage->isSetterAccessibleFrom(DC)) {
            Ctx.Diags.diagnose(keyPathExpr->getLoc(),
                               swift::diag::expr_deprecated_writable_keypath,
                               storage->getName());
          }
        }
      }
    }

    bool shouldWalkIntoSeparatelyCheckedClosure(ClosureExpr *expr) override {
      return false;
    }

    bool shouldWalkCaptureInitializerExpressions() override { return true; }

    bool shouldWalkIntoTapExpression() override { return false; }

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      if (!E || isa<ErrorExpr>(E) || !E->getType())
        return {false, E};

      if (auto *KPAE = dyn_cast<KeyPathApplicationExpr>(E)) {
        visitKeyPathApplicationExpr(KPAE);
        return {true, E};
      }

      return {true, E};
    }

  public:
    DeprecatedWritableKeyPathWalker(const DeclContext *DC)
        : Ctx(DC->getASTContext()), DC(DC) {}
  };

  DeprecatedWritableKeyPathWalker Walker(DC);
  const_cast<Expr *>(E)->walk(Walker);
}

static void maybeDiagnoseCallToKeyValueObserveMethod(const Expr *E,
                                                     const DeclContext *DC) {
  class KVOObserveCallWalker : public ASTWalker {
    const ASTContext &C;

  public:
    KVOObserveCallWalker(ASTContext &ctx) : C(ctx) {}

    void maybeDiagnoseCallExpr(CallExpr *expr) {
      auto fn = expr->getCalledValue();
      if (!fn)
        return;
      if (fn->getModuleContext()->getName() != C.Id_Foundation)
        return;
      if (!fn->getName().isCompoundName("observe",
                                        {"", "options", "changeHandler"}))
        return;
      auto args = cast<TupleExpr>(expr->getArg());
      auto firstArg = dyn_cast<KeyPathExpr>(args->getElement(0));
      if (!firstArg)
        return;
      auto lastComponent = firstArg->getComponents().back();
      if (lastComponent.getKind() != KeyPathExpr::Component::Kind::Property)
        return;
      auto property = lastComponent.getDeclRef().getDecl();
      if (!property)
        return;
      auto propertyVar = cast<VarDecl>(property);
      if (propertyVar->shouldUseObjCDispatch() ||
          (propertyVar->isObjC() &&
           propertyVar->getParsedAccessor(AccessorKind::Set)))
        return;
      C.Diags
          .diagnose(expr->getLoc(),
                    diag::observe_keypath_property_not_objc_dynamic,
                    property->getName(), fn->getName())
          .highlight(lastComponent.getLoc());
    }

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      if (!E || isa<ErrorExpr>(E) || !E->getType())
        return {false, E};

      if (auto *CE = dyn_cast<CallExpr>(E)) {
        maybeDiagnoseCallExpr(CE);
        return {false, E};
      }

      return {true, E};
    }
  };

  KVOObserveCallWalker Walker(DC->getASTContext());
  const_cast<Expr *>(E)->walk(Walker);
}

static void diagnoseExplicitUseOfLazyVariableStorage(const Expr *E,
                                                     const DeclContext *DC) {

  class ExplicitLazyVarStorageAccessFinder : public ASTWalker {
    const ASTContext &C;

  public:
    ExplicitLazyVarStorageAccessFinder(ASTContext &ctx) : C(ctx) {}

    void tryDiagnoseExplicitLazyStorageVariableUse(MemberRefExpr *MRE) {
      if (MRE->isImplicit()) {
        return;
      }
      auto VD = dyn_cast<VarDecl>(MRE->getMember().getDecl());
      if (!VD) {
        return;
      }
      auto sourceFileKind = VD->getDeclContext()->getParentSourceFile();
      if (!sourceFileKind) {
        return;
      }
      if (sourceFileKind->Kind != SourceFileKind::Library &&
          sourceFileKind->Kind != SourceFileKind::Main) {
        return;
      }
      if (VD->isLazyStorageProperty()) {
        C.Diags.diagnose(MRE->getLoc(), diag::lazy_var_storage_access);
      }
    }

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      if (!E || isa<ErrorExpr>(E) || !E->getType())
        return {false, E};

      if (auto *MRE = dyn_cast<MemberRefExpr>(E)) {
        tryDiagnoseExplicitLazyStorageVariableUse(MRE);
        return {false, E};
      }

      return {true, E};
    }
  };

  ExplicitLazyVarStorageAccessFinder Walker(DC->getASTContext());
  const_cast<Expr *>(E)->walk(Walker);
}

static void diagnoseComparisonWithNaN(const Expr *E, const DeclContext *DC) {
  class ComparisonWithNaNFinder : public ASTWalker {
    const ASTContext &C;
    const DeclContext *DC;

  public:
    ComparisonWithNaNFinder(const DeclContext *dc)
        : C(dc->getASTContext()), DC(dc) {}

    void tryDiagnoseComparisonWithNaN(BinaryExpr *BE) {
      ValueDecl *comparisonDecl = nullptr;

      // Comparison functions like == or <= take two arguments.
      if (BE->getArg()->getNumElements() != 2) {
        return;
      }

      // Dig out the function declaration.
      if (auto Fn = BE->getFn()) {
        if (auto DSCE = dyn_cast<DotSyntaxCallExpr>(Fn)) {
          comparisonDecl = DSCE->getCalledValue();
        } else {
          comparisonDecl = BE->getCalledValue();
        }
      }

      // Bail out if it isn't a function.
      if (!comparisonDecl || !isa<FuncDecl>(comparisonDecl)) {
        return;
      }

      // We're only interested in comparison functions like == or <=.
      auto comparisonDeclName = comparisonDecl->getBaseIdentifier();
      if (!comparisonDeclName.isStandardComparisonOperator()) {
        return;
      }

      auto firstArg = BE->getArg()->getElement(0);
      auto secondArg = BE->getArg()->getElement(1);

      // Both arguments must conform to FloatingPoint protocol.
      if (!conformsToKnownProtocol(const_cast<DeclContext *>(DC),
                                   firstArg->getType(),
                                   KnownProtocolKind::FloatingPoint) ||
          !conformsToKnownProtocol(const_cast<DeclContext *>(DC),
                                   secondArg->getType(),
                                   KnownProtocolKind::FloatingPoint)) {
        return;
      }

      // Convenience utility to extract argument decl.
      auto extractArgumentDecl = [&](Expr *arg) -> ValueDecl * {
        if (auto DRE = dyn_cast<DeclRefExpr>(arg)) {
          return DRE->getDecl();
        } else if (auto MRE = dyn_cast<MemberRefExpr>(arg)) {
          return MRE->getMember().getDecl();
        }
        return nullptr;
      };

      // Dig out the declarations for the arguments.
      auto *firstVal = extractArgumentDecl(firstArg);
      auto *secondVal = extractArgumentDecl(secondArg);

      // If we can't find declarations for both arguments, bail out,
      // because one of them has to be '.nan'.
      if (!firstArg && !secondArg) {
        return;
      }

      // Convenience utility to check if this is a 'nan' variable.
      auto isNanDecl = [&](ValueDecl *VD) {
        return VD && isa<VarDecl>(VD) && VD->getBaseIdentifier().is("nan");
      };

      // Diagnose comparison with '.nan'.
      //
      // If the comparison is done using '<=', '<', '==', '>', '>=', then
      // the result is always false. If the comparison is done using '!=',
      // then the result is always true.
      //
      // Emit a different diagnostic which doesn't mention using '.isNaN' if
      // the comparison isn't done using '==' or '!=' or if both sides are
      // '.nan'.
      if (isNanDecl(firstVal) && isNanDecl(secondVal)) {
        C.Diags.diagnose(BE->getLoc(), diag::nan_comparison_both_nan,
                         comparisonDeclName.str(), comparisonDeclName.is("!="));
      } else if (isNanDecl(firstVal) || isNanDecl(secondVal)) {
        if (comparisonDeclName.is("==") || comparisonDeclName.is("!=")) {
          auto exprStr =
              C.SourceMgr
                  .extractText(Lexer::getCharSourceRangeFromSourceRange(
                      C.SourceMgr, firstArg->getSourceRange()))
                  .str();
          auto prefix = exprStr;
          if (comparisonDeclName.is("!=")) {
            prefix = "!" + prefix;
          }
          C.Diags.diagnose(BE->getLoc(), diag::nan_comparison,
                           comparisonDeclName, comparisonDeclName.is("!="),
                           prefix, exprStr);
        } else {
          C.Diags.diagnose(BE->getLoc(), diag::nan_comparison_without_isnan,
                           comparisonDeclName, comparisonDeclName.is("!="));
        }
      }
    }

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      if (!E || isa<ErrorExpr>(E) || !E->getType())
        return {false, E};

      if (auto *BE = dyn_cast<BinaryExpr>(E)) {
        tryDiagnoseComparisonWithNaN(BE);
        return {false, E};
      }

      return {true, E};
    }
  };

  ComparisonWithNaNFinder Walker(DC);
  const_cast<Expr *>(E)->walk(Walker);
}

//===----------------------------------------------------------------------===//
// High-level entry points.
//===----------------------------------------------------------------------===//

/// Emit diagnostics for syntactic restrictions on a given expression.
void swift::performSyntacticExprDiagnostics(const Expr *E,
                                            const DeclContext *DC,
                                            bool isExprStmt) {
  auto &ctx = DC->getASTContext();
  TypeChecker::diagnoseSelfAssignment(E);
  diagSyntacticUseRestrictions(E, DC, isExprStmt);
  diagRecursivePropertyAccess(E, DC);
  diagnoseImplicitSelfUseInClosure(E, DC);
  diagnoseUnintendedOptionalBehavior(E, DC);
  maybeDiagnoseCallToKeyValueObserveMethod(E, DC);
  diagnoseExplicitUseOfLazyVariableStorage(E, DC);
  diagnoseComparisonWithNaN(E, DC);
  if (!ctx.isSwiftVersionAtLeast(5))
    diagnoseDeprecatedWritableKeyPath(E, DC);
  if (!ctx.LangOpts.DisableAvailabilityChecking)
    diagnoseExprAvailability(E, const_cast<DeclContext*>(DC));
  if (ctx.LangOpts.EnableObjCInterop)
    diagDeprecatedObjCSelectors(DC, E);
  diagnoseConstantArgumentRequirement(E, DC);
}

void swift::performStmtDiagnostics(const Stmt *S, DeclContext *DC) {
  auto &ctx = DC->getASTContext();

  TypeChecker::checkUnsupportedProtocolType(ctx, const_cast<Stmt *>(S));
    
  if (auto switchStmt = dyn_cast<SwitchStmt>(S))
    checkSwitch(ctx, switchStmt);

  checkStmtConditionTrailingClosure(ctx, S);
  
  // Check for implicit optional promotions in stmt-condition patterns.
  if (auto *lcs = dyn_cast<LabeledConditionalStmt>(S))
    for (const auto &elt : lcs->getCond())
      checkImplicitPromotionsInCondition(elt, ctx);

  if (!ctx.LangOpts.DisableAvailabilityChecking)
    diagnoseStmtAvailability(S, const_cast<DeclContext*>(DC));
}

//===----------------------------------------------------------------------===//
// Utility functions
//===----------------------------------------------------------------------===//

void swift::fixItAccess(InFlightDiagnostic &diag, ValueDecl *VD,
                        AccessLevel desiredAccess, bool isForSetter,
                        bool shouldUseDefaultAccess) {
  StringRef fixItString;
  switch (desiredAccess) {
  case AccessLevel::Private:      fixItString = "private ";      break;
  case AccessLevel::FilePrivate:  fixItString = "fileprivate ";  break;
  case AccessLevel::Internal:     fixItString = "internal ";     break;
  case AccessLevel::Public:       fixItString = "public ";       break;
  case AccessLevel::Open:         fixItString = "open ";         break;
  }

  DeclAttributes &attrs = VD->getAttrs();
  AbstractAccessControlAttr *attr;
  if (isForSetter) {
    attr = attrs.getAttribute<SetterAccessAttr>();
    cast<AbstractStorageDecl>(VD)->overwriteSetterAccess(desiredAccess);
  } else {
    attr = attrs.getAttribute<AccessControlAttr>();
    VD->overwriteAccess(desiredAccess);

    if (auto *ASD = dyn_cast<AbstractStorageDecl>(VD)) {
      if (auto *getter = ASD->getAccessor(AccessorKind::Get))
        getter->overwriteAccess(desiredAccess);

      if (auto *setterAttr = attrs.getAttribute<SetterAccessAttr>()) {
        if (setterAttr->getAccess() > desiredAccess)
          fixItAccess(diag, VD, desiredAccess, true);
      } else {
        ASD->overwriteSetterAccess(desiredAccess);
      }
    }
  }

  if (isForSetter && VD->getFormalAccess() == desiredAccess) {
    assert(attr);
    attr->setInvalid();
    // Remove the setter attribute.
    diag.fixItRemove(attr->Range);

  } else if (attr) {
    // If the formal access already matches the desired access, the problem
    // must be in a parent scope. Don't emit a fix-it.
    // FIXME: It's also possible for access to already be /broader/ than what's
    // desired, in which case the problem is also in a parent scope. However,
    // this function is sometimes called to make access narrower, so assuming
    // that a broader scope is acceptable breaks some diagnostics.
    if (attr->getAccess() != desiredAccess) {
      if (shouldUseDefaultAccess) {
        // Remove the attribute if replacement is not preferred.
        diag.fixItRemove(attr->getRange());
      } else {
        // This uses getLocation() instead of getRange() because we don't want to
        // replace the "(set)" part of a setter attribute.
        diag.fixItReplace(attr->getLocation(), fixItString.drop_back());
      }
      attr->setInvalid();
    }

  } else if (auto *override = VD->getAttrs().getAttribute<OverrideAttr>()) {
    // Insert the access in front of 'override', if it exists, in order to
    // match the same keyword order as produced by method autocompletion.
    diag.fixItInsert(override->getLocation(), fixItString);

  } else if (auto var = dyn_cast<VarDecl>(VD)) {
    if (auto PBD = var->getParentPatternBinding())
      diag.fixItInsert(PBD->getStartLoc(), fixItString);

  } else {
    diag.fixItInsert(VD->getStartLoc(), fixItString);
  }
}

/// Retrieve the type name to be used for determining whether we can
/// omit needless words.
static OmissionTypeName getTypeNameForOmission(Type type) {
  if (!type)
    return "";

  ASTContext &ctx = type->getASTContext();
  Type boolType;
  if (auto boolDecl = ctx.getBoolDecl())
    boolType = boolDecl->getDeclaredInterfaceType();
  auto objcBoolType = ctx.getObjCBoolType();

  /// Determine the options associated with the given type.
  auto getOptions = [&](Type type) {
    // Look for Boolean types.
    OmissionTypeOptions options;

    // Look for Boolean types.
    if (boolType && type->isEqual(boolType)) {
      // Swift.Bool
      options |= OmissionTypeFlags::Boolean;
    } else if (objcBoolType && type->isEqual(objcBoolType)) {
      // ObjectiveC.ObjCBool
      options |= OmissionTypeFlags::Boolean;
    }

    return options;
  };

  do {
    // Look through typealiases.
    if (auto aliasTy = dyn_cast<TypeAliasType>(type.getPointer())) {
      type = aliasTy->getSinglyDesugaredType();
      continue;
    }

    // Strip off lvalue/inout types.
    Type newType = type->getWithoutSpecifierType();
    if (newType.getPointer() != type.getPointer()) {
      type = newType;
      continue;
    }

    // Look through reference-storage types.
    newType = type->getReferenceStorageReferent();
    if (newType.getPointer() != type.getPointer()) {
      type = newType;
      continue;
    }

    // Look through parentheses.
    type = type->getWithoutParens();

    // Look through optionals.
    if (auto optObjectTy = type->getOptionalObjectType()) {
      type = optObjectTy;
      continue;
    }

    break;
  } while (true);

  // Nominal types.
  if (auto nominal = type->getAnyNominal()) {
    // If we have a collection, get the element type.
    if (auto bound = type->getAs<BoundGenericType>()) {
      ASTContext &ctx = nominal->getASTContext();
      auto args = bound->getGenericArgs();
      if (!args.empty() &&
          (bound->getDecl() == ctx.getArrayDecl() ||
           bound->getDecl() == ctx.getSetDecl())) {
        return OmissionTypeName(nominal->getName().str(),
                                getOptions(bound),
                                getTypeNameForOmission(args[0]).Name);
      }
    }

    // AnyObject -> "Object".
    if (type->isAnyObject())
      return "Object";

    return OmissionTypeName(nominal->getName().str(), getOptions(type));
  }

  // Generic type parameters.
  if (auto genericParamTy = type->getAs<GenericTypeParamType>()) {
    if (auto genericParam = genericParamTy->getDecl())
      return genericParam->getName().str();

    return "";
  }

  // Dependent members.
  if (auto dependentMemberTy = type->getAs<DependentMemberType>()) {
    return dependentMemberTy->getName().str();
  }

  // Archetypes.
  if (auto archetypeTy = type->getAs<ArchetypeType>()) {
    return archetypeTy->getName().str();
  }

  // Function types.
  if (auto funcTy = type->getAs<AnyFunctionType>()) {
    if (funcTy->getRepresentation() == AnyFunctionType::Representation::Block)
      return "Block";

    return "Function";
  }
  return "";
}

Optional<DeclName> TypeChecker::omitNeedlessWords(AbstractFunctionDecl *afd) {
  auto &Context = afd->getASTContext();

  if (afd->isInvalid() || isa<DestructorDecl>(afd))
    return None;

  const DeclName name = afd->getName();
  if (!name)
    return None;

  // String'ify the arguments.
  StringRef baseNameStr = name.getBaseName().userFacingName();
  SmallVector<StringRef, 4> argNameStrs;
  for (auto arg : name.getArgumentNames()) {
    if (arg.empty())
      argNameStrs.push_back("");
    else
      argNameStrs.push_back(arg.str());
  }

  // String'ify the parameter types.
  SmallVector<OmissionTypeName, 4> paramTypes;

  // Always look at the parameters in the last parameter list.
  for (auto param : *afd->getParameters()) {
    paramTypes.push_back(getTypeNameForOmission(param->getInterfaceType())
                         .withDefaultArgument(param->isDefaultArgument()));
  }
  
  // Handle contextual type, result type, and returnsSelf.
  Type contextType = afd->getDeclContext()->getDeclaredInterfaceType();
  Type resultType;
  bool returnsSelf = afd->hasDynamicSelfResult();

  if (auto func = dyn_cast<FuncDecl>(afd)) {
    resultType = func->getResultInterfaceType();
    resultType = func->mapTypeIntoContext(resultType);
  } else if (isa<ConstructorDecl>(afd)) {
    resultType = contextType;
  }

  // Figure out the first parameter name.
  StringRef firstParamName;
  auto params = afd->getParameters();
  if (params->size() != 0 && !params->get(0)->getName().empty())
    firstParamName = params->get(0)->getName().str();

  StringScratchSpace scratch;
  if (!swift::omitNeedlessWords(baseNameStr, argNameStrs, firstParamName,
                                getTypeNameForOmission(resultType),
                                getTypeNameForOmission(contextType),
                                paramTypes, returnsSelf, false,
                                /*allPropertyNames=*/nullptr,
                                None, None, scratch))
    return None;

  /// Retrieve a replacement identifier.
  auto getReplacementIdentifier = [&](StringRef name,
                                      DeclBaseName old) -> DeclBaseName{
    if (name.empty())
      return Identifier();

    if (!old.empty() && name == old.userFacingName())
      return old;

    return Context.getIdentifier(name);
  };

  auto newBaseName = getReplacementIdentifier(
      baseNameStr, name.getBaseName());
  SmallVector<Identifier, 4> newArgNames;
  auto oldArgNames = name.getArgumentNames();
  for (unsigned i = 0, n = argNameStrs.size(); i != n; ++i) {
    auto argBaseName = getReplacementIdentifier(argNameStrs[i],
                                                oldArgNames[i]);
    newArgNames.push_back(argBaseName.getIdentifier());
  }

  return DeclName(Context, newBaseName, newArgNames);
}

Optional<Identifier> TypeChecker::omitNeedlessWords(VarDecl *var) {
  auto &Context = var->getASTContext();

  if (var->isInvalid())
    return None;

  if (var->getName().empty())
    return None;

  auto name = var->getName().str();

  // Dig out the context type.
  Type contextType = var->getDeclContext()->getDeclaredInterfaceType();
  if (!contextType)
    return None;

  // Dig out the type of the variable.
  Type type = var->getValueInterfaceType();
  while (auto optObjectTy = type->getOptionalObjectType())
    type = optObjectTy;

  // Omit needless words.
  StringScratchSpace scratch;
  OmissionTypeName typeName = getTypeNameForOmission(var->getInterfaceType());
  OmissionTypeName contextTypeName = getTypeNameForOmission(contextType);
  if (::omitNeedlessWords(name, { }, "", typeName, contextTypeName, { },
                          /*returnsSelf=*/false, true,
                          /*allPropertyNames=*/nullptr, None, None, scratch)) {
    return Context.getIdentifier(name);
  }

  return None;
}
