//===--- CSDiagnostics.cpp - Constraint Diagnostics -----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 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 diagnostics for constraint system.
//
//===----------------------------------------------------------------------===//

#include "CSDiagnostics.h"
#include "MiscDiagnostics.h"
#include "TypeCheckProtocol.h"
#include "TypoCorrection.h"
#include "swift/Sema/IDETypeChecking.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/ProtocolConformanceRef.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/Types.h"
#include "swift/Basic/SourceLoc.h"
#include "swift/Parse/Lexer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallString.h"
#include <string>

using namespace swift;
using namespace constraints;

static bool hasFixFor(const Solution &solution, ConstraintLocator *locator) {
  return llvm::any_of(solution.Fixes, [&locator](const ConstraintFix *fix) {
    return fix->getLocator() == locator;
  });
}

FailureDiagnostic::~FailureDiagnostic() {}

bool FailureDiagnostic::diagnose(bool asNote) {
  return asNote ? diagnoseAsNote() : diagnoseAsError();
}

bool FailureDiagnostic::diagnoseAsNote() {
  return false;
}

ASTNode FailureDiagnostic::getAnchor() const {
  auto *locator = getLocator();
  // Resolve the locator to a specific expression.

  auto anchor = locator->getAnchor();

  {
    SourceRange range;
    auto path = locator->getPath();

    simplifyLocator(anchor, path, range);
    if (!anchor)
      return locator->getAnchor();
  }

  // FIXME: Work around an odd locator representation that doesn't separate the
  // base of a subscript member from the member access.
  if (locator->isLastElement<LocatorPathElt::SubscriptMember>()) {
    if (auto subscript = getAsExpr<SubscriptExpr>(anchor))
      anchor = subscript->getBase();
  }

  return anchor;
}

Type FailureDiagnostic::getType(ASTNode node, bool wantRValue) const {
  return resolveType(getRawType(node), /*reconstituteSugar=*/false, wantRValue);
}

Type FailureDiagnostic::getRawType(ASTNode node) const {
  return S.getType(node);
}

template <typename... ArgTypes>
InFlightDiagnostic
FailureDiagnostic::emitDiagnostic(ArgTypes &&... Args) const {
  return emitDiagnosticAt(getLoc(), std::forward<ArgTypes>(Args)...);
}

template <typename... ArgTypes>
InFlightDiagnostic
FailureDiagnostic::emitDiagnosticAt(ArgTypes &&... Args) const {
  auto &DE = getASTContext().Diags;
  return DE.diagnose(std::forward<ArgTypes>(Args)...);
}

Expr *FailureDiagnostic::findParentExpr(const Expr *subExpr) const {
  auto &cs = getConstraintSystem();
  return cs.getParentExpr(const_cast<Expr *>(subExpr));
}

Expr *
FailureDiagnostic::getArgumentListExprFor(ConstraintLocator *locator) const {
  auto path = locator->getPath();
  auto iter = path.begin();
  if (!locator->findFirst<LocatorPathElt::ApplyArgument>(iter))
    return nullptr;

  // Form a new locator that ends at the ApplyArgument element, then simplify
  // to get the argument list.
  auto newPath = ArrayRef<LocatorPathElt>(path.begin(), iter + 1);
  auto argListLoc = getConstraintLocator(locator->getAnchor(), newPath);
  return getAsExpr(simplifyLocatorToAnchor(argListLoc));
}

Expr *FailureDiagnostic::getBaseExprFor(const Expr *anchor) const {
  if (!anchor)
    return nullptr;

  if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor))
    return UDE->getBase();
  else if (auto *SE = dyn_cast<SubscriptExpr>(anchor))
    return SE->getBase();
  else if (auto *MRE = dyn_cast<MemberRefExpr>(anchor))
    return MRE->getBase();
  else if (auto *call = dyn_cast<CallExpr>(anchor)) {
    auto fnType = getType(call->getFn());
    if (fnType->isCallableNominalType(getDC())) {
      return call->getFn();
    }
  }

  return nullptr;
}

Type FailureDiagnostic::restoreGenericParameters(
    Type type,
    llvm::function_ref<void(GenericTypeParamType *, Type)> substitution) {
  llvm::SmallPtrSet<GenericTypeParamType *, 4> processed;
  return type.transform([&](Type type) -> Type {
    if (auto *typeVar = type->getAs<TypeVariableType>()) {
      type = resolveType(typeVar);
      if (auto *GP = typeVar->getImpl().getGenericParameter()) {
        if (processed.insert(GP).second)
          substitution(GP, type);
        return GP;
      }
    }

    return type;
  });
}

bool FailureDiagnostic::conformsToKnownProtocol(
    Type type, KnownProtocolKind protocol) const {
  auto &cs = getConstraintSystem();
  return constraints::conformsToKnownProtocol(cs.DC, type, protocol);
}

Type RequirementFailure::getOwnerType() const {
  auto anchor = getRawAnchor();

  // If diagnostic is anchored at assignment expression
  // it means that requirement failure happend while trying
  // to convert source to destination, which means that
  // owner type is actually not an assignment expression
  // itself but its source.
  if (auto *assignment = getAsExpr<AssignExpr>(anchor))
    anchor = assignment->getSrc();

  return getType(anchor)->getInOutObjectType()->getMetatypeInstanceType();
}

const GenericContext *RequirementFailure::getGenericContext() const {
  if (auto *genericCtx = AffectedDecl->getAsGenericContext())
    return genericCtx;

  auto parentDecl = AffectedDecl->getDeclContext()->getAsDecl();
  if (!parentDecl)
    return nullptr;

  return parentDecl->getAsGenericContext();
}

const Requirement &RequirementFailure::getRequirement() const {
  // If this is a conditional requirement failure we need to
  // fetch conformance from constraint system associated with
  // type requirement this conditional conformance belongs to.
  auto requirements = isConditional()
                          ? Conformance->getConditionalRequirements()
                          : Signature->getRequirements();
  return requirements[getRequirementIndex()];
}

ProtocolConformance *RequirementFailure::getConformanceForConditionalReq(
    ConstraintLocator *locator) {
  auto &solution = getSolution();
  auto reqElt = locator->castLastElementTo<LocatorPathElt::AnyRequirement>();
  if (!reqElt.isConditionalRequirement())
    return nullptr;

  auto path = locator->getPath();
  auto *typeReqLoc = getConstraintLocator(getRawAnchor(), path.drop_back());

  auto result = llvm::find_if(
      solution.Conformances,
      [&](const std::pair<ConstraintLocator *, ProtocolConformanceRef>
              &conformance) { return conformance.first == typeReqLoc; });
  assert(result != solution.Conformances.end());

  auto conformance = result->second;
  assert(conformance.isConcrete());
  return conformance.getConcrete();
}

ValueDecl *RequirementFailure::getDeclRef() const {
  // Get a declaration associated with given type (if any).
  // This is used to retrieve affected declaration when
  // failure is in any way contextual, and declaration can't
  // be fetched directly from constraint system.
  auto getAffectedDeclFromType = [](Type type) -> ValueDecl * {
    assert(type);
    // If problem is related to a typealias, let's point this
    // diagnostic directly to its declaration without desugaring.
    if (auto *alias = dyn_cast<TypeAliasType>(type.getPointer()))
      return alias->getDecl();

    if (auto *opaque = type->getAs<OpaqueTypeArchetypeType>())
      return opaque->getDecl();

    return type->getAnyGeneric();
  };

  // If the locator is for a result builder body result type, the requirement
  // came from the function's return type.
  if (getLocator()->isForResultBuilderBodyResult()) {
    auto *func = getAsDecl<FuncDecl>(getAnchor());
    return getAffectedDeclFromType(func->getResultInterfaceType());
  }

  if (isFromContextualType())
    return getAffectedDeclFromType(getContextualType(getRawAnchor()));

  if (auto overload = getCalleeOverloadChoiceIfAvailable(getLocator())) {
    // If there is a declaration associated with this
    // failure e.g. an overload choice of the call
    // expression, let's see whether failure is
    // associated with it directly or rather with
    // one of its parents.
    if (auto *decl = overload->choice.getDeclOrNull()) {
      // If declaration is an operator let's always use
      // it to produce `in reference to` diagnostics.
      if (decl->isOperator())
        return decl;

      auto *DC = decl->getDeclContext();

      do {
        if (auto *parent = DC->getAsDecl()) {
          if (auto *GC = parent->getAsGenericContext()) {
            // FIXME: Is this intending an exact match?
            if (GC->getGenericSignature().getPointer() != Signature.getPointer())
              continue;

            // If this is a signature if an extension
            // then it means that code has referenced
            // something incorrectly and diagnostic
            // should point to the referenced declaration.
            if (isa<ExtensionDecl>(parent))
              break;

            return cast<ValueDecl>(parent);
          }
        }
      } while ((DC = DC->getParent()));

      return decl;
    }
  }

  return getAffectedDeclFromType(getOwnerType());
}

GenericSignature RequirementFailure::getSignature(ConstraintLocator *locator) {
  if (isConditional())
    return Conformance->getGenericSignature();

  if (auto genericElt = locator->findLast<LocatorPathElt::OpenedGeneric>())
    return genericElt->getSignature();

  llvm_unreachable("Type requirement failure should always have signature");
}

bool RequirementFailure::isFromContextualType() const {
  auto path = getLocator()->getPath();
  assert(!path.empty());
  return path.front().getKind() == ConstraintLocator::ContextualType;
}

const DeclContext *RequirementFailure::getRequirementDC() const {
  // In case of conditional requirement failure, we don't
  // have to guess where the it comes from.
  if (isConditional())
    return Conformance->getDeclContext();

  const auto &req = getRequirement();
  auto *DC = AffectedDecl->getDeclContext();

  do {
    if (auto sig = DC->getGenericSignatureOfContext()) {
      if (sig->isRequirementSatisfied(req))
        return DC;
    }
  } while ((DC = DC->getParent()));

  return AffectedDecl->getAsGenericContext();
}

bool RequirementFailure::isStaticOrInstanceMember(const ValueDecl *decl) {
  if (decl->isInstanceMember())
    return true;

  if (auto *AFD = dyn_cast<AbstractFunctionDecl>(decl))
    return AFD->isStatic() && !AFD->isOperator();

  return decl->isStatic();
}

bool RequirementFailure::diagnoseAsError() {
  const auto *reqDC = getRequirementDC();
  auto *genericCtx = getGenericContext();
  if (!genericCtx)
    return false;

  auto lhs = getLHS();
  auto rhs = getRHS();

  if (auto *OTD = dyn_cast<OpaqueTypeDecl>(AffectedDecl)) {
    auto *namingDecl = OTD->getNamingDecl();
    emitDiagnostic(diag::type_does_not_conform_in_opaque_return,
                   namingDecl->getDescriptiveKind(), namingDecl->getName(),
                   lhs, rhs, rhs->isAnyObject());

    if (auto *repr = namingDecl->getOpaqueResultTypeRepr()) {
      emitDiagnosticAt(repr->getLoc(), diag::opaque_return_type_declared_here)
          .highlight(repr->getSourceRange());
    }
    return true;
  }

  if (reqDC->isTypeContext() && genericCtx != reqDC &&
      (genericCtx->isChildContextOf(reqDC) ||
       isStaticOrInstanceMember(AffectedDecl))) {
    auto *NTD = reqDC->getSelfNominalTypeDecl();
    emitDiagnostic(
        getDiagnosticInRereference(), AffectedDecl->getDescriptiveKind(),
        AffectedDecl->getName(), NTD->getDeclaredType(), lhs, rhs);
  } else {
    emitDiagnostic(getDiagnosticOnDecl(), AffectedDecl->getDescriptiveKind(),
                   AffectedDecl->getName(), lhs, rhs);
  }

  emitRequirementNote(reqDC->getAsDecl(), lhs, rhs);
  return true;
}

bool RequirementFailure::diagnoseAsNote() {
  const auto &req = getRequirement();
  const auto *reqDC = getRequirementDC();

  emitDiagnosticAt(reqDC->getAsDecl(), getDiagnosticAsNote(), getLHS(),
                   getRHS(), req.getFirstType(), req.getSecondType(), "");
  return true;
}

void RequirementFailure::emitRequirementNote(const Decl *anchor, Type lhs,
                                             Type rhs) const {
  auto &req = getRequirement();

  if (req.getKind() != RequirementKind::SameType) {
    if (auto wrappedType = lhs->getOptionalObjectType()) {
      auto kind = (req.getKind() == RequirementKind::Superclass ?
                   ConstraintKind::Subtype : ConstraintKind::ConformsTo);
      if (TypeChecker::typesSatisfyConstraint(wrappedType, rhs,
                                              /*openArchetypes=*/false,
                                              kind, getDC()))
        emitDiagnostic(diag::wrapped_type_satisfies_requirement, wrappedType);
    }
  }

  if (isConditional()) {
    emitDiagnosticAt(anchor,
                     diag::requirement_implied_by_conditional_conformance,
                     resolveType(Conformance->getType()),
                     Conformance->getProtocol()->getDeclaredInterfaceType());
    return;
  }

  if (req.getKind() == RequirementKind::Layout ||
      rhs->isEqual(req.getSecondType())) {
    emitDiagnosticAt(anchor, diag::where_requirement_failure_one_subst,
                     req.getFirstType(), lhs);
    return;
  }

  if (lhs->isEqual(req.getFirstType())) {
    emitDiagnosticAt(anchor, diag::where_requirement_failure_one_subst,
                     req.getSecondType(), rhs);
    return;
  }

  emitDiagnosticAt(anchor, diag::where_requirement_failure_both_subst,
                   req.getFirstType(), lhs, req.getSecondType(), rhs);
}

bool MissingConformanceFailure::diagnoseAsError() {
  auto anchor = getAnchor();
  auto nonConformingType = getLHS();
  auto protocolType = getRHS();

  // If this is a requirement of a pattern-matching operator,
  // let's see whether argument already has a fix associated
  // with it and if so skip conformance error, otherwise we'd
  // produce an unrelated `<type> doesn't conform to Equatable protocol`
  // diagnostic.
  if (isPatternMatchingOperator(anchor)) {
    auto *expr = castToExpr(anchor);
    if (auto *binaryOp = dyn_cast_or_null<BinaryExpr>(findParentExpr(expr))) {
      auto *caseExpr = binaryOp->getArg()->getElement(0);

      llvm::SmallPtrSet<Expr *, 4> anchors;
      for (const auto *fix : getSolution().Fixes) {
        if (auto anchor = fix->getAnchor()) {
          if (anchor.is<Expr *>())
            anchors.insert(getAsExpr(anchor));
        }
      }

      bool hasFix = false;
      forEachExprInConstraintSystem(caseExpr, [&](Expr *expr) -> Expr * {
        hasFix |= anchors.count(expr);
        return hasFix ? nullptr : expr;
      });

      if (hasFix)
        return false;
    }
  }

  // If the problem has been (unambiguously) determined to be related
  // to one of of the standard comparison operators and argument is
  // enum with associated values, let's produce a tailored note which
  // says that conformances for enums with associated values can't be
  // synthesized.
  if (isStandardComparisonOperator(anchor)) {
    auto *expr = castToExpr(anchor);
    auto isEnumWithAssociatedValues = [](Type type) -> bool {
      if (auto *enumType = type->getAs<EnumType>())
        return !enumType->getDecl()->hasOnlyCasesWithoutAssociatedValues();
      return false;
    };

    // Limit this to `Equatable` and `Comparable` protocols for now.
    auto *protocol = getRHS()->castTo<ProtocolType>()->getDecl();
    if (isEnumWithAssociatedValues(getLHS()) &&
        (protocol->isSpecificProtocol(KnownProtocolKind::Equatable) ||
         protocol->isSpecificProtocol(KnownProtocolKind::Comparable))) {
      if (RequirementFailure::diagnoseAsError()) {
        auto opName = getOperatorName(expr);
        emitDiagnostic(diag::no_binary_op_overload_for_enum_with_payload,
                       opName->str());
        return true;
      }
    }
  }

  if (diagnoseAsAmbiguousOperatorRef())
    return true;

  if (nonConformingType->isObjCExistentialType()) {
    emitDiagnostic(diag::protocol_does_not_conform_static, nonConformingType,
                   protocolType);
    return true;
  }

  if (diagnoseTypeCannotConform(nonConformingType, protocolType))
    return true;

  // If none of the special cases could be diagnosed,
  // let's fallback to the most general diagnostic.
  return RequirementFailure::diagnoseAsError();
}

bool MissingConformanceFailure::diagnoseTypeCannotConform(
    Type nonConformingType, Type protocolType) const {
  if (getRequirement().getKind() == RequirementKind::Layout ||
      !(nonConformingType->is<AnyFunctionType>() ||
      nonConformingType->is<TupleType>() ||
      nonConformingType->isExistentialType() ||
      nonConformingType->is<AnyMetatypeType>())) {
    return false;
  }

  emitDiagnostic(diag::type_cannot_conform,
                 nonConformingType->isExistentialType(), 
                 nonConformingType, 
                 nonConformingType->isEqual(protocolType),
                 protocolType);

  emitDiagnostic(diag::only_concrete_types_conform_to_protocols);

  if (auto *OTD = dyn_cast<OpaqueTypeDecl>(AffectedDecl)) {
    auto *namingDecl = OTD->getNamingDecl();
    if (auto *repr = namingDecl->getOpaqueResultTypeRepr()) {
      emitDiagnosticAt(repr->getLoc(), diag::required_by_opaque_return,
                       namingDecl->getDescriptiveKind(),
                       namingDecl->getName())
          .highlight(repr->getSourceRange());
    }
    return true;
  }

  auto &req = getRequirement();
  auto *reqDC = getRequirementDC();
  auto *genericCtx = getGenericContext();
  auto noteLocation = reqDC->getAsDecl()->getLoc();

  if (!noteLocation.isValid())
    noteLocation = getLoc();

  if (isConditional()) {
    emitDiagnosticAt(noteLocation,
                     diag::requirement_implied_by_conditional_conformance,
                     resolveType(Conformance->getType()),
                     Conformance->getProtocol()->getDeclaredInterfaceType());
  } else if (genericCtx != reqDC && (genericCtx->isChildContextOf(reqDC) ||
                                     isStaticOrInstanceMember(AffectedDecl))) {
    emitDiagnosticAt(noteLocation, diag::required_by_decl_ref,
                     AffectedDecl->getDescriptiveKind(),
                     AffectedDecl->getName(),
                     reqDC->getSelfNominalTypeDecl()->getDeclaredType(),
                     req.getFirstType(), nonConformingType);
  } else {
    emitDiagnosticAt(noteLocation, diag::required_by_decl,
                     AffectedDecl->getDescriptiveKind(),
                     AffectedDecl->getName(), req.getFirstType(),
                     nonConformingType);
  }

  return true;
}

bool MissingConformanceFailure::diagnoseAsAmbiguousOperatorRef() {
  auto anchor = getRawAnchor();
  auto *ODRE = getAsExpr<OverloadedDeclRefExpr>(anchor);
  if (!ODRE)
    return false;

  auto name = ODRE->getDecls().front()->getBaseName();
  if (!(name.isOperator() && getLHS()->isStdlibType() && getRHS()->isStdlibType()))
    return false;

  // If this is an operator reference and both types are from stdlib,
  // let's produce a generic diagnostic about invocation and a note
  // about missing conformance just in case.
  auto operatorID = name.getIdentifier();

  auto *fnType = getType(anchor)->getAs<AnyFunctionType>();
  auto params = fnType->getParams();
  if (params.size() == 2) {
    auto lhsType = params[0].getPlainType();
    auto rhsType = params[1].getPlainType();

    if (lhsType->isEqual(rhsType)) {
      emitDiagnostic(diag::cannot_apply_binop_to_same_args, operatorID.str(),
                     lhsType);
    } else {
      emitDiagnostic(diag::cannot_apply_binop_to_args, operatorID.str(),
                     lhsType, rhsType);
    }
  } else {
    emitDiagnostic(diag::cannot_apply_unop_to_arg, operatorID.str(),
                   params[0].getPlainType());
  }

  diagnoseAsNote();
  return true;
}

Optional<Diag<Type, Type>> GenericArgumentsMismatchFailure::getDiagnosticFor(
    ContextualTypePurpose context) {
  switch (context) {
  case CTP_Initialization:
  case CTP_AssignSource:
    return diag::cannot_convert_assign;
  case CTP_ReturnStmt:
  case CTP_ReturnSingleExpr:
    return diag::cannot_convert_to_return_type;
  case CTP_DefaultParameter:
  case CTP_AutoclosureDefaultParameter:
    return diag::cannot_convert_default_arg_value;
  case CTP_YieldByValue:
    return diag::cannot_convert_yield_value;
  case CTP_CallArgument:
    return diag::cannot_convert_argument_value;
  case CTP_ClosureResult:
    return diag::cannot_convert_closure_result;
  case CTP_ArrayElement:
    return diag::cannot_convert_array_element;
  case CTP_DictionaryKey:
    return diag::cannot_convert_dict_key;
  case CTP_DictionaryValue:
    return diag::cannot_convert_dict_value;
  case CTP_CoerceOperand:
    return diag::cannot_convert_coerce;
  case CTP_SubscriptAssignSource:
    return diag::cannot_convert_subscript_assign;
  case CTP_Condition:
    return diag::cannot_convert_condition_value;
  case CTP_WrappedProperty:
    return diag::wrapped_value_mismatch;
  case CTP_ComposedPropertyWrapper:
    return diag::composed_property_wrapper_mismatch;

  case CTP_ThrowStmt:
  case CTP_ForEachStmt:
  case CTP_Unused:
  case CTP_CannotFail:
  case CTP_YieldByReference:
  case CTP_CalleeResult:
  case CTP_EnumCaseRawValue:
    break;
  }
  return None;
}

void GenericArgumentsMismatchFailure::emitNoteForMismatch(int position) {
  auto *locator = getLocator();
  // Since there could be implicit conversions associated with argument
  // to parameter conversions, let's use parameter type as a source of
  // generic parameter information.
  auto paramSourceTy =
      locator->isLastElement<LocatorPathElt::ApplyArgToParam>() ? getRequired()
                                                                : getActual();

  auto genericTypeDecl = paramSourceTy->getAnyGeneric();
  auto param = genericTypeDecl->getGenericParams()->getParams()[position];

  auto lhs = getActual()->getGenericArgs()[position];
  auto rhs = getRequired()->getGenericArgs()[position];

  auto noteLocation = param->getLoc();

  if (!noteLocation.isValid())
    noteLocation = getLoc();

  emitDiagnosticAt(noteLocation, diag::generic_argument_mismatch,
                   param->getName(), lhs, rhs);
}

bool GenericArgumentsMismatchFailure::diagnoseAsError() {
  auto anchor = getAnchor();

  auto fromType = getFromType();
  auto toType = getToType();

  // This is a situation where right-hand size type is wrapped
  // into a number of optionals and argument isn't e.g.
  //
  // func test(_: UnsafePointer<Int>??) {}
  //
  // var value: Float = 0
  // test(&value)
  //
  // `value` has to get implicitly wrapped into 2 optionals
  // before pointer types could be compared.
  auto path = getLocator()->getPath();
  unsigned toDrop = 0;
  for (const auto &elt : llvm::reverse(path)) {
    if (!elt.is<LocatorPathElt::OptionalPayload>())
      break;

    // Disregard optional payload element to look at its source.
    ++toDrop;
  }

  path = path.drop_back(toDrop);

  Optional<Diag<Type, Type>> diagnostic;
  if (path.empty()) {
    if (isExpr<AssignExpr>(anchor)) {
      diagnostic = getDiagnosticFor(CTP_AssignSource);
    } else if (isExpr<CoerceExpr>(anchor)) {
      diagnostic = getDiagnosticFor(CTP_CoerceOperand);
    } else {
      return false;
    }
  } else {
    const auto &last = path.back();
    switch (last.getKind()) {
    case ConstraintLocator::ContextualType: {
      auto purpose = getContextualTypePurpose();
      assert(!(purpose == CTP_Unused || purpose == CTP_CannotFail));

      // If this is call to a closure e.g. `let _: A = { B() }()`
      // let's point diagnostic to its result.
      if (auto *call = getAsExpr<CallExpr>(anchor)) {
        auto *fnExpr = call->getFn();
        if (auto *closure = dyn_cast<ClosureExpr>(fnExpr)) {
          purpose = CTP_ClosureResult;
          if (closure->hasSingleExpressionBody())
            anchor = closure->getSingleExpressionBody();
        }
      }

      diagnostic = getDiagnosticFor(purpose);
      break;
    }

    case ConstraintLocator::AutoclosureResult:
    case ConstraintLocator::ApplyArgToParam:
    case ConstraintLocator::ApplyArgument: {
      diagnostic = diag::cannot_convert_argument_value;
      break;
    }

    case ConstraintLocator::ParentType: {
      diagnostic = diag::cannot_convert_parent_type;
      break;
    }

    case ConstraintLocator::ClosureBody:
    case ConstraintLocator::ClosureResult: {
      diagnostic = diag::cannot_convert_closure_result;
      break;
    }

    case ConstraintLocator::TupleElement: {
      auto rawAnchor = getRawAnchor();

      if (isExpr<ArrayExpr>(rawAnchor)) {
        diagnostic = getDiagnosticFor(CTP_ArrayElement);
      } else if (isExpr<DictionaryExpr>(rawAnchor)) {
        auto eltLoc = last.castTo<LocatorPathElt::TupleElement>();
        diagnostic = getDiagnosticFor(
            eltLoc.getIndex() == 0 ? CTP_DictionaryKey : CTP_DictionaryValue);
      }
      break;
    }

    case ConstraintLocator::UnresolvedMemberChainResult: {
      diagnostic = diag::cannot_convert_chain_result_type;
      break;
    }

    default:
      break;
    }
  }

  if (!diagnostic) {
    // Handle all mismatches involving an `AssignExpr`
    if (auto *assignExpr = getAsExpr<AssignExpr>(anchor)) {
      diagnostic = getDiagnosticFor(CTP_AssignSource);
      fromType = getType(assignExpr->getSrc());
      toType = getType(assignExpr->getDest());
    } else {
      // If we couldn't find a specific diagnostic let's fallback to
      // attempt to handle cases where we have an apply arg to param.
      auto applyInfo = getFunctionArgApplyInfo(getLocator());
      if (applyInfo) {
        diagnostic = diag::cannot_convert_argument_value;
        fromType = applyInfo->getArgType();
        toType = applyInfo->getParamType();
      }
    }
  }
  
  if (!diagnostic)
    return false;

  emitDiagnosticAt(::getLoc(anchor), *diagnostic, fromType, toType);
  emitNotesForMismatches();
  return true;
}

bool LabelingFailure::diagnoseAsError() {
  auto *argExpr = getArgumentListExprFor(getLocator());
  if (!argExpr)
    return false;

  return diagnoseArgumentLabelError(getASTContext(), argExpr, CorrectLabels,
                                    isExpr<SubscriptExpr>(getRawAnchor()));
}

bool LabelingFailure::diagnoseAsNote() {
  auto *argExpr = getArgumentListExprFor(getLocator());
  if (!argExpr)
    return false;

  SmallVector<Identifier, 4> argLabels;
  if (isa<ParenExpr>(argExpr)) {
    argLabels.push_back(Identifier());
  } else if (auto *tuple = dyn_cast<TupleExpr>(argExpr)) {
    argLabels.append(tuple->getElementNames().begin(),
                     tuple->getElementNames().end());
  } else {
    return false;
  }

  auto stringifyLabels = [](ArrayRef<Identifier> labels) -> std::string {
    std::string str;
    for (auto label : labels) {
      str += label.empty() ? "_" : label.str();
      str += ':';
    }
    return "(" + str + ")";
  };

  auto selectedOverload = getCalleeOverloadChoiceIfAvailable(getLocator());
  if (!selectedOverload)
    return false;

  const auto &choice = selectedOverload->choice;
  if (auto *decl = choice.getDeclOrNull()) {
    emitDiagnosticAt(decl, diag::candidate_expected_different_labels,
                     stringifyLabels(argLabels),
                     stringifyLabels(CorrectLabels));
    return true;
  }

  return false;
}

bool ArrayLiteralToDictionaryConversionFailure::diagnoseAsError() {
  ArrayExpr *AE = getAsExpr<ArrayExpr>(getAnchor());
  assert(AE);

  if (AE->getNumElements() == 0) {
    emitDiagnostic(diag::should_use_empty_dictionary_literal)
      .fixItInsertAfter(getLoc(), ":");
    return true;
  }

  auto CTP = getConstraintSystem().getContextualTypePurpose(AE);
  emitDiagnostic(diag::should_use_dictionary_literal,
                 getToType()->lookThroughAllOptionalTypes(),
                 CTP == CTP_Initialization);

  auto diagnostic = emitDiagnostic(diag::meant_dictionary_lit);
  if (AE->getNumElements() == 1)
    diagnostic.fixItInsertAfter(AE->getElement(0)->getEndLoc(), ": <#value#>");
  return true;
}

bool NoEscapeFuncToTypeConversionFailure::diagnoseAsError() {
  if (diagnoseParameterUse())
    return true;

  if (auto *typeVar = getRawFromType()->getAs<TypeVariableType>()) {
    if (auto *GP = typeVar->getImpl().getGenericParameter()) {
      emitDiagnostic(diag::converting_noescape_to_type, GP);
      return true;
    }
  }

  emitDiagnostic(diag::converting_noescape_to_type, getToType());
  return true;
}

bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const {
  auto convertTo = getToType();
  // If the other side is not a function, we have common case diagnostics
  // which handle function-to-type conversion diagnostics.
  if (!convertTo->is<FunctionType>())
    return false;

  auto anchor = getAnchor();
  auto diagnostic = diag::general_noescape_to_escaping;

  ParamDecl *PD = nullptr;
  if (auto *DRE = getAsExpr<DeclRefExpr>(anchor)) {
    PD = dyn_cast<ParamDecl>(DRE->getDecl());

    // If anchor is not a parameter declaration there
    // is no need to dig up more information.
    if (!PD)
      return false;

    // Let's check whether this is a function parameter passed
    // as an argument to another function which accepts @escaping
    // function at that position.
    if (auto argApplyInfo = getFunctionArgApplyInfo(getLocator())) {
      auto paramInterfaceTy = argApplyInfo->getParamInterfaceType();
      if (paramInterfaceTy->isTypeParameter()) {
        auto diagnoseGenericParamFailure = [&](GenericTypeParamDecl *decl) {
          emitDiagnostic(diag::converting_noespace_param_to_generic_type,
                         PD->getName(), paramInterfaceTy);

          auto declLoc = decl->getLoc();
          if (declLoc.isValid())
            emitDiagnosticAt(decl, diag::generic_parameters_always_escaping);
        };

        // If this is a situation when non-escaping parameter is passed
        // to the argument which represents generic parameter, there is
        // a tailored diagnostic for that.

        if (auto *DMT = paramInterfaceTy->getAs<DependentMemberType>()) {
          diagnoseGenericParamFailure(DMT->getRootGenericParam()->getDecl());
          return true;
        }

        if (auto *GP = paramInterfaceTy->getAs<GenericTypeParamType>()) {
          diagnoseGenericParamFailure(GP->getDecl());
          return true;
        }
      }

      // If there are no generic parameters involved, this could
      // only mean that parameter is expecting @escaping function type.
      diagnostic = diag::passing_noescape_to_escaping;
    }
  } else if (auto *AE = getAsExpr<AssignExpr>(getRawAnchor())) {
    if (auto *DRE = dyn_cast<DeclRefExpr>(AE->getSrc())) {
      PD = dyn_cast<ParamDecl>(DRE->getDecl());
      diagnostic = diag::assigning_noescape_to_escaping;
    }
  }

  if (!PD)
    return false;

  emitDiagnostic(diagnostic, PD->getName());

  // Give a note and fix-it
  auto note = emitDiagnosticAt(PD, diag::noescape_parameter, PD->getName());

  SourceLoc reprLoc;
  SourceLoc autoclosureEndLoc;
  if (auto *repr = PD->getTypeRepr()) {
    reprLoc = repr->getStartLoc();
    if (auto *attrRepr = dyn_cast<AttributedTypeRepr>(repr)) {
      autoclosureEndLoc = Lexer::getLocForEndOfToken(
          getASTContext().SourceMgr,
          attrRepr->getAttrs().getLoc(TAK_autoclosure));
    }
  }
  if (!PD->isAutoClosure()) {
    note.fixItInsert(reprLoc, "@escaping ");
  } else {
    note.fixItInsertAfter(autoclosureEndLoc, " @escaping");
  }

  return true;
}

ASTNode InvalidCoercionFailure::getAnchor() const {
  auto anchor = FailureDiagnostic::getAnchor();
  if (auto *assignExpr = getAsExpr<AssignExpr>(anchor))
    return assignExpr->getSrc();
  return anchor;
}

bool InvalidCoercionFailure::diagnoseAsError() {
  auto fromType = getFromType();
  auto toType = getToType();

  emitDiagnostic(diag::cannot_coerce_to_type, fromType, toType);

  if (UseConditionalCast) {
    emitDiagnostic(diag::missing_optional_downcast)
        .highlight(getSourceRange())
        .fixItReplace(getLoc(), "as?");
  } else {
    emitDiagnostic(diag::missing_forced_downcast)
        .highlight(getSourceRange())
        .fixItReplace(getLoc(), "as!");
  }

  return true;
}

bool MissingAddressOfFailure::diagnoseAsError() {
  auto argTy = getFromType();
  auto paramTy = getToType();

  if (paramTy->getAnyPointerElementType()) {
    emitDiagnostic(diag::cannot_convert_argument_value, argTy, paramTy)
        .fixItInsert(getSourceRange().Start, "&");
  } else {
    emitDiagnostic(diag::missing_address_of, argTy)
        .fixItInsert(getSourceRange().Start, "&");
  }
  return true;
}

ASTNode MissingExplicitConversionFailure::getAnchor() const {
  auto anchor = FailureDiagnostic::getAnchor();

  if (auto *assign = getAsExpr<AssignExpr>(anchor))
    return assign->getSrc();

  if (auto *paren = getAsExpr<ParenExpr>(anchor))
    return paren->getSubExpr();

  return anchor;
}

bool MissingExplicitConversionFailure::diagnoseAsError() {
  auto *DC = getDC();
  auto *anchor = castToExpr(getAnchor());

  auto fromType = getFromType();
  auto toType = getToType();

  if (!toType->hasTypeRepr())
    return false;

  bool useAs = TypeChecker::isExplicitlyConvertibleTo(fromType, toType, DC);

  auto *expr = findParentExpr(anchor);
  if (!expr)
    expr = const_cast<Expr *>(anchor);

  // If we're performing pattern matching,
  // "as" means something completely different...
  if (auto binOpExpr = dyn_cast<BinaryExpr>(expr)) {
    auto overloadedFn = dyn_cast<OverloadedDeclRefExpr>(binOpExpr->getFn());
    if (overloadedFn && !overloadedFn->getDecls().empty()) {
      ValueDecl *decl0 = overloadedFn->getDecls()[0];
      if (decl0->getBaseName() == decl0->getASTContext().Id_MatchOperator)
        return false;
    }
  }

  bool needsParensInside = exprNeedsParensBeforeAddingAs(anchor);
  bool needsParensOutside = exprNeedsParensAfterAddingAs(anchor, expr);

  llvm::SmallString<2> insertBefore;
  llvm::SmallString<32> insertAfter;
  if (needsParensOutside) {
    insertBefore += "(";
  }
  if (needsParensInside) {
    insertBefore += "(";
    insertAfter += ")";
  }
  insertAfter += useAs ? " as " : " as! ";
  insertAfter += toType->getWithoutParens()->getString();
  if (needsParensOutside)
    insertAfter += ")";

  auto diagnose = [&]() {
    if (useAs) {
      return emitDiagnostic(diag::missing_explicit_conversion, fromType,
                            toType);
    } else {
      // Emit error diagnostic.
      emitDiagnostic(diag::cannot_coerce_to_type, fromType, toType);
      // Emit and return note suggesting as! where the fix-it will be placed.
      return emitDiagnostic(diag::missing_forced_downcast);
    }
  };

  auto diag = diagnose();
  if (!insertBefore.empty()) {
    diag.fixItInsert(getSourceRange().Start, insertBefore);
  }
  diag.fixItInsertAfter(getSourceRange().End, insertAfter);
  return true;
}

SourceRange MemberAccessOnOptionalBaseFailure::getSourceRange() const {
  if (auto componentPathElt =
          getLocator()->getLastElementAs<LocatorPathElt::KeyPathComponent>()) {
    auto anchor = getAnchor();
    auto keyPathExpr = castToExpr<KeyPathExpr>(anchor);
    if (componentPathElt->getIndex() == 0) {
      if (auto rootType = keyPathExpr->getRootType()) {
        return rootType->getSourceRange();
      } else {
        return keyPathExpr->getComponents().front().getLoc();
      }
    } else {
      auto componentIdx = componentPathElt->getIndex() - 1;
      auto component = keyPathExpr->getComponents()[componentIdx];
      return component.getSourceRange();
    }
  }
  return FailureDiagnostic::getSourceRange();
}

bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() {
  auto baseType = getMemberBaseType();
  auto locator = getLocator();
  
  bool resultIsOptional = ResultTypeIsOptional;

  // If we've resolved the member overload to one that returns an optional
  // type, then the result of the expression is optional (and we want to offer
  // only a '?' fixit) even though the constraint system didn't need to add any
  // additional optionality.
  auto overload = getOverloadChoiceIfAvailable(locator);
  if (overload && overload->openedType->getOptionalObjectType())
    resultIsOptional = true;

  auto unwrappedBaseType = baseType->getOptionalObjectType();
  if (!unwrappedBaseType)
    return false;
  
  auto sourceRange = getSourceRange();

  auto componentPathElt =
      locator->getLastElementAs<LocatorPathElt::KeyPathComponent>();
  if (componentPathElt && componentPathElt->getIndex() == 0) {
    // For members where the base type is an optional key path root
    // let's emit a tailored note suggesting to use its unwrapped type.
    auto *keyPathExpr = castToExpr<KeyPathExpr>(getAnchor());
    if (auto rootType = keyPathExpr->getRootType()) {
      emitDiagnostic(diag::optional_base_not_unwrapped, baseType, Member,
                     unwrappedBaseType);

      emitDiagnostic(diag::optional_base_remove_optional_for_keypath_root,
                     unwrappedBaseType)
          .fixItReplace(rootType->getSourceRange(),
                        unwrappedBaseType.getString());
    } else {
      emitDiagnostic(diag::invalid_optional_infered_keypath_root, baseType,
                     Member, unwrappedBaseType);
      emitDiagnostic(diag::optional_key_path_root_base_chain, Member)
          .fixItInsert(sourceRange.End, "?.");
      emitDiagnostic(diag::optional_key_path_root_base_unwrap, Member)
          .fixItInsert(sourceRange.End, "!.");
    }
  } else {
    emitDiagnostic(diag::optional_base_not_unwrapped, baseType, Member,
                   unwrappedBaseType);

    // FIXME: It would be nice to immediately offer "base?.member ?? defaultValue"
    // for non-optional results where that would be appropriate. For the moment
    // always offering "?" means that if the user chooses chaining, we'll end up
    // in MissingOptionalUnwrapFailure:diagnose() to offer a default value during
    // the next compile.
    emitDiagnostic(diag::optional_base_chain, Member)
        .fixItInsertAfter(sourceRange.End, "?");

    if (!resultIsOptional) {
      emitDiagnostic(diag::unwrap_with_force_value)
          .fixItInsertAfter(sourceRange.End, "!");
    }
  }

  return true;
}

void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt(
    DeclContext *DC, const Expr *expr) const {
  assert(expr);

  auto *anchor = getAsExpr(getAnchor());
  // If anchor is n explicit address-of, or expression which produces
  // an l-value (e.g. first argument of `+=` operator), let's not
  // suggest default value here because that would produce r-value type.
  if (!anchor || isa<InOutExpr>(anchor))
    return;

  if (auto argApplyInfo = getFunctionArgApplyInfo(getLocator()))
    if (argApplyInfo->getParameterFlags().isInOut())
      return;

  auto diag = emitDiagnosticAt(expr->getLoc(), diag::unwrap_with_default_value);

  // Figure out what we need to parenthesize.
  bool needsParensInside =
      exprNeedsParensBeforeAddingNilCoalescing(DC, const_cast<Expr *>(expr));
  auto parentExpr = findParentExpr(anchor);
  if (parentExpr && isa<UnresolvedMemberChainResultExpr>(parentExpr))
    parentExpr = findParentExpr(parentExpr);
  bool needsParensOutside = exprNeedsParensAfterAddingNilCoalescing(
      DC, const_cast<Expr *>(expr), parentExpr);

  llvm::SmallString<2> insertBefore;
  llvm::SmallString<32> insertAfter;
  if (needsParensOutside) {
    insertBefore += "(";
  }
  if (needsParensInside) {
    insertBefore += "(";
    insertAfter += ")";
  }
  insertAfter += " ?? <" "#default value#" ">";
  if (needsParensOutside)
    insertAfter += ")";

  if (!insertBefore.empty()) {
    diag.fixItInsert(expr->getStartLoc(), insertBefore);
  }
  diag.fixItInsertAfter(expr->getEndLoc(), insertAfter);
}

// Suggest a force-unwrap.
void MissingOptionalUnwrapFailure::offerForceUnwrapFixIt(
    const Expr *expr) const {
  auto diag = emitDiagnosticAt(expr->getLoc(), diag::unwrap_with_force_value);

  // If expr is optional as the result of an optional chain and this last
  // dot isn't a member returning optional, then offer to force the last
  // link in the chain, rather than an ugly parenthesized postfix force.
  if (auto optionalChain = dyn_cast<OptionalEvaluationExpr>(expr)) {
    if (auto dotExpr =
        dyn_cast<UnresolvedDotExpr>(optionalChain->getSubExpr())) {
      auto bind = dyn_cast<BindOptionalExpr>(dotExpr->getBase());
      if (bind && !getType(dotExpr)->getOptionalObjectType()) {
        diag.fixItReplace(SourceRange(bind->getLoc()), "!");
        return;
      }
    }
  }

  if (expr->canAppendPostfixExpression(true)) {
    diag.fixItInsertAfter(expr->getEndLoc(), "!");
  } else {
    diag.fixItInsert(expr->getStartLoc(), "(")
        .fixItInsertAfter(expr->getEndLoc(), ")!");
  }
}

// FIXME: This walks a partially-type checked function body, which
// is not guaranteed to yield consistent results. We should come up
// with another way of performing this analysis, for example by moving
// it to a post-type checking pass in MiscDiagnostics.
class VarDeclMultipleReferencesChecker : public ASTWalker {
  DeclContext *DC;
  VarDecl *varDecl;
  int count;

  std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
    if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
      if (DRE->getDecl() == varDecl)
        ++count;
    }

    // FIXME: We can see UnresolvedDeclRefExprs here because we have
    // not yet run preCheckExpression() on the entire function body
    // yet.
    //
    // We could consider pre-checking more eagerly.
    if (auto *UDRE = dyn_cast<UnresolvedDeclRefExpr>(E)) {
      auto name = UDRE->getName();
      auto loc = UDRE->getLoc();
      if (name.isSimpleName(varDecl->getName()) && loc.isValid()) {
        auto *otherDecl =
            ASTScope::lookupSingleLocalDecl(DC->getParentSourceFile(),
                                            name.getFullName(), loc);
        if (otherDecl == varDecl)
          ++count;
      }
    }

    return { true, E };
  }

public:
  VarDeclMultipleReferencesChecker(DeclContext *DC, VarDecl *varDecl)
      : DC(DC), varDecl(varDecl),count(0) {}
  int referencesCount() { return count; }
};

bool MissingOptionalUnwrapFailure::diagnoseAsError() {
  if (!getUnwrappedType()->isBool()) {
    if (diagnoseConversionToBool())
      return true;
  }

  auto *anchor = castToExpr(getAnchor());

  if (auto assignExpr = dyn_cast<AssignExpr>(anchor))
    anchor = assignExpr->getSrc();

  auto *unwrappedExpr = anchor->getValueProvidingExpr();

  if (auto *tryExpr = dyn_cast<OptionalTryExpr>(unwrappedExpr)) {
    bool isSwift5OrGreater = getASTContext().isSwiftVersionAtLeast(5);
    auto subExprType = getType(tryExpr->getSubExpr());
    bool subExpressionIsOptional = (bool)subExprType->getOptionalObjectType();

    if (isSwift5OrGreater && subExpressionIsOptional) {
      // Using 'try!' won't change the type for a 'try?' with an optional
      // sub-expr under Swift 5+, so just report that a missing unwrap can't be
      // handled here.
      return false;
    }

    emitDiagnosticAt(tryExpr->getTryLoc(), diag::missing_unwrap_optional_try,
                     getType(anchor))
        .fixItReplace({tryExpr->getTryLoc(), tryExpr->getQuestionLoc()},
                      "try!");
    return true;
  }

  auto baseType = getBaseType();
  auto unwrappedType = getUnwrappedType();

  assert(!baseType->hasTypeVariable() &&
         "Base type must not be a type variable");
  assert(!baseType->isHole() && "Base type must not be a type hole");
  assert(!unwrappedType->hasTypeVariable() &&
         "Unwrapped type must not be a type variable");
  assert(!unwrappedType->isHole() && "Unwrapped type must not be a type hole");

  if (!baseType->getOptionalObjectType())
    return false;

  emitDiagnosticAt(unwrappedExpr->getLoc(), diag::optional_not_unwrapped,
                   baseType, unwrappedType);

  // If the expression we're unwrapping is the only reference to a
  // local variable whose type isn't explicit in the source, then
  // offer unwrapping fixits on the initializer as well.
  if (auto declRef = dyn_cast<DeclRefExpr>(unwrappedExpr)) {
    if (auto varDecl = dyn_cast<VarDecl>(declRef->getDecl())) {
      bool singleUse = false;
      AbstractFunctionDecl *AFD = nullptr;
      if ((AFD = dyn_cast<AbstractFunctionDecl>(varDecl->getDeclContext()))) {
        auto checker = VarDeclMultipleReferencesChecker(getDC(), varDecl);
        AFD->getBody()->walk(checker);
        singleUse = checker.referencesCount() == 1;
      }

      PatternBindingDecl *binding = varDecl->getParentPatternBinding();
      if (singleUse && binding && binding->getNumPatternEntries() == 1 &&
          varDecl->getTypeSourceRangeForDiagnostics().isInvalid()) {

        auto *initializer = varDecl->getParentInitializer();
        if (!initializer)
          return true;

        if (auto declRefExpr = dyn_cast<DeclRefExpr>(initializer)) {
          if (declRefExpr->getDecl()->isImplicitlyUnwrappedOptional()) {
            emitDiagnosticAt(declRefExpr->getLoc(),
                             diag::unwrap_iuo_initializer, baseType);
          }
        }

        auto fnTy = AFD->getInterfaceType()->castTo<AnyFunctionType>();
        bool voidReturn =
            fnTy->getResult()->isEqual(TupleType::getEmpty(getASTContext()));

        auto diag =
            emitDiagnosticAt(varDecl->getLoc(), diag::unwrap_with_guard);
        diag.fixItInsert(binding->getStartLoc(), "guard ");
        if (voidReturn) {
          diag.fixItInsertAfter(binding->getEndLoc(), " else { return }");
        } else {
          diag.fixItInsertAfter(binding->getEndLoc(), " else { return <"
                                                      "#default value#"
                                                      "> }");
        }
        diag.flush();

        offerDefaultValueUnwrapFixIt(varDecl->getDeclContext(), initializer);
        offerForceUnwrapFixIt(initializer);
      }
    }
  }

  offerDefaultValueUnwrapFixIt(getDC(), unwrappedExpr);
  offerForceUnwrapFixIt(unwrappedExpr);
  return true;
}

bool RValueTreatedAsLValueFailure::diagnoseAsError() {
  Diag<StringRef> subElementDiagID;
  Diag<Type> rvalueDiagID = diag::assignment_lhs_not_lvalue;
  auto diagExpr = castToExpr(getRawAnchor());
  SourceLoc loc = diagExpr->getLoc();

  // Assignment is not allowed inside of a condition,
  // so let's not diagnose immutability, because
  // most likely the problem is related to use of `=` itself.
  if (getContextualTypePurpose(diagExpr) == CTP_Condition)
    return false;

  // If the failure happened at the end of an unresolved member chain, it should
  // be diagnosed instead as though it happened at the last element.
  if (auto chainExpr = dyn_cast<UnresolvedMemberChainResultExpr>(diagExpr))
      diagExpr = chainExpr->getSubExpr();

  if (auto assignExpr = dyn_cast<AssignExpr>(diagExpr)) {
    // Let's check whether this is an attempt to assign
    // variable or property to itself.
    if (TypeChecker::diagnoseSelfAssignment(assignExpr))
      return true;

    diagExpr = assignExpr->getDest();
  }

  if (auto callExpr = dyn_cast<ApplyExpr>(diagExpr)) {
    Expr *argExpr = callExpr->getArg();
    loc = callExpr->getFn()->getLoc();
    auto *locator = getLocator();

    // `argument attribute` is used for identification purposes
    // only, so it could be looked through in this situation.
    if (locator->isLastElement<LocatorPathElt::ArgumentAttribute>()) {
      auto path = locator->getPath();
      locator = getConstraintLocator(getRawAnchor(), path.drop_back());
    }

    if (isa<PrefixUnaryExpr>(callExpr) || isa<PostfixUnaryExpr>(callExpr)) {
      subElementDiagID = diag::cannot_apply_lvalue_unop_to_subelement;
      rvalueDiagID = diag::cannot_apply_lvalue_unop_to_rvalue;
      diagExpr = argExpr;
    } else if (isa<BinaryExpr>(callExpr)) {
      subElementDiagID = diag::cannot_apply_lvalue_binop_to_subelement;
      rvalueDiagID = diag::cannot_apply_lvalue_binop_to_rvalue;
      diagExpr = castToExpr(simplifyLocatorToAnchor(locator));
    } else if (auto argElt =
                   locator
                       ->getLastElementAs<LocatorPathElt::ApplyArgToParam>()) {
      subElementDiagID = diag::cannot_pass_rvalue_inout_subelement;
      rvalueDiagID = diag::cannot_pass_rvalue_inout;
      if (auto argTuple = dyn_cast<TupleExpr>(argExpr))
        diagExpr = argTuple->getElement(argElt->getArgIdx());
      else if (auto parens = dyn_cast<ParenExpr>(argExpr))
        diagExpr = parens->getSubExpr();
    } else {
      subElementDiagID = diag::assignment_lhs_is_apply_expression;
    }
  } else if (auto inoutExpr = dyn_cast<InOutExpr>(diagExpr)) {
    if (auto *parentExpr = findParentExpr(inoutExpr)) {
      if (auto *call =
              dyn_cast_or_null<ApplyExpr>(findParentExpr(parentExpr))) {
        // Since this `inout` expression is an argument to a call/operator
        // let's figure out whether this is an impliict conversion from
        // array to an unsafe pointer type and diagnose it.
        unsigned argIdx = 0;
        if (auto *TE = dyn_cast<TupleExpr>(parentExpr)) {
          for (unsigned n = TE->getNumElements(); argIdx != n; ++argIdx) {
            if (TE->getElement(argIdx) == inoutExpr)
              break;
          }
        }

        auto *argLoc = getConstraintLocator(
            call, {ConstraintLocator::ApplyArgument,
                   LocatorPathElt::ApplyArgToParam(argIdx, argIdx,
                                                   ParameterTypeFlags())});

        if (auto info = getFunctionArgApplyInfo(argLoc)) {
          auto paramType = info->getParamType();
          auto argType = getType(inoutExpr)->getWithoutSpecifierType();

          PointerTypeKind ptr;
          if (isArrayType(argType) &&
              paramType->getAnyPointerElementType(ptr) &&
              (ptr == PTK_UnsafePointer || ptr == PTK_UnsafeRawPointer)) {
            emitDiagnosticAt(inoutExpr->getLoc(),
                             diag::extra_address_of_unsafepointer, paramType)
                .highlight(inoutExpr->getSourceRange())
                .fixItRemove(inoutExpr->getStartLoc());
            return true;
          }
        }
      }
    }

    subElementDiagID = diag::cannot_pass_rvalue_inout_subelement;
    rvalueDiagID = diag::cannot_pass_rvalue_inout;
    diagExpr = inoutExpr->getSubExpr();
  } else if (isa<DeclRefExpr>(diagExpr)) {
    subElementDiagID = diag::assignment_lhs_is_immutable_variable;
  } else if (isa<ForceValueExpr>(diagExpr)) {
    subElementDiagID = diag::assignment_bang_has_immutable_subcomponent;
  } else if (isa<MemberRefExpr>(diagExpr)) {
    subElementDiagID = diag::assignment_lhs_is_immutable_property;
  } else if (auto member = dyn_cast<UnresolvedDotExpr>(diagExpr)) {
    subElementDiagID = diag::assignment_lhs_is_immutable_property;

    if (auto *ctor = dyn_cast<ConstructorDecl>(getDC())) {
      if (auto *baseRef = dyn_cast<DeclRefExpr>(member->getBase())) {
        if (baseRef->getDecl() == ctor->getImplicitSelfDecl() &&
            ctor->getDelegatingOrChainedInitKind().initKind ==
            BodyInitKind::Delegating) {
          emitDiagnosticAt(loc, diag::assignment_let_property_delegating_init,
                           member->getName());
          if (auto overload = getOverloadChoiceIfAvailable(
                  getConstraintLocator(member, ConstraintLocator::Member))) {
            if (auto *ref = overload->choice.getDeclOrNull())
              emitDiagnosticAt(ref, diag::decl_declared_here,
                               ref->getName());
          }
          return true;
        }
      }
    }

    if (auto resolvedOverload = getOverloadChoiceIfAvailable(getLocator())) {
      if (resolvedOverload->choice.getKind() ==
          OverloadChoiceKind::DynamicMemberLookup)
        subElementDiagID = diag::assignment_dynamic_property_has_immutable_base;

      if (resolvedOverload->choice.getKind() ==
          OverloadChoiceKind::KeyPathDynamicMemberLookup) {
        if (!getType(member->getBase(), /*wantRValue=*/false)->hasLValueType())
          subElementDiagID =
              diag::assignment_dynamic_property_has_immutable_base;
      }
    }
  } else if (isa<SubscriptExpr>(diagExpr)) {
      subElementDiagID = diag::assignment_subscript_has_immutable_base;
  } else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(diagExpr)) {
    subElementDiagID = diag::assignment_lhs_is_immutable_property;
  } else {
    subElementDiagID = diag::assignment_lhs_is_immutable_variable;
  }

  AssignmentFailure failure(diagExpr, getSolution(), loc, subElementDiagID,
                            rvalueDiagID);
  return failure.diagnose();
}

bool RValueTreatedAsLValueFailure::diagnoseAsNote() {
  auto overload = getCalleeOverloadChoiceIfAvailable(getLocator());
  if (!(overload && overload->choice.isDecl()))
    return false;

  auto *decl = overload->choice.getDecl();
  emitDiagnosticAt(decl, diag::candidate_is_not_assignable,
                   decl->getDescriptiveKind(), decl->getName());
  return true;
}

static VarDecl *findSimpleReferencedVarDecl(const Expr *E) {
  if (auto *LE = dyn_cast<LoadExpr>(E))
    E = LE->getSubExpr();

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

  return nullptr;
}

static std::pair<VarDecl *, VarDecl *> findReferencedVarDecl(const Expr *E) {
  E = E->getValueProvidingExpr();

  if (auto *LE = dyn_cast<LoadExpr>(E))
    return findReferencedVarDecl(LE->getSubExpr());

  if (auto *AE = dyn_cast<AssignExpr>(E))
    return findReferencedVarDecl(AE->getDest());

  if (auto *D = findSimpleReferencedVarDecl(E))
    return std::make_pair(nullptr, D);

  if (auto *MRE = dyn_cast<MemberRefExpr>(E)) {
    if (auto *BaseDecl = findSimpleReferencedVarDecl(MRE->getBase()))
      return std::make_pair(BaseDecl, cast<VarDecl>(MRE->getMember().getDecl()));
  }

  return std::make_pair(nullptr, nullptr);
}

bool TypeChecker::diagnoseSelfAssignment(const Expr *expr) {
  auto *assignExpr = dyn_cast<AssignExpr>(expr);
  if (!assignExpr)
    return false;

  auto *dstExpr = assignExpr->getDest();
  auto *srcExpr = assignExpr->getSrc();

  auto dstDecl = findReferencedVarDecl(dstExpr);
  auto srcDecl = findReferencedVarDecl(srcExpr);

  if (dstDecl.second &&
      dstDecl.second->hasStorage() &&
      dstDecl == srcDecl) {
    auto &DE = dstDecl.second->getASTContext().Diags;
    DE.diagnose(expr->getLoc(), dstDecl.first ? diag::self_assignment_prop
                                              : diag::self_assignment_var)
        .highlight(dstExpr->getSourceRange())
        .highlight(srcExpr->getSourceRange());
    return true;
  }

  return false;
}

bool TrailingClosureAmbiguityFailure::diagnoseAsNote() {
  auto *anchor = castToExpr(getAnchor());
  const auto *expr = findParentExpr(anchor);
  auto *callExpr = dyn_cast_or_null<CallExpr>(expr);
  if (!callExpr)
    return false;
  if (!callExpr->hasTrailingClosure())
    return false;
  if (callExpr->getFn() != anchor)
    return false;

  llvm::SmallMapVector<Identifier, const ValueDecl *, 8> choicesByLabel;
  for (const auto &choice : Choices) {
    auto *callee = dyn_cast<AbstractFunctionDecl>(choice.getDecl());
    if (!callee)
      return false;

    const ParameterList *paramList = callee->getParameters();
    const ParamDecl *param = paramList->getArray().back();

    // Sanity-check that the trailing closure corresponds to this parameter.
    if (!param->hasInterfaceType() ||
        !param->getInterfaceType()->is<AnyFunctionType>())
      return false;

    Identifier trailingClosureLabel = param->getArgumentName();
    auto &choiceForLabel = choicesByLabel[trailingClosureLabel];

    // FIXME: Cargo-culted from diagnoseAmbiguity: apparently the same decl can
    // appear more than once?
    if (choiceForLabel == callee)
      continue;

    // If just providing the trailing closure label won't solve the ambiguity,
    // don't bother offering the fix-it.
    if (choiceForLabel != nullptr)
      return false;

    choiceForLabel = callee;
  }

  // If we got here, then all of the choices have unique labels. Offer them in
  // order.
  for (const auto &choicePair : choicesByLabel) {
    auto diag = emitDiagnosticAt(
        expr->getLoc(), diag::ambiguous_because_of_trailing_closure,
        choicePair.first.empty(), choicePair.second->getName());
    swift::fixItEncloseTrailingClosure(getASTContext(), diag, callExpr,
                                       choicePair.first);
  }

  return true;
}

AssignmentFailure::AssignmentFailure(Expr *destExpr, const Solution &solution,
                                     SourceLoc diagnosticLoc)
    : FailureDiagnostic(solution, destExpr), DestExpr(destExpr),
      Loc(diagnosticLoc),
      DeclDiagnostic(findDeclDiagonstic(getASTContext(), destExpr)),
      TypeDiagnostic(diag::assignment_lhs_not_lvalue) {}

bool AssignmentFailure::diagnoseAsError() {
  auto *DC = getDC();

  // Walk through the destination expression, resolving what the problem is.  If
  // we find a node in the lvalue path that is problematic, this returns it.
  Expr *immutableExpr;
  Optional<OverloadChoice> choice;
  std::tie(immutableExpr, choice) = resolveImmutableBase(DestExpr);

  // Attempt diagnostics based on the overload choice.
  if (choice.hasValue()) {

    auto getKeyPathArgument = [](SubscriptExpr *expr) {
      auto *TE = dyn_cast<TupleExpr>(expr->getIndex());
      assert(TE->getNumElements() == 1);
      assert(TE->getElementName(0).str() == "keyPath");
      return TE->getElement(0);
    };

    if (!choice->isDecl()) {
      if (choice->getKind() == OverloadChoiceKind::KeyPathApplication &&
          !isa<ApplyExpr>(immutableExpr)) {
        std::string message = "key path is read-only";
        if (auto *SE = dyn_cast<SubscriptExpr>(immutableExpr)) {
          if (auto *DRE = dyn_cast<DeclRefExpr>(getKeyPathArgument(SE))) {
            auto identifier = DRE->getDecl()->getBaseIdentifier();
            message =
                "'" + identifier.str().str() + "' is a read-only key path";
          }
        }
        emitDiagnosticAt(Loc, DeclDiagnostic, message)
            .highlight(immutableExpr->getSourceRange());
        return true;
      }
      return false;
    }

    // Otherwise, we cannot resolve this because the available setter candidates
    // are all mutating and the base must be mutating.  If we dug out a
    // problematic decl, we can produce a nice tailored diagnostic.
    if (auto *VD = dyn_cast<VarDecl>(choice->getDecl())) {
      std::string message = "'";
      message += VD->getName().str().str();
      message += "'";

      auto type = getType(immutableExpr);

      if (isKnownKeyPathType(type))
        message += " is read-only";
      else if (VD->isCaptureList())
        message += " is an immutable capture";
      else if (VD->isImplicit())
        message += " is immutable";
      else if (VD->isLet())
        message += " is a 'let' constant";
      else if (!VD->isSettable(DC))
        message += " is a get-only property";
      else if (!VD->isSetterAccessibleFrom(DC))
        message += " setter is inaccessible";
      else {
        message += " is immutable";
      }

      emitDiagnosticAt(Loc, DeclDiagnostic, message)
          .highlight(immutableExpr->getSourceRange());

      // If there is a masked property of the same type, emit a
      // note to fixit prepend a 'self.' or 'Type.'.
      if (auto typeContext = DC->getInnermostTypeContext()) {
        SmallVector<ValueDecl *, 2> results;
        DC->lookupQualified(typeContext->getSelfNominalTypeDecl(),
                            VD->createNameRef(), NL_QualifiedDefault, results);

        auto foundProperty = llvm::find_if(results, [&](ValueDecl *decl) {
          // We're looking for a settable property that is the same type as the
          // var we found.
          auto *var = dyn_cast<VarDecl>(decl);
          if (!var || var == VD)
            return false;

          if (!var->isSettable(DC) || !var->isSetterAccessibleFrom(DC))
            return false;

          if (!var->getType()->isEqual(VD->getType()))
            return false;

          // Don't suggest a property if we're in one of its accessors.
          auto *methodDC = DC->getInnermostMethodContext();
          if (auto *AD = dyn_cast_or_null<AccessorDecl>(methodDC))
            if (AD->getStorage() == var)
              return false;

          return true;
        });

        if (foundProperty != results.end()) {
          auto startLoc = immutableExpr->getStartLoc();
          auto *property = *foundProperty;
          auto selfTy = typeContext->getSelfTypeInContext();

          // If we found an instance property, suggest inserting "self.",
          // otherwise suggest "Type." for a static property.
          std::string fixItText;
          if (property->isInstanceMember()) {
            fixItText = "self.";
          } else {
            fixItText = selfTy->getString() + ".";
          }
          emitDiagnosticAt(startLoc, diag::masked_mutable_property, fixItText,
                           property->getDescriptiveKind(), selfTy)
              .fixItInsert(startLoc, fixItText);
        }
      }

      // If this is a simple variable marked with a 'let', emit a note to fixit
      // hint it to 'var'.
      VD->emitLetToVarNoteIfSimple(DC);
      return true;
    }

    // If the underlying expression was a read-only subscript, diagnose that.
    if (auto *SD = dyn_cast_or_null<SubscriptDecl>(choice->getDecl())) {
      StringRef message;
      if (!SD->supportsMutation())
        message = "subscript is get-only";
      else if (!SD->isSetterAccessibleFrom(DC))
        message = "subscript setter is inaccessible";
      else
        message = "subscript is immutable";

      emitDiagnosticAt(Loc, DeclDiagnostic, message)
          .highlight(immutableExpr->getSourceRange());
      return true;
    }

    // If we're trying to set an unapplied method, say that.
    if (auto *VD = choice->getDecl()) {
      std::string message = "'";
      message += VD->getBaseIdentifier().str();
      message += "'";

      auto diagID = DeclDiagnostic;
      if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
        if (AFD->hasImplicitSelfDecl()) {
          message += " is a method";
          diagID = diag::assignment_lhs_is_immutable_variable;
        } else {
          message += " is a function";
        }
      } else
        message += " is not settable";

      emitDiagnosticAt(Loc, diagID, message)
          .highlight(immutableExpr->getSourceRange());
      return true;
    }
  }

  // Fall back to producing diagnostics based on the expression since we
  // couldn't determine anything from the OverloadChoice.

  // If a keypath was the problem but wasn't resolved into a vardecl
  // it is ambiguous or unable to be used for setting.
  if (auto *KPE = dyn_cast_or_null<KeyPathExpr>(immutableExpr)) {
    emitDiagnosticAt(Loc, DeclDiagnostic, "immutable key path")
        .highlight(KPE->getSourceRange());
    return true;
  }

  if (auto LE = dyn_cast<LiteralExpr>(immutableExpr)) {
    emitDiagnosticAt(Loc, DeclDiagnostic, "literals are not mutable")
        .highlight(LE->getSourceRange());
    return true;
  }

  // If the expression is the result of a call, it is an rvalue, not a mutable
  // lvalue.
  if (auto *AE = dyn_cast<ApplyExpr>(immutableExpr)) {
    // Handle literals, which are a call to the conversion function.
    auto argsTuple =
        dyn_cast<TupleExpr>(AE->getArg()->getSemanticsProvidingExpr());
    if (isa<CallExpr>(AE) && AE->isImplicit() && argsTuple &&
        argsTuple->getNumElements() == 1) {
      if (auto LE = dyn_cast<LiteralExpr>(
              argsTuple->getElement(0)->getSemanticsProvidingExpr())) {
        emitDiagnosticAt(Loc, DeclDiagnostic, "literals are not mutable")
            .highlight(LE->getSourceRange());
        return true;
      }
    }

    std::string name = "call";
    if (isa<PrefixUnaryExpr>(AE) || isa<PostfixUnaryExpr>(AE))
      name = "unary operator";
    else if (isa<BinaryExpr>(AE))
      name = "binary operator";
    else if (isa<CallExpr>(AE))
      name = "function call";
    else if (isa<DotSyntaxCallExpr>(AE) || isa<DotSyntaxBaseIgnoredExpr>(AE))
      name = "method call";

    if (auto *DRE = dyn_cast<DeclRefExpr>(AE->getFn()->getValueProvidingExpr()))
      name = std::string("'") +
             DRE->getDecl()->getBaseIdentifier().str().str() + "'";

    emitDiagnosticAt(Loc, DeclDiagnostic, name + " returns immutable value")
        .highlight(AE->getSourceRange());
    return true;
  }

  if (auto contextualType = getContextualType(immutableExpr)) {
    Type neededType = contextualType->getInOutObjectType();
    Type actualType = getType(immutableExpr)->getInOutObjectType();
    if (!neededType->isEqual(actualType)) {
      if (DeclDiagnostic.ID != diag::cannot_pass_rvalue_inout_subelement.ID) {
        emitDiagnosticAt(Loc, DeclDiagnostic,
                         "implicit conversion from '" +
                             actualType->getString() + "' to '" +
                             neededType->getString() + "' requires a temporary")
            .highlight(immutableExpr->getSourceRange());
      }
      return true;
    }
  }

  if (auto IE = dyn_cast<IfExpr>(immutableExpr)) {
    emitDiagnosticAt(Loc, DeclDiagnostic,
                     "result of conditional operator '? :' is never mutable")
        .highlight(IE->getQuestionLoc())
        .highlight(IE->getColonLoc());
    return true;
  }

  emitDiagnosticAt(Loc, TypeDiagnostic, getType(DestExpr))
      .highlight(immutableExpr->getSourceRange());
  return true;
}

std::pair<Expr *, Optional<OverloadChoice>>
AssignmentFailure::resolveImmutableBase(Expr *expr) const {
  auto *DC = getDC();
  expr = expr->getValueProvidingExpr();

  auto isImmutable = [&DC](ValueDecl *decl) {
    if (auto *storage = dyn_cast<AbstractStorageDecl>(decl))
      return !storage->isSettable(nullptr) ||
             !storage->isSetterAccessibleFrom(DC);

    // If this is not something which could possibly be mutable,
    // then it's immutable.
    return true;
  };

  // Provide specific diagnostics for assignment to subscripts whose base expr
  // is known to be an rvalue.
  if (auto *SE = dyn_cast<SubscriptExpr>(expr)) {
    // If we found a decl for the subscript, check to see if it is a set-only
    // subscript decl.
    if (SE->hasDecl()) {
      const auto &declRef = SE->getDecl();
      if (auto *subscript =
              dyn_cast_or_null<SubscriptDecl>(declRef.getDecl())) {
        if (isImmutable(subscript))
          return {expr, OverloadChoice(getType(SE->getBase()), subscript,
                                       FunctionRefKind::DoubleApply)};
      }
    }

    Optional<OverloadChoice> member = getMemberRef(
        getConstraintLocator(SE, ConstraintLocator::SubscriptMember));

    // If it isn't settable, return it.
    if (member) {
      if (member->isDecl() && isImmutable(member->getDecl()))
        return {expr, member};

      // We still have a choice, the choice is not a decl
      if (!member->isDecl()) {
        // This must be a keypath application
        assert(member->getKind() == OverloadChoiceKind::KeyPathApplication);

        auto *argType = getType(SE->getIndex())->castTo<TupleType>();
        assert(argType->getNumElements() == 1);

        auto indexType = resolveType(argType->getElementType(0));

        if (auto bgt = indexType->getAs<BoundGenericType>()) {
          // In Swift versions lower than 5, this check will fail as read only
          // key paths can masquerade as writable for compatibilty reasons.
          // This is fine as in this case we just fall back on old diagnostics.
          auto &ctx = getASTContext();
          if (bgt->getDecl() == ctx.getKeyPathDecl() ||
              bgt->getDecl() == ctx.getPartialKeyPathDecl()) {
            return {expr, member};
          }
        }
      }
    }

    // If it is settable, then the base must be the problem, recurse.
    return resolveImmutableBase(SE->getBase());
  }

  // Look through property references.
  if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
    // If we found a decl for the UDE, check it.
    auto loc = getConstraintLocator(UDE, ConstraintLocator::Member);

    auto member = getMemberRef(loc);

    // If we can resolve a member, we can determine whether it is settable in
    // this context.
    if (member && member->isDecl() && isImmutable(member->getDecl()))
      return {expr, member};

    // If we weren't able to resolve a member or if it is mutable, then the
    // problem must be with the base, recurse.
    return resolveImmutableBase(UDE->getBase());
  }

  if (auto *MRE = dyn_cast<MemberRefExpr>(expr)) {
    // If the member isn't settable, then it is the problem: return it.
    if (auto member = dyn_cast<AbstractStorageDecl>(MRE->getMember().getDecl()))
      if (isImmutable(member))
        return {expr, OverloadChoice(getType(MRE->getBase()), member,
                                     FunctionRefKind::SingleApply)};

    // If we weren't able to resolve a member or if it is mutable, then the
    // problem must be with the base, recurse.
    return resolveImmutableBase(MRE->getBase());
  }

  if (auto *UME = dyn_cast<UnresolvedMemberExpr>(expr)) {
    auto loc = getConstraintLocator(UME, ConstraintLocator::UnresolvedMember);
    auto member = getMemberRef(loc);

    // If we can resolve a member, we can determine whether it is settable in
    // this context.
    if (member && member->isDecl() && isImmutable(member->getDecl()))
      return {expr, member};
    else
      return {expr, None};
  }

  if (auto *DRE = dyn_cast<DeclRefExpr>(expr))
    return {expr,
            OverloadChoice(Type(), DRE->getDecl(), FunctionRefKind::Unapplied)};

  // Look through x!
  if (auto *FVE = dyn_cast<ForceValueExpr>(expr))
    return resolveImmutableBase(FVE->getSubExpr());

  // Look through x?
  if (auto *BOE = dyn_cast<BindOptionalExpr>(expr))
    return resolveImmutableBase(BOE->getSubExpr());

  // Look through implicit conversions
  if (auto *ICE = dyn_cast<ImplicitConversionExpr>(expr))
    if (!isa<LoadExpr>(ICE->getSubExpr()))
      return resolveImmutableBase(ICE->getSubExpr());

  if (auto *SAE = dyn_cast<SelfApplyExpr>(expr))
    return resolveImmutableBase(SAE->getFn());

  return {expr, None};
}

Optional<OverloadChoice>
AssignmentFailure::getMemberRef(ConstraintLocator *locator) const {
  auto member = getOverloadChoiceIfAvailable(locator);
  if (!member)
    return None;

  if (!member->choice.isDecl())
    return member->choice;

  auto *DC = getDC();
  auto *decl = member->choice.getDecl();
  if (isa<SubscriptDecl>(decl) &&
      isValidDynamicMemberLookupSubscript(cast<SubscriptDecl>(decl), DC)) {
    auto *subscript = cast<SubscriptDecl>(decl);
    // If this is a keypath dynamic member lookup, we have to
    // adjust the locator to find member referred by it.
    if (isValidKeyPathDynamicMemberLookup(subscript)) {
      // Type has a following format:
      // `(Self) -> (dynamicMember: {Writable}KeyPath<T, U>) -> U`
      auto *fullType = member->openedFullType->castTo<FunctionType>();
      auto *fnType = fullType->getResult()->castTo<FunctionType>();

      auto paramTy = fnType->getParams()[0].getPlainType();
      auto keyPath = paramTy->getAnyNominal();
      auto memberLoc = getConstraintLocator(
          locator, LocatorPathElt::KeyPathDynamicMember(keyPath));

      auto memberRef = getOverloadChoiceIfAvailable(memberLoc);
      return memberRef ? Optional<OverloadChoice>(memberRef->choice) : None;
    }

    // If this is a string based dynamic lookup, there is no member declaration.
    return None;
  }

  return member->choice;
}

Diag<StringRef> AssignmentFailure::findDeclDiagonstic(ASTContext &ctx,
                                                      const Expr *destExpr) {
  if (isa<ApplyExpr>(destExpr) || isa<SelfApplyExpr>(destExpr))
    return diag::assignment_lhs_is_apply_expression;

  if (isa<UnresolvedDotExpr>(destExpr) || isa<MemberRefExpr>(destExpr))
    return diag::assignment_lhs_is_immutable_property;

  if (auto *subscript = dyn_cast<SubscriptExpr>(destExpr)) {
    auto diagID = diag::assignment_subscript_has_immutable_base;
    // If the destination is a subscript with a 'dynamicLookup:' label and if
    // the tuple is implicit, then this was actually a @dynamicMemberLookup
    // access. Emit a more specific diagnostic.
    if (subscript->getIndex()->isImplicit() &&
        subscript->getArgumentLabels().size() == 1 &&
        subscript->getArgumentLabels().front() == ctx.Id_dynamicMember)
      diagID = diag::assignment_dynamic_property_has_immutable_base;

    return diagID;
  }

  return diag::assignment_lhs_is_immutable_variable;
}

bool ContextualFailure::diagnoseAsError() {
  auto anchor = getAnchor();
  auto path = getLocator()->getPath();

  if (CTP == CTP_ReturnSingleExpr || CTP == CTP_ReturnStmt) {
    // Special case the "conversion to void".
    if (getToType()->isVoid()) {
      emitDiagnostic(diag::cannot_return_value_from_void_func)
          .highlight(getSourceRange());
      return true;
    }
  }

  if (diagnoseConversionToNil())
    return true;

  if (path.empty()) {
    if (auto *KPE = getAsExpr<KeyPathExpr>(anchor)) {
      emitDiagnosticAt(KPE->getLoc(),
                       diag::expr_smart_keypath_value_covert_to_contextual_type,
                       getFromType(), getToType());
      return true;
    }

    if (diagnoseCoercionToUnrelatedType())
      return true;

    if (isExpr<OptionalTryExpr>(anchor)) {
      emitDiagnostic(diag::cannot_convert_initializer_value, getFromType(),
                     getToType());
      return true;
    }

    if (isExpr<AssignExpr>(anchor)) {
      auto diagnostic = emitDiagnostic(diag::cannot_convert_assign,
                                       getFromType(), getToType());
      tryIntegerCastFixIts(diagnostic);
      return true;
    }

    return false;
  }

  if (diagnoseMissingFunctionCall())
    return true;

  // Special case of some common conversions involving Swift.String
  // indexes, catching cases where people attempt to index them with an integer.
  if (isIntegerToStringIndexConversion()) {
    emitDiagnostic(diag::string_index_not_integer, getFromType())
        .highlight(getSourceRange());
    emitDiagnostic(diag::string_index_not_integer_note);
    return true;
  }

  auto fromType = getFromType();
  auto toType = getToType();

  Diag<Type, Type> diagnostic;
  switch (path.back().getKind()) {
  case ConstraintLocator::ClosureBody:
  case ConstraintLocator::ClosureResult: {
    auto *closure = castToExpr<ClosureExpr>(getRawAnchor());
    if (closure->hasExplicitResultType() &&
        closure->getExplicitResultTypeRepr()) {
      auto resultRepr = closure->getExplicitResultTypeRepr();
      emitDiagnosticAt(resultRepr->getStartLoc(),
                       diag::incorrect_explicit_closure_result, fromType,
                       toType)
          .fixItReplace(resultRepr->getSourceRange(), toType.getString());
      return true;
    }

    diagnostic = diag::cannot_convert_closure_result;
    break;
  }

  case ConstraintLocator::Condition: {
    // Tailored diagnostics for optional or assignment use
    // in condition expression.
    if (diagnoseConversionToBool())
      return true;

    diagnostic = diag::cannot_convert_condition_value;
    break;
  }
      
  case ConstraintLocator::InstanceType: {
    if (diagnoseCoercionToUnrelatedType())
      return true;
    break;
  }

  case ConstraintLocator::TernaryBranch: {
    auto *ifExpr = castToExpr<IfExpr>(getRawAnchor());
    fromType = getType(ifExpr->getThenExpr());
    toType = getType(ifExpr->getElseExpr());
    diagnostic = diag::if_expr_cases_mismatch;
    break;
  }

  case ConstraintLocator::ContextualType: {
    if (diagnoseConversionToBool())
      return true;

    if (diagnoseThrowsTypeMismatch())
      return true;

    if (diagnoseYieldByReferenceMismatch())
      return true;

    if (isExpr<OptionalTryExpr>(anchor) ||
        isExpr<OptionalEvaluationExpr>(anchor)) {
      auto objectType = fromType->getOptionalObjectType();
      if (objectType->isEqual(toType)) {
        MissingOptionalUnwrapFailure failure(getSolution(), getType(anchor),
                                             toType,
                                             getConstraintLocator(anchor));
        if (failure.diagnoseAsError())
          return true;
      }
    }

    if (CTP == CTP_ForEachStmt) {
      if (fromType->isAnyExistentialType()) {
        emitDiagnostic(diag::type_cannot_conform,
                       /*isExistentialType=*/true, fromType, 
                       fromType->isEqual(toType), toType);
        emitDiagnostic(diag::only_concrete_types_conform_to_protocols);
        return true;
      }

      emitDiagnostic(
          diag::foreach_sequence_does_not_conform_to_expected_protocol,
          fromType, toType, bool(fromType->getOptionalObjectType()))
          .highlight(getSourceRange());
      return true;
    }

    if (auto *call = getAsExpr<CallExpr>(anchor)) {
      if (isa<ClosureExpr>(call->getFn()))
        CTP = CTP_ClosureResult;
    }

    if (auto msg = getDiagnosticFor(CTP, toType)) {
      diagnostic = *msg;
      break;
    }
    return false;
  }

  case ConstraintLocator::UnresolvedMemberChainResult: {
    auto &solution = getSolution();

    auto overload =
        getCalleeOverloadChoiceIfAvailable(getConstraintLocator(anchor));
    if (!(overload && overload->choice.isDecl()))
      return false;

    auto *choice = overload->choice.getDecl();
    auto fnType = fromType->getAs<FunctionType>();
    if (!fnType) {
      emitDiagnostic(diag::expected_result_in_contextual_member,
                     choice->getName(), fromType, toType);
      return true;
    }

    // If member type is a function and contextual type matches
    // its result type, most likely problem is related to a
    // missing call e.g.:
    //
    // struct S {
    //   static func foo() -> S {}
    // }
    //
    // let _: S = .foo

    auto params = fnType->getParams();

    ParameterListInfo info(
        params, choice,
        hasAppliedSelf(overload->choice, [&solution](Type type) {
          return solution.simplifyType(type);
        }));
    auto numMissingArgs = llvm::count_if(
        indices(params), [&info](const unsigned paramIdx) -> bool {
          return !info.hasDefaultArgument(paramIdx);
        });

    if (numMissingArgs == 0 || numMissingArgs > 1) {
      auto applyFixIt = [&](InFlightDiagnostic &diagnostic) {
        // If there are no parameters we can suggest a fix-it
        // to form an explicit call.
        if (numMissingArgs == 0)
          diagnostic.fixItInsertAfter(getSourceRange().End, "()");
      };
      if (fnType->getResult()->isEqual(toType)) {
        auto diag = emitDiagnostic(
                      diag::expected_parens_in_contextual_member_type,
                      choice->getName(), fnType->getResult());
        applyFixIt(diag);
      } else {
        auto diag = emitDiagnostic(diag::expected_parens_in_contextual_member,
                                   choice->getName());
        applyFixIt(diag);
      }
    } else {
      emitDiagnostic(diag::expected_argument_in_contextual_member,
                     choice->getName(), params.front().getPlainType());
    }

    return true;
  }

  case ConstraintLocator::ResultBuilderBodyResult: {
    diagnostic = *getDiagnosticFor(CTP_Initialization, toType);
    break;
  }

  default:
    return false;
  }

  auto diag = emitDiagnostic(diagnostic, fromType, toType);
  diag.highlight(getSourceRange());

  (void)tryFixIts(diag);
  return true;
}

bool ContextualFailure::diagnoseAsNote() {
  auto overload = getCalleeOverloadChoiceIfAvailable(getLocator());
  if (!(overload && overload->choice.isDecl()))
    return false;

  auto *decl = overload->choice.getDecl();
  emitDiagnosticAt(decl, diag::found_candidate_type, getFromType());
  return true;
}

static Optional<Diag<Type>>
getContextualNilDiagnostic(ContextualTypePurpose CTP) {
  switch (CTP) {
  case CTP_Unused:
  case CTP_CannotFail:
    llvm_unreachable("These contextual type purposes cannot fail with a "
                     "conversion type specified!");
  case CTP_CalleeResult:
    llvm_unreachable("CTP_CalleeResult does not actually install a "
                     "contextual type");
  case CTP_Initialization:
    return diag::cannot_convert_initializer_value_nil;

  case CTP_ReturnSingleExpr:
  case CTP_ReturnStmt:
    return diag::cannot_convert_to_return_type_nil;

  case CTP_ThrowStmt:
  case CTP_ForEachStmt:
  case CTP_YieldByReference:
  case CTP_WrappedProperty:
  case CTP_ComposedPropertyWrapper:
    return None;

  case CTP_EnumCaseRawValue:
    return diag::cannot_convert_raw_initializer_value_nil;
  case CTP_DefaultParameter:
  case CTP_AutoclosureDefaultParameter:
    return diag::cannot_convert_default_arg_value_nil;
  case CTP_YieldByValue:
    return diag::cannot_convert_yield_value_nil;
  case CTP_CallArgument:
    return diag::cannot_convert_argument_value_nil;
  case CTP_ClosureResult:
    return diag::cannot_convert_closure_result_nil;
  case CTP_ArrayElement:
    return diag::cannot_convert_array_element_nil;
  case CTP_DictionaryKey:
    return diag::cannot_convert_dict_key_nil;
  case CTP_DictionaryValue:
    return diag::cannot_convert_dict_value_nil;
  case CTP_CoerceOperand:
    return diag::cannot_convert_coerce_nil;
  case CTP_AssignSource:
    return diag::cannot_convert_assign_nil;
  case CTP_SubscriptAssignSource:
    return diag::cannot_convert_subscript_assign_nil;
  case CTP_Condition:
    return diag::cannot_convert_condition_value_nil;
  }
  llvm_unreachable("Unhandled ContextualTypePurpose in switch");
}

bool ContextualFailure::diagnoseConversionToNil() const {
  auto anchor = getAnchor();

  if (!isExpr<NilLiteralExpr>(anchor))
    return false;

  auto *locator = getLocator();

  Optional<ContextualTypePurpose> CTP;
  // Easy case were failure has been identified as contextual already.
  if (locator->isLastElement<LocatorPathElt::ContextualType>()) {
    CTP = getContextualTypePurpose();
  } else {
    // Here we need to figure out where where `nil` is located.
    // It could be e.g. an argument to a subscript/call, assignment
    // source like `s[0] = nil` or an array element like `[nil]` or
    // `[nil: 42]` as a sub-expression to a larger one.
    auto *parentExpr = findParentExpr(getAsExpr(anchor));

    // Looks like it's something similar to `let _ = nil`.
    if (!parentExpr) {
      emitDiagnostic(diag::unresolved_nil_literal);
      return true;
    }

    // Two choices here - whether it's a regular assignment
    // e.g. `let _: S = nil` or a subscript one e.g. `s[0] = nil`.
    if (auto *AE = dyn_cast<AssignExpr>(parentExpr)) {
      CTP = isa<SubscriptExpr>(AE->getDest()) ? CTP_SubscriptAssignSource
                                              : CTP_AssignSource;
    } else if (isa<ArrayExpr>(parentExpr)) {
      CTP = CTP_ArrayElement;
    } else if (isa<ClosureExpr>(parentExpr)) {
      CTP = CTP_ClosureResult;
    } else if (isa<ParenExpr>(parentExpr) || isa<TupleExpr>(parentExpr)) {
      auto *enclosingExpr = findParentExpr(parentExpr);

      if (!enclosingExpr) {
        // If there is no enclosing expression it's something like
        // `(nil)` or `(a: nil)` which can't be inferred without a
        // contextual type.
        emitDiagnostic(diag::unresolved_nil_literal);
        return true;
      }

      if (auto *TE = dyn_cast<TupleExpr>(parentExpr)) {
        // In case of dictionary e.g. `[42: nil]` we need to figure
        // out whether nil is a "key" or a "value".
        if (isa<DictionaryExpr>(enclosingExpr)) {
          assert(TE->getNumElements() == 2);
          CTP = TE->getElement(0) == castToExpr(anchor) ? CTP_DictionaryKey
                                                        : CTP_DictionaryValue;
        } else {
          // Can't initialize one of the tuple elements with `nil`.
          CTP = CTP_Initialization;
        }
      }

      // `nil` is passed as an argument to a parameter which doesn't
      // expect it e.g. `foo(a: nil)`, `s[x: nil]` or `\S.[x: nil]`.
      // FIXME: Find a more robust way of checking this.
      if (isa<ApplyExpr>(enclosingExpr) || isa<SubscriptExpr>(enclosingExpr) ||
          isa<KeyPathExpr>(enclosingExpr))
        CTP = CTP_CallArgument;
    } else if (isa<CoerceExpr>(parentExpr)) {
      // `nil` is passed as a left-hand side of the coercion
      // operator e.g. `nil as Foo`
      CTP = CTP_CoerceOperand;
    } else {
      // Otherwise let's produce a generic `nil` conversion diagnostic.
      emitDiagnostic(diag::cannot_use_nil_with_this_type, getToType());
      return true;
    }
  }

  if (!CTP)
    return false;

  if (CTP == CTP_ThrowStmt) {
    emitDiagnostic(diag::cannot_throw_nil);
    return true;
  }

  auto diagnostic = getContextualNilDiagnostic(*CTP);
  if (!diagnostic)
    return false;

  emitDiagnostic(*diagnostic, getToType());

  if (CTP == CTP_Initialization) {
    auto *patternTR = getContextualTypeLoc(getRawAnchor()).getTypeRepr();
    if (!patternTR)
      return true;

    auto diag = emitDiagnosticAt(patternTR->getLoc(), diag::note_make_optional,
                                 OptionalType::get(getToType()));
    if (patternTR->isSimple()) {
      diag.fixItInsertAfter(patternTR->getEndLoc(), "?");
    } else {
      diag.fixItInsert(patternTR->getStartLoc(), "(");
      diag.fixItInsertAfter(patternTR->getEndLoc(), ")?");
    }
  }

  return true;
}

void ContextualFailure::tryFixIts(InFlightDiagnostic &diagnostic) const {
  auto *locator = getLocator();
  // Can't apply any of the fix-its below if this failure
  // is related to `inout` argument.
  if (locator->isLastElement<LocatorPathElt::LValueConversion>())
    return;

  if (trySequenceSubsequenceFixIts(diagnostic))
    return;

  if (tryIntegerCastFixIts(diagnostic))
    return;

  if (tryProtocolConformanceFixIt(diagnostic))
    return;

  if (tryTypeCoercionFixIt(diagnostic))
    return;
}

bool ContextualFailure::diagnoseMissingFunctionCall() const {
  if (getLocator()
      ->isLastElement<LocatorPathElt::UnresolvedMemberChainResult>())
    return false;

  auto *srcFT = getFromType()->getAs<FunctionType>();
  if (!srcFT ||
      !(srcFT->getParams().empty() ||
        getLocator()->isLastElement<LocatorPathElt::PatternMatch>()))
    return false;

  auto toType = getToType();
  if (toType->is<AnyFunctionType>() ||
      !TypeChecker::isConvertibleTo(srcFT->getResult(), toType, getDC()))
    return false;

  // Diagnose cases where the pattern tried to match associated values but
  // the case we found had none.
  if (auto match =
          getLocator()->getLastElementAs<LocatorPathElt::PatternMatch>()) {
    if (auto enumElementPattern =
            dyn_cast<EnumElementPattern>(match->getPattern())) {
      emitDiagnosticAt(enumElementPattern->getNameLoc(),
                       diag::enum_element_pattern_assoc_values_mismatch,
                       enumElementPattern->getName());
      emitDiagnosticAt(enumElementPattern->getNameLoc(),
                       diag::enum_element_pattern_assoc_values_remove)
          .fixItRemove(enumElementPattern->getSubPattern()->getSourceRange());
      return true;
    }
  }

  emitDiagnostic(diag::missing_nullary_call, srcFT->getResult())
      .highlight(getSourceRange())
      .fixItInsertAfter(getSourceRange().End, "()");

  tryComputedPropertyFixIts();
  return true;
}

bool ContextualFailure::diagnoseCoercionToUnrelatedType() const {
  auto anchor = getAnchor();

  if (auto *coerceExpr = getAsExpr<CoerceExpr>(anchor)) {
    const auto fromType = getType(coerceExpr->getSubExpr());
    const auto toType = getType(coerceExpr->getCastTypeRepr());

    auto diagnostic = getDiagnosticFor(CTP_CoerceOperand, toType);

    auto diag = emitDiagnostic(*diagnostic, fromType, toType);
    diag.highlight(getSourceRange());

    (void)tryFixIts(diag);
    
    return true;
  }

  return false;
}

bool ContextualFailure::diagnoseConversionToBool() const {
  auto toType = getToType();
  if (!toType->isBool())
    return false;

  auto *anchor = castToExpr(getAnchor());
  // Check for "=" converting to Bool.  The user probably meant ==.
  if (auto *AE = dyn_cast<AssignExpr>(anchor->getValueProvidingExpr())) {
    emitDiagnosticAt(AE->getEqualLoc(), diag::use_of_equal_instead_of_equality)
        .fixItReplace(AE->getEqualLoc(), "==")
        .highlight(AE->getDest()->getLoc())
        .highlight(AE->getSrc()->getLoc());
    return true;
  }

  // Determine if the boolean negation operator was applied to the anchor. This
  // upwards traversal of the AST is somewhat fragile, but enables much better
  // diagnostics if someone attempts to use an optional or integer as a boolean
  // condition.
  SourceLoc notOperatorLoc;
  if (Expr *parent = findParentExpr(anchor)) {
    if (isa<ParenExpr>(parent) && parent->isImplicit()) {
      if ((parent = findParentExpr(parent))) {
        auto parentOperatorApplication = dyn_cast<PrefixUnaryExpr>(parent);
        if (parentOperatorApplication) {
          auto operatorRefExpr =
              dyn_cast<DeclRefExpr>(parentOperatorApplication->getFn());
          if (operatorRefExpr && operatorRefExpr->getDecl()->getBaseName() ==
                                     getASTContext().Id_NegationOperator) {
            notOperatorLoc = operatorRefExpr->getLoc();
          }
        }
      }
    }
  }

  // If we're trying to convert something from optional type to Bool, then a
  // comparison against nil was probably expected.
  auto fromType = getFromType();
  if (fromType->getOptionalObjectType()) {
    StringRef prefix = "((";
    StringRef suffix;
    if (notOperatorLoc.isValid())
      suffix = ") == nil)";
    else
      suffix = ") != nil)";

    // Check if we need the inner parentheses.
    // Technically we only need them if there's something in 'expr' with
    // lower precedence than '!=', but the code actually comes out nicer
    // in most cases with parens on anything non-trivial.
    if (anchor->canAppendPostfixExpression()) {
      prefix = prefix.drop_back();
      suffix = suffix.drop_front();
    }
    // FIXME: The outer parentheses may be superfluous too.

    emitDiagnostic(diag::optional_used_as_boolean, fromType,
                   notOperatorLoc.isValid())
        .fixItInsert(getSourceRange().Start, prefix)
        .fixItInsertAfter(getSourceRange().End, suffix)
        .fixItRemove(notOperatorLoc);
    return true;
  }

  // If we're trying to convert something from optional type to an integer, then
  // a comparison against nil was probably expected.
  if (conformsToKnownProtocol(fromType, KnownProtocolKind::BinaryInteger) &&
      conformsToKnownProtocol(fromType,
                              KnownProtocolKind::ExpressibleByIntegerLiteral)) {
    StringRef prefix = "((";
    StringRef suffix;
    if (notOperatorLoc.isValid())
      suffix = ") == 0)";
    else
      suffix = ") != 0)";

    // Check if we need the inner parentheses.
    // Technically we only need them if there's something in 'expr' with
    // lower precedence than '!=', but the code actually comes out nicer
    // in most cases with parens on anything non-trivial.
    if (anchor->canAppendPostfixExpression()) {
      prefix = prefix.drop_back();
      suffix = suffix.drop_front();
    }
    // FIXME: The outer parentheses may be superfluous too.

    emitDiagnostic(diag::integer_used_as_boolean, fromType,
                   notOperatorLoc.isValid())
        .fixItInsert(getSourceRange().Start, prefix)
        .fixItInsertAfter(getSourceRange().End, suffix)
        .fixItRemove(notOperatorLoc);
    return true;
  }

  return false;
}

bool ContextualFailure::diagnoseThrowsTypeMismatch() const {
  // If this is conversion failure due to a return statement with an argument
  // that cannot be coerced to the result type of the function, emit a
  // specific error.
  if (CTP != CTP_ThrowStmt)
    return false;

  auto anchor = getAnchor();

  // If we tried to throw the error code of an error type, suggest object
  // construction.
  auto &Ctx = getASTContext();
  if (auto errorCodeProtocol =
          Ctx.getProtocol(KnownProtocolKind::ErrorCodeProtocol)) {
    Type errorCodeType = getFromType();
    auto conformance = TypeChecker::conformsToProtocol(
        errorCodeType, errorCodeProtocol, getDC());
    if (conformance) {
      Type errorType =
          conformance
              .getTypeWitnessByName(errorCodeType, getASTContext().Id_ErrorType)
              ->getCanonicalType();
      if (errorType) {
        auto diagnostic = emitDiagnostic(diag::cannot_throw_error_code,
                                         errorCodeType, errorType);
        if (auto *UDE = getAsExpr<UnresolvedDotExpr>(anchor)) {
          diagnostic.fixItInsert(UDE->getDotLoc(), "(");
          diagnostic.fixItInsertAfter(UDE->getEndLoc(), ")");
        }
        return true;
      }
    }
  }

  // The conversion destination of throw is always ErrorType (at the moment)
  // if this ever expands, this should be a specific form like () is for
  // return.
  emitDiagnostic(diag::cannot_convert_thrown_type, getFromType())
      .highlight(getSourceRange());
  return true;
}

bool ContextualFailure::diagnoseYieldByReferenceMismatch() const {
  if (CTP != CTP_YieldByReference)
    return false;

  auto anchor = getAnchor();
  auto exprType = getType(anchor, /*wantRValue=*/false);
  auto contextualType = getToType();

  if (auto exprLV = exprType->getAs<LValueType>()) {
    emitDiagnostic(diag::cannot_yield_wrong_type_by_reference,
                   exprLV->getObjectType(), contextualType);
  } else if (exprType->isEqual(contextualType)) {
    emitDiagnostic(diag::cannot_yield_rvalue_by_reference_same_type, exprType);
  } else {
    emitDiagnostic(diag::cannot_yield_rvalue_by_reference, exprType,
                   contextualType);
  }
  return true;
}

bool ContextualFailure::tryIntegerCastFixIts(
    InFlightDiagnostic &diagnostic) const {
  auto fromType = getFromType();
  auto toType = getToType();

  auto anchor = getAnchor();
  auto exprRange = getSourceRange();

  if (auto *assignment = getAsExpr<AssignExpr>(anchor)) {
    toType = toType->lookThroughAllOptionalTypes();
    anchor = assignment->getSrc();
    exprRange = assignment->getSrc()->getSourceRange();
  }

  if (!isIntegerType(fromType) || !isIntegerType(toType))
    return false;

  auto getInnerCastedExpr = [&](const Expr *expr) -> Expr * {
    if (auto *CE = dyn_cast<CoerceExpr>(expr))
      return CE->getSubExpr();

    auto *CE = dyn_cast<CallExpr>(expr);
    if (!CE)
      return nullptr;
    if (!isa<ConstructorRefCallExpr>(CE->getFn()))
      return nullptr;
    auto *parenE = dyn_cast<ParenExpr>(CE->getArg());
    if (!parenE)
      return nullptr;
    return parenE->getSubExpr();
  };

  if (auto *expr = getAsExpr(anchor)) {
    if (Expr *innerE = getInnerCastedExpr(expr)) {
      Type innerTy = getType(innerE);
      if (TypeChecker::isConvertibleTo(innerTy, toType, getDC())) {
        // Remove the unnecessary cast.
        diagnostic.fixItRemoveChars(getLoc(), innerE->getStartLoc())
            .fixItRemove(getSourceRange().End);
        return true;
      }
    }
  }

  // Add a wrapping integer cast.
  std::string convWrapBefore = toType.getString();
  convWrapBefore += "(";
  std::string convWrapAfter = ")";
  diagnostic.fixItInsert(exprRange.Start, convWrapBefore);
  diagnostic.fixItInsertAfter(exprRange.End, convWrapAfter);
  return true;
}

bool ContextualFailure::trySequenceSubsequenceFixIts(
    InFlightDiagnostic &diagnostic) const {
  if (!getASTContext().getStdlibModule())
    return false;

  auto String = getASTContext().getStringDecl()->getDeclaredInterfaceType();
  auto Substring = getASTContext().getSubstringDecl()->getDeclaredInterfaceType();

  // Substring -> String conversion
  // Wrap in String.init
  if (getFromType()->isEqual(Substring)) {
    if (getToType()->isEqual(String)) {
      auto *anchor = castToExpr(getAnchor())->getSemanticsProvidingExpr();
      if (auto *CE = dyn_cast<CoerceExpr>(anchor)) {
        anchor = CE->getSubExpr();
      }

      if (auto *call = dyn_cast<CallExpr>(anchor)) {
        auto *fnExpr = call->getFn();
        if (auto *closure = dyn_cast<ClosureExpr>(fnExpr)) {
          if (closure->hasSingleExpressionBody())
            anchor = closure->getSingleExpressionBody();
        }
      }

      auto range = anchor->getSourceRange();
      diagnostic.fixItInsert(range.Start, "String(");
      diagnostic.fixItInsertAfter(range.End, ")");
      return true;
    }
  }

  return false;
}

bool ContextualFailure::tryTypeCoercionFixIt(
    InFlightDiagnostic &diagnostic) const {
  auto fromType = getFromType();
  auto toType = getToType();

  // Look through optional types; casts can add them, but can't remove extra
  // ones.
  bool bothOptional =
      fromType->getOptionalObjectType() && toType->getOptionalObjectType();
  if (bothOptional)
    fromType = fromType->getOptionalObjectType();
  toType = toType->lookThroughAllOptionalTypes();

  if (!toType->hasTypeRepr())
    return false;

  CheckedCastKind Kind =
      TypeChecker::typeCheckCheckedCast(fromType, toType,
                                        CheckedCastContextKind::None, getDC(),
                                        SourceLoc(), nullptr, SourceRange());

  if (Kind != CheckedCastKind::Unresolved) {
    bool canUseAs = Kind == CheckedCastKind::Coercion ||
                    Kind == CheckedCastKind::BridgingCoercion;
    if (bothOptional && canUseAs)
      toType = OptionalType::get(toType);
    diagnostic.fixItInsert(Lexer::getLocForEndOfToken(getASTContext().SourceMgr,
                                                      getSourceRange().End),
                           diag::insert_type_coercion, canUseAs, toType);
    return true;
  }

  return false;
}

bool ContextualFailure::tryProtocolConformanceFixIt(
    InFlightDiagnostic &diagnostic) const {
  auto innermostTyCtx = getDC()->getInnermostTypeContext();
  if (!innermostTyCtx)
    return false;

  auto nominal = innermostTyCtx->getSelfNominalTypeDecl();
  if (!nominal)
    return false;

  auto fromType = getFromType();
  // We need to get rid of optionals and parens as it's not relevant when
  // printing the diagnostic and the fix-it.
  auto unwrappedToType =
      getToType()->lookThroughAllOptionalTypes()->getWithoutParens();

  // If the protocol requires a class & we don't have one (maybe the context
  // is a struct), then bail out instead of offering a broken fix-it later on.
  auto requiresClass = false;
  ExistentialLayout layout;
  if (unwrappedToType->isExistentialType()) {
    layout = unwrappedToType->getExistentialLayout();
    requiresClass = layout.requiresClass();
  }

  if (requiresClass && !fromType->is<ClassType>()) {
    return false;
  }

  // We can only offer a fix-it if we're assigning to a protocol type and
  // the type we're assigning is the same as the innermost type context.
  bool shouldOfferFixIt = nominal->getSelfTypeInContext()->isEqual(fromType) &&
                          unwrappedToType->isExistentialType();
  if (!shouldOfferFixIt)
    return false;

  diagnostic.flush();

  // Let's build a list of protocols that the context does not conform to.
  SmallVector<std::string, 8> missingProtoTypeStrings;
  SmallVector<ProtocolDecl *, 8> missingProtocols;
  for (auto protocol : layout.getProtocols()) {
    if (!TypeChecker::conformsToProtocol(fromType, protocol->getDecl(), getDC())) {
      missingProtoTypeStrings.push_back(protocol->getString());
      missingProtocols.push_back(protocol->getDecl());
    }
  }

  // If we have a protocol composition type and we don't conform to all
  // the protocols of the composition, then store the composition directly.
  // This is because we need to append 'Foo & Bar' instead of 'Foo, Bar' in
  // order to match the written type.
  if (auto compositionTy = unwrappedToType->getAs<ProtocolCompositionType>()) {
    if (compositionTy->getMembers().size() == missingProtoTypeStrings.size()) {
      missingProtoTypeStrings = {compositionTy->getString()};
    }
  }

  assert(!missingProtoTypeStrings.empty() &&
         "type already conforms to all the protocols?");

  // Combine all protocol names together, separated by commas.
  std::string protoString = llvm::join(missingProtoTypeStrings, ", ");

  // Emit a diagnostic to inform the user that they need to conform to the
  // missing protocols.
  auto conformanceDiag =
      emitDiagnostic(diag::assign_protocol_conformance_fix_it, unwrappedToType,
                     nominal->getDescriptiveKind(), fromType);
  if (nominal->getInherited().size() > 0) {
    auto lastInherited = nominal->getInherited().back().getLoc();
    auto lastInheritedEndLoc =
        Lexer::getLocForEndOfToken(getASTContext().SourceMgr, lastInherited);
    conformanceDiag.fixItInsert(lastInheritedEndLoc, ", " + protoString);
  } else {
    auto nameEndLoc = Lexer::getLocForEndOfToken(getASTContext().SourceMgr,
                                                 nominal->getNameLoc());
    conformanceDiag.fixItInsert(nameEndLoc, ": " + protoString);
  }

  // Emit fix-its to insert requirement stubs if we're in editor mode.
  if (!getASTContext().LangOpts.DiagnosticsEditorMode) {
    return true;
  }

  {
    llvm::SmallString<128> Text;
    llvm::raw_svector_ostream SS(Text);
    llvm::SetVector<MissingWitness> missingWitnesses;
    for (auto protocol : missingProtocols) {
      auto conformance = NormalProtocolConformance(
          nominal->getDeclaredType(), protocol, SourceLoc(), nominal,
          ProtocolConformanceState::Incomplete);
      ConformanceChecker checker(getASTContext(), &conformance,
                                 missingWitnesses);
      checker.resolveValueWitnesses();
      checker.resolveTypeWitnesses();
    }

    for (auto decl : missingWitnesses) {
      swift::printRequirementStub(decl.requirement, nominal, nominal->getDeclaredType(),
                                  nominal->getStartLoc(), SS);
    }

    if (!Text.empty()) {
      conformanceDiag.fixItInsertAfter(nominal->getBraces().Start, Text.str());
    }
  }

  return true;
}

void ContextualFailure::tryComputedPropertyFixIts() const {
  if (!isExpr<ClosureExpr>(getAnchor()))
    return;

  // It is possible that we're looking at a stored property being
  // initialized with a closure. Something like:
  //
  // var foo: Int = { return 0 }
  //
  // Let's offer another fix-it to remove the '=' to turn the stored
  // property into a computed property. If the variable is immutable, then
  // replace the 'let' with a 'var'.

  PatternBindingDecl *PBD = nullptr;

  if (auto TLCD = dyn_cast<TopLevelCodeDecl>(getDC())) {
    if (TLCD->getBody()->isImplicit()) {
      if (auto decl = TLCD->getBody()->getFirstElement().dyn_cast<Decl *>()) {
        if (auto binding = dyn_cast<PatternBindingDecl>(decl)) {
          PBD = binding;
        }
      }
    }
  } else if (auto PBI = dyn_cast<PatternBindingInitializer>(getDC())) {
    PBD = PBI->getBinding();
  }

  if (PBD) {
    if (auto VD = PBD->getSingleVar()) {
      const auto i = PBD->getPatternEntryIndexForVarDecl(VD);
      auto *initExpr = PBD->getInit(i);
      if (!VD->isStatic() &&
          !VD->getAttrs().getAttribute<DynamicReplacementAttr>() &&
          initExpr && isa<ClosureExpr>(initExpr)) {
        auto diag = emitDiagnostic(diag::extension_stored_property_fixit,
                                   VD->getName());
        diag.fixItRemove(PBD->getEqualLoc(i));

        if (VD->isLet()) {
          diag.fixItReplace(PBD->getStartLoc(), getTokenText(tok::kw_var));
        }

        if (auto lazyAttr = VD->getAttrs().getAttribute<LazyAttr>()) {
          diag.fixItRemove(lazyAttr->getRange());
        }
      }
    }
  }
}

bool ContextualFailure::isIntegerToStringIndexConversion() const {
  auto kind = KnownProtocolKind::ExpressibleByIntegerLiteral;

  auto fromType = getFromType();
  auto toType = getToType()->getCanonicalType();
  return (conformsToKnownProtocol(fromType, kind) &&
          toType.getString() == "String.CharacterView.Index");
}

Optional<Diag<Type, Type>>
ContextualFailure::getDiagnosticFor(ContextualTypePurpose context,
                                    Type contextualType) {
  auto forProtocol = contextualType->isExistentialType();
  switch (context) {
  case CTP_Initialization: {
    if (contextualType->isAnyObject())
      return diag::cannot_convert_initializer_value_anyobject;

    return forProtocol ? diag::cannot_convert_initializer_value_protocol
                       : diag::cannot_convert_initializer_value;
  }
  case CTP_ReturnStmt:
  case CTP_ReturnSingleExpr: {
    if (contextualType->isAnyObject())
      return diag::cannot_convert_return_type_to_anyobject;

    return forProtocol ? diag::cannot_convert_to_return_type_protocol
                       : diag::cannot_convert_to_return_type;
  }
  case CTP_EnumCaseRawValue:
    return diag::cannot_convert_raw_initializer_value;
  case CTP_DefaultParameter:
  case CTP_AutoclosureDefaultParameter:
    return forProtocol ? diag::cannot_convert_default_arg_value_protocol
                       : diag::cannot_convert_default_arg_value;
  case CTP_YieldByValue:
    return forProtocol ? diag::cannot_convert_yield_value_protocol
                       : diag::cannot_convert_yield_value;
  case CTP_CallArgument: {
    if (contextualType->isAnyObject())
      return diag::cannot_convert_argument_value_anyobject;

    return forProtocol ? diag::cannot_convert_argument_value_protocol
                       : diag::cannot_convert_argument_value;
  }
  case CTP_ClosureResult:
    return forProtocol ? diag::cannot_convert_closure_result_protocol
                       : diag::cannot_convert_closure_result;
  case CTP_ArrayElement:
    return forProtocol ? diag::cannot_convert_array_element_protocol
                       : diag::cannot_convert_array_element;
  case CTP_DictionaryKey:
    return forProtocol ? diag::cannot_convert_dict_key_protocol
                       : diag::cannot_convert_dict_key;
  case CTP_DictionaryValue:
    return forProtocol ? diag::cannot_convert_dict_value_protocol
                       : diag::cannot_convert_dict_value;
  case CTP_CoerceOperand:
    return forProtocol ? diag::cannot_convert_coerce_protocol
                       : diag::cannot_convert_coerce;
  case CTP_AssignSource: {
    if (contextualType->isAnyObject())
      return diag::cannot_convert_assign_anyobject;

    return forProtocol ? diag::cannot_convert_assign_protocol
                       : diag::cannot_convert_assign;
  }
  case CTP_SubscriptAssignSource:
    return forProtocol ? diag::cannot_convert_subscript_assign_protocol
                       : diag::cannot_convert_subscript_assign;
  case CTP_Condition:
    return diag::cannot_convert_condition_value;

  case CTP_WrappedProperty:
    return diag::wrapped_value_mismatch;
  case CTP_ComposedPropertyWrapper:
    return diag::composed_property_wrapper_mismatch;

  case CTP_ThrowStmt:
  case CTP_ForEachStmt:
  case CTP_Unused:
  case CTP_CannotFail:
  case CTP_YieldByReference:
  case CTP_CalleeResult:
    break;
  }
  return None;
}

bool TupleContextualFailure::diagnoseAsError() {
  Diag<Type, Type> diagnostic;
  auto purpose = getContextualTypePurpose();
  if (isNumElementsMismatch())
    diagnostic = diag::tuple_types_not_convertible_nelts;
  else if ((purpose == CTP_Initialization) && !getContextualType(getAnchor()))
    diagnostic = diag::tuple_types_not_convertible;
  else if (auto diag = getDiagnosticFor(purpose, getToType()))
    diagnostic = *diag;
  else
    return false;

  emitDiagnostic(diagnostic, getFromType(), getToType());
  return true;
}

bool FunctionTypeMismatch::diagnoseAsError() {
  auto purpose = getContextualTypePurpose();
  auto diagnostic = getDiagnosticFor(purpose, getToType());
  if (!diagnostic)
    return false;

  emitDiagnostic(*diagnostic, getFromType(), getToType());
  return true;
}

bool AutoClosureForwardingFailure::diagnoseAsError() {
  auto argRange = getSourceRange();
  emitDiagnostic(diag::invalid_autoclosure_forwarding)
      .highlight(argRange)
      .fixItInsertAfter(argRange.End, "()");
  return true;
}

bool AutoClosurePointerConversionFailure::diagnoseAsError() {
  auto diagnostic = diag::invalid_autoclosure_pointer_conversion;
  emitDiagnostic(diagnostic, getFromType(), getToType())
      .highlight(getSourceRange());
  return true;
}

bool NonOptionalUnwrapFailure::diagnoseAsError() {
  auto anchor = getAnchor();

  auto diagnostic = diag::invalid_optional_chain;
  if (isExpr<ForceValueExpr>(anchor))
    diagnostic = diag::invalid_force_unwrap;

  auto range = getSourceRange();
  emitDiagnostic(diagnostic, BaseType).highlight(range).fixItRemove(range.End);
  return true;
}

ASTNode MissingCallFailure::getAnchor() const {
  auto anchor = FailureDiagnostic::getAnchor();

  if (auto *FVE = getAsExpr<ForceValueExpr>(anchor))
    return FVE->getSubExpr();

  return anchor;
}

bool MissingCallFailure::diagnoseAsError() {
  auto anchor = getAnchor();
  SourceLoc insertLoc = getSourceRange().End;

  // Calls are not yet supported by key path, but it
  // is useful to record this fix to diagnose chaining
  // where one of the key path components is a method
  // reference.
  if (isExpr<KeyPathExpr>(anchor))
    return false;

  auto path = getLocator()->getPath();
  if (!path.empty()) {
    const auto &last = path.back();

    switch (last.getKind()) {
    case ConstraintLocator::ContextualType:
    case ConstraintLocator::ApplyArgToParam: {
      auto fnType = getType(anchor)->castTo<FunctionType>();
      emitDiagnostic(diag::missing_nullary_call, fnType->getResult())
          .fixItInsertAfter(insertLoc, "()");
      return true;
    }

    case ConstraintLocator::FunctionResult: {
      path = path.drop_back();
      if (path.back().getKind() != ConstraintLocator::AutoclosureResult)
        break;

      LLVM_FALLTHROUGH;
    }

    case ConstraintLocator::AutoclosureResult: {
      auto loc = getConstraintLocator(getRawAnchor(), path.drop_back());
      AutoClosureForwardingFailure failure(getSolution(), loc);
      return failure.diagnoseAsError();
    }
    default:
      break;
    }
  }

  if (auto *DRE = getAsExpr<DeclRefExpr>(anchor)) {
    emitDiagnostic(diag::did_not_call_function,
                   DRE->getDecl()->getBaseIdentifier())
        .fixItInsertAfter(insertLoc, "()");
    return true;
  }

  if (auto *UDE = getAsExpr<UnresolvedDotExpr>(anchor)) {
    emitDiagnostic(diag::did_not_call_method,
                   UDE->getName().getBaseIdentifier())
        .fixItInsertAfter(insertLoc, "()");
    return true;
  }

  if (auto *DSCE = getAsExpr<DotSyntaxCallExpr>(anchor)) {
    if (auto *DRE = dyn_cast<DeclRefExpr>(DSCE->getFn())) {
      emitDiagnostic(diag::did_not_call_method,
                     DRE->getDecl()->getBaseIdentifier())
          .fixItInsertAfter(insertLoc, "()");
      return true;
    }
  }

  if (auto *AE = getAsExpr<AssignExpr>(anchor)) {
    auto *srcExpr = AE->getSrc();
    if (auto *fnType = getType(srcExpr)->getAs<FunctionType>()) {
      emitDiagnosticAt(srcExpr->getLoc(), diag::missing_nullary_call,
                       fnType->getResult())
          .highlight(srcExpr->getSourceRange())
          .fixItInsertAfter(srcExpr->getEndLoc(), "()");
      return true;
    }
  }

  emitDiagnostic(diag::did_not_call_function_value)
      .fixItInsertAfter(insertLoc, "()");
  return true;
}

bool ExtraneousPropertyWrapperUnwrapFailure::diagnoseAsError() {
  auto newPrefix = usingProjection() ? "$" : "_";

  if (auto *member = getReferencedMember()) {
    emitDiagnostic(diag::incorrect_property_wrapper_reference_member,
                   member->getDescriptiveKind(), member->getName(), false,
                   getToType())
        .fixItInsert(getLoc(), newPrefix);
    return true;
  }

  emitDiagnostic(diag::incorrect_property_wrapper_reference, getPropertyName(),
                 getFromType(), getToType(), false)
      .fixItInsert(getLoc(), newPrefix);
  return true;
}

bool MissingPropertyWrapperUnwrapFailure::diagnoseAsError() {
  auto endLoc = getLoc().getAdvancedLoc(1);

  if (auto *member = getReferencedMember()) {
    emitDiagnostic(diag::incorrect_property_wrapper_reference_member,
                   member->getDescriptiveKind(), member->getName(), true,
                   getToType())
        .fixItRemoveChars(getLoc(), endLoc);
    return true;
  }

  emitDiagnostic(diag::incorrect_property_wrapper_reference, getPropertyName(),
                 getFromType(), getToType(), true)
      .fixItRemoveChars(getLoc(), endLoc);
  return true;
}

bool SubscriptMisuseFailure::diagnoseAsError() {
  auto *locator = getLocator();
  auto &sourceMgr = getASTContext().SourceMgr;

  auto *memberExpr = castToExpr<UnresolvedDotExpr>(getRawAnchor());

  auto memberRange = getSourceRange();

  {
    auto rawAnchor = getRawAnchor();
    auto path = locator->getPath();
    simplifyLocator(rawAnchor, path, memberRange);
  }

  auto nameLoc = DeclNameLoc(memberRange.Start);

  auto diag = emitDiagnostic(diag::could_not_find_subscript_member_did_you_mean,
                             getType(getAnchor()));

  diag.highlight(memberRange).highlight(nameLoc.getSourceRange());

  if (auto *parentExpr = dyn_cast_or_null<ApplyExpr>(findParentExpr(memberExpr))) {
    auto *argExpr = parentExpr->getArg();

    auto toCharSourceRange = Lexer::getCharSourceRangeFromSourceRange;
    auto lastArgSymbol = toCharSourceRange(sourceMgr, argExpr->getEndLoc());

    diag.fixItReplace(SourceRange(argExpr->getStartLoc()),
                      getTokenText(tok::l_square));
    diag.fixItRemove(nameLoc.getSourceRange());
    diag.fixItRemove(SourceRange(memberExpr->getDotLoc()));

    if (sourceMgr.extractText(lastArgSymbol) == getTokenText(tok::r_paren))
      diag.fixItReplace(SourceRange(argExpr->getEndLoc()),
                        getTokenText(tok::r_square));
    else
      diag.fixItInsertAfter(argExpr->getEndLoc(), getTokenText(tok::r_square));
  } else {
    diag.fixItReplace(SourceRange(memberExpr->getDotLoc(), memberExpr->getLoc()), "[<#index#>]");
  }
  diag.flush();

  if (auto overload = getOverloadChoiceIfAvailable(locator)) {
    emitDiagnosticAt(overload->choice.getDecl(), diag::kind_declared_here,
                     DescriptiveDeclKind::Subscript);
  }

  return true;
}

bool SubscriptMisuseFailure::diagnoseAsNote() {
  if (auto overload = getOverloadChoiceIfAvailable(getLocator())) {
    emitDiagnosticAt(overload->choice.getDecl(), diag::found_candidate);
    return true;
  }
  return false;
}

/// When a user refers a enum case with a wrong member name, we try to find a
/// enum element whose name differs from the wrong name only in convention;
/// meaning their lower case counterparts are identical.
///   - DeclName is valid when such a correct case is found; invalid otherwise.
DeclName MissingMemberFailure::findCorrectEnumCaseName(
    Type Ty, TypoCorrectionResults &corrections, DeclNameRef memberName) {
  if (memberName.isSpecial() || !memberName.isSimpleName())
    return DeclName();
  if (!Ty->getEnumOrBoundGenericEnum())
    return DeclName();
  auto candidate =
      corrections.getUniqueCandidateMatching([&](ValueDecl *candidate) {
        return (isa<EnumElementDecl>(candidate) &&
                candidate->getBaseIdentifier().str().equals_lower(
                    memberName.getBaseIdentifier().str()));
      });
  return (candidate ? candidate->getName() : DeclName());
}

bool MissingMemberFailure::diagnoseAsError() {
  auto anchor = getRawAnchor();
  auto memberBase = getAnchor();

  if (diagnoseForDynamicCallable())
    return true;
  
  if (diagnoseInLiteralCollectionContext())
    return true;

  if (diagnoseForSubscriptMemberWithTupleBase())
    return true;

  auto baseType = resolveType(getBaseType())->getWithoutSpecifierType();

  DeclNameLoc nameLoc(::getLoc(anchor));
  if (auto *UDE = getAsExpr<UnresolvedDotExpr>(anchor)) {
    nameLoc = UDE->getNameLoc();
  } else if (auto *UME = getAsExpr<UnresolvedMemberExpr>(anchor)) {
    nameLoc = UME->getNameLoc();
  }

  auto emitBasicError = [&](Type baseType) {
    auto diagnostic = diag::could_not_find_value_member;

    if (auto *metatype = baseType->getAs<MetatypeType>()) {
      baseType = metatype->getInstanceType();
      diagnostic = diag::could_not_find_type_member;
    }

    if (baseType->is<TupleType>())
      diagnostic = diag::could_not_find_tuple_member;

    bool hasUnresolvedPattern = false;
    if (auto *E = getAsExpr(anchor)) {
      forEachExprInConstraintSystem(const_cast<Expr *>(E), [&](Expr *expr) {
        hasUnresolvedPattern |= isa<UnresolvedPatternExpr>(expr);
        return hasUnresolvedPattern ? nullptr : expr;
      });
    }

    if (hasUnresolvedPattern && !baseType->getAs<EnumType>()) {
      emitDiagnostic(diag::cannot_match_unresolved_expr_pattern_with_value,
                     baseType);
      return;
    }

    emitDiagnostic(diagnostic, baseType, getName())
        .highlight(getSourceRange())
        .highlight(nameLoc.getSourceRange());
  };

  TypoCorrectionResults corrections(getName(), nameLoc);
  auto tryTypoCorrection = [&] (Type type) {
    TypeChecker::performTypoCorrection(getDC(), DeclRefKind::Ordinary, type,
                                       defaultMemberLookupOptions, corrections);
  };

  if (getName().getBaseName().getKind() == DeclBaseName::Kind::Subscript) {
    if (auto *metatype = baseType->getAs<MetatypeType>()) {
      emitDiagnostic(diag::could_not_find_type_member,
                     metatype->getInstanceType(), getName())
          .highlight(getSourceRange());
    } else {
      emitDiagnostic(diag::could_not_find_value_subscript, baseType)
          .highlight(getSourceRange());
    }
  } else if (getName().getBaseName() == "deinit") {
    // Specialised diagnostic if trying to access deinitialisers
    emitDiagnostic(diag::destructor_not_accessible).highlight(getSourceRange());
  } else if (auto metatypeTy = baseType->getAs<MetatypeType>()) {
    auto instanceTy = metatypeTy->getInstanceType();
    tryTypoCorrection(baseType);

    if (DeclName rightName =
            findCorrectEnumCaseName(instanceTy, corrections, getName())) {
      emitDiagnostic(diag::could_not_find_enum_case, instanceTy, getName(),
                     rightName)
          .fixItReplace(nameLoc.getBaseNameLoc(),
                        rightName.getBaseIdentifier().str());
      return true;
    }

    if (auto correction = corrections.claimUniqueCorrection()) {
      auto diagnostic =
          emitDiagnostic(diag::could_not_find_type_member_corrected, instanceTy,
                         getName(), correction->CorrectedName);
      diagnostic.highlight(getSourceRange())
          .highlight(nameLoc.getSourceRange());
      correction->addFixits(diagnostic);
    } else if (instanceTy->getAnyNominal() &&
               getName().getBaseName() == DeclBaseName::createConstructor()) {
      auto &cs = getConstraintSystem();

      auto result = cs.performMemberLookup(
          ConstraintKind::ValueMember, getName().withoutArgumentLabels(),
          metatypeTy, FunctionRefKind::DoubleApply, getLocator(),
          /*includeInaccessibleMembers=*/true);

      // If there are no `init` members at all produce a tailored
      // diagnostic for that, otherwise fallback to generic
      // "no such member" one.
      if (result.ViableCandidates.empty() &&
          result.UnviableCandidates.empty()) {
        emitDiagnostic(diag::no_accessible_initializers, instanceTy)
            .highlight(getSourceRange());
      } else {
        emitBasicError(baseType);
      }
    } else {
      emitBasicError(baseType);
    }
  } else if (auto moduleTy = baseType->getAs<ModuleType>()) {
    emitDiagnosticAt(::getLoc(memberBase), diag::no_member_of_module,
                     moduleTy->getModule()->getName(), getName())
        .highlight(getSourceRange())
        .highlight(nameLoc.getSourceRange());
    return true;
  } else {
    // Check for a few common cases that can cause missing members.
    auto *ED = baseType->getEnumOrBoundGenericEnum();
    if (ED && getName().isSimpleName("rawValue")) {
      auto loc = ED->getNameLoc();
      if (loc.isValid()) {
        emitBasicError(baseType);
        emitDiagnosticAt(loc, diag::did_you_mean_raw_type);
        return true;
      }
    } else if (baseType->isAny()) {
      emitBasicError(baseType);

      auto range = getSourceRange();
      emitDiagnostic(diag::any_as_anyobject_fixit)
          .fixItInsert(range.Start, "(")
          .fixItInsertAfter(range.End, " as AnyObject)");
      return true;
    }
    
    tryTypoCorrection(baseType);
    
    // If locator points to the member found via key path dynamic member lookup,
    // we provide a custom diagnostic and emit typo corrections for the wrapper type too.
    if (getLocator()->isForKeyPathDynamicMemberLookup()) {
      auto memberBaseType = getType(memberBase)->getWithoutSpecifierType();

      tryTypoCorrection(memberBaseType);

      if (auto correction = corrections.claimUniqueCorrection()) {
        auto diagnostic = emitDiagnostic(
            diag::could_not_find_value_dynamic_member_corrected, memberBaseType,
            baseType, getName(), correction->CorrectedName);
        diagnostic.highlight(getSourceRange())
            .highlight(nameLoc.getSourceRange());
        correction->addFixits(diagnostic);
      } else {
        auto diagnostic =
            emitDiagnostic(diag::could_not_find_value_dynamic_member,
                           memberBaseType, baseType, getName());
        diagnostic.highlight(getSourceRange())
            .highlight(nameLoc.getSourceRange());
      }
    } else {
      if (auto correction = corrections.claimUniqueCorrection()) {
        auto diagnostic =
            emitDiagnostic(diag::could_not_find_value_member_corrected,
                           baseType, getName(), correction->CorrectedName);
        diagnostic.highlight(getSourceRange())
            .highlight(nameLoc.getSourceRange());

        correction->addFixits(diagnostic);
      } else {
        emitBasicError(baseType);
      }
    }
  }

  // Note all the correction candidates.
  corrections.noteAllCandidates();
  return true;
}

bool MissingMemberFailure::diagnoseForDynamicCallable() const {
  auto *locator = getLocator();
  if (!locator->isLastElement<LocatorPathElt::DynamicCallable>())
    return false;

  auto memberName = getName();
  auto arguments = memberName.getArgumentNames();
  assert(arguments.size() == 1);

  auto &ctx = getASTContext();
  if (arguments.front() == ctx.Id_withKeywordArguments) {
    emitDiagnostic(diag::missing_dynamic_callable_kwargs_method, getBaseType());
    return true;
  }

  return false;
}

bool MissingMemberFailure::diagnoseInLiteralCollectionContext() const {
  auto *expr = castToExpr(getAnchor());
  auto *parentExpr = findParentExpr(expr);
  auto &solution = getSolution();

  if (!(parentExpr && isa<UnresolvedMemberExpr>(expr)))
    return false;

  if (!isa<UnresolvedMemberChainResultExpr>(parentExpr))
    return false;

  parentExpr = findParentExpr(parentExpr);
  if (!parentExpr)
    return false;

  auto parentType = getType(parentExpr);

  if (!parentType->isKnownStdlibCollectionType() && !parentType->is<TupleType>())
    return false;

  if (isa<TupleExpr>(parentExpr)) {
    parentExpr = findParentExpr(parentExpr);
    if (!parentExpr)
      return false;
  }

  if (auto *defaultableVar =
          getRawType(parentExpr)->getAs<TypeVariableType>()) {
    if (solution.DefaultedConstraints.count(
            defaultableVar->getImpl().getLocator()) != 0) {
      emitDiagnostic(diag::unresolved_member_no_inference, getName());
      return true;
    }
  }
  return false;
}

bool MissingMemberFailure::diagnoseForSubscriptMemberWithTupleBase() const {
  auto locator = getLocator();
  auto baseType = resolveType(getBaseType())->getWithoutSpecifierType();

  auto *SE = getAsExpr<SubscriptExpr>(locator->getAnchor());
  if (!SE)
    return false;

  auto tupleType = baseType->getAs<TupleType>();
  // For non-tuple type or empty tuples, let's fallback to the general
  // diagnostic logic.
  if (!tupleType || tupleType->getNumElements() == 0)
    return false;

  auto *index = SE->getIndex();
  if (SE->getNumArguments() == 1) {
    auto *literal =
        dyn_cast<IntegerLiteralExpr>(index->getSemanticsProvidingExpr());

    llvm::Regex NumericRegex("^[0-9]+$");
    // Literal expressions may have other types of representations e.g. 0x01,
    // 0b01. So let's make sure to only suggest this tailored literal fix-it for
    // number only literals.
    if (literal && NumericRegex.match(literal->getDigitsText())) {
      unsigned int literalValue = 0;
      literal->getDigitsText().getAsInteger(/*Radix=*/0, literalValue);

      // Verify if the literal value is within the bounds of tuple elements.
      if (!literal->isNegative() &&
          literalValue < tupleType->getNumElements()) {
        llvm::SmallString<4> dotAccess;
        llvm::raw_svector_ostream OS(dotAccess);
        OS << "." << literalValue;

        emitDiagnostic(
            diag::could_not_find_subscript_member_tuple_did_you_mean_use_dot,
            baseType, literal->getDigitsText())
            .fixItReplace(index->getSourceRange(), OS.str());
        return true;
      }
    }

    // For subscript access on tuple base types where the subscript index is a
    // string literal expression which value matches a tuple element label,
    // let's suggest tuple label access.
    auto stringLiteral =
        dyn_cast<StringLiteralExpr>(index->getSemanticsProvidingExpr());
    if (stringLiteral && !stringLiteral->getValue().empty() &&
        llvm::any_of(tupleType->getElements(), [&](TupleTypeElt element) {
          return element.getName().is(stringLiteral->getValue());
        })) {
      llvm::SmallString<16> dotAccess;
      llvm::raw_svector_ostream OS(dotAccess);
      OS << "." << stringLiteral->getValue();

      emitDiagnostic(
          diag::could_not_find_subscript_member_tuple_did_you_mean_use_dot,
          baseType, stringLiteral->getValue())
          .fixItReplace(index->getSourceRange(), OS.str());
      return true;
    }
  }

  emitDiagnostic(diag::could_not_find_subscript_member_tuple, baseType);
  return true;
}

bool UnintendedExtraGenericParamMemberFailure::diagnoseAsError() {
  MissingMemberFailure::diagnoseAsError();

  auto baseType = resolveType(getBaseType())->getWithoutSpecifierType();
  auto archetype = baseType->getMetatypeInstanceType()->castTo<ArchetypeType>();
  auto genericTy =
      archetype->mapTypeOutOfContext()->castTo<GenericTypeParamType>();
  SourceLoc loc = genericTy->getDecl()->getSourceRange().End;
  StringRef replacement;

  if (archetype->getConformsTo().size()) {
    loc = loc.getAdvancedLoc(
        archetype->getConformsTo().back()->getName().getLength());
    replacement = " &";
  } else {
    loc = loc.getAdvancedLoc(archetype->getName().getLength());
    replacement = ":";
  }
  emitDiagnosticAt(loc, diag::did_you_mean_generic_param_as_conformance,
                   ParamName, archetype)
      .fixItReplaceChars(loc, loc.getAdvancedLoc(1), replacement);
  return true;
}

bool InvalidMemberRefOnExistential::diagnoseAsError() {
  auto anchor = getRawAnchor();

  DeclNameLoc nameLoc;
  if (auto *UDE = getAsExpr<UnresolvedDotExpr>(anchor)) {
    nameLoc = UDE->getNameLoc();
  } else if (auto *UME = getAsExpr<UnresolvedMemberExpr>(anchor)) {
    nameLoc = UME->getNameLoc();
  }

  emitDiagnostic(diag::could_not_use_member_on_existential, getBaseType(),
                 getName())
      .highlight(nameLoc.getSourceRange())
      .highlight(getSourceRange());
  return true;
}

bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
  auto loc = getLoc();
  auto *DC = getDC();
  auto locator = getLocator();

  if (loc.isInvalid()) {
    return true;
  }

  auto getRootExpr = [this](const Expr *childExpr) {
    auto *currExpr = const_cast<Expr *>(childExpr);
    while (auto parent = findParentExpr(currExpr))
      currExpr = parent;
    return currExpr;
  };

  auto anchor = getAnchor();

  if (!anchor.is<Expr *>())
    return false;

  Expr *expr = findParentExpr(castToExpr(anchor));
  SourceRange baseRange = expr ? expr->getSourceRange() : SourceRange();

  // If the base is an implicit self type reference, and we're in a
  // an initializer, then the user wrote something like:
  //
  //   class Foo { let x = 1, y = x }
  //
  // which runs in type context, not instance context, or
  //
  //   class Bar {
  //     let otherwise = 1              // instance member
  //     var x: Int
  //     func init(x: Int =otherwise) { // default parameter
  //       self.x = x
  //     }
  //   }
  //
  // in which an instance member is used as a default value for a
  // parameter.
  //
  // Produce a tailored diagnostic for these cases since this
  // comes up and is otherwise non-obvious what is going on.

  if (Name.isSimpleName(DeclBaseName::createConstructor()) &&
      !BaseType->is<AnyMetatypeType>()) {
    if (auto *ctorRef = getAsExpr<UnresolvedDotExpr>(getRawAnchor())) {
      if (isa<SuperRefExpr>(ctorRef->getBase())) {
        emitDiagnostic(diag::super_initializer_not_in_initializer);
        return true;
      }

      auto isCallArgument = [this](Expr *expr) {
        auto argExpr = findParentExpr(expr);
        if (!argExpr)
          return false;
        auto possibleApplyExpr = findParentExpr(expr);
        return possibleApplyExpr && isa<ApplyExpr>(possibleApplyExpr);
      };

      auto *initCall = findParentExpr(findParentExpr(ctorRef));

      auto isMutable = [&DC](ValueDecl *decl) {
        if (auto *storage = dyn_cast<AbstractStorageDecl>(decl))
          return storage->isSettable(DC) && storage->isSetterAccessibleFrom(DC);

        return true;
      };

      auto *baseLoc = getConstraintLocator(ctorRef->getBase());
      if (auto selection = getCalleeOverloadChoiceIfAvailable(baseLoc)) {
        OverloadChoice choice = selection->choice;
        if (choice.isDecl() && isMutable(choice.getDecl()) &&
            !isCallArgument(initCall) &&
            getContextualTypePurpose(getRootExpr(ctorRef)) == CTP_Unused) {
          auto fixItLoc = ctorRef->getBase()->getSourceRange().End;
          emitDiagnostic(diag::init_not_instance_member_use_assignment)
              .fixItInsertAfter(fixItLoc, " = ");
          return true;
        }

        SourceRange fixItRng = ctorRef->getBase()->getSourceRange();
        emitDiagnostic(diag::init_not_instance_member)
            .fixItInsert(fixItRng.Start, "type(of: ")
            .fixItInsertAfter(fixItRng.End, ")");
        return true;
      }
    }
  }

  if (BaseType->is<AnyMetatypeType>() && !Member->isStatic()) {
    auto instanceTy = BaseType;

    if (auto *AMT = instanceTy->getAs<AnyMetatypeType>()) {
      instanceTy = AMT->getInstanceType();
    }

    auto *DC = getDC();
    if (DC->getContextKind() == DeclContextKind::Initializer) {
      auto *TypeDC = DC->getParent();
      bool propertyInitializer = true;
      // If the parent context is not a type context, we expect it
      // to be a defaulted parameter in a function declaration.
      if (!TypeDC->isTypeContext()) {
        assert(TypeDC->getContextKind() ==
               DeclContextKind::AbstractFunctionDecl &&
               "Expected function decl context for initializer!");
        TypeDC = TypeDC->getParent();
        propertyInitializer = false;
      }
      
      assert(TypeDC->isTypeContext() && "Expected type decl context!");
      
      if (TypeDC->getSelfNominalTypeDecl() == instanceTy->getAnyNominal()) {
        if (propertyInitializer) {
          emitDiagnostic(diag::instance_member_in_initializer, Name);
          return true;
        } else {
          emitDiagnostic(diag::instance_member_in_default_parameter, Name);
          return true;
        }
      }
    }

    if (auto *maybeCallExpr = getAsExpr(getRawAnchor())) {
      if (auto *UDE = dyn_cast<UnresolvedDotExpr>(maybeCallExpr)) {
        maybeCallExpr = UDE->getBase();
      }

      if (auto callExpr = dyn_cast<ApplyExpr>(maybeCallExpr)) {
        auto fnExpr = callExpr->getFn();
        auto fnType = getType(fnExpr)->getRValueType();
        auto arg = callExpr->getArg();

        if (fnType->is<ExistentialMetatypeType>()) {
          emitDiagnosticAt(arg->getStartLoc(),
                           diag::missing_init_on_metatype_initialization)
              .highlight(fnExpr->getSourceRange());
          return true;
        }
      }
    }

    // Check whether the instance member is declared on parent context and if so
    // provide more specialized message.
    auto memberTypeContext =
        Member->getDeclContext()->getInnermostTypeContext();
    auto currentTypeContext = getDC()->getInnermostTypeContext();

    if (memberTypeContext && currentTypeContext &&
        memberTypeContext->getSemanticDepth() <
        currentTypeContext->getSemanticDepth()) {
      emitDiagnostic(diag::could_not_use_instance_member_on_type,
                     currentTypeContext->getDeclaredInterfaceType(), Name,
                     memberTypeContext->getDeclaredInterfaceType(), true)
          .highlight(baseRange)
          .highlight(Member->getSourceRange());
      return true;
    }

    if (auto *UDE = getAsExpr<UnresolvedDotExpr>(getRawAnchor())) {
      auto *baseExpr = UDE->getBase();
      if (isa<TypeExpr>(baseExpr)) {
        emitDiagnostic(diag::instance_member_use_on_type, instanceTy, Name)
            .highlight(getSourceRange());
        return true;
      }
    }

    // Just emit a generic "instance member cannot be used" error
    emitDiagnostic(diag::could_not_use_instance_member_on_type, instanceTy,
                   Name, instanceTy, false)
        .highlight(getSourceRange());
    return true;
  } else {
    // If the base of the lookup is a protocol metatype, suggest
    // to replace the metatype with 'Self'
    // error saying the lookup cannot be on a protocol metatype
    Optional<InFlightDiagnostic> Diag;
    auto baseTy = BaseType;

    if (auto metatypeTy = baseTy->getAs<AnyMetatypeType>()) {
      auto instanceTy = metatypeTy->getInstanceType();

      // This will only happen if we have an unresolved dot expression
      // (.foo) where foo is a protocol member and the contextual type is
      // an optional protocol metatype.
      if (auto objectTy = instanceTy->getOptionalObjectType()) {
        instanceTy = objectTy;
        baseTy = MetatypeType::get(objectTy);
      }

      if (instanceTy->isExistentialType()) {
        // Give a customized message if we're accessing a member type
        // of a protocol -- otherwise a diagnostic talking about
        // static members doesn't make a whole lot of sense
        if (isa<TypeAliasDecl>(Member)) {
          Diag.emplace(
              emitDiagnostic(diag::typealias_outside_of_protocol, Name));
        } else if (isa<AssociatedTypeDecl>(Member)) {
          Diag.emplace(
              emitDiagnostic(diag::assoc_type_outside_of_protocol, Name));
        } else if (isa<ConstructorDecl>(Member)) {
          Diag.emplace(
              emitDiagnostic(diag::construct_protocol_by_name, instanceTy));
        } else {
          Diag.emplace(emitDiagnostic(
              diag::could_not_use_type_member_on_protocol_metatype, baseTy,
              Name));
        }

        Diag->highlight(baseRange).highlight(getSourceRange());

        // See through function decl context
        if (auto parent = getDC()->getInnermostTypeContext()) {
          // If we are in a protocol extension of 'Proto' and we see
          // 'Proto.static', suggest 'Self.static'
          if (auto extensionContext = parent->getExtendedProtocolDecl()) {
            if (extensionContext->getDeclaredType()->isEqual(instanceTy)) {
              Diag->fixItReplace(getSourceRange(), "Self");
            }
          }
        }

        return true;
      }
    }

    // If this is a reference to a static member by one of the key path
    // components, let's provide a tailored diagnostic and return because
    // that is unsupported so there is no fix-it.
    if (locator->isForKeyPathComponent()) {
      InvalidStaticMemberRefInKeyPath failure(getSolution(), Member, locator);
      return failure.diagnoseAsError();
    }

    if (isa<EnumElementDecl>(Member)) {
      Diag.emplace(
          emitDiagnostic(diag::could_not_use_enum_element_on_instance, Name));
    } else {
      Diag.emplace(emitDiagnostic(diag::could_not_use_type_member_on_instance,
                                  baseTy, Name));
    }

    Diag->highlight(getSourceRange());

    if (Name.isSimpleName(DeclBaseName::createConstructor()) &&
        !baseTy->is<AnyMetatypeType>()) {
      if (auto ctorRef = getAsExpr<UnresolvedDotExpr>(getRawAnchor())) {
        SourceRange fixItRng = ctorRef->getNameLoc().getSourceRange();
        Diag->fixItInsert(fixItRng.Start, "type(of: ");
        Diag->fixItInsertAfter(fixItRng.End, ")");
        return true;
      }
    }

    // Determine the contextual type of the expression
    Type contextualType = getContextualType(getRawAnchor());
    // Try to provide a fix-it that only contains a '.'
    if (contextualType && baseTy->isEqual(contextualType)) {
      Diag->fixItInsert(loc, ".");
      return true;
    }

    // Check if the expression is the matching operator ~=, most often used in
    // case statements. If so, try to provide a single dot fix-it
    const Expr *contextualTypeNode = getRootExpr(getAsExpr(getAnchor()));

    // The '~=' operator is an overloaded decl ref inside a binaryExpr
    if (auto binaryExpr = dyn_cast<BinaryExpr>(contextualTypeNode)) {
      if (auto overloadedFn
          = dyn_cast<OverloadedDeclRefExpr>(binaryExpr->getFn())) {
        if (!overloadedFn->getDecls().empty()) {
          // Fetch any declaration to check if the name is '~='
          ValueDecl *decl0 = overloadedFn->getDecls()[0];
          
          if (decl0->getBaseName() == decl0->getASTContext().Id_MatchOperator) {
            assert(binaryExpr->getArg()->getElements().size() == 2);
            
            // If the rhs of '~=' is the enum type, a single dot suffixes
            // since the type can be inferred
            Type secondArgType = getType(binaryExpr->getArg()->getElement(1));
            if (secondArgType->isEqual(baseTy)) {
              Diag->fixItInsert(loc, ".");
              return true;
            }
          }
        }
      }
    }

    // Fall back to a fix-it with a full type qualifier
    Expr *baseExpr = nullptr;
    if (const auto *SE = getAsExpr<SubscriptExpr>(getRawAnchor()))
      baseExpr = SE->getBase();
    else if (const auto UDE = getAsExpr<UnresolvedDotExpr>(getRawAnchor()))
      baseExpr = UDE->getBase();

    // An implicit 'self' reference base expression means we should
    // prepend with qualification.
    if (baseExpr && !baseExpr->isImplicit()) {
      Diag->fixItReplace(baseExpr->getSourceRange(),
                         diag::replace_with_type, baseTy);
    } else {
      Diag->fixItInsert(loc, diag::insert_type_qualification, baseTy);
    }

    return true;
  }

  return false;
}

bool PartialApplicationFailure::diagnoseAsError() {
  auto *anchor = castToExpr<UnresolvedDotExpr>(getRawAnchor());

  RefKind kind = RefKind::MutatingMethod;

  // If this is initializer delegation chain, we have a tailored message.
  if (getOverloadChoiceIfAvailable(
          getConstraintLocator(anchor, ConstraintLocator::ConstructorMember))) {
    kind = anchor->getBase()->isSuperExpr() ? RefKind::SuperInit
                                            : RefKind::SelfInit;
  } else if (anchor->getBase()->isSuperExpr()) {
    kind = RefKind::SuperMethod;
  }

  auto diagnostic = CompatibilityWarning
                        ? diag::partial_application_of_function_invalid_swift4
                        : diag::partial_application_of_function_invalid;

  emitDiagnosticAt(anchor->getNameLoc(), diagnostic, kind);
  return true;
}

bool InvalidDynamicInitOnMetatypeFailure::diagnoseAsError() {
  emitDiagnostic(diag::dynamic_construct_class,
                 BaseType->getMetatypeInstanceType())
      .highlight(BaseRange);
  emitDiagnosticAt(Init, diag::note_nonrequired_initializer, Init->isImplicit(),
                   Init->getName());
  return true;
}

bool InitOnProtocolMetatypeFailure::diagnoseAsError() {
  if (IsStaticallyDerived) {
    emitDiagnostic(diag::construct_protocol_by_name,
                   BaseType->getMetatypeInstanceType())
        .highlight(BaseRange);
  } else {
    emitDiagnostic(diag::construct_protocol_value, BaseType)
        .highlight(BaseRange);
  }

  return true;
}

SourceLoc ImplicitInitOnNonConstMetatypeFailure::getLoc() const {
  if (auto *apply = getAsExpr<ApplyExpr>(getRawAnchor()))
    return apply->getArg()->getStartLoc();

  return FailureDiagnostic::getLoc();
}

bool ImplicitInitOnNonConstMetatypeFailure::diagnoseAsError() {
  emitDiagnostic(diag::missing_init_on_metatype_initialization)
      .fixItInsert(getLoc(), ".init");
  return true;
}

ASTNode MissingArgumentsFailure::getAnchor() const {
  auto anchor = FailureDiagnostic::getAnchor();

  if (auto *captureList = getAsExpr<CaptureListExpr>(anchor))
    return captureList->getClosureBody();

  return anchor;
}

bool MissingArgumentsFailure::diagnoseAsError() {
  auto *locator = getLocator();

  if (!(locator->isLastElement<LocatorPathElt::ApplyArgToParam>() ||
        locator->isLastElement<LocatorPathElt::ContextualType>() ||
        locator->isLastElement<LocatorPathElt::ApplyArgument>() ||
        locator->isLastElement<LocatorPathElt::ClosureResult>() ||
        locator->isLastElement<LocatorPathElt::ClosureBody>()))
    return false;

  // If this is a misplaced `missng argument` situation, it would be
  // diagnosed by invalid conversion fix.
  if (isMisplacedMissingArgument(getSolution(), locator))
    return false;

  auto anchor = getAnchor();

  if (auto *closure = getAsExpr<ClosureExpr>(anchor))
    return diagnoseClosure(closure);

  // This is a situation where function type is passed as an argument
  // to a function type parameter and their argument arity is different.
  //
  // ```
  // func foo(_: (Int) -> Void) {}
  // func bar() {}
  //
  // foo(bar) // `() -> Void` vs. `(Int) -> Void`
  // ```
  if (locator->isLastElement<LocatorPathElt::ApplyArgToParam>()) {
    auto info = *(getFunctionArgApplyInfo(locator));

    auto *argExpr = info.getArgExpr();
    emitDiagnosticAt(argExpr->getLoc(), diag::cannot_convert_argument_value,
                     info.getArgType(), info.getParamType());
    // TODO: It would be great so somehow point out which arguments are missing.
    return true;
  }

  // Function type has fewer arguments than expected by context:
  //
  // ```
  // func foo() {}
  // let _: (Int) -> Void = foo
  // ```
  if (locator->isLastElement<LocatorPathElt::ContextualType>()) {
    emitDiagnostic(diag::cannot_convert_initializer_value, getType(anchor),
                   resolveType(getContextualType(getAnchor())));
    // TODO: It would be great so somehow point out which arguments are missing.
    return true;
  }

  if (diagnoseInvalidTupleDestructuring())
    return true;

  if (SynthesizedArgs.size() == 1)
    return diagnoseSingleMissingArgument();

  // At this point we know that this is a situation when
  // there are multiple arguments missing, so let's produce
  // a diagnostic which lists all of them and a fix-it
  // to add arguments at appropriate positions.

  SmallString<32> diagnostic;
  llvm::raw_svector_ostream arguments(diagnostic);

  interleave(
      SynthesizedArgs,
      [&](const SynthesizedArg &e) {
        const auto paramIdx = e.paramIdx;
        const auto &arg = e.param;

        if (arg.hasLabel()) {
          arguments << "'" << arg.getLabel().str() << "'";
        } else {
          arguments << "#" << (paramIdx + 1);
        }
      },
      [&] { arguments << ", "; });

  auto diag = emitDiagnostic(diag::missing_arguments_in_call, arguments.str());

  Expr *fnExpr = nullptr;
  Expr *argExpr = nullptr;
  unsigned numArguments = 0;
  Optional<unsigned> firstTrailingClosure = None;

  std::tie(fnExpr, argExpr, numArguments, firstTrailingClosure) =
      getCallInfo(getRawAnchor());

  // TODO(diagnostics): We should be able to suggest this fix-it
  // unconditionally.
  if (argExpr && numArguments == 0) {
    SmallString<32> scratch;
    llvm::raw_svector_ostream fixIt(scratch);
    interleave(
        SynthesizedArgs,
        [&](const SynthesizedArg &arg) {
          forFixIt(fixIt, arg.param);
        },
        [&] { fixIt << ", "; });

    auto *tuple = cast<TupleExpr>(argExpr);
    diag.fixItInsertAfter(tuple->getLParenLoc(), fixIt.str());
  }

  diag.flush();

  if (auto selectedOverload = getCalleeOverloadChoiceIfAvailable(locator)) {
    if (auto *decl = selectedOverload->choice.getDeclOrNull()) {
      emitDiagnosticAt(decl, diag::decl_declared_here, decl->getName());
    }
  }

  return true;
}

bool MissingArgumentsFailure::diagnoseAsNote() {
  auto *locator = getLocator();
  if (auto overload = getCalleeOverloadChoiceIfAvailable(locator)) {
    auto *fn = resolveType(overload->openedType)->getAs<AnyFunctionType>();
    auto loc = overload->choice.getDecl()->getLoc();

    if (loc.isInvalid())
      loc = getLoc();

    emitDiagnosticAt(loc, diag::candidate_partial_match,
                     fn->getParamListAsString(fn->getParams()));
    return true;
  }

  return false;
}

bool MissingArgumentsFailure::diagnoseSingleMissingArgument() const {
  auto &ctx = getASTContext();

  auto anchor = getRawAnchor();
  if (!(isExpr<CallExpr>(anchor) || isExpr<SubscriptExpr>(anchor) ||
        isExpr<UnresolvedMemberExpr>(anchor) ||
        isExpr<ObjectLiteralExpr>(anchor)))
    return false;

  if (SynthesizedArgs.size() != 1)
    return false;

  const auto &argument = SynthesizedArgs.front();
  auto position = argument.paramIdx;
  auto label = argument.param.getLabel();

  Expr *fnExpr = nullptr;
  Expr *argExpr = nullptr;
  unsigned numArgs = 0;
  Optional<unsigned> firstTrailingClosure = None;

  std::tie(fnExpr, argExpr, numArgs, firstTrailingClosure) =
      getCallInfo(anchor);

  if (!argExpr) {
    return false;
  }

  // Will the parameter accept a trailing closure?
  Type paramType = resolveType(argument.param.getPlainType());
  bool paramAcceptsTrailingClosure = paramType
      ->lookThroughAllOptionalTypes()->is<AnyFunctionType>();

  // Determine whether we're inserting as a trailing closure.
  bool insertingTrailingClosure =
    firstTrailingClosure && position > *firstTrailingClosure;

  SmallString<32> insertBuf;
  llvm::raw_svector_ostream insertText(insertBuf);

  if (insertingTrailingClosure)
    insertText << " ";
  else if (position != 0)
    insertText << ", ";

  forFixIt(insertText, argument.param);

  if (position == 0 && numArgs > 0 &&
      (!firstTrailingClosure || position < *firstTrailingClosure))
    insertText << ", ";

  SourceLoc insertLoc;

  if (position >= numArgs && insertingTrailingClosure) {
    // Add a trailing closure to the end.

    // fn { closure }:
    //   fn {closure} label: [argMissing]
    // fn() { closure }:
    //   fn() {closure} label: [argMissing]
    // fn(argX) { closure }:
    //   fn(argX) { closure } label: [argMissing]
    insertLoc = Lexer::getLocForEndOfToken(
        ctx.SourceMgr, argExpr->getEndLoc());
  } else if (auto *TE = dyn_cast<TupleExpr>(argExpr)) {
    // fn(argX, argY):
    //   fn([argMissing, ]argX, argY)
    //   fn(argX[, argMissing], argY)
    // fn(argX) { closure }:
    //   fn([argMissing, ]argX) { closure }
    //   fn(argX[, argMissing]) { closure }
    // fn(argX, argY):
    //   fn(argX, argY[, argMissing])
    if (numArgs == 0) {
      insertLoc = TE->getRParenLoc();
    } else if (position != 0) {
      auto argPos = std::min(TE->getNumElements(), position) - 1;
      insertLoc = Lexer::getLocForEndOfToken(
          ctx.SourceMgr, TE->getElement(argPos)->getEndLoc());
    } else {
      insertLoc = TE->getElementNameLoc(0);
      if (insertLoc.isInvalid())
        insertLoc = TE->getElement(0)->getStartLoc();
    }
  } else {
    auto *PE = cast<ParenExpr>(argExpr);
    if (PE->getRParenLoc().isValid()) {
      // fn():
      //   fn([argMissing])
      // fn(argX):
      //   fn(argX[, argMissing])
      //   fn([argMissing, ]argX)
      // fn() { closure }:
      //   fn([argMissing]) {closure}
      if (position == 0) {
        insertLoc = Lexer::getLocForEndOfToken(ctx.SourceMgr,
                                               PE->getLParenLoc());
      } else {
        insertLoc = Lexer::getLocForEndOfToken(
            ctx.SourceMgr, PE->getSubExpr()->getEndLoc());
      }
    } else {
      // fn { closure }:
      //   fn[(argMissing)] { closure }
      assert(!isExpr<SubscriptExpr>(anchor) && "bracket less subscript");
      assert(firstTrailingClosure &&
             "paren less ParenExpr without trailing closure");
      insertBuf.insert(insertBuf.begin(), '(');
      insertBuf.insert(insertBuf.end(), ')');
      insertLoc =
          Lexer::getLocForEndOfToken(ctx.SourceMgr, fnExpr->getEndLoc());
    }
  }

  if (insertLoc.isInvalid())
    return false;

  // If we are trying to insert a trailing closure but the parameter
  // corresponding to the missing argument doesn't support a trailing closure,
  // don't provide a Fix-It.
  // FIXME: It's possible to parenthesize and relabel the argument list to
  // accomodate this, but it's tricky.
  bool shouldEmitFixIt =
    !(insertingTrailingClosure && !paramAcceptsTrailingClosure);

  if (label.empty()) {
    auto diag = emitDiagnosticAt(
        insertLoc, diag::missing_argument_positional, position + 1);
    if (shouldEmitFixIt)
      diag.fixItInsert(insertLoc, insertText.str());
  } else if (isPropertyWrapperInitialization()) {
    auto *TE = cast<TypeExpr>(fnExpr);
    emitDiagnosticAt(TE->getLoc(), diag::property_wrapper_missing_arg_init,
                     label, resolveType(TE->getInstanceType())->getString());
  } else {
    auto diag = emitDiagnosticAt(
        insertLoc, diag::missing_argument_named, label);
    if (shouldEmitFixIt)
      diag.fixItInsert(insertLoc, insertText.str());
  }

  if (auto selectedOverload =
          getCalleeOverloadChoiceIfAvailable(getLocator())) {
    if (auto *decl = selectedOverload->choice.getDeclOrNull()) {
      emitDiagnosticAt(decl, diag::decl_declared_here, decl->getName());
    }
  }

  return true;
}

bool MissingArgumentsFailure::diagnoseClosure(const ClosureExpr *closure) {
  FunctionType *funcType = nullptr;

  auto *locator = getLocator();
  if (locator->isForContextualType()) {
    funcType = getContextualType(locator->getAnchor())->getAs<FunctionType>();
  } else if (auto info = getFunctionArgApplyInfo(locator)) {
    auto paramType = info->getParamType();
    // Drop a single layer of optionality because argument could get injected
    // into optional and that doesn't contribute to the problem.
    if (auto objectType = paramType->getOptionalObjectType())
      paramType = objectType;
    funcType = paramType->getAs<FunctionType>();
  } else if (locator->isLastElement<LocatorPathElt::ClosureResult>() ||
             locator->isLastElement<LocatorPathElt::ClosureBody>()) {
    // Based on the locator we know this this is something like this:
    // `let _: () -> ((Int) -> Void) = { return {} }`.
    funcType = getType(getRawAnchor())
                   ->castTo<FunctionType>()
                   ->getResult()
                   ->castTo<FunctionType>();
  }

  if (!funcType)
    return false;

  unsigned numSynthesized = SynthesizedArgs.size();
  auto diff = funcType->getNumParams() - numSynthesized;

  // If the closure didn't specify any arguments and it is in a context that
  // needs some, produce a fixit to turn "{...}" into "{ _,_ in ...}".
  if (diff == 0) {
    auto diag =
        emitDiagnosticAt(closure->getStartLoc(),
                         diag::closure_argument_list_missing, numSynthesized);

    std::string fixText; // Let's provide fixits for up to 10 args.
    if (funcType->getNumParams() <= 10) {
      fixText += " ";
      interleave(
          funcType->getParams(),
          [&fixText](const AnyFunctionType::Param &param) { fixText += '_'; },
          [&fixText] { fixText += ','; });
      fixText += " in ";
    }

    if (!fixText.empty()) {
      // Determine if there is already a space after the { in the closure to
      // make sure we introduce the right whitespace.
      auto afterBrace = closure->getStartLoc().getAdvancedLoc(1);
      auto text = getASTContext().SourceMgr.extractText({afterBrace, 1});
      if (text.size() == 1 && text == " ")
        fixText = fixText.erase(fixText.size() - 1);
      else
        fixText = fixText.erase(0, 1);
      diag.fixItInsertAfter(closure->getStartLoc(), fixText);
    }

    return true;
  }

  auto params = closure->getParameters();
  bool onlyAnonymousParams =
      std::all_of(params->begin(), params->end(),
                  [](ParamDecl *param) { return !param->hasName(); });

  auto diag = emitDiagnosticAt(
      params->getStartLoc(), diag::closure_argument_list_tuple,
      resolveType(funcType), funcType->getNumParams(), diff, diff == 1);

  // If the number of parameters is less than number of inferred
  // let's try to suggest a fix-it with the rest of the missing parameters.
  if (!closure->hasExplicitResultType() &&
      closure->getInLoc().isValid()) {
    SmallString<32> fixIt;
    llvm::raw_svector_ostream OS(fixIt);

    OS << ",";
    for (unsigned i = 0; i != numSynthesized; ++i) {
      OS << ((onlyAnonymousParams) ? "_" : "<#arg#>");
      OS << ((i == numSynthesized - 1) ? " " : ",");
    }

    diag.fixItInsertAfter(params->getEndLoc(), OS.str());
  }

  return true;
}

bool MissingArgumentsFailure::diagnoseInvalidTupleDestructuring() const {
  auto *locator = getLocator();
  if (!locator->isLastElement<LocatorPathElt::ApplyArgument>())
    return false;

  if (SynthesizedArgs.size() < 2)
    return false;

  auto anchor = getAnchor();

  Expr *argExpr = nullptr;
  // Something like `foo(x: (1, 2))`
  if (auto *TE = getAsExpr<TupleExpr>(anchor)) {
    if (TE->getNumElements() == 1)
      argExpr = TE->getElement(0);
  } else { // or `foo((1, 2))`
    argExpr = castToExpr<ParenExpr>(anchor)->getSubExpr();
  }

  if (!(argExpr && getType(argExpr)->getRValueType()->is<TupleType>()))
    return false;

  auto selectedOverload = getCalleeOverloadChoiceIfAvailable(locator);
  if (!selectedOverload)
    return false;

  auto *decl = selectedOverload->choice.getDeclOrNull();
  if (!decl)
    return false;

  auto name = decl->getBaseName();
  auto diagnostic =
      emitDiagnostic(diag::cannot_convert_single_tuple_into_multiple_arguments,
                     decl->getDescriptiveKind(), name, name.isSpecial(),
                     SynthesizedArgs.size(), isa<TupleExpr>(argExpr));

  // If argument is a literal tuple, let's suggest removal of parentheses.
  if (auto *TE = dyn_cast<TupleExpr>(argExpr)) {
    diagnostic.fixItRemove(TE->getLParenLoc()).fixItRemove(TE->getRParenLoc());
  }

  diagnostic.flush();

  // Add a note which points to the overload choice location.
  emitDiagnosticAt(decl, diag::decl_declared_here, decl->getName());
  return true;
}

bool MissingArgumentsFailure::isPropertyWrapperInitialization() const {
  auto *call = getAsExpr<CallExpr>(getRawAnchor());
  if (!(call && call->isImplicit()))
    return false;

  auto TE = dyn_cast<TypeExpr>(call->getFn());
  if (!TE)
    return false;

  auto instanceTy = TE->getInstanceType();
  if (!instanceTy)
    return false;

  auto *NTD = resolveType(instanceTy)->getAnyNominal();
  return NTD && NTD->getAttrs().hasAttribute<PropertyWrapperAttr>();
}

bool MissingArgumentsFailure::isMisplacedMissingArgument(
    const Solution &solution, ConstraintLocator *locator) {
  auto *calleeLocator = solution.getCalleeLocator(locator);
  auto overloadChoice = solution.getOverloadChoiceIfAvailable(calleeLocator);
  if (!overloadChoice)
    return false;

  auto *fnType =
      solution.simplifyType(overloadChoice->openedType)->getAs<FunctionType>();
  if (!(fnType && fnType->getNumParams() == 2))
    return false;

  auto anchor = locator->getAnchor();

  auto hasFixFor = [&](FixKind kind, ConstraintLocator *locator) -> bool {
    auto fix = llvm::find_if(solution.Fixes, [&](const ConstraintFix *fix) {
      return fix->getLocator() == locator;
    });

    if (fix == solution.Fixes.end())
      return false;

    return (*fix)->getKind() == kind;
  };

  auto *callLocator =
      solution.getConstraintLocator(anchor, {ConstraintLocator::ApplyArgument});

  auto argFlags = fnType->getParams()[0].getParameterFlags();
  auto *argLoc = solution.getConstraintLocator(
      callLocator, LocatorPathElt::ApplyArgToParam(0, 0, argFlags));

  if (!(hasFixFor(FixKind::AllowArgumentTypeMismatch, argLoc) &&
        hasFixFor(FixKind::AddMissingArguments, callLocator)))
    return false;

  Expr *argExpr = nullptr;
  if (auto *call = getAsExpr<CallExpr>(anchor)) {
    argExpr = call->getArg();
  } else if (auto *subscript = getAsExpr<SubscriptExpr>(anchor)) {
    argExpr = subscript->getIndex();
  } else {
    return false;
  }

  Expr *argument = nullptr;
  if (auto *PE = dyn_cast<ParenExpr>(argExpr)) {
    argument = PE->getSubExpr();
  } else {
    auto *tuple = cast<TupleExpr>(argExpr);
    if (tuple->getNumElements() != 1)
      return false;
    argument = tuple->getElement(0);
  }

  auto argType = solution.simplifyType(solution.getType(argument));
  auto paramType = fnType->getParams()[1].getPlainType();

  return TypeChecker::isConvertibleTo(argType, paramType, solution.getDC());
}

std::tuple<Expr *, Expr *, unsigned, Optional<unsigned>>
MissingArgumentsFailure::getCallInfo(ASTNode anchor) const {
  if (auto *call = getAsExpr<CallExpr>(anchor)) {
    return std::make_tuple(call->getFn(), call->getArg(),
                           call->getNumArguments(),
                           call->getUnlabeledTrailingClosureIndex());
  } else if (auto *SE = getAsExpr<SubscriptExpr>(anchor)) {
    return std::make_tuple(SE, SE->getIndex(), SE->getNumArguments(),
                           SE->getUnlabeledTrailingClosureIndex());
  } else if (auto *OLE = getAsExpr<ObjectLiteralExpr>(anchor)) {
    return std::make_tuple(OLE, OLE->getArg(), OLE->getNumArguments(),
                           OLE->getUnlabeledTrailingClosureIndex());
  }

  return std::make_tuple(nullptr, nullptr, 0, None);
}

void MissingArgumentsFailure::forFixIt(
    llvm::raw_svector_ostream &out,
    const AnyFunctionType::Param &argument) const {
  if (argument.hasLabel())
    out << argument.getLabel().str() << ": ";

  // Explode inout type.
  if (argument.isInOut())
    out << "&";

  auto resolvedType = resolveType(argument.getPlainType());
  // @autoclosure; the type should be the result type.
  if (argument.isAutoClosure())
    resolvedType = resolvedType->castTo<FunctionType>()->getResult();

  out << "<#" << resolvedType << "#>";
}

SourceLoc ClosureParamDestructuringFailure::getLoc() const {
  auto *closure = castToExpr<ClosureExpr>(getAnchor());
  auto paramList = closure->getParameters();
  return paramList->getStartLoc();
}

SourceRange ClosureParamDestructuringFailure::getSourceRange() const {
  auto *closure = castToExpr<ClosureExpr>(getAnchor());
  auto paramList = closure->getParameters();
  return paramList->getSourceRange();
}

bool ClosureParamDestructuringFailure::diagnoseAsError() {
  auto *closure = castToExpr<ClosureExpr>(getAnchor());
  auto params = closure->getParameters();

  // In case of implicit parameters e.g. $0, $1 we
  // can't really provide good fix-it because
  // structure of parameter type itself is unclear.
  for (auto *param : params->getArray()) {
    if (param->isImplicit()) {
      emitDiagnostic(diag::closure_tuple_parameter_destructuring_implicit,
                     getParameterType());
      return true;
    }
  }

  auto diag = emitDiagnostic(diag::closure_tuple_parameter_destructuring,
                             getParameterType());

  auto *closureBody = closure->getBody();
  if (!closureBody)
    return true;

  auto &sourceMgr = getASTContext().SourceMgr;
  auto bodyStmts = closureBody->getElements();

  SourceLoc bodyLoc;
  SourceLoc inLoc = closure->getInLoc();
  // If location for `in` is unknown we can't proceed
  // since we'll not be able to figure out source line
  // to place the fix-it on.
  if (inLoc.isInvalid())
    return true;

  // If the body is empty let's put the cursor
  // right after "in", otherwise make it start
  // location of the first statement in the body.
  if (bodyStmts.empty())
    bodyLoc = Lexer::getLocForEndOfToken(sourceMgr, inLoc);
  else
    bodyLoc = bodyStmts.front().getStartLoc();

  if (bodyLoc.isInvalid())
    return true;

  SmallString<64> fixIt;
  llvm::raw_svector_ostream OS(fixIt);

  // If this is multi-line closure we'd have to insert new lines
  // in the suggested 'let' to keep the structure of the code intact,
  // otherwise just use ';' to keep everything on the same line.
  auto inLine = sourceMgr.getLineAndColumnInBuffer(inLoc).first;
  auto bodyLine = sourceMgr.getLineAndColumnInBuffer(bodyLoc).first;
  auto isMultiLineClosure = bodyLine > inLine;
  auto indent =
      bodyStmts.empty() ? "" : Lexer::getIndentationForLine(sourceMgr, bodyLoc);

  SmallString<16> parameter;
  llvm::raw_svector_ostream parameterOS(parameter);

  parameterOS << "(";
  interleave(
      params->getArray(),
      [&](const ParamDecl *param) { parameterOS << param->getNameStr(); },
      [&] { parameterOS << ", "; });
  parameterOS << ")";

  // Check if there are any explicit types associated
  // with parameters, if there are, we'll have to add
  // type information to the replacement argument.
  bool explicitTypes =
      llvm::any_of(params->getArray(),
                   [](const ParamDecl *param) { return param->getTypeRepr(); });

  if (isMultiLineClosure)
    OS << '\n' << indent;

  // Let's form 'let <name> : [<type>]? = arg' expression.
  OS << "let " << parameterOS.str() << " = arg"
     << (isMultiLineClosure ? "\n" + indent : "; ");

  SmallString<64> argName;
  llvm::raw_svector_ostream nameOS(argName);
  if (explicitTypes) {
    nameOS << "(arg: " << getParameterType()->getString() << ")";
  } else {
    nameOS << "(arg)";
  }

  if (closure->hasSingleExpressionBody()) {
    // Let's see if we need to add result type to the argument/fix-it:
    //  - if the there is a result type associated with the closure;
    //  - and it's not a void type;
    //  - and it hasn't been explicitly written.
    auto resultType = resolveType(ContextualType->getResult());
    auto hasResult = [](Type resultType) -> bool {
      return resultType && !resultType->isVoid();
    };

    auto isValidType = [](Type resultType) -> bool {
      return resultType && !resultType->hasUnresolvedType() &&
             !resultType->hasTypeVariable();
    };

    // If there an expected result type but it hasn't been explicitly
    // provided, let's add it to the argument.
    if (hasResult(resultType) && !closure->hasExplicitResultType()) {
      nameOS << " -> ";
      if (isValidType(resultType))
        nameOS << resultType->getString();
      else
        nameOS << "<#Result#>";
    }

    if (auto stmt = bodyStmts.front().get<Stmt *>()) {
      // If the body is a single expression with implicit return.
      if (isa<ReturnStmt>(stmt) && stmt->isImplicit()) {
        // And there is non-void expected result type,
        // because we add 'let' expression to the body
        // we need to make such 'return' explicit.
        if (hasResult(resultType))
          OS << "return ";
      }
    }
  }

  diag.fixItReplace(getSourceRange(), nameOS.str())
      .fixItInsert(bodyLoc, OS.str());
  return true;
}

bool OutOfOrderArgumentFailure::diagnoseAsError() {
  auto anchor = getRawAnchor();
  auto *argExpr = isExpr<TupleExpr>(anchor)
                      ? castToExpr<TupleExpr>(anchor)
                      : getArgumentListExprFor(getLocator());
  if (!argExpr)
    return false;

  auto *tuple = cast<TupleExpr>(argExpr);

  Identifier first = tuple->getElementName(ArgIdx);
  Identifier second = tuple->getElementName(PrevArgIdx);

  // Build a mapping from arguments to parameters.
  SmallVector<unsigned, 4> argBindings(tuple->getNumElements());
  for (unsigned paramIdx = 0; paramIdx != Bindings.size(); ++paramIdx) {
    for (auto argIdx : Bindings[paramIdx])
      argBindings[argIdx] = paramIdx;
  }

  auto argRange = [&](unsigned argIdx, Identifier label) -> SourceRange {
    auto range = tuple->getElement(argIdx)->getSourceRange();
    if (!label.empty())
      range.Start = tuple->getElementNameLoc(argIdx);

    unsigned paramIdx = argBindings[argIdx];
    if (Bindings[paramIdx].size() > 1)
      range.End = tuple->getElement(Bindings[paramIdx].back())->getEndLoc();

    return range;
  };

  auto firstRange = argRange(ArgIdx, first);
  auto secondRange = argRange(PrevArgIdx, second);

  SourceLoc diagLoc = firstRange.Start;

  auto addFixIts = [&](InFlightDiagnostic diag) {
    // Don't add Fix-Its if one of the ranges is outside of the argument
    // list, which can happen when we're splicing together an argument list
    // from multiple sources.
    auto &SM = getASTContext().SourceMgr;
    auto argsRange = tuple->getSourceRange();
    if (!SM.rangeContains(argsRange, firstRange) ||
        !SM.rangeContains(argsRange, secondRange))
      return;

    diag.highlight(firstRange).highlight(secondRange);

    // Move the misplaced argument by removing it from one location and
    // inserting it in another location. To maintain argument comma
    // separation, since the argument is always moving to an earlier index
    // the preceding comma and whitespace is removed and a new trailing
    // comma and space is inserted with the moved argument.
    auto text = SM.extractText(
        Lexer::getCharSourceRangeFromSourceRange(SM, firstRange));

    auto removalRange =
        SourceRange(Lexer::getLocForEndOfToken(
                        SM, tuple->getElement(ArgIdx - 1)->getEndLoc()),
                    firstRange.End);
    diag.fixItRemove(removalRange);
    diag.fixItInsert(secondRange.Start,
                     text.str() + (isExpr<BinaryExpr>(anchor) ? "" : ", "));
  };

  // There are 4 diagnostic messages variations depending on
  // labeled/unlabeled arguments.
  if (first.empty() && second.empty()) {
    addFixIts(
        emitDiagnosticAt(diagLoc,
                         isExpr<BinaryExpr>(anchor)
                             ? diag::argument_out_of_order_binary_op
                             : diag::argument_out_of_order_unnamed_unnamed,
                         ArgIdx + 1, PrevArgIdx + 1));
  } else if (first.empty() && !second.empty()) {
    addFixIts(emitDiagnosticAt(diagLoc,
                               diag::argument_out_of_order_unnamed_named,
                               ArgIdx + 1, second));
  } else if (!first.empty() && second.empty()) {
    addFixIts(emitDiagnosticAt(diagLoc,
                               diag::argument_out_of_order_named_unnamed, first,
                               PrevArgIdx + 1));
  } else {
    addFixIts(emitDiagnosticAt(diagLoc, diag::argument_out_of_order_named_named,
                               first, second));
  }
  return true;
}

bool ExtraneousArgumentsFailure::diagnoseAsError() {
  // Simplified anchor would point directly to the
  // argument in case of contextual mismatch.
  auto anchor = getAnchor();

  if (auto *closure = getAsExpr<ClosureExpr>(anchor)) {
    auto fnType = ContextualType;
    auto params = closure->getParameters();

    auto diag = emitDiagnosticAt(
        params->getStartLoc(), diag::closure_argument_list_tuple, fnType,
        fnType->getNumParams(), params->size(), (params->size() == 1));

    bool onlyAnonymousParams =
        std::all_of(params->begin(), params->end(),
                    [](ParamDecl *param) { return !param->hasName(); });

    // If closure expects no parameters but N was given,
    // and all of them are anonymous let's suggest removing them.
    if (fnType->getNumParams() == 0 && onlyAnonymousParams) {
      auto inLoc = closure->getInLoc();
      auto &sourceMgr = getASTContext().SourceMgr;

      if (inLoc.isValid())
        diag.fixItRemoveChars(params->getStartLoc(),
                              Lexer::getLocForEndOfToken(sourceMgr, inLoc));
    }
    return true;
  }

  if (isContextualMismatch()) {
    auto *locator = getLocator();
    emitDiagnostic(locator->isLastElement<LocatorPathElt::ContextualType>()
                       ? diag::cannot_convert_initializer_value
                       : diag::cannot_convert_argument_value,
                   getType(anchor), ContextualType);
    return true;
  }

  if (ExtraArgs.size() == 1) {
    return diagnoseSingleExtraArgument();
  }

  if (ContextualType->getNumParams() == 0) {
    if (auto argExpr = getArgumentListExprFor(getLocator())) {
      emitDiagnostic(diag::extra_argument_to_nullary_call)
          .highlight(argExpr->getSourceRange())
          .fixItRemove(argExpr->getSourceRange());
      return true;
    }
  }

  if (ExtraArgs.size() < 2)
    return false;

  llvm::SmallString<64> positions;
  llvm::raw_svector_ostream OS(positions);

  interleave(
      ExtraArgs,
      [&](const std::pair<unsigned, AnyFunctionType::Param> &arg) {
        OS << "#" << (arg.first + 1);
      },
      [&] { OS << ", "; });

  emitDiagnostic(diag::extra_arguments_in_call, OS.str());

  if (auto overload = getCalleeOverloadChoiceIfAvailable(getLocator())) {
    if (auto *decl = overload->choice.getDeclOrNull()) {
      emitDiagnosticAt(decl, diag::decl_declared_here, decl->getName());
    }
  }

  return true;
}

bool ExtraneousArgumentsFailure::diagnoseAsNote() {
  auto overload = getCalleeOverloadChoiceIfAvailable(getLocator());
  if (!(overload && overload->choice.isDecl()))
    return false;

  auto *decl = overload->choice.getDecl();
  auto numArgs = getTotalNumArguments();
  emitDiagnosticAt(decl, diag::candidate_with_extraneous_args, ContextualType,
                   ContextualType->getNumParams(), numArgs, (numArgs == 1),
                   isExpr<ClosureExpr>(getAnchor()));
  return true;
}

bool ExtraneousArgumentsFailure::diagnoseSingleExtraArgument() const {
  auto *locator = getLocator();

  // This specifically handles a case of `Void(...)` which generates
  // constraints differently from other constructor invocations and
  // wouldn't have `ApplyArgument` as a last element in the locator.
  if (auto *call = getAsExpr<CallExpr>(getRawAnchor())) {
    auto *TE = dyn_cast<TypeExpr>(call->getFn());
    if (TE && getType(TE)->getMetatypeInstanceType()->isVoid()) {
      emitDiagnosticAt(call->getLoc(), diag::extra_argument_to_nullary_call)
          .highlight(call->getArg()->getSourceRange());
      return true;
    }
  }

  auto *arguments = getArgumentListExprFor(locator);
  if (!arguments)
    return false;

  const auto &e = ExtraArgs.front();
  auto index = e.first;
  auto argument = e.second;

  auto tuple = dyn_cast<TupleExpr>(arguments);
  auto argExpr = tuple ? tuple->getElement(index)
                       : cast<ParenExpr>(arguments)->getSubExpr();

  auto loc = argExpr->getLoc();
  if (tuple && index == tuple->getNumElements() - 1 &&
      tuple->hasTrailingClosure()) {
    emitDiagnosticAt(loc, diag::extra_trailing_closure_in_call)
        .highlight(argExpr->getSourceRange());
  } else if (ContextualType->getNumParams() == 0) {
    auto *PE = dyn_cast<ParenExpr>(arguments);
    Expr *subExpr = nullptr;
    if (PE)
      subExpr = PE->getSubExpr();

    if (subExpr && argument.getPlainType()->isVoid()) {
      emitDiagnosticAt(loc, diag::extra_argument_to_nullary_call)
          .fixItRemove(subExpr->getSourceRange());
    } else {
      emitDiagnosticAt(loc, diag::extra_argument_to_nullary_call)
          .highlight(argExpr->getSourceRange());
    }
  } else if (argument.hasLabel()) {
    emitDiagnosticAt(loc, diag::extra_argument_named, argument.getLabel())
        .highlight(argExpr->getSourceRange());
  } else {
    emitDiagnosticAt(loc, diag::extra_argument_positional)
        .highlight(argExpr->getSourceRange());
  }
  return true;
}

bool InaccessibleMemberFailure::diagnoseAsError() {
  auto anchor = getRawAnchor();
  // Let's try to avoid over-diagnosing chains of inaccessible
  // members e.g.:
  //
  // struct A {
  //   struct B {
  //     struct C {}
  //   }
  // }
  //
  // _ = A.B.C()
  //
  // We'll have a fix for each `B', `C` and `C.init` but it makes
  // sense to diagnose only `B` and consider the rest hidden.
  Expr *baseExpr = nullptr;
  DeclNameLoc nameLoc;
  if (auto *UDE = getAsExpr<UnresolvedDotExpr>(anchor)) {
    baseExpr = UDE->getBase();
    nameLoc = UDE->getNameLoc();
  } else if (auto *UME = getAsExpr<UnresolvedMemberExpr>(anchor)) {
    nameLoc = UME->getNameLoc();
  } else if (auto *SE = getAsExpr<SubscriptExpr>(anchor)) {
    baseExpr = SE->getBase();
  } else if (auto *call = getAsExpr<CallExpr>(anchor)) {
    baseExpr = call->getFn();
  }

  if (baseExpr) {
    auto *locator = getConstraintLocator(baseExpr, ConstraintLocator::Member);
    const auto &solution = getSolution();
    if (llvm::any_of(solution.Fixes, [&locator](const ConstraintFix *fix) {
          return fix->getLocator() == locator;
        }))
      return false;
  }

  auto loc = nameLoc.isValid() ? nameLoc.getStartLoc() : ::getLoc(anchor);
  auto accessLevel = Member->getFormalAccessScope().accessLevelForDiagnostics();
  if (auto *CD = dyn_cast<ConstructorDecl>(Member)) {
    emitDiagnosticAt(loc, diag::init_candidate_inaccessible,
                     CD->getResultInterfaceType(), accessLevel)
        .highlight(nameLoc.getSourceRange());
  } else {
    emitDiagnosticAt(loc, diag::candidate_inaccessible, Member->getBaseName(),
                     accessLevel)
        .highlight(nameLoc.getSourceRange());
  }

  emitDiagnosticAt(Member, diag::decl_declared_here, Member->getName());
  return true;
}

SourceLoc AnyObjectKeyPathRootFailure::getLoc() const {
  auto anchor = getAnchor();

  if (auto *KPE = getAsExpr<KeyPathExpr>(anchor)) {
    if (auto rootTyRepr = KPE->getRootType())
      return rootTyRepr->getLoc();
  }

  return ::getLoc(anchor);
}

SourceRange AnyObjectKeyPathRootFailure::getSourceRange() const {
  auto anchor = getAnchor();

  if (auto *KPE = getAsExpr<KeyPathExpr>(anchor)) {
    if (auto rootTyRepr = KPE->getRootType())
      return rootTyRepr->getSourceRange();
  }

  return ::getSourceRange(anchor);
}

bool AnyObjectKeyPathRootFailure::diagnoseAsError() {
  // Diagnose use of AnyObject as root for a keypath
  emitDiagnostic(diag::expr_swift_keypath_anyobject_root)
      .highlight(getSourceRange());
  return true;
}

SourceLoc KeyPathSubscriptIndexHashableFailure::getLoc() const {
  auto *locator = getLocator();

  if (locator->isKeyPathSubscriptComponent()) {
    auto *KPE = castToExpr<KeyPathExpr>(getAnchor());
    if (auto kpElt = locator->findFirst<LocatorPathElt::KeyPathComponent>())
      return KPE->getComponents()[kpElt->getIndex()].getLoc();
  }

  return FailureDiagnostic::getLoc();
}

bool KeyPathSubscriptIndexHashableFailure::diagnoseAsError() {
  emitDiagnostic(diag::expr_keypath_subscript_index_not_hashable,
                 resolveType(NonConformingType));
  return true;
}

SourceLoc InvalidMemberRefInKeyPath::getLoc() const {
  auto anchor = getRawAnchor();

  if (auto *KPE = getAsExpr<KeyPathExpr>(anchor)) {
    auto *locator = getLocator();
    auto component = locator->findFirst<LocatorPathElt::KeyPathComponent>();
    assert(component);
    return KPE->getComponents()[component->getIndex()].getLoc();
  }

  return ::getLoc(anchor);
}

bool InvalidStaticMemberRefInKeyPath::diagnoseAsError() {
  emitDiagnostic(diag::expr_keypath_static_member, getName(),
                 isForKeyPathDynamicMemberLookup());
  return true;
}

bool InvalidEnumCaseRefInKeyPath::diagnoseAsError() {
  emitDiagnostic(diag::expr_keypath_enum_case, getName(),
                 isForKeyPathDynamicMemberLookup());
  return true;
}

bool InvalidMemberWithMutatingGetterInKeyPath::diagnoseAsError() {
  emitDiagnostic(diag::expr_keypath_mutating_getter, getName(),
                 isForKeyPathDynamicMemberLookup());
  return true;
}

bool InvalidMethodRefInKeyPath::diagnoseAsError() {
  emitDiagnostic(diag::expr_keypath_not_property, getKind(), getName(),
                 isForKeyPathDynamicMemberLookup());
  return true;
}

SourceLoc InvalidUseOfAddressOf::getLoc() const {
  auto anchor = getAnchor();

  if (auto *assign = getAsExpr<AssignExpr>(anchor))
    return assign->getSrc()->getLoc();

  return ::getLoc(anchor);
}

bool InvalidUseOfAddressOf::diagnoseAsError() {
  if (auto argApplyInfo = getFunctionArgApplyInfo(getLocator())) {
    if (!argApplyInfo->getParameterFlags().isInOut()) {
      emitDiagnostic(diag::extra_address_of, getToType())
          .highlight(getSourceRange())
          .fixItRemove(getSourceRange().Start);
      return true;
    }
  }

  emitDiagnostic(diag::extraneous_address_of);
  return true;
}

bool ExtraneousReturnFailure::diagnoseAsError() {
  emitDiagnostic(diag::cannot_return_value_from_void_func);
  if (auto FD = dyn_cast<FuncDecl>(getDC())) {
    // We only want to emit the note + fix-it if the function does not
    // have an explicit return type. The reason we also need to check
    // whether the parameter list has a valid loc is to guard against
    // cases like like 'var foo: () { return 1 }' as here that loc will
    // be invalid. We also need to check that the name is not empty,
    // because certain decls will have empty name (like setters).
    if (FD->getResultTypeRepr() == nullptr &&
        FD->getParameters()->getStartLoc().isValid() &&
        !FD->getBaseIdentifier().empty()) {
      auto fixItLoc = Lexer::getLocForEndOfToken(
          getASTContext().SourceMgr, FD->getParameters()->getEndLoc());
      emitDiagnostic(diag::add_return_type_note)
          .fixItInsert(fixItLoc, " -> <#Return Type#>");
    }
  }

  return true;
}

bool CollectionElementContextualFailure::diagnoseAsError() {
  auto anchor = getRawAnchor();
  auto *locator = getLocator();

  auto eltType = getFromType();
  auto contextualType = getToType();

  auto isFixedToDictionary = [&](ArrayExpr *anchor) {
    return llvm::any_of(getSolution().Fixes, [&](ConstraintFix *fix) {
      auto *fixAnchor = getAsExpr<ArrayExpr>(fix->getAnchor());
      return fixAnchor && fixAnchor == anchor &&
        fix->getKind() == FixKind::TreatArrayLiteralAsDictionary;
    });
  };

  bool treatAsDictionary = false;
  Optional<InFlightDiagnostic> diagnostic;
  if (auto *AE = getAsExpr<ArrayExpr>(anchor)) {
    if (!(treatAsDictionary = isFixedToDictionary(AE))) {
      if (diagnoseMergedLiteralElements())
        return true;

      diagnostic.emplace(emitDiagnostic(diag::cannot_convert_array_element,
                                        eltType, contextualType));
    }
  }

  if (treatAsDictionary || isExpr<DictionaryExpr>(anchor)) {
    auto eltLoc = locator->castLastElementTo<LocatorPathElt::TupleElement>();
    switch (eltLoc.getIndex()) {
    case 0: // key
      diagnostic.emplace(emitDiagnostic(diag::cannot_convert_dict_key, eltType,
                                        contextualType));
      break;

    case 1: // value
      diagnostic.emplace(emitDiagnostic(diag::cannot_convert_dict_value,
                                        eltType, contextualType));
      break;

    default:
      break;
    }
  }

  if (locator->isForSequenceElementType()) {
    // If this is a conversion failure related to binding of `for-each`
    // statement it has to be diagnosed as pattern match if there are
    // holes present in the contextual type.
    if (FailureDiagnostic::getContextualTypePurpose(getAnchor()) ==
            ContextualTypePurpose::CTP_ForEachStmt &&
        contextualType->hasUnresolvedType()) {
      diagnostic.emplace(emitDiagnostic(
          (contextualType->is<TupleType>() && !eltType->is<TupleType>())
              ? diag::cannot_match_expr_tuple_pattern_with_nontuple_value
              : diag::cannot_match_unresolved_expr_pattern_with_value,
          eltType));
    } else {
      diagnostic.emplace(
          emitDiagnostic(contextualType->isExistentialType()
                             ? diag::cannot_convert_sequence_element_protocol
                             : diag::cannot_convert_sequence_element_value,
                         eltType, contextualType));
    }
  }

  if (!diagnostic)
    return false;

  (void)trySequenceSubsequenceFixIts(*diagnostic);
  return true;
}

bool CollectionElementContextualFailure::diagnoseMergedLiteralElements() {
  auto elementAnchor = simplifyLocatorToAnchor(getLocator());
  if (!elementAnchor)
    return false;

  auto *typeVar = getRawType(elementAnchor)->getAs<TypeVariableType>();
  if (!typeVar || !typeVar->getImpl().getAtomicLiteralKind())
    return false;

  // This element is a literal whose type variable could have been merged with others,
  // but the conversion constraint to the array element type was only placed on one
  // of them. So, we want to emit the error for each element whose type variable is in
  // this equivalence class.
  auto &cs = getConstraintSystem();
  auto node = cs.getRepresentative(typeVar)->getImpl().getGraphNode();
  for (const auto *typeVar : node->getEquivalenceClass()) {
    auto anchor = typeVar->getImpl().getLocator()->getAnchor();
    emitDiagnosticAt(constraints::getLoc(anchor), diag::cannot_convert_array_element,
                     getFromType(), getToType());
  }

  return true;
}

bool MissingContextualConformanceFailure::diagnoseAsError() {
  auto anchor = getAnchor();
  auto path = getLocator()->getPath();

  Optional<Diag<Type, Type>> diagnostic;
  if (path.empty()) {
    assert(isExpr<AssignExpr>(anchor));
    if (isa<SubscriptExpr>(castToExpr<AssignExpr>(anchor)->getDest())) {
      diagnostic = getDiagnosticFor(CTP_SubscriptAssignSource, getToType());
    } else {
      diagnostic = getDiagnosticFor(CTP_AssignSource, getToType());
    }
  } else {
    const auto &last = path.back();
    switch (last.getKind()) {
    case ConstraintLocator::ContextualType:
      assert(Context != CTP_Unused);
      diagnostic = getDiagnosticFor(Context, getToType());
      break;

    case ConstraintLocator::SequenceElementType: {
      diagnostic = diag::cannot_convert_sequence_element_protocol;
      break;
    }

    default:
      break;
    }
  }

  if (!diagnostic)
    return false;

  auto srcType = getFromType();
  auto dstType = getToType();

  emitDiagnostic(*diagnostic, srcType, dstType);

  if (isExpr<InOutExpr>(anchor))
    return true;

  if (srcType->isAny() && dstType->isAnyObject()) {
    emitDiagnostic(diag::any_as_anyobject_fixit)
        .fixItInsertAfter(getSourceRange().End, " as AnyObject");
  }

  return true;
}

bool MissingGenericArgumentsFailure::hasLoc(GenericTypeParamType *GP) const {
  return GP->getDecl()->getStartLoc().isValid();
}

bool MissingGenericArgumentsFailure::diagnoseAsError() {
  llvm::SmallDenseMap<TypeRepr *, SmallVector<GenericTypeParamType *, 4>>
      scopedParameters;

  auto isScoped =
      findArgumentLocations([&](TypeRepr *base, GenericTypeParamType *GP) {
        scopedParameters[base].push_back(GP);
      });

  if (!isScoped) {
    auto anchor = getAnchor();
    assert(anchor.is<Expr *>() || anchor.is<TypeRepr *>());
    return diagnoseForAnchor(anchor, Parameters);
  }

  bool diagnosed = false;
  for (const auto &scope : scopedParameters)
    diagnosed |= diagnoseForAnchor(scope.first, scope.second);
  return diagnosed;
}

bool MissingGenericArgumentsFailure::diagnoseForAnchor(
    ASTNode anchor, ArrayRef<GenericTypeParamType *> params) const {
  bool diagnosed = false;
  for (auto *GP : params)
    diagnosed |= diagnoseParameter(anchor, GP);

  if (!diagnosed)
    return false;

  auto *DC = getDeclContext();
  if (!DC)
    return true;

  if (auto *SD = dyn_cast<SubscriptDecl>(DC)) {
    emitDiagnosticAt(SD, diag::note_call_to_subscript, SD->getName());
    return true;
  }

  if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {
    if (isa<ConstructorDecl>(AFD)) {
      emitDiagnosticAt(AFD, diag::note_call_to_initializer);
    } else {
      emitDiagnosticAt(AFD,
                       AFD->isOperator() ? diag::note_call_to_operator
                                         : diag::note_call_to_func,
                       AFD->getName());
    }
    return true;
  }

  emitGenericSignatureNote(anchor);
  return true;
}

bool MissingGenericArgumentsFailure::diagnoseParameter(
    ASTNode anchor, GenericTypeParamType *GP) const {
  auto &solution = getSolution();
  auto loc = ::getLoc(anchor);

  auto *locator = getLocator();
  // Type variables associated with missing generic parameters are
  // going to be completely cut off from the rest of constraint system,
  // that's why we'd get two fixes in this case which is not ideal.
  if (locator->isForContextualType() &&
      llvm::count_if(solution.DefaultedConstraints,
                     [&GP](const ConstraintLocator *locator) {
                       return locator->getGenericParameter() == GP;
                     }) > 1) {
    return false;
  }

  if (auto *CE = getAsExpr<ExplicitCastExpr>(getRawAnchor())) {
    const auto castTo = getType(CE->getCastTypeRepr());
    auto *NTD = castTo->getAnyNominal();
    emitDiagnosticAt(loc, diag::unbound_generic_parameter_cast, GP,
                     NTD ? NTD->getDeclaredType() : castTo);
  } else {
    emitDiagnosticAt(loc, diag::unbound_generic_parameter, GP);
  }

  Type baseTyForNote;
  auto *DC = getDeclContext();
  if (!DC)
    return true;

  if (!hasLoc(GP))
    return true;

  if (auto *NTD =
          dyn_cast_or_null<NominalTypeDecl>(DC->getSelfNominalTypeDecl())) {
    baseTyForNote = NTD->getDeclaredType();
  } else if (auto *TAD = dyn_cast<TypeAliasDecl>(DC)) {
    baseTyForNote = TAD->getUnboundGenericType();
  } else {
    return true;
  }

  emitDiagnosticAt(GP->getDecl(), diag::archetype_declared_in_type, GP,
                   baseTyForNote);
  return true;
}

void MissingGenericArgumentsFailure::emitGenericSignatureNote(
    ASTNode anchor) const {
  auto &solution = getSolution();
  auto *paramDC = getDeclContext();

  if (!paramDC)
    return;

  auto *GTD = dyn_cast<GenericTypeDecl>(paramDC);
  if (!GTD || anchor.is<Expr *>())
    return;

  auto getParamDecl =
      [](const ConstraintLocator *locator) -> GenericTypeParamDecl * {
    return locator->isForGenericParameter()
               ? locator->getGenericParameter()->getDecl()
               : nullptr;
  };

  llvm::SmallDenseMap<GenericTypeParamDecl *, Type> params;
  for (auto &entry : solution.typeBindings) {
    auto *typeVar = entry.first;

    auto *GP = typeVar->getImpl().getGenericParameter();
    if (!GP)
      continue;

    auto type = resolveType(typeVar);
    assert(!type->is<TypeVariableType>());

    // If this is one of the defaulted parameter types, attempt
    // to emit placeholder for it instead of `Any`.
    if (llvm::any_of(solution.DefaultedConstraints,
                     [&](const ConstraintLocator *locator) {
                       return GP->getDecl() == getParamDecl(locator);
                     }))
      continue;

    params[GP->getDecl()] = type;
  }

  auto getPreferredType = [&](const GenericTypeParamDecl *GP) -> Type {
    auto type = params.find(GP);
    return (type == params.end()) ? Type() : type->second;
  };

  SmallString<64> paramsAsString;
  auto baseType = anchor.get<TypeRepr *>();
  if (TypeChecker::getDefaultGenericArgumentsString(paramsAsString, GTD,
                                                    getPreferredType)) {
    auto diagnostic = emitDiagnosticAt(
        baseType->getLoc(), diag::unbound_generic_parameter_explicit_fix);

    if (auto *genericTy = dyn_cast<GenericIdentTypeRepr>(baseType)) {
      // If some of the eneric arguments have been specified, we need to
      // replace existing signature with a new one.
      diagnostic.fixItReplace(genericTy->getAngleBrackets(), paramsAsString);
    } else {
      // Otherwise we can simply insert new generic signature.
      diagnostic.fixItInsertAfter(baseType->getEndLoc(), paramsAsString);
    }
  }
}

bool MissingGenericArgumentsFailure::findArgumentLocations(
    llvm::function_ref<void(TypeRepr *, GenericTypeParamType *)> callback) {
  using Callback = llvm::function_ref<void(TypeRepr *, GenericTypeParamType *)>;

  auto *const typeRepr = [this]() -> TypeRepr * {
    const auto anchor = getRawAnchor();
    if (const auto *TE = getAsExpr<TypeExpr>(anchor))
      return TE->getTypeRepr();
    else if (const auto *ECE = getAsExpr<ExplicitCastExpr>(anchor))
      return ECE->getCastTypeRepr();
    else
      return nullptr;
  }();

  if (!typeRepr)
    return false;

  struct AssociateMissingParams : public ASTWalker {
    llvm::SmallVector<GenericTypeParamType *, 4> Params;
    Callback Fn;

    AssociateMissingParams(ArrayRef<GenericTypeParamType *> params,
                           Callback callback)
        : Params(params.begin(), params.end()), Fn(callback) {}

    bool walkToTypeReprPre(TypeRepr *T) override {
      if (Params.empty())
        return false;

      auto *ident = dyn_cast<ComponentIdentTypeRepr>(T);
      if (!ident)
        return true;

      auto *decl = dyn_cast_or_null<GenericTypeDecl>(ident->getBoundDecl());
      if (!decl)
        return true;

      auto *paramList = decl->getGenericParams();
      if (!paramList)
        return true;

      // There could a situation like `S<S>()`, so we need to be
      // careful not to point at first `S` because it has all of
      // its generic parameters specified.
      if (auto *generic = dyn_cast<GenericIdentTypeRepr>(ident)) {
        if (paramList->size() == generic->getNumGenericArgs())
          return true;
      }

      for (auto *candidate : paramList->getParams()) {
        auto result =
            llvm::find_if(Params, [&](const GenericTypeParamType *param) {
              return candidate == param->getDecl();
            });

        if (result != Params.end()) {
          Fn(ident, *result);
          Params.erase(result);
        }
      }

      // Keep walking.
      return true;
    }

    bool allParamsAssigned() const { return Params.empty(); }

  } associator(Parameters, callback);

  typeRepr->walk(associator);
  return associator.allParamsAssigned();
}

SourceLoc SkipUnhandledConstructInResultBuilderFailure::getLoc() const {
  if (auto stmt = unhandled.dyn_cast<Stmt *>())
    return stmt->getStartLoc();

  return unhandled.get<Decl *>()->getLoc();
}

/// Determine whether the given "if" chain has a missing "else".
static bool hasMissingElseInChain(IfStmt *ifStmt) {
  if (!ifStmt->getElseStmt())
    return true;

  if (auto ifElse = dyn_cast<IfStmt>(ifStmt->getElseStmt()))
    return hasMissingElseInChain(ifElse);

  return false;
}

void SkipUnhandledConstructInResultBuilderFailure::diagnosePrimary(
    bool asNote) {
  if (auto stmt = unhandled.dyn_cast<Stmt *>()) {
    emitDiagnostic(asNote ? diag::note_result_builder_control_flow
                          : diag::result_builder_control_flow,
                   builder->getName());

    // Emit custom notes to help the user introduce the appropriate 'build'
    // functions.
    SourceLoc buildInsertionLoc;
    std::string stubIndent;
    Type componentType;
    std::tie(buildInsertionLoc, stubIndent, componentType) =
        determineResultBuilderBuildFixItInfo(builder);

    if (buildInsertionLoc.isInvalid()) {
      // Do nothing.
    } else if (isa<IfStmt>(stmt) && hasMissingElseInChain(cast<IfStmt>(stmt))) {
      auto diag = emitDiagnosticAt(
          builder->getLoc(), diag::result_builder_missing_build_optional,
          builder->getDeclaredInterfaceType());

      std::string fixItString;
      {
        llvm::raw_string_ostream out(fixItString);
        printResultBuilderBuildFunction(
            builder, componentType, ResultBuilderBuildFunction::BuildOptional,
            stubIndent, out);
      }

      diag.fixItInsert(buildInsertionLoc, fixItString);
    } else if (isa<SwitchStmt>(stmt) || isa<IfStmt>(stmt)) {
      auto diag = emitDiagnosticAt(
          builder->getLoc(), diag::result_builder_missing_build_either,
          builder->getDeclaredInterfaceType());

      std::string fixItString;
      {
        llvm::raw_string_ostream out(fixItString);
        printResultBuilderBuildFunction(
            builder, componentType,
            ResultBuilderBuildFunction::BuildEitherFirst,
            stubIndent, out);
        out << '\n';
        printResultBuilderBuildFunction(
            builder, componentType,
            ResultBuilderBuildFunction::BuildEitherSecond,
            stubIndent, out);
      }

      diag.fixItInsert(buildInsertionLoc, fixItString);
    } else if (isa<ForEachStmt>(stmt)) {
      auto diag = emitDiagnosticAt(
          builder->getLoc(), diag::result_builder_missing_build_array,
          builder->getDeclaredInterfaceType());

      std::string fixItString;
      {
        llvm::raw_string_ostream out(fixItString);
        printResultBuilderBuildFunction(
            builder, componentType, ResultBuilderBuildFunction::BuildArray,
            stubIndent, out);
      }

      diag.fixItInsert(buildInsertionLoc, fixItString);
    }
  } else {
    emitDiagnostic(asNote ? diag::note_result_builder_decl
                          : diag::result_builder_decl,
                   builder->getName());
  }
}

bool SkipUnhandledConstructInResultBuilderFailure::diagnoseAsError() {
  diagnosePrimary(/*asNote=*/false);
  emitDiagnosticAt(builder, diag::kind_declname_declared_here,
                   builder->getDescriptiveKind(), builder->getName());
  return true;
}

bool SkipUnhandledConstructInResultBuilderFailure::diagnoseAsNote() {
  diagnosePrimary(/*asNote=*/true);
  return true;
}

bool MutatingMemberRefOnImmutableBase::diagnoseAsError() {
  auto *anchor = castToExpr(getRawAnchor());
  auto baseExpr = getBaseExprFor(anchor);
  if (!baseExpr)
    return false;

  auto diagIDsubelt = diag::cannot_pass_rvalue_mutating_subelement;
  auto diagIDmember = diag::cannot_pass_rvalue_mutating;

  if (auto *storage = dyn_cast<AbstractStorageDecl>(Member)) {
    if (storage->isGetterMutating()) {
      diagIDsubelt = diag::cannot_pass_rvalue_mutating_getter_subelement;
      diagIDmember = diag::cannot_pass_rvalue_mutating_getter;
    }
  }

  const auto &solution = getSolution();
  AssignmentFailure failure(baseExpr, solution, anchor->getLoc(), diagIDsubelt,
                            diagIDmember);
  return failure.diagnoseAsError();
}

bool InvalidTupleSplatWithSingleParameterFailure::diagnoseAsError() {
  auto selectedOverload = getCalleeOverloadChoiceIfAvailable(getLocator());
  if (!selectedOverload || !selectedOverload->choice.isDecl())
    return false;

  auto *choice = selectedOverload->choice.getDecl();

  auto *argExpr = getArgumentListExprFor(getLocator());
  if (!argExpr)
    return false;

  using Substitution = std::pair<GenericTypeParamType *, Type>;
  llvm::SmallVector<Substitution, 8> substitutions;

  auto paramTy = restoreGenericParameters(
      ParamType, [&](GenericTypeParamType *GP, Type resolvedType) {
        substitutions.push_back(std::make_pair(GP, resolvedType));
      });

  DeclBaseName name = choice->getBaseName();

  std::string subsStr;
  if (!substitutions.empty()) {
    llvm::array_pod_sort(
        substitutions.begin(), substitutions.end(),
        [](const std::pair<GenericTypeParamType *, Type> *lhs,
           const std::pair<GenericTypeParamType *, Type> *rhs) -> int {
          GenericParamKey key1(lhs->first);
          GenericParamKey key2(rhs->first);
          return key1 < key2 ? -1 : (key1 == key2) ? 0 : 1;
        });

    subsStr += " [with ";
    interleave(
        substitutions,
        [&subsStr](const Substitution &substitution) {
          subsStr += substitution.first->getString();
          subsStr += " = ";
          subsStr += substitution.second->getString();
        },
        [&subsStr] { subsStr += ", "; });
    subsStr += ']';
  }

  auto diagnostic =
      name.isSpecial()
          ? emitDiagnosticAt(argExpr->getLoc(),
                             diag::single_tuple_parameter_mismatch_special,
                             choice->getDescriptiveKind(), paramTy, subsStr)
          : emitDiagnosticAt(
                argExpr->getLoc(), diag::single_tuple_parameter_mismatch_normal,
                choice->getDescriptiveKind(), name, paramTy, subsStr);

  auto newLeftParenLoc = argExpr->getStartLoc();
  if (auto *TE = dyn_cast<TupleExpr>(argExpr)) {
    auto firstArgLabel = TE->getElementName(0);
    // Cover situations like:
    //
    // func foo(x: (Int, Int)) {}
    // foo(x: 0, 1)
    //
    // Where left paren should be suggested after the label,
    // since the label belongs to the parameter itself.
    if (!firstArgLabel.empty()) {
      auto paramTuple = resolveType(ParamType)->castTo<TupleType>();
      // If the label of the first argument matches the one required
      // by the parameter it would be omitted from the fixed parameter type.
      if (!paramTuple->getElement(0).hasName())
        newLeftParenLoc = Lexer::getLocForEndOfToken(getASTContext().SourceMgr,
                                                     TE->getElementNameLoc(0));
    }
  }

  diagnostic.highlight(argExpr->getSourceRange())
      .fixItInsertAfter(newLeftParenLoc, "(")
      .fixItInsert(argExpr->getEndLoc(), ")");

  return true;
}

bool ThrowingFunctionConversionFailure::diagnoseAsError() {
  emitDiagnostic(diag::throws_functiontype_mismatch, getFromType(),
                 getToType());
  return true;
}

bool AsyncFunctionConversionFailure::diagnoseAsError() {
  emitDiagnostic(diag::async_functiontype_mismatch, getFromType(),
                 getToType());
  return true;
}

bool InOutConversionFailure::diagnoseAsError() {
  auto *locator = getLocator();
  auto path = locator->getPath();

  if (!path.empty() &&
      path.back().getKind() == ConstraintLocator::FunctionArgument) {
    if (auto argApplyInfo = getFunctionArgApplyInfo(locator)) {
      emitDiagnostic(diag::cannot_convert_argument_value,
                     argApplyInfo->getArgType(), argApplyInfo->getParamType());
    } else {
      assert(locator->findLast<LocatorPathElt::ContextualType>());
      auto anchor = getAnchor();
      auto contextualType = getContextualType(anchor);
      auto purpose = getContextualTypePurpose();
      auto diagnostic = getDiagnosticFor(purpose, contextualType);

      if (!diagnostic)
        return false;

      emitDiagnostic(*diagnostic, getType(anchor), contextualType);
    }

    return true;
  }

  emitDiagnostic(diag::cannot_pass_rvalue_inout_converted, getFromType(),
                 getToType());
  fixItChangeArgumentType();
  return true;
}

void InOutConversionFailure::fixItChangeArgumentType() const {
  auto *argExpr = castToExpr(getAnchor());
  auto *DC = getDC();

  if (auto *IOE = dyn_cast<InOutExpr>(argExpr))
    argExpr = IOE->getSubExpr();

  auto *DRE = dyn_cast<DeclRefExpr>(argExpr);
  if (!DRE)
    return;

  auto *VD = dyn_cast_or_null<VarDecl>(DRE->getDecl());
  if (!VD)
    return;

  // Don't emit for non-local variables.
  // (But in script-mode files, we consider module-scoped
  // variables in the same file to be local variables.)
  auto VDC = VD->getDeclContext();
  bool isLocalVar = VDC->isLocalContext();
  if (!isLocalVar && VDC->isModuleScopeContext()) {
    auto argFile = DC->getParentSourceFile();
    auto varFile = VDC->getParentSourceFile();
    isLocalVar = (argFile == varFile && argFile->isScriptMode());
  }
  if (!isLocalVar)
    return;

  auto actualType = getFromType();
  auto neededType = getToType();

  SmallString<32> scratch;
  SourceLoc endLoc;   // Filled in if we decide to diagnose this
  SourceLoc startLoc; // Left invalid if we're inserting

  auto isSimpleTypelessPattern = [](Pattern *P) -> bool {
    if (auto VP = dyn_cast_or_null<BindingPattern>(P))
      P = VP->getSubPattern();
    return P && isa<NamedPattern>(P);
  };

  auto typeRange = VD->getTypeSourceRangeForDiagnostics();
  if (typeRange.isValid()) {
    startLoc = typeRange.Start;
    endLoc = typeRange.End;
  } else if (isSimpleTypelessPattern(VD->getParentPattern())) {
    endLoc = VD->getNameLoc();
    scratch += ": ";
  }

  if (endLoc.isInvalid())
    return;

  scratch += neededType.getString();

  // Adjust into the location where we actually want to insert
  endLoc = Lexer::getLocForEndOfToken(getASTContext().SourceMgr, endLoc);

  // Since we already adjusted endLoc, this will turn an insertion
  // into a zero-character replacement.
  if (!startLoc.isValid())
    startLoc = endLoc;

  emitDiagnosticAt(VD, diag::inout_change_var_type_if_possible, actualType,
                   neededType)
      .fixItReplaceChars(startLoc, endLoc, scratch);
}

bool ArgumentMismatchFailure::diagnoseAsError() {
  if (diagnoseMisplacedMissingArgument())
    return true;

  if (diagnoseConversionToBool())
    return true;

  if (diagnoseArchetypeMismatch())
    return true;

  if (diagnosePatternMatchingMismatch())
    return true;

  if (diagnoseUseOfReferenceEqualityOperator())
    return true;

  if (diagnosePropertyWrapperMismatch())
    return true;

  if (diagnoseTrailingClosureMismatch())
    return true;

  auto argType = getFromType();
  auto paramType = getToType();

  if (paramType->isAnyObject()) {
    emitDiagnostic(diag::cannot_convert_argument_value_anyobject, argType,
                   paramType);
    return true;
  }

  Diag<Type, Type> diagnostic = diag::cannot_convert_argument_value;

  // If parameter type is a protocol value, let's says that
  // argument doesn't conform to a give protocol.
  if (paramType->isExistentialType())
    diagnostic = diag::cannot_convert_argument_value_protocol;

  auto diag = emitDiagnostic(diagnostic, argType, paramType);

  // If argument is an l-value type and parameter is a pointer type,
  // let's match up its element type to the argument to see whether
  // it would be appropriate to suggest adding `&`.
  auto argument = getAnchor();
  if (getType(argument, /*wantRValue=*/false)->is<LValueType>()) {
    auto elementTy = paramType->getAnyPointerElementType();
    if (elementTy && argType->isEqual(elementTy)) {
      diag.fixItInsert(::getSourceRange(argument).Start, "&");
      return true;
    }
  }

  tryFixIts(diag);
  return true;
}

bool ArgumentMismatchFailure::diagnoseAsNote() {
  auto *locator = getLocator();
  if (auto *callee = getCallee()) {
    emitDiagnosticAt(
        callee, diag::candidate_has_invalid_argument_at_position, getToType(),
        getParamPosition(),
        locator->isLastElement<LocatorPathElt::LValueConversion>());
    return true;
  }

  return false;
}

bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const {
  auto *locator = getLocator();

  if (!isArgumentOfReferenceEqualityOperator(locator))
    return false;

  auto *binaryOp = castToExpr<BinaryExpr>(getRawAnchor());
  auto *lhs = binaryOp->getArg()->getElement(0);
  auto *rhs = binaryOp->getArg()->getElement(1);

  auto name = *getOperatorName(binaryOp->getFn());

  auto lhsType = getType(lhs);
  auto rhsType = getType(rhs);

  // If both arguments where incorrect e.g. both are function types,
  // let's avoid producing a diagnostic second time, because first
  // one would cover both arguments.
  if (getAsExpr(getAnchor()) == rhs && rhsType->is<FunctionType>()) {
    auto *argLoc = getConstraintLocator(
        binaryOp,
        {ConstraintLocator::ApplyArgument,
         LocatorPathElt::ApplyArgToParam(0, 0, getParameterFlagsAtIndex(0))});

    if (llvm::any_of(getSolution().Fixes, [&argLoc](const ConstraintFix *fix) {
          return fix->getLocator() == argLoc;
        }))
      return true;
  }

  // Regardless of whether the type has reference or value semantics,
  // comparison with nil is illegal, albeit for different reasons spelled
  // out by the diagnosis.
  if (isa<NilLiteralExpr>(lhs) || isa<NilLiteralExpr>(rhs)) {
    std::string revisedName = std::string(name);
    revisedName.pop_back();

    auto loc = binaryOp->getLoc();
    auto nonNilType = isa<NilLiteralExpr>(lhs) ? rhsType : lhsType;
    auto nonNilExpr = isa<NilLiteralExpr>(lhs) ? rhs : lhs;

    // If we made it here, then we're trying to perform a comparison with
    // reference semantics rather than value semantics. The fixit will
    // lop off the extra '=' in the operator.
    if (nonNilType->getOptionalObjectType()) {
      emitDiagnosticAt(
          loc, diag::value_type_comparison_with_nil_illegal_did_you_mean,
          nonNilType)
          .fixItReplace(loc, revisedName);
    } else {
      emitDiagnosticAt(loc, diag::value_type_comparison_with_nil_illegal,
                       nonNilType)
          .highlight(nonNilExpr->getSourceRange());
    }

    return true;
  }

  if (lhsType->is<FunctionType>() || rhsType->is<FunctionType>()) {
    emitDiagnosticAt(binaryOp->getLoc(), diag::cannot_reference_compare_types,
                     name.str(), lhsType, rhsType)
        .highlight(lhs->getSourceRange())
        .highlight(rhs->getSourceRange());
    return true;
  }

  return false;
}

bool ArgumentMismatchFailure::diagnosePatternMatchingMismatch() const {
  if (!isArgumentOfPatternMatchingOperator(getLocator()))
    return false;

  auto *op = castToExpr<BinaryExpr>(getRawAnchor());
  auto *lhsExpr = op->getArg()->getElement(0);
  auto *rhsExpr = op->getArg()->getElement(1);

  auto lhsType = getType(lhsExpr);
  auto rhsType = getType(rhsExpr);

  auto diagnostic =
      lhsType->is<UnresolvedType>()
          ? emitDiagnostic(
                diag::cannot_match_unresolved_expr_pattern_with_value, rhsType)
          : emitDiagnostic(diag::cannot_match_expr_pattern_with_value, lhsType,
                           rhsType);

  diagnostic.highlight(lhsExpr->getSourceRange());
  diagnostic.highlight(rhsExpr->getSourceRange());

  if (auto optUnwrappedType = rhsType->getOptionalObjectType()) {
    if (lhsType->isEqual(optUnwrappedType)) {
      diagnostic.fixItInsertAfter(lhsExpr->getEndLoc(), "?");
    }
  }

  return true;
}

bool ArgumentMismatchFailure::diagnoseArchetypeMismatch() const {
  auto *argTy = getFromType()->getAs<ArchetypeType>();
  auto *paramTy = getToType()->getAs<ArchetypeType>();

  if (!(argTy && paramTy))
    return false;

  // Produce this diagnostic only if the names
  // of the generic parameters are the same.
  if (argTy->getName() != paramTy->getName())
    return false;

  auto getGenericTypeDecl = [&](ArchetypeType *archetype) -> ValueDecl * {
    auto paramType = archetype->getInterfaceType();

    if (auto *GTPT = paramType->getAs<GenericTypeParamType>())
      return GTPT->getDecl();

    if (auto *DMT = paramType->getAs<DependentMemberType>())
      return DMT->getAssocType();

    return nullptr;
  };

  auto *argDecl = getGenericTypeDecl(argTy);
  auto *paramDecl = getGenericTypeDecl(paramTy);

  if (!(paramDecl && argDecl))
    return false;

  emitDiagnostic(diag::cannot_convert_argument_value_generic, argTy,
                 describeGenericType(argDecl), paramTy,
                 describeGenericType(paramDecl));

  emitDiagnosticAt(argDecl, diag::descriptive_generic_type_declared_here,
                   describeGenericType(argDecl, true));

  emitDiagnosticAt(paramDecl, diag::descriptive_generic_type_declared_here,
                   describeGenericType(paramDecl, true));

  return true;
}

bool ArgumentMismatchFailure::diagnoseMisplacedMissingArgument() const {
  const auto &solution = getSolution();
  auto *locator = getLocator();

  if (!MissingArgumentsFailure::isMisplacedMissingArgument(solution, locator))
    return false;

  // Assign new type variable to a type of a parameter.
  auto *fnType = getFnType();
  const auto &param = fnType->getParams()[0];

  auto anchor = getRawAnchor();

  MissingArgumentsFailure failure(
      solution, {SynthesizedArg{0, param}},
      getConstraintLocator(anchor, ConstraintLocator::ApplyArgument));

  return failure.diagnoseSingleMissingArgument();
}

bool ArgumentMismatchFailure::diagnosePropertyWrapperMismatch() const {
  auto argType = getFromType();
  auto paramType = getToType();

  // Verify that this is an implicit call to a property wrapper initializer
  // in a form of `init(wrappedValue:)` or deprecated `init(initialValue:)`.
  auto *call = getAsExpr<CallExpr>(getRawAnchor());
  if (!(call && call->isImplicit() && isa<TypeExpr>(call->getFn()) &&
        call->getNumArguments() == 1 &&
        (call->getArgumentLabels().front() == getASTContext().Id_wrappedValue ||
         call->getArgumentLabels().front() == getASTContext().Id_initialValue)))
    return false;

  auto argExpr = cast<TupleExpr>(call->getArg())->getElement(0);
  // If this is an attempt to initialize property wrapper with opaque value
  // of error type, let's just ignore that problem since original mismatch
  // has been diagnosed already.
  if (argExpr->isImplicit() && isa<OpaqueValueExpr>(argExpr) &&
      argType->is<ErrorType>())
    return true;

  emitDiagnostic(diag::cannot_convert_initializer_value, argType, paramType);
  return true;
}

bool ArgumentMismatchFailure::diagnoseTrailingClosureMismatch() const {
  if (!Info.isTrailingClosure())
    return false;

  auto paramType = getToType();
  if (paramType->lookThroughAllOptionalTypes()->is<AnyFunctionType>())
    return false;

  emitDiagnostic(diag::trailing_closure_bad_param, paramType)
      .highlight(getSourceRange());

  if (auto overload = getCalleeOverloadChoiceIfAvailable(getLocator())) {
    if (auto *decl = overload->choice.getDeclOrNull()) {
      emitDiagnosticAt(decl, diag::decl_declared_here, decl->getName());
    }
  }

  return true;
}

void ExpandArrayIntoVarargsFailure::tryDropArrayBracketsFixIt(
    const Expr *anchor) const {
  // If this is an array literal, offer to remove the brackets and pass the
  // elements directly as variadic arguments.
  if (auto *arrayExpr = dyn_cast<ArrayExpr>(anchor)) {
    auto diag = emitDiagnosticAt(arrayExpr->getLoc(),
                                 diag::suggest_pass_elements_directly);
    diag.fixItRemove(arrayExpr->getLBracketLoc())
        .fixItRemove(arrayExpr->getRBracketLoc());
    // Handle the case where the array literal has a trailing comma.
    if (arrayExpr->getNumCommas() == arrayExpr->getNumElements())
      diag.fixItRemove(arrayExpr->getCommaLocs().back());
  }
}

bool ExpandArrayIntoVarargsFailure::diagnoseAsError() {
  if (auto *anchor = getAsExpr(getAnchor())) {
    emitDiagnostic(diag::cannot_convert_array_to_variadic, getFromType(),
                   getToType());
    tryDropArrayBracketsFixIt(anchor);
    // TODO: Array splat fix-it once that's supported.
    return true;
  }
  return false;
}

bool ExpandArrayIntoVarargsFailure::diagnoseAsNote() {
  auto overload = getCalleeOverloadChoiceIfAvailable(getLocator());
  auto *anchor = getAsExpr(getAnchor());
  if (!overload || !anchor)
    return false;

  if (auto chosenDecl = overload->choice.getDeclOrNull()) {
    emitDiagnosticAt(chosenDecl, diag::candidate_would_match_array_to_variadic,
                     getToType());
    tryDropArrayBracketsFixIt(anchor);
    return true;
  }
  return false;
}

bool ExtraneousCallFailure::diagnoseAsError() {
  auto anchor = getAnchor();
  auto *locator = getLocator();

  // If this is something like `foo()` where `foo` is a variable
  // or a property, let's suggest dropping `()`.
  auto removeParensFixIt = [&](InFlightDiagnostic &diagnostic) {
    auto *argLoc =
        getConstraintLocator(getRawAnchor(), ConstraintLocator::ApplyArgument);

    if (auto *TE = getAsExpr<TupleExpr>(simplifyLocatorToAnchor(argLoc))) {
      if (TE->getNumElements() == 0) {
        diagnostic.fixItRemove(TE->getSourceRange());
      }
    }
  };

  if (auto overload = getCalleeOverloadChoiceIfAvailable(locator)) {
    if (auto *decl = overload->choice.getDeclOrNull()) {
      if (auto *enumCase = dyn_cast<EnumElementDecl>(decl)) {
        auto diagnostic =
            emitDiagnostic(diag::unexpected_arguments_in_enum_case,
                           enumCase->getBaseIdentifier());
        removeParensFixIt(diagnostic);
        return true;
      }
    }
  }

  if (auto *UDE = getAsExpr<UnresolvedDotExpr>(anchor)) {
    auto *baseExpr = UDE->getBase();
    auto *call = castToExpr<CallExpr>(getRawAnchor());

    if (getType(baseExpr)->isAnyObject()) {
      emitDiagnostic(diag::cannot_call_with_params,
                     UDE->getName().getBaseName().userFacingName(),
                     getType(call->getArg())->getString(),
                     isa<TypeExpr>(baseExpr));
      return true;
    }
  }

  auto diagnostic =
      emitDiagnostic(diag::cannot_call_non_function_value, getType(anchor));
  removeParensFixIt(diagnostic);
  return true;
}

void NonEphemeralConversionFailure::emitSuggestionNotes() const {
  auto getPointerKind = [](Type ty) -> PointerTypeKind {
    PointerTypeKind pointerKind;
    auto pointeeType = ty->lookThroughSingleOptionalType()
                         ->getAnyPointerElementType(pointerKind);
    assert(pointeeType && "Expected a pointer!");
    (void)pointeeType;

    return pointerKind;
  };

  // This must stay in sync with diag::ephemeral_use_array_with_unsafe_buffer
  // and diag::ephemeral_use_with_unsafe_pointer.
  enum AlternativeKind {
    AK_Raw = 0,
    AK_MutableRaw,
    AK_Typed,
    AK_MutableTyped,
  };

  auto getAlternativeKind = [&]() -> Optional<AlternativeKind> {
    switch (getPointerKind(getParamType())) {
    case PTK_UnsafeRawPointer:
      return AK_Raw;
    case PTK_UnsafeMutableRawPointer:
      return AK_MutableRaw;
    case PTK_UnsafePointer:
      return AK_Typed;
    case PTK_UnsafeMutablePointer:
      return AK_MutableTyped;
    case PTK_AutoreleasingUnsafeMutablePointer:
      return None;
    }
    llvm_unreachable("invalid pointer kind");
  };

  // First emit a note about the implicit conversion only lasting for the
  // duration of the call.
  auto *argExpr = getArgExpr();
  emitDiagnosticAt(
      argExpr->getLoc(), diag::ephemeral_pointer_argument_conversion_note,
      getArgType(), getParamType(), getCallee(), getCalleeFullName())
      .highlight(argExpr->getSourceRange());

  // Then try to find a suitable alternative.
  switch (ConversionKind) {
  case ConversionRestrictionKind::ArrayToPointer: {
    // Don't suggest anything for optional arrays, as there's currently no
    // direct alternative.
    if (getArgType()->getOptionalObjectType())
      break;

    // We can suggest using withUnsafe[Mutable][Bytes/BufferPointer].
    if (auto alternative = getAlternativeKind())
      emitDiagnosticAt(argExpr->getLoc(),
                       diag::ephemeral_use_array_with_unsafe_buffer,
                       *alternative);
    break;
  }
  case ConversionRestrictionKind::StringToPointer: {
    // Don't suggest anything for optional strings, as there's currently no
    // direct alternative.
    if (getArgType()->getOptionalObjectType())
      break;

    // We can suggest withCString as long as the resulting pointer is
    // immutable.
    switch (getPointerKind(getParamType())) {
    case PTK_UnsafePointer:
    case PTK_UnsafeRawPointer:
      emitDiagnosticAt(argExpr->getLoc(),
                       diag::ephemeral_use_string_with_c_string);
      break;
    case PTK_UnsafeMutableRawPointer:
    case PTK_UnsafeMutablePointer:
    case PTK_AutoreleasingUnsafeMutablePointer:
      // There's nothing really sensible we can suggest for a mutable pointer.
      break;
    }
    break;
  }
  case ConversionRestrictionKind::InoutToPointer:
    // For an arbitrary inout-to-pointer, we can suggest
    // withUnsafe[Mutable][Bytes/Pointer].
    if (auto alternative = getAlternativeKind())
      emitDiagnosticAt(argExpr->getLoc(),
                       diag::ephemeral_use_with_unsafe_pointer, *alternative);
    break;
  case ConversionRestrictionKind::DeepEquality:
  case ConversionRestrictionKind::Superclass:
  case ConversionRestrictionKind::Existential:
  case ConversionRestrictionKind::MetatypeToExistentialMetatype:
  case ConversionRestrictionKind::ExistentialMetatypeToMetatype:
  case ConversionRestrictionKind::ValueToOptional:
  case ConversionRestrictionKind::OptionalToOptional:
  case ConversionRestrictionKind::ClassMetatypeToAnyObject:
  case ConversionRestrictionKind::ExistentialMetatypeToAnyObject:
  case ConversionRestrictionKind::ProtocolMetatypeToProtocolClass:
  case ConversionRestrictionKind::PointerToPointer:
  case ConversionRestrictionKind::ArrayUpcast:
  case ConversionRestrictionKind::DictionaryUpcast:
  case ConversionRestrictionKind::SetUpcast:
  case ConversionRestrictionKind::HashableToAnyHashable:
  case ConversionRestrictionKind::CFTollFreeBridgeToObjC:
  case ConversionRestrictionKind::ObjCTollFreeBridgeToCF:
    llvm_unreachable("Expected an ephemeral conversion!");
  }
}

bool NonEphemeralConversionFailure::diagnosePointerInit() const {
  auto *constructor = dyn_cast_or_null<ConstructorDecl>(getCallee());
  if (!constructor)
    return false;

  auto constructedTy = getFnType()->getResult();

  // Strip off a level of optionality if we have a failable initializer.
  if (constructor->isFailable())
    constructedTy = constructedTy->getOptionalObjectType();

  // This must stay in sync with diag::cannot_construct_dangling_pointer.
  enum ConstructorKind {
    CK_Pointer = 0,
    CK_BufferPointer,
  };

  // Consider OpaquePointer as well as the other kinds of pointers.
  auto isConstructingPointer =
      constructedTy->getAnyPointerElementType() ||
      constructedTy->getAnyNominal() == getASTContext().getOpaquePointerDecl();

  ConstructorKind constructorKind;
  auto parameterCount = constructor->getParameters()->size();
  if (isConstructingPointer && parameterCount == 1) {
    constructorKind = CK_Pointer;
  } else if (constructedTy->getAnyBufferPointerElementType() &&
             parameterCount == 2) {
    constructorKind = CK_BufferPointer;
  } else {
    return false;
  }

  auto diagID = DowngradeToWarning
                    ? diag::cannot_construct_dangling_pointer_warning
                    : diag::cannot_construct_dangling_pointer;

  auto anchor = getRawAnchor();
  emitDiagnosticAt(::getLoc(anchor), diagID, constructedTy, constructorKind)
      .highlight(::getSourceRange(anchor));

  emitSuggestionNotes();
  return true;
}

bool NonEphemeralConversionFailure::diagnoseAsNote() {
  // We can only emit a useful note if we have a callee.
  if (auto *callee = getCallee()) {
    emitDiagnosticAt(callee, diag::candidate_performs_illegal_ephemeral_conv,
                     getParamPosition());
    return true;
  }
  return false;
}

bool NonEphemeralConversionFailure::diagnoseAsError() {
  // Emit a specialized diagnostic for
  // Unsafe[Mutable][Raw]Pointer.init([mutating]:) &
  // Unsafe[Mutable][Raw]BufferPointer.init(start:count:).
  if (diagnosePointerInit())
    return true;

  // Otherwise, emit a more general diagnostic.
  SmallString<8> scratch;
  auto argDesc = getArgDescription(scratch);

  auto *argExpr = getArgExpr();
  if (isa<InOutExpr>(argExpr)) {
    auto diagID = DowngradeToWarning
                      ? diag::cannot_use_inout_non_ephemeral_warning
                      : diag::cannot_use_inout_non_ephemeral;

    emitDiagnosticAt(argExpr->getLoc(), diagID, argDesc, getCallee(),
                     getCalleeFullName())
        .highlight(argExpr->getSourceRange());
  } else {
    auto diagID = DowngradeToWarning
                      ? diag::cannot_pass_type_to_non_ephemeral_warning
                      : diag::cannot_pass_type_to_non_ephemeral;

    emitDiagnosticAt(argExpr->getLoc(), diagID, getArgType(), argDesc,
                     getCallee(), getCalleeFullName())
        .highlight(argExpr->getSourceRange());
  }
  emitSuggestionNotes();
  return true;
}

bool AssignmentTypeMismatchFailure::diagnoseMissingConformance() const {
  auto srcType = getFromType();
  auto dstType = getToType()->lookThroughAllOptionalTypes();

  llvm::SmallPtrSet<ProtocolDecl *, 4> srcMembers;
  llvm::SmallPtrSet<ProtocolDecl *, 4> dstMembers;

  auto retrieveProtocols = [](Type type,
                              llvm::SmallPtrSetImpl<ProtocolDecl *> &members) {
    if (auto *protocol = type->getAs<ProtocolType>())
      members.insert(protocol->getDecl());

    if (auto *composition = type->getAs<ProtocolCompositionType>()) {
      for (auto member : composition->getMembers()) {
        if (auto *protocol = member->getAs<ProtocolType>())
          members.insert(protocol->getDecl());
      }
    }
  };

  retrieveProtocols(srcType, srcMembers);
  retrieveProtocols(dstType, dstMembers);

  if (srcMembers.empty() || dstMembers.empty())
    return false;

  // Let's check whether there is an overlap between source and destination.
  for (auto *member : srcMembers)
    dstMembers.erase(member);

  if (dstMembers.size() == 1)
    dstType = (*dstMembers.begin())->getDeclaredType();

  emitDiagnostic(diag::cannot_convert_assign_protocol, srcType, dstType);
  return true;
}

bool AssignmentTypeMismatchFailure::diagnoseAsError() {
  if (diagnoseMissingConformance())
    return true;

  return ContextualFailure::diagnoseAsError();
}

bool AssignmentTypeMismatchFailure::diagnoseAsNote() {
  auto anchor = getAnchor();

  if (auto overload =
          getCalleeOverloadChoiceIfAvailable(getConstraintLocator(anchor))) {
    if (auto *decl = overload->choice.getDeclOrNull()) {
      emitDiagnosticAt(decl,
                       diag::cannot_convert_candidate_result_to_contextual_type,
                       decl->getName(), getFromType(), getToType());
      return true;
    }
  }

  return false;
}

bool MissingContextualBaseInMemberRefFailure::diagnoseAsError() {
  auto *anchor = castToExpr(getAnchor());
  // Member reference could be wrapped into a number of parens
  // e.g. `((.foo))`.
  auto *parentExpr = findParentExpr(anchor);

  // Look through immediate call of unresolved member (e.g., `.foo(0)`).
  if (parentExpr && isa<CallExpr>(parentExpr))
    parentExpr = findParentExpr(parentExpr);

  // FIXME: We should probably look through the entire member chain so that
  // something like `let _ = .foo().bar` gets the "no contextual type" error
  // rather than the "Cannot infer contextual base" error.
  UnresolvedMemberChainResultExpr *resultExpr = nullptr;
  if (parentExpr && isa<UnresolvedMemberChainResultExpr>(parentExpr)) {
    resultExpr = cast<UnresolvedMemberChainResultExpr>(parentExpr);
    parentExpr = findParentExpr(parentExpr);
  }

  do {
    // If we have found something which isn't a paren let's stop,
    // otherwise let's keep unwrapping until there are either no
    // more parens or no more parents...
    if (!parentExpr || !isa<ParenExpr>(parentExpr))
      break;
  } while ((parentExpr = findParentExpr(parentExpr)));

  auto diagnostic = parentExpr || (resultExpr && getContextualType(resultExpr))
                        ? diag::cannot_infer_base_of_unresolved_member
                        : diag::unresolved_member_no_inference;

  emitDiagnostic(diagnostic, MemberName).highlight(getSourceRange());
  return true;
}

bool UnableToInferClosureParameterType::diagnoseAsError() {
  auto *closure = castToExpr<ClosureExpr>(getRawAnchor());

  // Let's check whether this closure is an argument to
  // a call which couldn't be properly resolved e.g.
  // missing  member or invalid contextual reference and
  // if so let's not diagnose this problem because main
  // issue here is inability to establish context for
  // closure inference.
  //
  // TODO(diagnostics): Once we gain an ability to determine
  // originating source of type holes this check could be
  // significantly simplified.
  {
    auto &solution = getSolution();

    // If there is a contextual mismatch associated with this
    // closure, let's not diagnose any parameter type issues.
    if (hasFixFor(solution, getConstraintLocator(
                                closure, LocatorPathElt::ContextualType())))
      return false;

    if (auto *parentExpr = findParentExpr(closure)) {
      while (parentExpr &&
             (isa<TupleExpr>(parentExpr) || isa<ParenExpr>(parentExpr))) {
        parentExpr = findParentExpr(parentExpr);
      }

      if (parentExpr) {
        // Missing or invalid member reference in call.
        if (auto *AE = dyn_cast<ApplyExpr>(parentExpr)) {
          if (getType(AE->getFn())->is<UnresolvedType>())
            return false;
        }

        // Any fix anchored on parent expression makes it unnecessary
        // to diagnose unability to infer parameter type because it's
        // an indication that proper context couldn't be established to
        // resolve the closure.
        ASTNode parentNode(parentExpr);
        if (llvm::any_of(solution.Fixes,
                         [&parentNode](const ConstraintFix *fix) -> bool {
                           return fix->getAnchor() == parentNode;
                         }))
          return false;
      }
    }
  }

  auto paramIdx = getLocator()
                      ->castLastElementTo<LocatorPathElt::TupleElement>()
                      .getIndex();

  auto *PD = closure->getParameters()->get(paramIdx);

  llvm::SmallString<16> id;
  llvm::raw_svector_ostream OS(id);

  if (PD->isAnonClosureParam()) {
    OS << "$" << paramIdx;
  } else {
    OS << "'" << PD->getParameterName() << "'";
  }

  auto loc = PD->isAnonClosureParam() ? getLoc() : PD->getLoc();
  emitDiagnosticAt(loc, diag::cannot_infer_closure_parameter_type, OS.str());
  return true;
}

bool UnableToInferClosureReturnType::diagnoseAsError() {
  auto *closure = castToExpr<ClosureExpr>(getRawAnchor());

  auto diagnostic = emitDiagnostic(diag::cannot_infer_closure_result_type,
                                   closure->hasSingleExpressionBody());

  // If there is a location for an 'in' token, then the argument list was
  // specified somehow but no return type was.  Insert a "-> ReturnType "
  // before the in token.
  if (closure->getInLoc().isValid()) {
    diagnostic.fixItInsert(closure->getInLoc(),
                           diag::insert_closure_return_type_placeholder,
                           /*argListSpecified=*/false);
  } else if (closure->getParameters()->size() == 0) {
    // Otherwise, the closure must take zero arguments.
    //
    // As such, we insert " () -> ReturnType in " right after the '{' that
    // starts the closure body.
    diagnostic.fixItInsertAfter(closure->getBody()->getLBraceLoc(),
                                diag::insert_closure_return_type_placeholder,
                                /*argListSpecified=*/true);
  }

  return true;
}

static std::pair<StringRef, StringRef>
getImportModuleAndDefaultType(const ASTContext &ctx,
                              const ObjectLiteralExpr *expr) {
  const auto &target = ctx.LangOpts.Target;

  switch (expr->getLiteralKind()) {
    case ObjectLiteralExpr::colorLiteral: {
      if (target.isMacOSX()) {
        return std::make_pair("AppKit", "NSColor");
      } else if (target.isiOS() || target.isTvOS()) {
        return std::make_pair("UIKit", "UIColor");
      }
      break;
    }

    case ObjectLiteralExpr::imageLiteral: {
      if (target.isMacOSX()) {
        return std::make_pair("AppKit", "NSImage");
      } else if (target.isiOS() || target.isTvOS()) {
        return std::make_pair("UIKit", "UIImage");
      }
      break;
    }

    case ObjectLiteralExpr::fileLiteral: {
      return std::make_pair("Foundation", "URL");
    }
  }

  return std::make_pair("", "");
}

SourceLoc UnableToInferProtocolLiteralType::getLoc() const {
  return ::getLoc(getRawAnchor());
}

bool UnableToInferProtocolLiteralType::diagnoseAsError() {
  auto &ctx = getASTContext();
  auto *expr = castToExpr<ObjectLiteralExpr>(getRawAnchor());

  StringRef importModule;
  StringRef importDefaultTypeName;
  std::tie(importModule, importDefaultTypeName) =
      getImportModuleAndDefaultType(ctx, expr);

  auto plainName = expr->getLiteralKindPlainName();
  emitDiagnostic(diag::object_literal_default_type_missing, plainName);
  if (!importModule.empty()) {
    emitDiagnostic(diag::object_literal_resolve_import, importModule,
                   importDefaultTypeName, plainName);
  }

  return true;
}

bool MissingQuialifierInMemberRefFailure::diagnoseAsError() {
  auto selectedOverload = getOverloadChoiceIfAvailable(getLocator());
  if (!selectedOverload)
    return false;

  auto *UDE = castToExpr<UnresolvedDotExpr>(getRawAnchor());

  auto baseType = getType(UDE->getBase());

  auto methodKind = baseType->isAnyExistentialType()
                        ? DescriptiveDeclKind::StaticMethod
                        : DescriptiveDeclKind::Method;

  auto choice = selectedOverload->choice.getDeclOrNull();
  if (!choice)
    return false;

  auto *DC = choice->getDeclContext();
  if (!(DC->isModuleContext() || DC->isModuleScopeContext())) {
    emitDiagnostic(diag::member_shadows_function, UDE->getName(), methodKind,
                   choice->getDescriptiveKind(), choice->getName());
    return true;
  }

  auto qualifier = DC->getParentModule()->getName();

  emitDiagnostic(diag::member_shadows_global_function, UDE->getName(),
                 methodKind, choice->getDescriptiveKind(),
                 choice->getName(), qualifier);

  SmallString<32> namePlusDot = qualifier.str();
  namePlusDot.push_back('.');

  emitDiagnostic(diag::fix_unqualified_access_top_level_multi, namePlusDot,
                 choice->getDescriptiveKind(), qualifier)
      .fixItInsert(UDE->getStartLoc(), namePlusDot);

  emitDiagnosticAt(choice, diag::decl_declared_here, choice->getName());
  return true;
}

bool CoercionAsForceCastFailure::diagnoseAsError() {
  emitDiagnostic(diag::coercion_may_fail_warning, getFromType(), getToType())
      .highlight(getSourceRange());
  return true;
}

bool KeyPathRootTypeMismatchFailure::diagnoseAsError() {
  auto locator = getLocator();
  assert(locator->isKeyPathRoot() && "Expected a key path root");
  
  auto baseType = getFromType();
  auto rootType = getToType();

  emitDiagnostic(diag::expr_keypath_root_type_mismatch,
                 rootType, baseType);
  return true;
}

bool MultiArgFuncKeyPathFailure::diagnoseAsError() {
  // Diagnose use a keypath where a function with multiple arguments is expected
  emitDiagnostic(diag::expr_keypath_multiparam_func_conversion,
                 resolveType(functionType));
  return true;
}

bool UnableToInferKeyPathRootFailure::diagnoseAsError() {
  assert(isExpr<KeyPathExpr>(getAnchor()) && "Expected key path expression");
  auto &ctx = getASTContext();
  auto contextualType = getContextualType(getAnchor());
  auto *keyPathExpr = castToExpr<KeyPathExpr>(getAnchor());

  auto emitKeyPathDiagnostic = [&]() {
    if (contextualType &&
        contextualType->getAnyNominal() == ctx.getAnyKeyPathDecl()) {
      return emitDiagnostic(
          diag::cannot_infer_keypath_root_anykeypath_context);
    }
    return emitDiagnostic(
        diag::cannot_infer_contextual_keypath_type_specify_root);
  };

  emitKeyPathDiagnostic()
      .highlight(keyPathExpr->getLoc())
      .fixItInsertAfter(keyPathExpr->getStartLoc(), "<#Root#>");
  return true;
}

Optional<Diag<Type, Type>>
AbstractRawRepresentableFailure::getDiagnostic() const {
  auto *locator = getLocator();

  if (locator->isForContextualType()) {
    return diag::cannot_convert_initializer_value;
  } else if (locator->isForAssignment()) {
    return diag::cannot_convert_assign;
  } else if (locator->isLastElement<LocatorPathElt::ApplyArgToParam>()) {
    return diag::cannot_convert_argument_value;
  }

  return None;
}

bool AbstractRawRepresentableFailure::diagnoseAsError() {
  auto message = getDiagnostic();
  if (!message)
    return false;

  auto diagnostic = emitDiagnostic(*message, getFromType(), getToType());
  fixIt(diagnostic);
  return true;
}

bool AbstractRawRepresentableFailure::diagnoseAsNote() {
  auto *locator = getLocator();

  Optional<InFlightDiagnostic> diagnostic;
  if (locator->isForContextualType()) {
    auto overload = getCalleeOverloadChoiceIfAvailable(locator);
    if (!overload)
      return false;

    if (auto *decl = overload->choice.getDeclOrNull()) {
      diagnostic.emplace(emitDiagnosticAt(
          decl, diag::cannot_convert_candidate_result_to_contextual_type,
          decl->getName(), ExpectedType, RawReprType));
    }
  } else if (auto argConv =
                 locator->getLastElementAs<LocatorPathElt::ApplyArgToParam>()) {
    diagnostic.emplace(
        emitDiagnostic(diag::candidate_has_invalid_argument_at_position,
                       RawReprType, argConv->getParamIdx(), /*inOut=*/false));
  }

  if (diagnostic) {
    fixIt(*diagnostic);
    return true;
  }

  return false;
}

void MissingRawRepresentableInitFailure::fixIt(
    InFlightDiagnostic &diagnostic) const {
  if (auto *E = getAsExpr(getAnchor())) {
    auto range = E->getSourceRange();
    auto rawReprObjType = RawReprType->getOptionalObjectType();
    auto valueObjType = ExpectedType->getOptionalObjectType();

    if (rawReprObjType && valueObjType) {
      std::string mapCodeFix;

      // Check whether expression has been be wrapped in parens first.
      if (!E->canAppendPostfixExpression()) {
        diagnostic.fixItInsert(range.Start, "(");
        mapCodeFix += ")";
      }

      mapCodeFix += ".map { ";
      mapCodeFix += rawReprObjType->getString();
      mapCodeFix += "(rawValue: $0) }";

      diagnostic.fixItInsertAfter(range.End, mapCodeFix);
    } else if (rawReprObjType) {
      diagnostic
          .fixItInsert(range.Start, rawReprObjType->getString() + "(rawValue: ")
          .fixItInsertAfter(range.End, ")");
    } else if (valueObjType) {
      diagnostic.flush();

      std::string fixItBefore = RawReprType->getString() + "(rawValue: ";
      std::string fixItAfter;

      if (!E->canAppendPostfixExpression(true)) {
        fixItBefore += "(";
        fixItAfter += ")";
      }

      fixItAfter += "!) ?? <#default value#>";

      emitDiagnostic(diag::construct_raw_representable_from_unwrapped_value,
                     RawReprType, valueObjType)
          .highlight(range)
          .fixItInsert(range.Start, fixItBefore)
          .fixItInsertAfter(range.End, fixItAfter);
    } else {
      diagnostic
          .fixItInsert(range.Start, RawReprType->getString() + "(rawValue: ")
          .fixItInsertAfter(range.End, ") ?? <#default value#>");
    }
  }
}

void MissingRawValueFailure::fixIt(InFlightDiagnostic &diagnostic) const {
  auto *E = getAsExpr(getAnchor());
  if (!E)
    return;

  std::string fix;

  auto range = E->getSourceRange();
  if (!E->canAppendPostfixExpression()) {
    diagnostic.fixItInsert(range.Start, "(");
    fix += ")";
  }

  // If raw representable is an optional we need to map its raw value out
  // out first and then, if destination is not optional, allow to specify
  // default value.
  if (RawReprType->getOptionalObjectType()) {
    fix += "?.rawValue";

    if (!ExpectedType->getOptionalObjectType())
      fix += " ?? <#default value#>";
  } else {
    fix += ".rawValue";
  }

  diagnostic.fixItInsertAfter(range.End, fix);
}

bool MissingOptionalUnwrapKeyPathFailure::diagnoseAsError() {
  emitDiagnostic(diag::optional_not_unwrapped, getFromType(),
                 getFromType()->lookThroughSingleOptionalType());
  
  emitDiagnostic(diag::optional_keypath_application_base)
      .fixItInsertAfter(getLoc(), "?");
  emitDiagnostic(diag::unwrap_with_force_value)
      .fixItInsertAfter(getLoc(), "!");
  return true;
}

SourceLoc MissingOptionalUnwrapKeyPathFailure::getLoc() const {
  auto *SE = castToExpr<SubscriptExpr>(getAnchor());
  return SE->getBase()->getEndLoc();
}

bool TrailingClosureRequiresExplicitLabel::diagnoseAsError() {
  auto argInfo = *getFunctionArgApplyInfo(getLocator());

  {
    auto diagnostic = emitDiagnostic(
        diag::unlabeled_trailing_closure_deprecated, argInfo.getParamLabel());
    fixIt(diagnostic, argInfo);
  }

  if (auto *callee = argInfo.getCallee()) {
    emitDiagnosticAt(callee, diag::decl_declared_here, callee->getName());
  }

  return true;
}

void TrailingClosureRequiresExplicitLabel::fixIt(
    InFlightDiagnostic &diagnostic, const FunctionArgApplyInfo &info) const {
  auto &ctx = getASTContext();

  // Dig out source locations.
  SourceLoc existingRParenLoc;
  SourceLoc leadingCommaLoc;

  auto anchor = getRawAnchor();
  auto *arg = info.getArgListExpr();
  Expr *fn = nullptr;

  if (auto *applyExpr = getAsExpr<ApplyExpr>(anchor)) {
    fn = applyExpr->getFn();
  } else {
    // Covers subscripts, unresolved members etc.
    fn = getAsExpr(anchor);
  }

  if (!fn)
    return;

  auto *trailingClosure = info.getArgExpr();

  if (auto tupleExpr = dyn_cast<TupleExpr>(arg)) {
    existingRParenLoc = tupleExpr->getRParenLoc();
    assert(tupleExpr->getNumElements() >= 2 && "Should be a ParenExpr?");
    leadingCommaLoc = Lexer::getLocForEndOfToken(
        ctx.SourceMgr,
        tupleExpr->getElements()[tupleExpr->getNumElements() - 2]->getEndLoc());
  } else {
    auto parenExpr = cast<ParenExpr>(arg);
    existingRParenLoc = parenExpr->getRParenLoc();
  }

  // Figure out the text to be inserted before the trailing closure.
  SmallString<16> insertionText;
  SourceLoc insertionLoc;
  if (leadingCommaLoc.isValid()) {
    insertionText += ", ";
    assert(existingRParenLoc.isValid());
    insertionLoc = leadingCommaLoc;
  } else if (existingRParenLoc.isInvalid()) {
    insertionText += "(";
    insertionLoc = Lexer::getLocForEndOfToken(ctx.SourceMgr, fn->getEndLoc());
  } else {
    insertionLoc = existingRParenLoc;
  }

  // Add the label, if there is one.
  auto paramName = info.getParamLabel();
  if (!paramName.empty()) {
    insertionText += paramName.str();
    insertionText += ": ";
  }

  // If there is an existing right parentheses/brace, remove it while we
  // insert the new text.
  if (existingRParenLoc.isValid()) {
    SourceLoc afterExistingRParenLoc =
        Lexer::getLocForEndOfToken(ctx.SourceMgr, existingRParenLoc);
    diagnostic.fixItReplaceChars(insertionLoc, afterExistingRParenLoc,
                                 insertionText);
  } else {
    // Insert the appropriate prefix.
    diagnostic.fixItInsert(insertionLoc, insertionText);
  }

  // Insert a right parenthesis/brace after the closing '}' of the trailing
  // closure;
  SourceLoc newRParenLoc =
      Lexer::getLocForEndOfToken(ctx.SourceMgr, trailingClosure->getEndLoc());
  diagnostic.fixItInsert(newRParenLoc,
                         isExpr<SubscriptExpr>(anchor) ? "]" : ")");
}

bool InvalidEmptyKeyPathFailure::diagnoseAsError() {
  auto *KPE = getAsExpr<KeyPathExpr>(getAnchor());
  assert(KPE && KPE->hasSingleInvalidComponent() &&
         "Expected a malformed key path expression");

  // If we have a string interpolation represented as key path expressions
  // e.g. \(x), \(x, a: 1). Let's skip it because this would be already
  // diagnosed and it is not the case for an extra empty key path diagnostic.
  auto *root = KPE->getParsedRoot();
  if (root && (isa<ParenExpr>(root) || isa<TupleExpr>(root)))
    return true;

  emitDiagnostic(diag::expr_swift_keypath_empty);
  return true;
}

bool MissingContextualTypeForNil::diagnoseAsError() {
  auto *expr = castToExpr<NilLiteralExpr>(getAnchor());

  // If this is a standalone `nil` literal expression e.g.
  // `_ = nil`, let's diagnose it here because solver can't
  // attempt any types for it.
  auto *parentExpr = findParentExpr(expr);

  while (parentExpr && isa<IdentityExpr>(parentExpr))
    parentExpr = findParentExpr(parentExpr);

  // In cases like `_ = nil?` AST would have `nil`
  // wrapped in `BindOptionalExpr`.
  if (parentExpr && isa<BindOptionalExpr>(parentExpr))
    parentExpr = findParentExpr(parentExpr);

  if (parentExpr) {
    // `_ = nil as? ...`
    if (isa<ConditionalCheckedCastExpr>(parentExpr)) {
      emitDiagnostic(diag::conditional_cast_from_nil);
      return true;
    }

    // `_ = nil!`
    if (isa<ForceValueExpr>(parentExpr)) {
      emitDiagnostic(diag::cannot_force_unwrap_nil_literal);
      return true;
    }

    // `_ = nil?`
    if (isa<OptionalEvaluationExpr>(parentExpr)) {
      emitDiagnostic(diag::unresolved_nil_literal);
      return true;
    }
  }

  emitDiagnostic(diag::unresolved_nil_literal);
  return true;
}

bool ReferenceToInvalidDeclaration::diagnoseAsError() {
  auto *decl = castToExpr<DeclRefExpr>(getAnchor())->getDecl();
  assert(decl);

  auto &DE = getASTContext().Diags;
  // This problem should have been already diagnosed during
  // validation of the declaration.
  if (DE.hadAnyError())
    return true;

  // If no errors have been emitted yet, let's emit one
  // about reference to an invalid declaration.

  emitDiagnostic(diag::reference_to_invalid_decl, decl->getName());
  emitDiagnosticAt(decl, diag::decl_declared_here, decl->getName());
  return true;
}

bool InvalidReturnInResultBuilderBody::diagnoseAsError() {
  auto *closure = castToExpr<ClosureExpr>(getAnchor());

  auto returnStmts = TypeChecker::findReturnStatements(closure);
  assert(!returnStmts.empty());

  auto loc = returnStmts.front()->getReturnLoc();
  emitDiagnosticAt(loc, diag::result_builder_disabled_by_return, BuilderType);

  // Note that one can remove all of the return statements.
  {
    auto diag = emitDiagnosticAt(loc, diag::result_builder_remove_returns);
    for (auto returnStmt : returnStmts)
      diag.fixItRemove(returnStmt->getReturnLoc());
  }

  return true;
}

bool MemberMissingExplicitBaseTypeFailure::diagnoseAsError() {
  auto UME = castToExpr<UnresolvedMemberExpr>(getAnchor());
  auto memberName = UME->getName().getBaseIdentifier().str();
  auto &DE = getASTContext().Diags;
  auto &solution = getSolution();

  auto selected = solution.getOverloadChoice(getLocator());
  auto baseType =
      resolveType(selected.choice.getBaseType()->getMetatypeInstanceType());

  SmallVector<Type, 4> optionals;
  auto baseTyUnwrapped = baseType->lookThroughAllOptionalTypes(optionals);

  if (!optionals.empty()) {
    auto baseTyName = baseType->getCanonicalType().getString();
    auto baseTyUnwrappedName = baseTyUnwrapped->getString();
    auto loc = UME->getLoc();
    auto startLoc = UME->getStartLoc();

    DE.diagnoseWithNotes(
        DE.diagnose(loc, diag::optional_ambiguous_case_ref, baseTyName,
                    baseTyUnwrappedName, memberName),
        [&]() {
          DE.diagnose(UME->getDotLoc(), diag::optional_fixit_ambiguous_case_ref)
              .fixItInsert(startLoc, "Optional");
          DE.diagnose(UME->getDotLoc(),
                      diag::type_fixit_optional_ambiguous_case_ref,
                      baseTyUnwrappedName, memberName)
              .fixItInsert(startLoc, baseTyUnwrappedName);
        });
  } else {
    auto baseTypeName = baseType->getCanonicalType().getString();
    auto baseOptionalTypeName =
        OptionalType::get(baseType)->getCanonicalType().getString();

    DE.diagnoseWithNotes(
        DE.diagnose(UME->getLoc(), diag::optional_ambiguous_case_ref,
                    baseTypeName, baseOptionalTypeName, memberName),
        [&]() {
          DE.diagnose(UME->getDotLoc(),
                      diag::type_fixit_optional_ambiguous_case_ref,
                      baseOptionalTypeName, memberName)
              .fixItInsert(UME->getDotLoc(), baseOptionalTypeName);
          DE.diagnose(UME->getDotLoc(),
                      diag::type_fixit_optional_ambiguous_case_ref,
                      baseTypeName, memberName)
              .fixItInsert(UME->getDotLoc(), baseTypeName);
        });
  }
  return true;
}
