//===--- CSApply.cpp - Constraint Application -----------------------------===//
//
// 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 application of a solution to a constraint
// system to a particular expression, resulting in a
// fully-type-checked expression.
//
//===----------------------------------------------------------------------===//

#include "CSDiagnostics.h"
#include "CodeSynthesis.h"
#include "MiscDiagnostics.h"
#include "TypeCheckProtocol.h"
#include "TypeCheckType.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/ClangModuleLoader.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/OperatorNameLookup.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/Basic/StringExtras.h"
#include "swift/Sema/ConstraintSystem.h"
#include "swift/Sema/SolutionResult.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Mangle.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/SaveAndRestore.h"

using namespace swift;
using namespace constraints;

/// Retrieve the fixed type for the given type variable.
Type Solution::getFixedType(TypeVariableType *typeVar) const {
  auto knownBinding = typeBindings.find(typeVar);
  assert(knownBinding != typeBindings.end());
  return knownBinding->second;
}

/// Determine whether the given type is an opened AnyObject.
///
/// This comes up in computeSubstitutions() when accessing
/// members via dynamic lookup.
static bool isOpenedAnyObject(Type type) {
  auto archetype = type->getAs<OpenedArchetypeType>();
  if (!archetype)
    return false;

  return archetype->getOpenedExistentialType()->isAnyObject();
}

SubstitutionMap
Solution::computeSubstitutions(GenericSignature sig,
                               ConstraintLocator *locator) const {
  if (sig.isNull())
    return SubstitutionMap();

  // Gather the substitutions from dependent types to concrete types.
  auto openedTypes = OpenedTypes.find(locator);

  // If we have a member reference on an existential, there are no
  // opened types or substitutions.
  if (openedTypes == OpenedTypes.end())
    return SubstitutionMap();

  TypeSubstitutionMap subs;
  for (const auto &opened : openedTypes->second)
    subs[opened.first] = getFixedType(opened.second);

  auto lookupConformanceFn =
      [&](CanType original, Type replacement,
          ProtocolDecl *protoType) -> ProtocolConformanceRef {
    if (replacement->hasError() ||
        isOpenedAnyObject(replacement) ||
        replacement->is<GenericTypeParamType>()) {
      return ProtocolConformanceRef(protoType);
    }

    // FIXME: Retrieve the conformance from the solution itself.
    return TypeChecker::conformsToProtocol(replacement, protoType,
                                           getConstraintSystem().DC);
  };

  return SubstitutionMap::get(sig,
                              QueryTypeSubstitutionMap{subs},
                              lookupConformanceFn);
}

static ConcreteDeclRef generateDeclRefForSpecializedCXXFunctionTemplate(
    ASTContext &ctx, AbstractFunctionDecl *oldDecl, SubstitutionMap subst,
    clang::FunctionDecl *specialized) {
  // Create a new ParameterList with the substituted type.
  auto oldFnType =
      cast<GenericFunctionType>(oldDecl->getInterfaceType().getPointer());
  auto newFnType = oldFnType->substGenericArgs(subst);
  // The constructor type is a function type as follows:
  //   (CType.Type) -> (Generic) -> CType
  // And a method's function type is as follows:
  //   (inout CType) -> (Generic) -> Void
  // In either case, we only want the result of that function type because that
  // is the function type with the generic params that need to be substituted:
  //   (Generic) -> CType
  if (isa<ConstructorDecl>(oldDecl) || oldDecl->isInstanceMember())
    newFnType = cast<FunctionType>(newFnType->getResult().getPointer());
  SmallVector<ParamDecl *, 4> newParams;
  unsigned i = 0;
  for (auto paramTy : newFnType->getParams()) {
    auto *oldParamDecl = oldDecl->getParameters()->get(i);
    auto *newParamDecl =
        ParamDecl::cloneWithoutType(oldDecl->getASTContext(), oldParamDecl);
    newParamDecl->setInterfaceType(paramTy.getParameterType());
    newParams.push_back(newParamDecl);
    (void)++i;
  }
  auto *newParamList =
      ParameterList::create(ctx, SourceLoc(), newParams, SourceLoc());

  if (isa<ConstructorDecl>(oldDecl)) {
    DeclName ctorName(ctx, DeclBaseName::createConstructor(), newParamList);
    auto newCtorDecl = ConstructorDecl::createImported(
        ctx, specialized, ctorName, oldDecl->getLoc(), /*failable=*/false,
        /*failabilityLoc=*/SourceLoc(), /*throws=*/false,
        /*throwsLoc=*/SourceLoc(), newParamList, /*genericParams=*/nullptr,
        oldDecl->getDeclContext());
    return ConcreteDeclRef(newCtorDecl);
  }

  // Generate a name for the specialized function.
  std::string newNameStr;
  llvm::raw_string_ostream buffer(newNameStr);
  clang::MangleContext *mangler =
      specialized->getASTContext().createMangleContext();
  mangler->mangleName(specialized, buffer);
  buffer.flush();
  // Add all parameters as empty parameters.
  auto newName = DeclName(
      ctx, DeclName(ctx.getIdentifier(newNameStr)).getBaseName(), newParamList);

  auto newFnDecl = FuncDecl::createImported(
      ctx, oldDecl->getLoc(), newName, oldDecl->getNameLoc(),
      /*Async=*/false, oldDecl->hasThrows(), newParamList,
      newFnType->getResult(), /*GenericParams=*/nullptr,
      oldDecl->getDeclContext(), specialized);
  newFnDecl->setSelfAccessKind(cast<FuncDecl>(oldDecl)->getSelfAccessKind());
  return ConcreteDeclRef(newFnDecl);
}

ConcreteDeclRef
Solution::resolveConcreteDeclRef(ValueDecl *decl,
                                 ConstraintLocator *locator) const {
  if (!decl)
    return ConcreteDeclRef();

  // Get the generic signatue of the decl and compute the substitutions.
  auto sig = decl->getInnermostDeclContext()->getGenericSignatureOfContext();
  auto subst = computeSubstitutions(sig, locator);

  // If this is a C++ function template, get it's specialization for the given
  // substitution map and update the decl accordingly.
  if (decl->getClangDecl() &&
      isa<clang::FunctionTemplateDecl>(decl->getClangDecl())) {
    auto *newFn =
        decl->getASTContext()
            .getClangModuleLoader()
            ->instantiateCXXFunctionTemplate(
                decl->getASTContext(),
                const_cast<clang::FunctionTemplateDecl *>(
                    cast<clang::FunctionTemplateDecl>(decl->getClangDecl())),
                subst);
    return generateDeclRefForSpecializedCXXFunctionTemplate(
        decl->getASTContext(), cast<AbstractFunctionDecl>(decl), subst, newFn);
  }

  return ConcreteDeclRef(decl, subst);
}

ConstraintLocator *Solution::getCalleeLocator(ConstraintLocator *locator,
                                              bool lookThroughApply) const {
  auto &cs = getConstraintSystem();
  return cs.getCalleeLocator(
      locator, lookThroughApply,
      [&](Expr *expr) -> Type { return getType(expr); },
      [&](Type type) -> Type { return simplifyType(type)->getRValueType(); },
      [&](ConstraintLocator *locator) -> Optional<SelectedOverload> {
        return getOverloadChoiceIfAvailable(locator);
      });
}

ConstraintLocator *
Solution::getConstraintLocator(ASTNode anchor,
                               ArrayRef<LocatorPathElt> path) const {
  auto &cs = getConstraintSystem();
  return cs.getConstraintLocator(anchor, path);
}

ConstraintLocator *
Solution::getConstraintLocator(ConstraintLocator *base,
                               ArrayRef<LocatorPathElt> path) const {
  auto &cs = getConstraintSystem();
  return cs.getConstraintLocator(base, path);
}

/// Return the implicit access kind for a MemberRefExpr with the
/// specified base and member in the specified DeclContext.
static AccessSemantics
getImplicitMemberReferenceAccessSemantics(Expr *base, VarDecl *member,
                                          DeclContext *DC) {
  // Check whether this is a member access on 'self'.
  bool isAccessOnSelf = false;
  if (auto *baseDRE = dyn_cast<DeclRefExpr>(base->getValueProvidingExpr()))
    if (auto *baseVar = dyn_cast<VarDecl>(baseDRE->getDecl()))
      isAccessOnSelf = baseVar->isSelfParameter();

  // If the value is always directly accessed from this context, do it.
  return member->getAccessSemanticsFromContext(DC, isAccessOnSelf);
}

/// This extends functionality of `Expr::isTypeReference` with
/// support for `UnresolvedDotExpr` and `UnresolvedMemberExpr`.
/// This method could be used on not yet fully type-checked AST.
bool ConstraintSystem::isTypeReference(Expr *E) {
  return E->isTypeReference(
      [&](Expr *E) -> Type { return simplifyType(getType(E)); },
      [&](Expr *E) -> Decl * {
        if (auto *UDE = dyn_cast<UnresolvedDotExpr>(E)) {
          return findResolvedMemberRef(
              getConstraintLocator(UDE, ConstraintLocator::Member));
        }

        if (auto *UME = dyn_cast<UnresolvedMemberExpr>(E)) {
          return findResolvedMemberRef(
              getConstraintLocator(UME, ConstraintLocator::UnresolvedMember));
        }

        if (isa<OverloadSetRefExpr>(E))
          return findResolvedMemberRef(
              getConstraintLocator(const_cast<Expr *>(E)));

        return nullptr;
      });
}

bool Solution::isTypeReference(Expr *E) const {
  return E->isTypeReference(
      [&](Expr *expr) -> Type { return simplifyType(getType(expr)); },
      [&](Expr *expr) -> Decl * {
        ConstraintLocator *locator = nullptr;
        if (auto *UDE = dyn_cast<UnresolvedDotExpr>(E)) {
          locator = getConstraintLocator(UDE, {ConstraintLocator::Member});
        }

        if (auto *UME = dyn_cast<UnresolvedMemberExpr>(E)) {
          locator =
              getConstraintLocator(UME, {ConstraintLocator::UnresolvedMember});
        }

        if (isa<OverloadSetRefExpr>(E))
          locator = getConstraintLocator(const_cast<Expr *>(E));

        if (locator) {
          if (auto selectedOverload = getOverloadChoiceIfAvailable(locator)) {
            const auto &choice = selectedOverload->choice;
            return choice.getDeclOrNull();
          }
        }

        return nullptr;
      });
}

bool ConstraintSystem::isStaticallyDerivedMetatype(Expr *E) {
  return E->isStaticallyDerivedMetatype(
      [&](Expr *E) -> Type { return simplifyType(getType(E)); },
      [&](Expr *E) -> bool { return isTypeReference(E); });
}

bool Solution::isStaticallyDerivedMetatype(Expr *E) const {
  return E->isStaticallyDerivedMetatype(
      [&](Expr *E) -> Type { return simplifyType(getType(E)); },
      [&](Expr *E) -> bool { return isTypeReference(E); });
}

Type ConstraintSystem::getInstanceType(TypeExpr *E) {
  if (!hasType(E))
    return Type();

  if (auto metaType = getType(E)->getAs<MetatypeType>())
    return metaType->getInstanceType();

  return ErrorType::get(getType(E)->getASTContext());
}

Type ConstraintSystem::getResultType(const AbstractClosureExpr *E) {
  return E->getResultType([&](Expr *E) -> Type { return getType(E); });
}

static bool buildObjCKeyPathString(KeyPathExpr *E,
                                   llvm::SmallVectorImpl<char> &buf) {
  for (auto &component : E->getComponents()) {
    switch (component.getKind()) {
    case KeyPathExpr::Component::Kind::OptionalChain:
    case KeyPathExpr::Component::Kind::OptionalForce:
    case KeyPathExpr::Component::Kind::OptionalWrap:
      // KVC propagates nulls, so these don't affect the key path string.
      continue;
    case KeyPathExpr::Component::Kind::Identity:
      // The identity component can be elided from the KVC string (unless it's
      // the only component, in which case we use @"self").
      continue;

    case KeyPathExpr::Component::Kind::Property: {
      // Property references must be to @objc properties.
      // TODO: If we added special properties matching KVC operators like '@sum',
      // '@count', etc. those could be mapped too.
      auto property = cast<VarDecl>(component.getDeclRef().getDecl());
      if (!property->isObjC())
        return false;
      if (!buf.empty()) {
        buf.push_back('.');
      }
      auto objcName = property->getObjCPropertyName().str();
      buf.append(objcName.begin(), objcName.end());
      continue;
    }
    case KeyPathExpr::Component::Kind::TupleElement:
    case KeyPathExpr::Component::Kind::Subscript:
      // Subscripts and tuples aren't generally represented in KVC.
      // TODO: There are some subscript forms we could map to KVC, such as
      // when indexing a Dictionary or NSDictionary by string, or when applying
      // a mapping subscript operation to Array/Set or NSArray/NSSet.
      return false;
    case KeyPathExpr::Component::Kind::Invalid:
    case KeyPathExpr::Component::Kind::UnresolvedProperty:
    case KeyPathExpr::Component::Kind::UnresolvedSubscript:
      // Don't bother building the key path string if the key path didn't even
      // resolve.
      return false;
    case KeyPathExpr::Component::Kind::DictionaryKey:
      llvm_unreachable("DictionaryKey only valid in #keyPath expressions.");
      return false;
    }
  }
  
  // If there are no non-identity components, this is the "self" key.
  if (buf.empty()) {
    auto self = StringRef("self");
    buf.append(self.begin(), self.end());
  }
  
  return true;
}

namespace {

  /// Rewrites an expression by applying the solution of a constraint
  /// system to that expression.
  class ExprRewriter : public ExprVisitor<ExprRewriter, Expr *> {
  public:
    ConstraintSystem &cs;
    DeclContext *dc;
    Solution &solution;
    Optional<SolutionApplicationTarget> target;
    bool SuppressDiagnostics;

    /// Coerce the given tuple to another tuple type.
    ///
    /// \param expr The expression we're converting.
    ///
    /// \param fromTuple The tuple type we're converting from, which is the same
    /// as \c expr->getType().
    ///
    /// \param toTuple The tuple type we're converting to.
    ///
    /// \param locator Locator describing where this tuple conversion occurs.
    ///
    /// \param sources The sources of each of the elements to be used in the
    /// resulting tuple, as provided by \c computeTupleShuffle.
    Expr *coerceTupleToTuple(Expr *expr, TupleType *fromTuple,
                             TupleType *toTuple,
                             ConstraintLocatorBuilder locator,
                             ArrayRef<unsigned> sources);

    /// Coerce a subclass, class-constrained archetype, class-constrained
    /// existential or to a superclass type.
    ///
    /// Also supports metatypes of the above.
    ///
    /// \param expr The expression to be coerced.
    /// \param toType The type to which the expression will be coerced.
    ///
    /// \return The coerced expression, whose type will be equivalent to
    /// \c toType.
    Expr *coerceSuperclass(Expr *expr, Type toType);

    /// Coerce the given value to existential type.
    ///
    /// The following conversions are supported:
    /// - concrete to existential
    /// - existential to existential
    /// - concrete metatype to existential metatype
    /// - existential metatype to existential metatype
    ///
    /// \param expr The expression to be coerced.
    /// \param toType The type to which the expression will be coerced.
    ///
    /// \return The coerced expression, whose type will be equivalent to
    /// \c toType.
    Expr *coerceExistential(Expr *expr, Type toType);

    /// Coerce an expression of (possibly unchecked) optional
    /// type to have a different (possibly unchecked) optional type.
    Expr *coerceOptionalToOptional(Expr *expr, Type toType,
                                   ConstraintLocatorBuilder locator,
                                   Optional<Pattern*> typeFromPattern = None);

    /// Coerce an expression of implicitly unwrapped optional type to its
    /// underlying value type, in the correct way for an implicit
    /// look-through.
    Expr *coerceImplicitlyUnwrappedOptionalToValue(Expr *expr, Type objTy);

    /// Peephole an array upcast.
    void peepholeArrayUpcast(ArrayExpr *expr, Type toType, bool bridged,
                             Type elementType,
                             ConstraintLocatorBuilder locator);

    /// Peephole a dictionary upcast.
    void peepholeDictionaryUpcast(DictionaryExpr *expr, Type toType,
                                  bool bridged, Type keyType,
                                  Type valueType,
                                  ConstraintLocatorBuilder locator);

    /// Try to peephole the collection upcast, eliminating the need for
    /// a separate collection-upcast expression.
    ///
    /// \returns true if the peephole operation succeeded, in which case
    /// \c expr already subsumes the upcast.
    bool peepholeCollectionUpcast(Expr *expr, Type toType,  bool bridged,
                                  ConstraintLocatorBuilder locator);

    /// Build a collection upcast expression.
    ///
    /// \param bridged Whether this is a bridging conversion, meaning that the
    /// element types themselves are bridged (vs. simply coerced).
    Expr *buildCollectionUpcastExpr(Expr *expr, Type toType,
                                    bool bridged,
                                    ConstraintLocatorBuilder locator);

    /// Build the expression that performs a bridging operation from the
    /// given expression to the given \c toType.
    Expr *buildObjCBridgeExpr(Expr *expr, Type toType,
                              ConstraintLocatorBuilder locator);

    static Type getBaseType(AnyFunctionType *fnType,
                            bool wantsRValueInstanceType = true) {
      auto params = fnType->getParams();
      assert(params.size() == 1);

      const auto &base = params.front();
      if (wantsRValueInstanceType)
        return base.getPlainType()->getMetatypeInstanceType();

      return base.getOldType();
    }

    /// Check whether it is possible to have an ObjC key path string for the keypath expression
    /// and set the key path string, if yes
    void checkAndSetObjCKeyPathString(KeyPathExpr *keyPath) {
      if (cs.getASTContext().LangOpts.EnableObjCInterop) {
        SmallString<64> compatStringBuf;
        if (buildObjCKeyPathString(keyPath, compatStringBuf)) {
            auto stringCopy = cs.getASTContext().AllocateCopy<char>(compatStringBuf.begin(),
                                                                    compatStringBuf.end());
            auto stringExpr = new (cs.getASTContext()) StringLiteralExpr(
                                  StringRef(stringCopy, compatStringBuf.size()),
                                  SourceRange(),
                                  /*implicit*/ true);
            cs.setType(
                stringExpr,
                cs.getASTContext().getStringDecl()->getDeclaredInterfaceType());
            keyPath->setObjCStringLiteralExpr(stringExpr);
        }
      }
    }

    // Returns None if the AST does not contain enough information to recover
    // substitutions; this is different from an Optional(SubstitutionMap()),
    // indicating a valid call to a non-generic operator.
    Optional<SubstitutionMap>
    getOperatorSubstitutions(ValueDecl *witness, Type refType) {
      // We have to recover substitutions in this hacky way because
      // the AST does not retain enough information to devirtualize
      // calls like this.
      auto witnessType = witness->getInterfaceType();

      // Compute the substitutions.
      auto *gft = witnessType->getAs<GenericFunctionType>();
      if (gft == nullptr) {
        if (refType->isEqual(witnessType))
          return SubstitutionMap();
        return None;
      }

      auto sig = gft->getGenericSignature();
      auto *env = sig->getGenericEnvironment();

      witnessType = FunctionType::get(gft->getParams(),
                                      gft->getResult(),
                                      gft->getExtInfo());
      witnessType = env->mapTypeIntoContext(witnessType);

      TypeSubstitutionMap subs;
      auto substType = witnessType->substituteBindingsTo(
        refType,
        [&](ArchetypeType *origType, CanType substType,
            ArchetypeType*, ArrayRef<ProtocolConformanceRef>) -> CanType {
          if (auto gpType = dyn_cast<GenericTypeParamType>(
                origType->getInterfaceType()->getCanonicalType()))
            subs[gpType] = substType;

          return substType;
        });

      // If substitution failed, it means that the protocol requirement type
      // and the witness type did not match up. The only time that this
      // should happen is when the witness is defined in a base class and
      // the actual call uses a derived class. For example,
      //
      // protocol P { func +(lhs: Self, rhs: Self) }
      // class Base : P { func +(lhs: Base, rhs: Base) {} }
      // class Derived : Base {}
      //
      // If we enter this code path with two operands of type Derived,
      // we know we're calling the protocol requirement P.+, with a
      // substituted type of (Derived, Derived) -> (). But the type of
      // the witness is (Base, Base) -> (). Just bail out and make a
      // witness method call in this rare case; SIL mandatory optimizations
      // will likely devirtualize it anyway.
      if (!substType)
        return None;

      return SubstitutionMap::get(sig,
                                  QueryTypeSubstitutionMap{subs},
                                  LookUpConformanceInModule(cs.DC->getParentModule()));
    }

  public:
    /// Build a reference to the given declaration.
    Expr *buildDeclRef(SelectedOverload overload, DeclNameLoc loc,
                       ConstraintLocatorBuilder locator, bool implicit) {
      auto choice = overload.choice;
      assert(choice.getKind() != OverloadChoiceKind::DeclViaDynamic);
      auto *decl = choice.getDecl();
      auto fullType = simplifyType(overload.openedFullType);

      // Determine the declaration selected for this overloaded reference.
      auto &ctx = cs.getASTContext();
      
      auto semantics = decl->getAccessSemanticsFromContext(cs.DC,
                                                           /*isAccessOnSelf*/false);

      // If this is a member of a nominal type, build a reference to the
      // member with an implied base type.
      if (decl->getDeclContext()->isTypeContext() && isa<FuncDecl>(decl)) {
        assert(cast<FuncDecl>(decl)->isOperator() && "Must be an operator");

        auto baseTy = getBaseType(fullType->castTo<FunctionType>());

        // Handle operator requirements found in protocols.
        if (auto proto = dyn_cast<ProtocolDecl>(decl->getDeclContext())) {
          bool isCurried = shouldBuildCurryThunk(choice, /*baseIsInstance=*/false);

          // If we have a concrete conformance, build a call to the witness.
          //
          // FIXME: This is awful. We should be able to handle this as a call to
          // the protocol requirement with Self == the concrete type, and SILGen
          // (or later) can devirtualize as appropriate.
          auto conformance =
            TypeChecker::conformsToProtocol(baseTy, proto, cs.DC);
          if (conformance.isConcrete()) {
            if (auto witness = conformance.getConcrete()->getWitnessDecl(decl)) {
              bool isMemberOperator = witness->getDeclContext()->isTypeContext();

              if (!isMemberOperator || !isCurried) {
                // The fullType was computed by substituting the protocol
                // requirement so it always has a (Self) -> ... curried
                // application. Strip it off if the witness was a top-level
                // function.
                Type refType;
                if (isMemberOperator)
                  refType = fullType;
                else
                  refType = fullType->castTo<AnyFunctionType>()->getResult();

                // Build the AST for the call to the witness.
                auto subMap = getOperatorSubstitutions(witness, refType);
                if (subMap) {
                  ConcreteDeclRef witnessRef(witness, *subMap);
                  auto declRefExpr =  new (ctx) DeclRefExpr(witnessRef, loc,
                                                            /*Implicit=*/false);
                  declRefExpr->setFunctionRefKind(choice.getFunctionRefKind());
                  cs.setType(declRefExpr, refType);

                  Expr *refExpr;
                  if (isMemberOperator) {
                    // If the operator is a type member, add the implicit
                    // (Self) -> ... call.
                    Expr *base =
                      TypeExpr::createImplicitHack(loc.getBaseNameLoc(), baseTy,
                                                   ctx);
                    cs.setType(base, MetatypeType::get(baseTy));

                    refExpr = new (ctx) DotSyntaxCallExpr(declRefExpr,
                                                          SourceLoc(), base);
                    auto refType = fullType->castTo<FunctionType>()->getResult();
                    cs.setType(refExpr, refType);
                  } else {
                    refExpr = declRefExpr;
                  }

                  return forceUnwrapIfExpected(refExpr, choice, locator);
                }
              }
            }
          }
        }

        // Build a reference to the member.
        Expr *base =
          TypeExpr::createImplicitHack(loc.getBaseNameLoc(), baseTy, ctx);
        cs.cacheExprTypes(base);

        return buildMemberRef(base, SourceLoc(), overload, loc, locator,
                              locator, implicit, semantics);
      }

      if (isa<TypeDecl>(decl) && !isa<ModuleDecl>(decl)) {
        auto typeExpr = TypeExpr::createImplicitHack(
            loc.getBaseNameLoc(), fullType->getMetatypeInstanceType(), ctx);
        cs.cacheType(typeExpr);
        return typeExpr;
      }

      auto ref = resolveConcreteDeclRef(decl, locator);
      auto declRefExpr =
          new (ctx) DeclRefExpr(ref, loc, implicit, semantics, fullType);
      cs.cacheType(declRefExpr);
      declRefExpr->setFunctionRefKind(choice.getFunctionRefKind());
      return forceUnwrapIfExpected(declRefExpr, choice, locator);
    }

    /// Describes an opened existential that has not yet been closed.
    struct OpenedExistential {
      /// The archetype describing this opened existential.
      OpenedArchetypeType *Archetype;

      /// The existential value being opened.
      Expr *ExistentialValue;

      /// The opaque value (of archetype type) stored within the
      /// existential.
      OpaqueValueExpr *OpaqueValue;

      /// The depth of this currently-opened existential. Once the
      /// depth of the expression stack is equal to this value, the
      /// existential can be closed.
      unsigned Depth;
    };

    /// A stack of opened existentials that have not yet been closed.
    /// Ordered by decreasing depth.
    llvm::SmallVector<OpenedExistential, 2> OpenedExistentials;

    /// A stack of expressions being walked, used to compute existential depth.
    llvm::SmallVector<Expr *, 8> ExprStack;

    /// A map of apply exprs to their callee locators. This is necessary
    /// because after rewriting an apply's function expr, its callee locator
    /// will no longer be equivalent to the one stored in the solution.
    llvm::DenseMap<ApplyExpr *, ConstraintLocator *> CalleeLocators;

    /// A cache of decl references with their contextual substitutions for a
    /// given callee locator.
    llvm::DenseMap<ConstraintLocator *, ConcreteDeclRef> CachedConcreteRefs;

    /// Resolves the contextual substitutions for a reference to a declaration
    /// at a given locator. This should be preferred to
    /// Solution::resolveConcreteDeclRef as it caches the result.
    ConcreteDeclRef
    resolveConcreteDeclRef(ValueDecl *decl, ConstraintLocatorBuilder locator) {
      if (!decl)
        return ConcreteDeclRef();

      // Cache the resulting concrete reference. Ideally this would be done on
      // Solution, however unfortunately that would require a const_cast which
      // would be undefined behaviour if we ever had a `const Solution`.
      auto *loc = getConstraintSystem().getConstraintLocator(locator);
      auto &ref = CachedConcreteRefs[loc];
      if (!ref)
        ref = solution.resolveConcreteDeclRef(decl, loc);

      return ref;
    }

    /// Members which are AbstractFunctionDecls but not FuncDecls cannot
    /// mutate self.
    bool isNonMutatingMember(ValueDecl *member) {
      if (!isa<AbstractFunctionDecl>(member))
        return false;
      return !isa<FuncDecl>(member) || !cast<FuncDecl>(member)->isMutating();
    }

    /// If the expression might be a dynamic method call, return the base
    /// value for the call.
    Expr *getBaseExpr(Expr *expr) {
      // Keep going up as long as this expression is the parent's base.
      if (auto unresolvedDot = dyn_cast<UnresolvedDotExpr>(expr)) {
        return unresolvedDot->getBase();
      // Remaining cases should only come up when we're re-typechecking.
      // FIXME: really it would be much better if Sema had stricter phase
      // separation.
      } else if (auto dotSyntax = dyn_cast<DotSyntaxCallExpr>(expr)) {
        return dotSyntax->getArg();
      } else if (auto ctorRef = dyn_cast<ConstructorRefCallExpr>(expr)) {
        return ctorRef->getArg();
      } else if (auto apply = dyn_cast<ApplyExpr>(expr)) {
        return apply->getFn();
      } else if (auto lookupRef = dyn_cast<LookupExpr>(expr)) {
        return lookupRef->getBase();
      } else if (auto load = dyn_cast<LoadExpr>(expr)) {
        return load->getSubExpr();
      } else if (auto inout = dyn_cast<InOutExpr>(expr)) {
        return inout->getSubExpr();
      } else if (auto force = dyn_cast<ForceValueExpr>(expr)) {
        return force->getSubExpr();
      } else {
        return nullptr;
      }
    }

    /// Calculates the nesting depth of the current application.
    unsigned getArgCount(unsigned maxArgCount) {
      // FIXME: Walking over the ExprStack to figure out the number of argument
      // lists being applied is brittle. We should instead be checking
      // hasAppliedSelf to figure out if the self param is applied, and looking
      // at the FunctionRefKind to see if the parameter list is applied.
      unsigned e = ExprStack.size();
      unsigned argCount;

      // Starting from the current expression, count up if the expression is
      // equal to its parent expression's base.
      Expr *prev = ExprStack.back();

      for (argCount = 1; argCount < maxArgCount && argCount < e; ++argCount) {
        Expr *result = ExprStack[e - argCount - 1];
        Expr *base = getBaseExpr(result);
        if (base != prev)
          break;
        prev = result;
      }

      return argCount;
    }

    /// Open an existential value into a new, opaque value of
    /// archetype type.
    ///
    /// \param base An expression of existential type whose value will
    /// be opened.
    ///
    /// \param archetype The archetype that describes the opened existential
    /// type.
    ///
    /// \param member The member that is being referenced on the existential
    /// type.
    ///
    /// \returns An OpaqueValueExpr that provides a reference to the value
    /// stored within the expression or its metatype (if the base was a
    /// metatype).
    Expr *openExistentialReference(Expr *base, OpenedArchetypeType *archetype,
                                   ValueDecl *member) {
      assert(archetype && "archetype not already opened?");

      // Dig out the base type.
      Type baseTy = cs.getType(base);

      // Look through lvalues.
      bool isLValue = false;
      if (auto lvalueTy = baseTy->getAs<LValueType>()) {
        isLValue = true;
        baseTy = lvalueTy->getObjectType();
      }

      // Look through metatypes.
      bool isMetatype = false;
      if (auto metaTy = baseTy->getAs<AnyMetatypeType>()) {
        isMetatype = true;
        baseTy = metaTy->getInstanceType();
      }

      assert(baseTy->isAnyExistentialType() && "Type must be existential");

      // If the base was an lvalue but it will only be treated as an
      // rvalue, turn the base into an rvalue now. This results in
      // better SILGen.
      if (isLValue &&
          (isNonMutatingMember(member) ||
           member->getDeclContext()->getDeclaredInterfaceType()
             ->hasReferenceSemantics())) {
        base = cs.coerceToRValue(base);
        isLValue = false;
      }

      // Determine the number of applications that need to occur before
      // we can close this existential, and record it.
      unsigned maxArgCount = member->getNumCurryLevels();
      unsigned depth = ExprStack.size() - getArgCount(maxArgCount);

      // Invalid case -- direct call of a metatype. Has one less argument
      // application because there's no ".init".
      if (isa<ApplyExpr>(ExprStack.back()))
        depth++;

      // Create the opaque opened value. If we started with a
      // metatype, it's a metatype.
      Type opaqueType = archetype;
      if (isMetatype)
        opaqueType = MetatypeType::get(opaqueType);
      if (isLValue)
        opaqueType = LValueType::get(opaqueType);

      ASTContext &ctx = cs.getASTContext();
      auto archetypeVal =
          new (ctx) OpaqueValueExpr(base->getSourceRange(), opaqueType);
      cs.cacheType(archetypeVal);

      // Record the opened existential.
      OpenedExistentials.push_back({archetype, base, archetypeVal, depth});

      return archetypeVal;
    }

    /// Trying to close the active existential, if there is one.
    bool closeExistential(Expr *&result, ConstraintLocatorBuilder locator,
                          bool force=false) {
      if (OpenedExistentials.empty())
        return false;

      auto &record = OpenedExistentials.back();
      assert(record.Depth <= ExprStack.size());

      if (!force && record.Depth < ExprStack.size() - 1)
        return false;

      // If we had a return type of 'Self', erase it.
      Type resultTy;
      resultTy = cs.getType(result);
      if (resultTy->hasOpenedExistential(record.Archetype)) {
        Type erasedTy = resultTy->eraseOpenedExistential(record.Archetype);
        auto range = result->getSourceRange();
        result = coerceToType(result, erasedTy, locator);
        // FIXME: Implement missing tuple-to-tuple conversion
        if (result == nullptr) {
          result = new (cs.getASTContext()) ErrorExpr(range);
          cs.setType(result, erasedTy);
          // The opaque value is no longer reachable in an AST walk as
          // a result of the result above being replaced with an
          // ErrorExpr, but there is code expecting to have a type set
          // on it. Since we no longer have a reachable reference,
          // we'll null this out.
          record.OpaqueValue = nullptr;
        }
      }

      // Form the open-existential expression.
      result = new (cs.getASTContext()) OpenExistentialExpr(
                                  record.ExistentialValue,
                                  record.OpaqueValue,
                                  result, cs.getType(result));
      cs.cacheType(result);

      OpenedExistentials.pop_back();
      return true;
    }

    /// Determines if a partially-applied member reference should be
    /// converted into a fully-applied member reference with a pair of
    /// closures.
    bool shouldBuildCurryThunk(OverloadChoice choice,
                               bool baseIsInstance) {
      ValueDecl *member = choice.getDecl();
      auto isDynamic = choice.getKind() == OverloadChoiceKind::DeclViaDynamic;

      // FIXME: We should finish plumbing this through for dynamic
      // lookup as well.
      if (isDynamic || member->getAttrs().hasAttribute<OptionalAttr>())
        return false;

      // If we're inside a selector expression, don't build the thunk.
      // Were not actually going to emit the member reference, just
      // look at the AST.
      for (auto expr : ExprStack)
        if (isa<ObjCSelectorExpr>(expr))
          return false;

      // Unbound instance method references always build a thunk, even if
      // we apply the arguments (eg, SomeClass.method(self)(a)), to avoid
      // representational issues.
      if (!baseIsInstance && member->isInstanceMember())
        return true;

      // Figure out how many argument lists we need.
      unsigned maxArgCount = member->getNumCurryLevels();

      unsigned argCount = [&]() -> unsigned {
        Expr *prev = ExprStack.back();

        // FIXME: Representational gunk because "T(...)" is really
        // "T.init(...)" -- pretend it has two argument lists like
        // a real '.' call.
        if (isa<ConstructorDecl>(member) &&
            isa<CallExpr>(prev) &&
            isa<TypeExpr>(cast<CallExpr>(prev)->getFn())) {
          assert(maxArgCount == 2);
          return 2;
        }

        // Similarly, ".foo(...)" really applies two argument lists.
        if (isa<CallExpr>(prev) &&
            isa<UnresolvedMemberExpr>(cast<CallExpr>(prev)->getFn()))
          return 2;

        return getArgCount(maxArgCount);
      }();

      // If we have fewer argument lists than expected, build a thunk.
      if (argCount < maxArgCount)
        return true;

      return false;
    }

    AutoClosureExpr *buildCurryThunk(ValueDecl *member,
                                     FunctionType *selfFnTy,
                                     Expr *selfParamRef,
                                     Expr *ref,
                                     ConstraintLocatorBuilder locator) {
      auto &context = cs.getASTContext();

      OptionSet<ParameterList::CloneFlags> options
        = (ParameterList::Implicit |
           ParameterList::NamedArguments);
      auto *params = getParameterList(member)->clone(context, options);

      for (auto idx : indices(*params)) {
        auto *param = params->get(idx);
        auto arg = selfFnTy->getParams()[idx];

        param->setInterfaceType(
            arg.getParameterType()->mapTypeOutOfContext());
        param->setSpecifier(
          ParamDecl::getParameterSpecifierForValueOwnership(
            arg.getValueOwnership()));
      }

      auto resultTy = selfFnTy->getResult();
      auto discriminator = AutoClosureExpr::InvalidDiscriminator;
      auto closure =
          new (context) AutoClosureExpr(/*set body later*/nullptr, resultTy,
                                        discriminator, cs.DC);
      closure->setParameterList(params);
      closure->setType(selfFnTy);
      closure->setThunkKind(AutoClosureExpr::Kind::SingleCurryThunk);
      cs.cacheType(closure);

      auto refTy = cs.getType(ref)->castTo<FunctionType>();
      auto calleeParams = refTy->getResult()->castTo<FunctionType>()->getParams();
      auto calleeResultTy = refTy->getResult()->castTo<FunctionType>()->getResult();

      auto selfParam = refTy->getParams()[0];
      auto selfParamTy = selfParam.getPlainType();

      Expr *selfOpenedRef = selfParamRef;

      // If the 'self' parameter has non-trivial ownership, adjust the
      // argument accordingly.
      switch (selfParam.getValueOwnership()) {
      case ValueOwnership::Default:
      case ValueOwnership::InOut:
        break;

      case ValueOwnership::Owned:
      case ValueOwnership::Shared:
        auto selfArgTy = ParenType::get(context,
                                        selfParam.getPlainType(),
                                        selfParam.getParameterFlags());
        selfOpenedRef->setType(selfArgTy);
        cs.cacheType(selfOpenedRef);
        break;
      }

      if (selfParamTy->hasOpenedExistential()) {
        // If we're opening an existential:
        // - the type of 'ref' inside the closure is written in terms of the
        //   open existental archetype
        // - the type of the closure, 'selfFnTy' is written in terms of the
        //   erased existential bounds
        if (selfParam.isInOut())
          selfParamTy = LValueType::get(selfParamTy);

        selfOpenedRef =
            new (context) OpaqueValueExpr(SourceLoc(), selfParamTy);
        cs.cacheType(selfOpenedRef);
      }

      // (Self) -> ...
      ApplyExpr *selfCall = new (context) DotSyntaxCallExpr(
          ref, SourceLoc(), selfOpenedRef);
      selfCall->setType(refTy->getResult());
      cs.cacheType(selfCall);

      if (selfParamRef->isSuperExpr())
        selfCall->setIsSuper(true);

      // Pass all the closure parameters to the call.
      SmallVector<Identifier, 4> labels;
      SmallVector<SourceLoc, 4> labelLocs;
      SmallVector<Expr *, 4> args;

      for (auto idx : indices(*params)) {
        auto *param = params->get(idx);
        auto calleeParamType = calleeParams[idx].getParameterType();

        auto type = param->getType();

        Expr *paramRef =
          new (context) DeclRefExpr(param, DeclNameLoc(), /*implicit*/ true);
        paramRef->setType(
            param->isInOut()
              ? LValueType::get(type)
              : type);
        cs.cacheType(paramRef);

        paramRef = coerceToType(
            paramRef,
            param->isInOut()
              ? LValueType::get(calleeParamType)
              : calleeParamType,
            locator);

        if (param->isInOut()) {
          paramRef =
            new (context) InOutExpr(SourceLoc(), paramRef, calleeParamType,
                                    /*implicit=*/true);
          cs.cacheType(paramRef);
        } else if (param->isVariadic()) {
          paramRef =
            new (context) VarargExpansionExpr(paramRef, /*implicit*/ true);
          paramRef->setType(calleeParamType);
          cs.cacheType(paramRef);
        }

        args.push_back(paramRef);

        labels.push_back(calleeParams[idx].getLabel());
        labelLocs.push_back(SourceLoc());
      }

      Expr *closureArg;
      if (args.size() == 1 &&
          labels[0].empty() &&
          !calleeParams[0].getParameterFlags().isVariadic()) {
        closureArg = new (context) ParenExpr(SourceLoc(), args[0], SourceLoc(),
                                             /*hasTrailingClosure=*/false);
        closureArg->setImplicit();
      } else {
        closureArg = TupleExpr::create(context, SourceLoc(), args, labels, labelLocs,
                                       SourceLoc(), /*hasTrailingClosure=*/false,
                                       /*implicit=*/true);
      }

      auto argTy = AnyFunctionType::composeInput(context, calleeParams,
                                                 /*canonical*/false);
      closureArg->setType(argTy);
      cs.cacheType(closureArg);

      // (Self) -> (Args...) -> ...
      auto *closureCall =
        CallExpr::create(context, selfCall, closureArg, { }, { },
                         /*hasTrailingClosure=*/false,
                         /*implicit=*/true);
      closureCall->setType(calleeResultTy);
      cs.cacheType(closureCall);

      Expr *closureBody = closureCall;
      closureBody = coerceToType(closureCall, resultTy, locator);

      if (selfFnTy->getExtInfo().isThrowing()) {
        closureBody = new (context) TryExpr(closureBody->getStartLoc(), closureBody,
                                            cs.getType(closureBody),
                                            /*implicit=*/true);
        cs.cacheType(closureBody);
      }

      if (selfParam.getPlainType()->hasOpenedExistential()) {
        closureBody =
          new (context) OpenExistentialExpr(
            selfParamRef, cast<OpaqueValueExpr>(selfOpenedRef),
            closureBody, resultTy);
        cs.cacheType(closureBody);
      }

      closure->setBody(closureBody);

      return closure;
    }

    /// Build a new member reference with the given base and member.
    Expr *buildMemberRef(Expr *base, SourceLoc dotLoc,
                         SelectedOverload overload, DeclNameLoc memberLoc,
                         ConstraintLocatorBuilder locator,
                         ConstraintLocatorBuilder memberLocator, bool Implicit,
                         AccessSemantics semantics) {
      auto choice = overload.choice;
      auto openedType = overload.openedType;

      ValueDecl *member = choice.getDecl();

      auto &context = cs.getASTContext();

      bool isSuper = base->isSuperExpr();

      // The formal type of the 'self' value for the call.
      Type baseTy = cs.getType(base)->getRValueType();

      // Figure out the actual base type, and whether we have an instance of
      // that type or its metatype.
      bool baseIsInstance = true;
      bool isExistentialMetatype = false;
      if (auto baseMeta = baseTy->getAs<AnyMetatypeType>()) {
        baseIsInstance = false;
        isExistentialMetatype = baseMeta->is<ExistentialMetatypeType>();
        baseTy = baseMeta->getInstanceType();
      }

      // Build a member reference.
      auto memberRef = resolveConcreteDeclRef(member, memberLocator);

      // If we're referring to a member type, it's just a type
      // reference.
      if (auto *TD = dyn_cast<TypeDecl>(member)) {
        Type refType = simplifyType(openedType);
        auto ref = TypeExpr::createForDecl(memberLoc, TD, cs.DC);
        cs.setType(ref, refType);
        auto *result = new (context) DotSyntaxBaseIgnoredExpr(
            base, dotLoc, ref, refType);
        cs.setType(result, refType);
        return result;
      }

      auto refTy = simplifyType(overload.openedFullType);

      // If we're referring to the member of a module, it's just a simple
      // reference.
      if (baseTy->is<ModuleType>()) {
        assert(semantics == AccessSemantics::Ordinary &&
               "Direct property access doesn't make sense for this");
        auto ref = new (context) DeclRefExpr(memberRef, memberLoc, Implicit);
        cs.setType(ref, refTy);
        ref->setFunctionRefKind(choice.getFunctionRefKind());
        auto *DSBI = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr(
            base, dotLoc, ref, cs.getType(ref)));
        return forceUnwrapIfExpected(DSBI, choice, memberLocator);
      }

      bool isUnboundInstanceMember =
        (!baseIsInstance && member->isInstanceMember());
      bool isPartialApplication = shouldBuildCurryThunk(choice, baseIsInstance);

      // The formal type of the 'self' value for the member's declaration.
      Type containerTy = getBaseType(refTy->castTo<FunctionType>());

      // If we have an opened existential, selfTy and baseTy will both be
      // the same opened existential type.
      Type selfTy = containerTy;

      // If we opened up an existential when referencing this member, update
      // the base accordingly.
      bool openedExistential = false;

      // For a partial application, we have to open the existential inside
      // the thunk itself.
      auto knownOpened = solution.OpenedExistentialTypes.find(
                           getConstraintSystem().getConstraintLocator(
                             memberLocator));
      if (knownOpened != solution.OpenedExistentialTypes.end()) {
        // Determine if we're going to have an OpenExistentialExpr around
        // this member reference.
        //
        // If we have a partial application of a protocol method, we open
        // the existential in the curry thunk, instead of opening it here,
        // because we won't have a 'self' value until the curry thunk is
        // applied.
        //
        // However, a partial application of a class method on a subclass
        // existential does need to open the existential, so that it can be
        // upcast to the appropriate class reference type.
        if (!isPartialApplication || !containerTy->hasOpenedExistential()) {
          // Open the existential before performing the member reference.
          base = openExistentialReference(base, knownOpened->second, member);
          baseTy = knownOpened->second;
          selfTy = baseTy;
          openedExistential = true;
        } else {
          // Erase opened existentials from the type of the thunk; we're
          // going to open the existential inside the thunk's body.
          containerTy = containerTy->eraseOpenedExistential(knownOpened->second);
          selfTy = containerTy;
        }
      }

      // References to properties with accessors and storage usually go
      // through the accessors, but sometimes are direct.
      if (auto *VD = dyn_cast<VarDecl>(member)) {
        if (semantics == AccessSemantics::Ordinary)
          semantics = getImplicitMemberReferenceAccessSemantics(base, VD, dc);
      }

      auto isDynamic = choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
      if (baseIsInstance) {
        // Convert the base to the appropriate container type, turning it
        // into an lvalue if required.

        // If the base is already an lvalue with the right base type, we can
        // pass it as an inout qualified type.
        auto selfParamTy = isDynamic ? selfTy : containerTy;

        if (selfTy->isEqual(baseTy))
          if (cs.getType(base)->is<LValueType>())
            selfParamTy = InOutType::get(selfTy);

        base = coerceSelfArgumentToType(
                 base, selfParamTy, member,
                 locator.withPathElement(ConstraintLocator::MemberRefBase));
      } else {
        if (!isExistentialMetatype || openedExistential) {
          // Convert the base to an rvalue of the appropriate metatype.
          base = coerceToType(base,
                              MetatypeType::get(
                                isDynamic ? selfTy : containerTy),
                              locator.withPathElement(
                                ConstraintLocator::MemberRefBase));
        }

        if (!base)
          return nullptr;

        base = cs.coerceToRValue(base);
      }
      assert(base && "Unable to convert base?");

      // Handle dynamic references.
      if (isDynamic || member->getAttrs().hasAttribute<OptionalAttr>()) {
        base = cs.coerceToRValue(base);
        Expr *ref = new (context) DynamicMemberRefExpr(base, dotLoc, memberRef,
                                                       memberLoc);
        ref->setImplicit(Implicit);
        // FIXME: FunctionRefKind

        // Compute the type of the reference.
        Type refType = simplifyType(openedType);

        // If the base was an opened existential, erase the opened
        // existential.
        if (openedExistential) {
          refType = refType->eraseOpenedExistential(
              baseTy->castTo<OpenedArchetypeType>());
        }

        cs.setType(ref, refType);

        closeExistential(ref, locator, /*force=*/openedExistential);

        // If this attribute was inferred based on deprecated Swift 3 rules,
        // complain.
        if (auto attr = member->getAttrs().getAttribute<ObjCAttr>()) {
          if (attr->isSwift3Inferred() &&
              context.LangOpts.WarnSwift3ObjCInference ==
                  Swift3ObjCInferenceWarnings::Minimal) {
            context.Diags.diagnose(
                memberLoc, diag::expr_dynamic_lookup_swift3_objc_inference,
                member->getDescriptiveKind(), member->getName(),
                member->getDeclContext()->getSelfNominalTypeDecl()->getName());
            context.Diags
                .diagnose(member, diag::make_decl_objc,
                          member->getDescriptiveKind())
                .fixItInsert(member->getAttributeInsertionLoc(false), "@objc ");
          }
        }

        if (isDynamic) {
          // Rewrite for implicit unwrapping if the solution requires it.
          auto *dynamicLocator =
              cs.getConstraintLocator(memberLocator.withPathElement(
                  ConstraintLocator::DynamicLookupResult));

          if (solution.getDisjunctionChoice(dynamicLocator)) {
            auto *forceValue =
                new (context) ForceValueExpr(ref, ref->getEndLoc());
            auto optTy = cs.getType(forceValue->getSubExpr());
            cs.setType(forceValue, optTy->getOptionalObjectType());
            ref = forceValue;
          }
        }

        // We also need to handle the implicitly unwrap of the result
        // of the called function if that's the type checking solution
        // we ended up with.
        return forceUnwrapIfExpected(
            ref, choice, memberLocator,
            member->getAttrs().hasAttribute<OptionalAttr>());
      }

      // For properties, build member references.
      if (auto *varDecl = dyn_cast<VarDecl>(member)) {
        if (isUnboundInstanceMember) {
          assert(memberLocator.getBaseLocator() &&
                 cs.UnevaluatedRootExprs.count(
                     getAsExpr(memberLocator.getBaseLocator()->getAnchor())) &&
                 "Attempt to reference an instance member of a metatype");
          auto baseInstanceTy = cs.getType(base)
              ->getInOutObjectType()->getMetatypeInstanceType();
          base = new (context) UnevaluatedInstanceExpr(base, baseInstanceTy);
          cs.cacheType(base);
          base->setImplicit();
        }

        auto hasDynamicSelf =
          varDecl->getValueInterfaceType()->hasDynamicSelfType();

        auto memberRefExpr
          = new (context) MemberRefExpr(base, dotLoc, memberRef,
                                        memberLoc, Implicit, semantics);
        memberRefExpr->setIsSuper(isSuper);

        if (hasDynamicSelf)
          refTy = refTy->replaceCovariantResultType(containerTy, 1);
        cs.setType(memberRefExpr, refTy->castTo<FunctionType>()->getResult());

        Expr *result = memberRefExpr;
        closeExistential(result, locator);

        if (hasDynamicSelf) {
          if (!baseTy->isEqual(containerTy)) {
            result = new (context) CovariantReturnConversionExpr(
                result, simplifyType(openedType));
            cs.cacheType(result);
          }
        }
        return forceUnwrapIfExpected(result, choice, memberLocator);
      }

      if (member->getInterfaceType()->hasDynamicSelfType())
        refTy = refTy->replaceCovariantResultType(containerTy, 2);

      // Handle all other references.
      auto declRefExpr = new (context) DeclRefExpr(memberRef, memberLoc,
                                                   Implicit, semantics);
      declRefExpr->setFunctionRefKind(choice.getFunctionRefKind());
      declRefExpr->setType(refTy);
      cs.setType(declRefExpr, refTy);
      Expr *ref = declRefExpr;

      if (isPartialApplication) {
        auto curryThunkTy = refTy->castTo<FunctionType>();

        // A partial application thunk consists of two nested closures:
        //
        // { self in { args... in self.method(args...) } }
        //
        // If the reference has an applied 'self', eg 'let fn = foo.method',
        // the outermost closure is wrapped inside a single ApplyExpr:
        //
        // { self in { args... in self.method(args...) } }(foo)
        //
        // This is done instead of just hoising the expression 'foo' up
        // into the closure, which would change evaluation order.
        //
        // However, for a super method reference, eg, 'let fn = super.foo',
        // the base expression is always a SuperRefExpr, possibly wrapped
        // by an upcast. Since SILGen expects super method calls to have a
        // very specific shape, we only emit a single closure here and
        // capture the original SuperRefExpr, since its evaluation does not
        // have side effects, instead of abstracting out a 'self' parameter.
        if (isSuper) {
          auto selfFnTy = curryThunkTy->getResult()->castTo<FunctionType>();

          auto closure = buildCurryThunk(member, selfFnTy, base, ref,
                                         memberLocator);

          // Skip the code below -- we're not building an extra level of
          // call by applying the 'super', instead the closure we just
          // built is the curried reference.
          return closure;
        }

        // Another case where we want to build a single closure is when
        // we have a partial application of a constructor on a statically-
        // derived metatype value. Again, there are no order of evaluation
        // concerns here, and keeping the call and base together in the AST
        // improves SILGen.
        if (isa<ConstructorDecl>(member) &&
            cs.isStaticallyDerivedMetatype(base)) {
          auto selfFnTy = curryThunkTy->getResult()->castTo<FunctionType>();

          // Add a useless ".self" to avoid downstream diagnostics.
          base = new (context) DotSelfExpr(base, SourceLoc(), base->getEndLoc(),
                                           cs.getType(base));
          cs.setType(base, base->getType());

          auto closure = buildCurryThunk(member, selfFnTy, base, ref,
                                         memberLocator);

          // Skip the code below -- we're not building an extra level of
          // call by applying the metatype instead the closure we just
          // built is the curried reference.
          return closure;
        }

        // Check if we need to open an existential stored inside 'self'.
        auto knownOpened = solution.OpenedExistentialTypes.find(
                             getConstraintSystem().getConstraintLocator(
                               memberLocator));
        if (knownOpened != solution.OpenedExistentialTypes.end()) {
          curryThunkTy =
            curryThunkTy->eraseOpenedExistential(knownOpened->second)
              ->castTo<FunctionType>();
        }

        auto discriminator = AutoClosureExpr::InvalidDiscriminator;

        // The outer closure.
        //
        //    let outerClosure = "{ self in \(closure) }"
        auto selfParam = curryThunkTy->getParams()[0];
        auto selfParamDecl = new (context) ParamDecl(
            SourceLoc(),
            /*argument label*/ SourceLoc(), Identifier(),
            /*parameter name*/ SourceLoc(), context.Id_self,
            cs.DC);

        auto selfParamTy = selfParam.getPlainType();
        bool isLValue = selfParam.isInOut();

        selfParamDecl->setInterfaceType(selfParamTy->mapTypeOutOfContext());
        selfParamDecl->setSpecifier(
          ParamDecl::getParameterSpecifierForValueOwnership(
            selfParam.getValueOwnership()));

        auto *outerParams =
            ParameterList::create(context, SourceLoc(), selfParamDecl,
                                  SourceLoc());

        // The inner closure.
        //
        //     let closure = "{ args... in self.member(args...) }"
        auto selfFnTy = curryThunkTy->getResult()->castTo<FunctionType>();

        Expr *selfParamRef =
            new (context) DeclRefExpr(selfParamDecl, DeclNameLoc(),
                                      /*implicit=*/true);

        selfParamRef->setType(
          isLValue ? LValueType::get(selfParamTy) : selfParamTy);
        cs.cacheType(selfParamRef);

        if (isLValue) {
          selfParamRef =
            new (context) InOutExpr(SourceLoc(), selfParamRef, selfParamTy,
                                    /*implicit=*/true);
          cs.cacheType(selfParamRef);
        }

        auto closure = buildCurryThunk(member, selfFnTy, selfParamRef, ref,
                                       memberLocator);

        auto outerClosure =
            new (context) AutoClosureExpr(closure, selfFnTy,
                                          discriminator, cs.DC);
        outerClosure->setThunkKind(AutoClosureExpr::Kind::DoubleCurryThunk);

        outerClosure->setParameterList(outerParams);
        outerClosure->setType(curryThunkTy);
        cs.cacheType(outerClosure);

        // Replace the DeclRefExpr with a closure expression which SILGen
        // knows how to emit.
        ref = outerClosure;
      }

      // If this is a method whose result type is dynamic Self, or a
      // construction, replace the result type with the actual object type.
      if (!member->getDeclContext()->getSelfProtocolDecl()) {
        if (auto func = dyn_cast<AbstractFunctionDecl>(member)) {
          if (func->hasDynamicSelfResult() &&
              !baseTy->getOptionalObjectType()) {
            if (!baseTy->isEqual(containerTy)) {
              auto dynamicSelfFnType = refTy->replaceCovariantResultType(baseTy, 2);
              ref = new (context) CovariantFunctionConversionExpr(ref,
                                                            dynamicSelfFnType);
              cs.cacheType(ref);
            }
          }
        }
      }

      ApplyExpr *apply;
      if (isa<ConstructorDecl>(member)) {
        // FIXME: Provide type annotation.
        ref = forceUnwrapIfExpected(ref, choice, memberLocator);
        apply = new (context) ConstructorRefCallExpr(ref, base);
      } else if (isUnboundInstanceMember) {
        auto refType = cs.simplifyType(openedType);
        if (!cs.getType(ref)->isEqual(refType)) {
          ref = new (context) FunctionConversionExpr(ref, refType);
          cs.cacheType(ref);
        }

        // Reference to an unbound instance method.
        Expr *result = new (context) DotSyntaxBaseIgnoredExpr(base, dotLoc,
                                                              ref,
                                                              cs.getType(ref));
        cs.cacheType(result);
        closeExistential(result, locator, /*force=*/openedExistential);
        return forceUnwrapIfExpected(result, choice, memberLocator);
      } else {
        assert((!baseIsInstance || member->isInstanceMember()) &&
               "can't call a static method on an instance");
        ref = forceUnwrapIfExpected(ref, choice, memberLocator);
        apply = new (context) DotSyntaxCallExpr(ref, dotLoc, base);
        if (Implicit) {
          apply->setImplicit();
        }
      }

      return finishApply(apply, openedType, locator, memberLocator);
    }

    /// Convert the given literal expression via a protocol pair.
    ///
    /// This routine handles the two-step literal conversion process used
    /// by integer, float, character, extended grapheme cluster, and string
    /// literals. The first step uses \c builtinProtocol while the second
    /// step uses \c protocol.
    ///
    /// \param literal The literal expression.
    ///
    /// \param type The literal type. This type conforms to \c protocol,
    /// and may also conform to \c builtinProtocol.
    ///
    /// \param protocol The protocol that describes the literal requirement.
    ///
    /// \param literalType The name of the associated type in \c protocol that
    /// describes the argument type of the conversion function (\c
    /// literalFuncName).
    ///
    /// \param literalFuncName The name of the conversion function requirement
    /// in \c protocol.
    ///
    /// \param builtinProtocol The "builtin" form of the protocol, which
    /// always takes builtin types and can only be properly implemented
    /// by standard library types. If \c type does not conform to this
    /// protocol, it's literal type will.
    ///
    /// \param builtinLiteralFuncName The name of the conversion function
    /// requirement in \c builtinProtocol.
    ///
    /// \param brokenProtocolDiag The diagnostic to emit if the protocol
    /// is broken.
    ///
    /// \param brokenBuiltinProtocolDiag The diagnostic to emit if the builtin
    /// protocol is broken.
    ///
    /// \returns the converted literal expression.
    Expr *convertLiteralInPlace(LiteralExpr *literal, Type type,
                                ProtocolDecl *protocol, Identifier literalType,
                                DeclName literalFuncName,
                                ProtocolDecl *builtinProtocol,
                                DeclName builtinLiteralFuncName,
                                Diag<> brokenProtocolDiag,
                                Diag<> brokenBuiltinProtocolDiag);

    /// Finish a function application by performing the appropriate
    /// conversions on the function and argument expressions and setting
    /// the resulting type.
    ///
    /// \param apply The function application to finish type-checking, which
    /// may be a newly-built expression.
    ///
    /// \param openedType The "opened" type this expression had during
    /// type checking, which will be used to specialize the resulting,
    /// type-checked expression appropriately.
    ///
    /// \param locator The locator for the original expression.
    ///
    /// \param calleeLocator The locator that identifies the apply's callee.
    Expr *finishApply(ApplyExpr *apply, Type openedType,
                      ConstraintLocatorBuilder locator,
                      ConstraintLocatorBuilder calleeLocator);

    /// Build the function and argument for a `@dynamicCallable` application.
    std::pair</*fn*/ Expr *, /*arg*/ Expr *>
    buildDynamicCallable(ApplyExpr *apply, SelectedOverload selected,
                         FuncDecl *method, AnyFunctionType *methodType,
                         ConstraintLocatorBuilder applyFunctionLoc);

  private:
    /// Simplify the given type by substituting all occurrences of
    /// type variables for their fixed types.
    Type simplifyType(Type type) {
      return solution.simplifyType(type);
    }

  public:
    /// Coerce the given expression to the given type.
    ///
    /// This operation cannot fail.
    ///
    /// \param expr The expression to coerce.
    /// \param toType The type to coerce the expression to.
    /// \param locator Locator used to describe where in this expression we are.
    /// \param typeFromPattern Optionally, the caller can specify the pattern
    ///   from where the toType is derived, so that we can deliver better fixit.
    ///
    /// \returns the coerced expression, which will have type \c ToType.
    Expr *coerceToType(Expr *expr, Type toType,
                       ConstraintLocatorBuilder locator,
                       Optional<Pattern*> typeFromPattern = None);
    
    /// Coerce the given expression (which is the argument to a call) to
    /// the given parameter type.
    ///
    /// This operation cannot fail.
    ///
    /// \param arg The argument expression.
    /// \param funcType The function type.
    /// \param callee The callee for the function being applied.
    /// \param apply The ApplyExpr that forms the call.
    /// \param argLabels The argument labels provided for the call.
    /// \param locator Locator used to describe where in this expression we are.
    ///
    /// \returns the coerced expression, which will have type \c ToType.
    Expr *
    coerceCallArguments(Expr *arg, AnyFunctionType *funcType,
                        ConcreteDeclRef callee, ApplyExpr *apply,
                        ArrayRef<Identifier> argLabels,
                        ConstraintLocatorBuilder locator);

    /// Coerce the given 'self' argument (e.g., for the base of a
    /// member expression) to the given type.
    ///
    /// \param expr The expression to coerce.
    ///
    /// \param baseTy The base type
    ///
    /// \param member The member being accessed.
    ///
    /// \param locator Locator used to describe where in this expression we are.
    Expr *coerceSelfArgumentToType(Expr *expr,
                                   Type baseTy, ValueDecl *member,
                                   ConstraintLocatorBuilder locator);

  private:
    /// Build a new subscript.
    ///
    /// \param base The base of the subscript.
    /// \param index The index of the subscript.
    /// \param locator The locator used to refer to the subscript.
    /// \param isImplicit Whether this is an implicit subscript.
    Expr *buildSubscript(Expr *base, Expr *index,
                         ArrayRef<Identifier> argLabels,
                         bool hasTrailingClosure,
                         ConstraintLocatorBuilder locator, bool isImplicit,
                         AccessSemantics semantics,
                         const SelectedOverload &selected) {
      // Build the new subscript.
      auto newSubscript = buildSubscriptHelper(base, index, argLabels,
                                               selected, hasTrailingClosure,
                                               locator, isImplicit, semantics);

      if (selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic) {
        // Rewrite for implicit unwrapping if the solution requires it.
        auto *dynamicLocator = cs.getConstraintLocator(
            locator, {ConstraintLocator::SubscriptMember,
                      ConstraintLocator::DynamicLookupResult});

        if (solution.getDisjunctionChoice(dynamicLocator)) {
          auto *forceValue = new (cs.getASTContext())
              ForceValueExpr(newSubscript, newSubscript->getEndLoc());
          auto optTy = cs.getType(forceValue->getSubExpr());
          cs.setType(forceValue, optTy->getOptionalObjectType());
          newSubscript = forceValue;
        }
      }

      if (selected.choice.isDecl()) {
        auto locatorKind = ConstraintLocator::SubscriptMember;
        if (selected.choice.getKind() ==
            OverloadChoiceKind::DynamicMemberLookup)
          locatorKind = ConstraintLocator::Member;

        if (selected.choice.getKind() ==
                OverloadChoiceKind::KeyPathDynamicMemberLookup &&
            !isExpr<SubscriptExpr>(locator.getAnchor()))
          locatorKind = ConstraintLocator::Member;

        newSubscript =
            forceUnwrapIfExpected(newSubscript, selected.choice,
                                  locator.withPathElement(locatorKind));
      }

      return newSubscript;
    }

    Expr *buildSubscriptHelper(Expr *base, Expr *index,
                               ArrayRef<Identifier> argLabels,
                               const SelectedOverload &selected,
                               bool hasTrailingClosure,
                               ConstraintLocatorBuilder locator,
                               bool isImplicit, AccessSemantics semantics) {
      auto choice = selected.choice;
      auto &ctx = cs.getASTContext();

      // Apply a key path if we have one.
      if (choice.getKind() == OverloadChoiceKind::KeyPathApplication) {
        auto applicationTy =
            simplifyType(selected.openedType)->castTo<FunctionType>();

        index = cs.coerceToRValue(index);
        // The index argument should be (keyPath: KeyPath<Root, Value>).
        // Dig the key path expression out of the arguments.
        auto indexKP = cast<TupleExpr>(index)->getElement(0);
        auto keyPathExprTy = cs.getType(indexKP);
        auto keyPathTy = applicationTy->getParams().front().getOldType();

        Type valueTy;
        Type baseTy;
        bool resultIsLValue;
        
        if (auto nom = keyPathTy->getAs<NominalType>()) {
          // AnyKeyPath is <T> rvalue T -> rvalue Any?
          if (nom->getDecl() == cs.getASTContext().getAnyKeyPathDecl()) {
            valueTy = ProtocolCompositionType::get(cs.getASTContext(), {},
                                                  /*explicit anyobject*/ false);
            valueTy = OptionalType::get(valueTy);
            resultIsLValue = false;
            base = cs.coerceToRValue(base);
            baseTy = cs.getType(base);
            // We don't really want to attempt AnyKeyPath application
            // if we know a more specific key path type is being applied.
            if (!keyPathTy->isEqual(keyPathExprTy)) {
              ctx.Diags
                  .diagnose(base->getLoc(),
                            diag::expr_smart_keypath_application_type_mismatch,
                            keyPathExprTy, baseTy)
                  .highlight(index->getSourceRange());
            }
          } else {
            llvm_unreachable("unknown key path class!");
          }
        } else {
          auto keyPathBGT = keyPathTy->castTo<BoundGenericType>();
          baseTy = keyPathBGT->getGenericArgs()[0];

          // Coerce the index to the key path's type
          indexKP = coerceToType(indexKP, keyPathTy, locator);

          // Coerce the base to the key path's expected base type.
          if (!baseTy->isEqual(cs.getType(base)->getRValueType()))
            base = coerceToType(base, baseTy, locator);

          if (keyPathBGT->getDecl()
                == cs.getASTContext().getPartialKeyPathDecl()) {
            // PartialKeyPath<T> is rvalue T -> rvalue Any
            valueTy = ProtocolCompositionType::get(cs.getASTContext(), {},
                                                 /*explicit anyobject*/ false);
            resultIsLValue = false;
            base = cs.coerceToRValue(base);
          } else {
            // *KeyPath<T, U> is T -> U, with rvalueness based on mutability
            // of base and keypath
            valueTy = keyPathBGT->getGenericArgs()[1];
        
            // The result may be an lvalue based on the base and key path kind.
            if (keyPathBGT->getDecl() == cs.getASTContext().getKeyPathDecl()) {
              resultIsLValue = false;
              base = cs.coerceToRValue(base);
            } else if (keyPathBGT->getDecl() ==
                         cs.getASTContext().getWritableKeyPathDecl()) {
              resultIsLValue = cs.getType(base)->hasLValueType();
            } else if (keyPathBGT->getDecl() ==
                       cs.getASTContext().getReferenceWritableKeyPathDecl()) {
              resultIsLValue = true;
              base = cs.coerceToRValue(base);
            } else {
              llvm_unreachable("unknown key path class!");
            }
          }
        }
        if (resultIsLValue)
          valueTy = LValueType::get(valueTy);
        
        auto keyPathAp = new (cs.getASTContext())
           KeyPathApplicationExpr(base, index->getStartLoc(), indexKP,
                                  index->getEndLoc(), valueTy,
                                  base->isImplicit() && index->isImplicit());
        cs.setType(keyPathAp, valueTy);
        return keyPathAp;
      }
      
      auto subscript = cast<SubscriptDecl>(choice.getDecl());

      auto baseTy = cs.getType(base)->getRValueType();
      
      bool baseIsInstance = true;
      if (auto baseMeta = baseTy->getAs<AnyMetatypeType>()) {
        baseIsInstance = false;
        baseTy = baseMeta->getInstanceType();
      }

      // Check whether the base is 'super'.
      bool isSuper = base->isSuperExpr();

      // Use the correct locator kind based on the subscript kind.
      auto locatorKind = ConstraintLocator::SubscriptMember;
      if (choice.getKind() == OverloadChoiceKind::DynamicMemberLookup)
        locatorKind = ConstraintLocator::Member;

      if (choice.getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup) {
        locatorKind = isExpr<SubscriptExpr>(locator.getAnchor())
                          ? ConstraintLocator::SubscriptMember
                          : ConstraintLocator::Member;
      }

      // If we opened up an existential when performing the subscript, open
      // the base accordingly.
      auto memberLoc = locator.withPathElement(locatorKind);
      auto knownOpened = solution.OpenedExistentialTypes.find(
          cs.getConstraintLocator(memberLoc));
      if (knownOpened != solution.OpenedExistentialTypes.end()) {
        base = openExistentialReference(base, knownOpened->second, subscript);
        baseTy = knownOpened->second;
      }

      // Compute the concrete reference to the subscript.
      auto subscriptRef = resolveConcreteDeclRef(subscript, memberLoc);

      // Coerce the index argument.
      auto openedFullFnType = simplifyType(selected.openedFullType)
                                  ->castTo<FunctionType>();
      auto fullSubscriptTy = openedFullFnType->getResult()
                                  ->castTo<FunctionType>();
      index = coerceCallArguments(index, fullSubscriptTy, subscriptRef, nullptr,
                                  argLabels,
                                  locator.withPathElement(
                                    ConstraintLocator::ApplyArgument));
      if (!index)
        return nullptr;

      auto getType = [&](Expr *E) -> Type { return cs.getType(E); };

      // Handle dynamic lookup.
      if (choice.getKind() == OverloadChoiceKind::DeclViaDynamic ||
          subscript->getAttrs().hasAttribute<OptionalAttr>()) {
        base = coerceSelfArgumentToType(base, baseTy, subscript, locator);
        if (!base)
          return nullptr;

        // TODO: diagnose if semantics != AccessSemantics::Ordinary?
        auto subscriptExpr = DynamicSubscriptExpr::create(
            ctx, base, index, subscriptRef, isImplicit, getType);
        auto resultTy = simplifyType(selected.openedType)
                            ->castTo<FunctionType>()
                            ->getResult();
        assert(!selected.openedFullType->hasOpenedExistential()
               && "open existential archetype in AnyObject subscript type?");
        cs.setType(subscriptExpr, resultTy);
        Expr *result = subscriptExpr;
        closeExistential(result, locator);
        return result;
      }

      // Convert the base.
      auto openedBaseType =
          getBaseType(openedFullFnType, /*wantsRValue*/ false);
      auto containerTy = solution.simplifyType(openedBaseType);
      
      if (baseIsInstance) {
        base = coerceSelfArgumentToType(
          base, containerTy, subscript,
          locator.withPathElement(ConstraintLocator::MemberRefBase));
      } else {
        base = coerceToType(base,
                            MetatypeType::get(containerTy),
                            locator.withPathElement(
                              ConstraintLocator::MemberRefBase));
        
        if (!base)
          return nullptr;
        
        base = cs.coerceToRValue(base);
      }
      if (!base)
        return nullptr;

      // Form the subscript expression.
      auto subscriptExpr = SubscriptExpr::create(
          ctx, base, index, subscriptRef, isImplicit, semantics, getType);
      cs.setType(subscriptExpr, fullSubscriptTy->getResult());
      subscriptExpr->setIsSuper(isSuper);

      Expr *result = subscriptExpr;
      closeExistential(result, locator);

      if (subscript->getElementInterfaceType()->hasDynamicSelfType()) {
        auto dynamicSelfFnType =
          openedFullFnType->replaceCovariantResultType(baseTy, 2);
        result =
            new (ctx) CovariantReturnConversionExpr(result, dynamicSelfFnType);
        cs.cacheType(result);
        cs.setType(result, simplifyType(baseTy));
      }

      return result;
    }

    /// Build a new reference to another constructor.
    Expr *buildOtherConstructorRef(Type openedFullType,
                                   ConcreteDeclRef ref, Expr *base,
                                   DeclNameLoc loc,
                                   ConstraintLocatorBuilder locator,
                                   bool implicit) {
      auto &ctx = cs.getASTContext();

      // The constructor was opened with the allocating type, not the
      // initializer type. Map the former into the latter.
      auto resultTy = solution.simplifyType(openedFullType);

      auto selfTy = getBaseType(resultTy->castTo<FunctionType>());

      // Also replace the result type with the base type, so that calls
      // to constructors defined in a superclass will know to cast the
      // result to the derived type.
      resultTy = resultTy->replaceCovariantResultType(selfTy, 2);

      ParameterTypeFlags flags;
      if (!selfTy->hasReferenceSemantics())
        flags = flags.withInOut(true);

      auto selfParam = AnyFunctionType::Param(selfTy, Identifier(), flags);
      resultTy = FunctionType::get({selfParam},
                                   resultTy->castTo<FunctionType>()->getResult(),
                                   resultTy->castTo<FunctionType>()->getExtInfo());

      // Build the constructor reference.
      Expr *ctorRef = cs.cacheType(
          new (ctx) OtherConstructorDeclRefExpr(ref, loc, implicit, resultTy));

      // Wrap in covariant `Self` return if needed.
      if (selfTy->hasReferenceSemantics()) {
        auto covariantTy = resultTy->replaceCovariantResultType(
          cs.getType(base)->getWithoutSpecifierType(), 2);
        if (!covariantTy->isEqual(resultTy))
          ctorRef = cs.cacheType(
               new (ctx) CovariantFunctionConversionExpr(ctorRef, covariantTy));
      }

      return ctorRef;
    }

    /// Build an implicit argument for keypath based dynamic lookup,
    /// which consists of KeyPath expression and a single component.
    ///
    /// \param keyPathTy The type of the keypath argument.
    /// \param dotLoc The location of the '.' preceding member name.
    /// \param memberLoc The locator to be associated with new argument.
    Expr *buildKeyPathDynamicMemberIndexExpr(BoundGenericType *keyPathTy,
                                             SourceLoc dotLoc,
                                             ConstraintLocator *memberLoc) {
      auto &ctx = cs.getASTContext();
      auto *anchor = getAsExpr(memberLoc->getAnchor());

      SmallVector<KeyPathExpr::Component, 2> components;

      // Let's create a KeyPath expression and fill in "parsed path"
      // after component is built.
      auto *keyPath = new (ctx) KeyPathExpr(/*backslashLoc=*/dotLoc,
                                            /*parsedRoot=*/nullptr,
                                            /*parsedPath=*/anchor,
                                            /*hasLeadingDot=*/false,
                                            /*isImplicit=*/true);
      // Type of the keypath expression we are forming is known
      // in advance, so let's set it right away.
      keyPath->setType(keyPathTy);
      cs.cacheType(keyPath);

      auto *componentLoc = cs.getConstraintLocator(
          memberLoc,
          LocatorPathElt::KeyPathDynamicMember(keyPathTy->getAnyNominal()));
      auto overload = solution.getOverloadChoice(componentLoc);

      // Looks like there is a chain of implicit `subscript(dynamicMember:)`
      // calls necessary to resolve a member reference.
      switch (overload.choice.getKind()) {
      case OverloadChoiceKind::DynamicMemberLookup:
      case OverloadChoiceKind::KeyPathDynamicMemberLookup: {
        buildKeyPathSubscriptComponent(overload, dotLoc, /*indexExpr=*/nullptr,
                                       ctx.Id_dynamicMember, componentLoc,
                                       components);
        keyPath->resolveComponents(ctx, components);
        cs.cacheExprTypes(keyPath);
        return keyPath;
      }

      default:
        break;
      }

      // We can't reuse existing expression because type-check
      // based diagnostics could hold the reference to original AST.
      Expr *componentExpr = nullptr;
      auto *dotExpr = new (ctx) KeyPathDotExpr(dotLoc);

      // Determines whether this index is built to be used for
      // one of the existing keypath components e.g. `\Lens<[Int]>.count`
      // instead of a regular expression e.g. `lens[0]`.
      bool forKeyPathComponent = false;
      // Looks like keypath dynamic member lookup was used inside
      // of a keypath expression e.g. `\Lens<[Int]>.count` where
      // `count` is referenced using dynamic lookup.
      if (auto *KPE = dyn_cast<KeyPathExpr>(anchor)) {
        auto kpElt = memberLoc->findFirst<LocatorPathElt::KeyPathComponent>();
        assert(kpElt && "no keypath component node");
        auto &origComponent = KPE->getComponents()[kpElt->getIndex()];

        using ComponentKind = KeyPathExpr::Component::Kind;
        if (origComponent.getKind() == ComponentKind::UnresolvedProperty) {
          anchor = new (ctx) UnresolvedDotExpr(
              dotExpr, dotLoc, origComponent.getUnresolvedDeclName(),
              DeclNameLoc(origComponent.getLoc()),
              /*Implicit=*/true);
        } else if (origComponent.getKind() ==
                   ComponentKind::UnresolvedSubscript) {
          anchor = SubscriptExpr::create(
              ctx, dotExpr, origComponent.getIndexExpr(), ConcreteDeclRef(),
              /*implicit=*/true, AccessSemantics::Ordinary,
              [&](Expr *expr) { return simplifyType(cs.getType(expr)); });
        } else {
          return nullptr;
        }

        anchor->setType(simplifyType(overload.openedType));
        cs.cacheType(anchor);
        forKeyPathComponent = true;
      }

      if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
        componentExpr =
            forKeyPathComponent
                ? UDE
                : new (ctx) UnresolvedDotExpr(dotExpr, dotLoc, UDE->getName(),
                                              UDE->getNameLoc(),
                                              /*Implicit=*/true);

        buildKeyPathPropertyComponent(overload, UDE->getLoc(), componentLoc,
                                      components);
      } else if (auto *SE = dyn_cast<SubscriptExpr>(anchor)) {
        componentExpr = SE;
        // If this is not for a keypath component, we have to copy
        // original subscript expression because expression based
        // diagnostics might have a reference to it, so it couldn't
        // be modified.
        if (!forKeyPathComponent) {
          SmallVector<Expr *, 4> arguments;
          if (auto *TE = dyn_cast<TupleExpr>(SE->getIndex())) {
            auto args = TE->getElements();
            arguments.append(args.begin(), args.end());
          } else {
            arguments.push_back(SE->getIndex()->getSemanticsProvidingExpr());
          }

          SmallVector<TrailingClosure, 2> trailingClosures;
          if (SE->hasTrailingClosure()) {
            auto *closure = arguments.back();
            trailingClosures.push_back({closure});
          }

          componentExpr = SubscriptExpr::create(
              ctx, dotExpr, SE->getStartLoc(), arguments,
              SE->getArgumentLabels(), SE->getArgumentLabelLocs(),
              SE->getEndLoc(), trailingClosures,
              SE->hasDecl() ? SE->getDecl() : ConcreteDeclRef(),
              /*implicit=*/true, SE->getAccessSemantics());
        }

        buildKeyPathSubscriptComponent(overload, SE->getLoc(), SE->getIndex(),
                                       SE->getArgumentLabels(), componentLoc,
                                       components);
      } else {
        return nullptr;
      }

      assert(componentExpr);
      Type ty = simplifyType(cs.getType(anchor));
      componentExpr->setType(ty);
      cs.cacheType(componentExpr);

      keyPath->setParsedPath(componentExpr);
      keyPath->resolveComponents(ctx, components);
      cs.cacheExprTypes(keyPath);

      // See whether there's an equivalent ObjC key path string we can produce
      // for interop purposes.
      checkAndSetObjCKeyPathString(keyPath);

      return keyPath;
    }

    /// Bridge the given value (which is an error type) to NSError.
    Expr *bridgeErrorToObjectiveC(Expr *value) {
      auto &ctx = cs.getASTContext();

      auto nsErrorType = ctx.getNSErrorType();
      assert(nsErrorType && "Missing NSError?");

      auto result = new (ctx) BridgeToObjCExpr(value, nsErrorType);
      return cs.cacheType(result);
    }

    /// Bridge the given value to its corresponding Objective-C object
    /// type.
    ///
    /// This routine should only be used for bridging value types.
    ///
    /// \param value The value to be bridged.
    Expr *bridgeToObjectiveC(Expr *value, Type objcType) {
      auto result = new (cs.getASTContext()) BridgeToObjCExpr(value, objcType);
      return cs.cacheType(result);
    }

    /// Bridge the given object from Objective-C to its value type.
    ///
    /// This routine should only be used for bridging value types.
    ///
    /// \param object The object, whose type should already be of the type
    /// that the value type bridges through.
    ///
    /// \param valueType The value type to which we are bridging.
    ///
    /// \param conditional Whether the bridging should be conditional. If false,
    /// uses forced bridging.
    ///
    /// \returns a value of type \c valueType (optional if \c conditional) that
    /// stores the bridged result or (when \c conditional) an empty optional if
    /// conditional bridging fails.
    Expr *bridgeFromObjectiveC(Expr *object, Type valueType, bool conditional) {
      auto &ctx = cs.getASTContext();

      if (!conditional) {
        auto result = new (ctx) BridgeFromObjCExpr(object, valueType);
        return cs.cacheType(result);
      }

      // Find the _BridgedToObjectiveC protocol.
      auto bridgedProto =
          ctx.getProtocol(KnownProtocolKind::ObjectiveCBridgeable);

      // Try to find the conformance of the value type to _BridgedToObjectiveC.
      auto bridgedToObjectiveCConformance
        = TypeChecker::conformsToProtocol(valueType,
                                          bridgedProto,
                                          cs.DC);

      FuncDecl *fn = nullptr;

      if (bridgedToObjectiveCConformance) {
        assert(bridgedToObjectiveCConformance.getConditionalRequirements()
                   .empty() &&
               "cannot conditionally conform to _BridgedToObjectiveC");
        // The conformance to _BridgedToObjectiveC is statically known.
        // Retrieve the bridging operation to be used if a static conformance
        // to _BridgedToObjectiveC can be proven.
        fn = conditional ? ctx.getConditionallyBridgeFromObjectiveCBridgeable()
                         : ctx.getForceBridgeFromObjectiveCBridgeable();
      } else {
        // Retrieve the bridging operation to be used if a static conformance
        // to _BridgedToObjectiveC cannot be proven.
        fn = conditional ? ctx.getConditionallyBridgeFromObjectiveC()
                         : ctx.getForceBridgeFromObjectiveC();
      }

      if (!fn) {
        ctx.Diags.diagnose(object->getLoc(), diag::missing_bridging_function,
                           conditional);
        return nullptr;
      }

      // Form a reference to the function. The bridging operations are generic,
      // so we need to form substitutions and compute the resulting type.
      auto genericSig = fn->getGenericSignature();

      auto subMap = SubstitutionMap::get(
          genericSig,
          [&](SubstitutableType *type) -> Type {
            assert(type->isEqual(genericSig->getGenericParams()[0]));
            return valueType;
          },
          [&](CanType origType, Type replacementType,
              ProtocolDecl *protoType) -> ProtocolConformanceRef {
            assert(bridgedToObjectiveCConformance);
            return bridgedToObjectiveCConformance;
          });

      ConcreteDeclRef fnSpecRef(fn, subMap);

      auto resultType = OptionalType::get(valueType);

      auto result = new (ctx)
          ConditionalBridgeFromObjCExpr(object, resultType, fnSpecRef);
      return cs.cacheType(result);
    }

    /// Bridge the given object from Objective-C to its value type.
    ///
    /// This routine should only be used for bridging value types.
    ///
    /// \param object The object, whose type should already be of the type
    /// that the value type bridges through.
    ///
    /// \param valueType The value type to which we are bridging.
    ///
    /// \returns a value of type \c valueType that stores the bridged result.
    Expr *forceBridgeFromObjectiveC(Expr *object, Type valueType) {
      return bridgeFromObjectiveC(object, valueType, false);
    }
    
  public:
    ExprRewriter(ConstraintSystem &cs, Solution &solution,
                 Optional<SolutionApplicationTarget> target,
                 bool suppressDiagnostics)
        : cs(cs), dc(cs.DC), solution(solution), target(target),
          SuppressDiagnostics(suppressDiagnostics) {}

    ConstraintSystem &getConstraintSystem() const { return cs; }

    /// Simplify the expression type and return the expression.
    ///
    /// This routine is used for 'simple' expressions that only need their
    /// types simplified, with no further computation.
    Expr *simplifyExprType(Expr *expr) {
      auto toType = simplifyType(cs.getType(expr));
      cs.setType(expr, toType);
      return expr;
    }

    Expr *visitErrorExpr(ErrorExpr *expr) {
      // Do nothing with error expressions.
      return expr;
    }

    Expr *visitCodeCompletionExpr(CodeCompletionExpr *expr) {
      // Do nothing with code completion expressions.
      auto toType = simplifyType(cs.getType(expr));
      cs.setType(expr, toType);
      return expr;
    }

    Expr *handleIntegerLiteralExpr(LiteralExpr *expr) {
      // If the literal has been assigned a builtin integer type,
      // don't mess with it.
      if (cs.getType(expr)->is<AnyBuiltinIntegerType>())
        return expr;

      auto &ctx = cs.getASTContext();
      ProtocolDecl *protocol = TypeChecker::getProtocol(
          cs.getASTContext(), expr->getLoc(),
          KnownProtocolKind::ExpressibleByIntegerLiteral);
      ProtocolDecl *builtinProtocol = TypeChecker::getProtocol(
          cs.getASTContext(), expr->getLoc(),
          KnownProtocolKind::ExpressibleByBuiltinIntegerLiteral);

      // For type-sugar reasons, prefer the spelling of the default literal
      // type.
      auto type = simplifyType(cs.getType(expr));
      if (auto defaultType = TypeChecker::getDefaultType(protocol, dc)) {
        if (defaultType->isEqual(type))
          type = defaultType;
      }
      if (auto floatProtocol = TypeChecker::getProtocol(
              cs.getASTContext(), expr->getLoc(),
              KnownProtocolKind::ExpressibleByFloatLiteral)) {
        if (auto defaultFloatType =
                TypeChecker::getDefaultType(floatProtocol, dc)) {
          if (defaultFloatType->isEqual(type))
            type = defaultFloatType;
        }
      }

      DeclName initName(ctx, DeclBaseName::createConstructor(),
                        {ctx.Id_integerLiteral});
      DeclName builtinInitName(ctx, DeclBaseName::createConstructor(),
                               {ctx.Id_builtinIntegerLiteral});

      auto *result = convertLiteralInPlace(
          expr, type, protocol, ctx.Id_IntegerLiteralType, initName,
          builtinProtocol, builtinInitName, diag::integer_literal_broken_proto,
          diag::builtin_integer_literal_broken_proto);
      if (result) {
        // TODO: It seems that callers expect this to have types assigned...
        result->setType(cs.getType(result));
      }
      return result;
    }
    
    Expr *visitNilLiteralExpr(NilLiteralExpr *expr) {
      auto type = simplifyType(cs.getType(expr));

      // By far the most common 'nil' literal is for Optional<T>.none.
      // We don't have to look up the witness in this case since SILGen
      // knows how to lower it directly.
      if (auto objectType = type->getOptionalObjectType()) {
        cs.setType(expr, type);
        return expr;
      }

      auto &ctx = cs.getASTContext();
      auto *protocol = TypeChecker::getProtocol(
          ctx, expr->getLoc(), KnownProtocolKind::ExpressibleByNilLiteral);

      // For type-sugar reasons, prefer the spelling of the default literal
      // type.
      if (auto defaultType = TypeChecker::getDefaultType(protocol, dc)) {
        if (defaultType->isEqual(type))
          type = defaultType;
      }

      DeclName initName(ctx, DeclBaseName::createConstructor(),
                        {ctx.Id_nilLiteral});
      return convertLiteralInPlace(expr, type, protocol,
                                   Identifier(), initName,
                                   nullptr,
                                   Identifier(),
                                   diag::nil_literal_broken_proto,
                                   diag::nil_literal_broken_proto);
    }

    
    Expr *visitIntegerLiteralExpr(IntegerLiteralExpr *expr) {
      return handleIntegerLiteralExpr(expr);
    }

    Expr *visitFloatLiteralExpr(FloatLiteralExpr *expr) {
      // If the literal has been assigned a builtin float type,
      // don't mess with it.
      if (cs.getType(expr)->is<BuiltinFloatType>())
        return expr;

      auto &ctx = cs.getASTContext();
      ProtocolDecl *protocol = TypeChecker::getProtocol(
          cs.getASTContext(), expr->getLoc(),
          KnownProtocolKind::ExpressibleByFloatLiteral);
      ProtocolDecl *builtinProtocol = TypeChecker::getProtocol(
          cs.getASTContext(), expr->getLoc(),
          KnownProtocolKind::ExpressibleByBuiltinFloatLiteral);

      // For type-sugar reasons, prefer the spelling of the default literal
      // type.
      auto type = simplifyType(cs.getType(expr));
      if (auto defaultType = TypeChecker::getDefaultType(protocol, dc)) {
        if (defaultType->isEqual(type))
          type = defaultType;
      }

      // Get the _MaxBuiltinFloatType decl, or look for it if it's not cached.
      auto maxFloatTypeDecl = ctx.get_MaxBuiltinFloatTypeDecl();
      // Presence of this declaration has been validated in CSGen.
      assert(maxFloatTypeDecl);

      auto maxType = maxFloatTypeDecl->getUnderlyingType();

      DeclName initName(ctx, DeclBaseName::createConstructor(),
                        {ctx.Id_floatLiteral});
      DeclName builtinInitName(ctx, DeclBaseName::createConstructor(),
                               {ctx.Id_builtinFloatLiteral});

      expr->setBuiltinType(maxType);
      return convertLiteralInPlace(
          expr, type, protocol, ctx.Id_FloatLiteralType, initName,
          builtinProtocol, builtinInitName, diag::float_literal_broken_proto,
          diag::builtin_float_literal_broken_proto);
    }

    Expr *visitBooleanLiteralExpr(BooleanLiteralExpr *expr) {
      if (cs.getType(expr) && cs.getType(expr)->is<BuiltinIntegerType>())
        return expr;

      auto &ctx = cs.getASTContext();
      ProtocolDecl *protocol = TypeChecker::getProtocol(
          cs.getASTContext(), expr->getLoc(),
          KnownProtocolKind::ExpressibleByBooleanLiteral);
      ProtocolDecl *builtinProtocol = TypeChecker::getProtocol(
          cs.getASTContext(), expr->getLoc(),
          KnownProtocolKind::ExpressibleByBuiltinBooleanLiteral);
      if (!protocol || !builtinProtocol)
        return nullptr;

      auto type = simplifyType(cs.getType(expr));
      DeclName initName(ctx, DeclBaseName::createConstructor(),
                        {ctx.Id_booleanLiteral});
      DeclName builtinInitName(ctx, DeclBaseName::createConstructor(),
                               {ctx.Id_builtinBooleanLiteral});
      return convertLiteralInPlace(
          expr, type, protocol, ctx.Id_BooleanLiteralType, initName,
          builtinProtocol, builtinInitName, diag::boolean_literal_broken_proto,
          diag::builtin_boolean_literal_broken_proto);
    }

    Expr *handleStringLiteralExpr(LiteralExpr *expr) {
      auto stringLiteral = dyn_cast<StringLiteralExpr>(expr);
      auto magicLiteral = dyn_cast<MagicIdentifierLiteralExpr>(expr);
      assert(bool(stringLiteral) != bool(magicLiteral) &&
             "literal must be either a string literal or a magic literal");

      auto type = simplifyType(cs.getType(expr));
      auto &ctx = cs.getASTContext();

      bool isStringLiteral = true;
      bool isGraphemeClusterLiteral = false;
      ProtocolDecl *protocol = TypeChecker::getProtocol(
          ctx, expr->getLoc(), KnownProtocolKind::ExpressibleByStringLiteral);

      if (!TypeChecker::conformsToProtocol(type, protocol, cs.DC)) {
        // If the type does not conform to ExpressibleByStringLiteral, it should
        // be ExpressibleByExtendedGraphemeClusterLiteral.
        protocol = TypeChecker::getProtocol(
            cs.getASTContext(), expr->getLoc(),
            KnownProtocolKind::ExpressibleByExtendedGraphemeClusterLiteral);
        isStringLiteral = false;
        isGraphemeClusterLiteral = true;
      }
      if (!TypeChecker::conformsToProtocol(type, protocol, cs.DC)) {
        // ... or it should be ExpressibleByUnicodeScalarLiteral.
        protocol = TypeChecker::getProtocol(
            cs.getASTContext(), expr->getLoc(),
            KnownProtocolKind::ExpressibleByUnicodeScalarLiteral);
        isStringLiteral = false;
        isGraphemeClusterLiteral = false;
      }

      // For type-sugar reasons, prefer the spelling of the default literal
      // type.
      if (auto defaultType = TypeChecker::getDefaultType(protocol, dc)) {
        if (defaultType->isEqual(type))
          type = defaultType;
      }

      ProtocolDecl *builtinProtocol;
      Identifier literalType;
      DeclName literalFuncName;
      DeclName builtinLiteralFuncName;
      Diag<> brokenProtocolDiag;
      Diag<> brokenBuiltinProtocolDiag;

      if (isStringLiteral) {
        literalType = ctx.Id_StringLiteralType;

        literalFuncName = DeclName(ctx, DeclBaseName::createConstructor(),
                                   {ctx.Id_stringLiteral});

        builtinProtocol = TypeChecker::getProtocol(
            cs.getASTContext(), expr->getLoc(),
            KnownProtocolKind::ExpressibleByBuiltinStringLiteral);
        builtinLiteralFuncName =
            DeclName(ctx, DeclBaseName::createConstructor(),
                     {ctx.Id_builtinStringLiteral,
                      ctx.getIdentifier("utf8CodeUnitCount"),
                      ctx.getIdentifier("isASCII")});
        if (stringLiteral)
          stringLiteral->setEncoding(StringLiteralExpr::UTF8);
        else
          magicLiteral->setStringEncoding(StringLiteralExpr::UTF8);

        brokenProtocolDiag = diag::string_literal_broken_proto;
        brokenBuiltinProtocolDiag = diag::builtin_string_literal_broken_proto;
      } else if (isGraphemeClusterLiteral) {
        literalType = ctx.Id_ExtendedGraphemeClusterLiteralType;
        literalFuncName = DeclName(ctx, DeclBaseName::createConstructor(),
                                   {ctx.Id_extendedGraphemeClusterLiteral});
        builtinLiteralFuncName =
            DeclName(ctx, DeclBaseName::createConstructor(),
                     {ctx.Id_builtinExtendedGraphemeClusterLiteral,
                      ctx.getIdentifier("utf8CodeUnitCount"),
                      ctx.getIdentifier("isASCII")});

        builtinProtocol = TypeChecker::getProtocol(
            cs.getASTContext(), expr->getLoc(),
            KnownProtocolKind::
                ExpressibleByBuiltinExtendedGraphemeClusterLiteral);
        brokenProtocolDiag =
            diag::extended_grapheme_cluster_literal_broken_proto;
        brokenBuiltinProtocolDiag =
            diag::builtin_extended_grapheme_cluster_literal_broken_proto;
      } else {
        // Otherwise, we should have just one Unicode scalar.
        literalType = ctx.Id_UnicodeScalarLiteralType;

        literalFuncName = DeclName(ctx, DeclBaseName::createConstructor(),
                                   {ctx.Id_unicodeScalarLiteral});
        builtinLiteralFuncName =
            DeclName(ctx, DeclBaseName::createConstructor(),
                     {ctx.Id_builtinUnicodeScalarLiteral});

        builtinProtocol = TypeChecker::getProtocol(
            cs.getASTContext(), expr->getLoc(),
            KnownProtocolKind::ExpressibleByBuiltinUnicodeScalarLiteral);

        brokenProtocolDiag = diag::unicode_scalar_literal_broken_proto;
        brokenBuiltinProtocolDiag =
            diag::builtin_unicode_scalar_literal_broken_proto;

        stringLiteral->setEncoding(StringLiteralExpr::OneUnicodeScalar);
      }

      return convertLiteralInPlace(expr,
                                   type,
                                   protocol,
                                   literalType,
                                   literalFuncName,
                                   builtinProtocol,
                                   builtinLiteralFuncName,
                                   brokenProtocolDiag,
                                   brokenBuiltinProtocolDiag);
    }
    
    Expr *visitStringLiteralExpr(StringLiteralExpr *expr) {
      return handleStringLiteralExpr(expr);
    }

    Expr *
    visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *expr) {
      // Figure out the string type we're converting to.
      auto openedType = cs.getType(expr);
      auto type = simplifyType(openedType);
      cs.setType(expr, type);

      auto &ctx = cs.getASTContext();
      auto loc = expr->getStartLoc();

      auto fetchProtocolInitWitness =
          [&](KnownProtocolKind protocolKind, Type type,
              ArrayRef<Identifier> argLabels) -> ConcreteDeclRef {
        auto proto = TypeChecker::getProtocol(ctx, loc, protocolKind);
        assert(proto && "Missing string interpolation protocol?");

        auto conformance =
          TypeChecker::conformsToProtocol(type, proto, cs.DC);
        assert(conformance && "string interpolation type conforms to protocol");

        DeclName constrName(ctx, DeclBaseName::createConstructor(), argLabels);

        ConcreteDeclRef witness =
            conformance.getWitnessByName(type->getRValueType(), constrName);
        if (!witness || !isa<AbstractFunctionDecl>(witness.getDecl()))
          return nullptr;
        return witness;
      };

      auto *interpolationProto = TypeChecker::getProtocol(
          cs.getASTContext(), expr->getLoc(),
          KnownProtocolKind::ExpressibleByStringInterpolation);
      auto associatedTypeDecl =
          interpolationProto->getAssociatedType(ctx.Id_StringInterpolation);
      if (associatedTypeDecl == nullptr) {
        ctx.Diags.diagnose(expr->getStartLoc(),
                           diag::interpolation_broken_proto);
        return nullptr;
      }
      auto interpolationType =
        simplifyType(DependentMemberType::get(openedType, associatedTypeDecl));

      // Fetch needed witnesses.
      ConcreteDeclRef builderInit = fetchProtocolInitWitness(
          KnownProtocolKind::StringInterpolationProtocol, interpolationType,
          {ctx.Id_literalCapacity, ctx.Id_interpolationCount});
      if (!builderInit) return nullptr;
      expr->setBuilderInit(builderInit);

      ConcreteDeclRef resultInit = fetchProtocolInitWitness(
          KnownProtocolKind::ExpressibleByStringInterpolation, type,
          {ctx.Id_stringInterpolation});
      if (!resultInit) return nullptr;
      expr->setInitializer(resultInit);

      // Make the integer literals for the parameters.
      auto buildExprFromUnsigned = [&](unsigned value) {
        LiteralExpr *expr = IntegerLiteralExpr::createFromUnsigned(ctx, value);
        cs.setType(expr, ctx.getIntDecl()->getDeclaredInterfaceType());
        return handleIntegerLiteralExpr(expr);
      };

      expr->setLiteralCapacityExpr(
          buildExprFromUnsigned(expr->getLiteralCapacity()));
      expr->setInterpolationCountExpr(
          buildExprFromUnsigned(expr->getInterpolationCount()));

      // This OpaqueValueExpr represents the result of builderInit above in
      // silgen.
      OpaqueValueExpr *interpolationExpr =
          new (ctx) OpaqueValueExpr(expr->getSourceRange(), interpolationType);
      cs.setType(interpolationExpr, interpolationType);
      expr->setInterpolationExpr(interpolationExpr);

      auto appendingExpr = expr->getAppendingExpr();
      appendingExpr->setSubExpr(interpolationExpr);

      return expr;
    }
    
    Expr *visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *expr) {
      switch (expr->getKind()) {
#define MAGIC_STRING_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
      case MagicIdentifierLiteralExpr::NAME: \
        return handleStringLiteralExpr(expr);
#define MAGIC_INT_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
      case MagicIdentifierLiteralExpr::NAME: \
        return handleIntegerLiteralExpr(expr);
#define MAGIC_POINTER_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
      case MagicIdentifierLiteralExpr::NAME: \
        return expr;
#include "swift/AST/MagicIdentifierKinds.def"
      }


      llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in switch.");
    }

    Expr *visitObjectLiteralExpr(ObjectLiteralExpr *expr) {
      if (cs.getType(expr) && !cs.getType(expr)->hasTypeVariable())
        return expr;

      // Figure out the type we're converting to.
      auto openedType = cs.getType(expr);
      auto type = simplifyType(openedType);
      cs.setType(expr, type);

      if (type->is<UnresolvedType>())
        return expr;

      auto &ctx = cs.getASTContext();

      Type conformingType = type;
      if (auto baseType = conformingType->getOptionalObjectType()) {
        // The type may be optional due to a failable initializer in the
        // protocol.
        conformingType = baseType;
      }

      // Find the appropriate object literal protocol.
      auto proto = TypeChecker::getLiteralProtocol(ctx, expr);
      assert(proto && "Missing object literal protocol?");
      auto conformance =
        TypeChecker::conformsToProtocol(conformingType, proto, cs.DC);
      assert(conformance && "object literal type conforms to protocol");

      auto constrName = TypeChecker::getObjectLiteralConstructorName(ctx, expr);

      ConcreteDeclRef witness = conformance.getWitnessByName(
          conformingType->getRValueType(), constrName);

      auto selectedOverload = solution.getOverloadChoiceIfAvailable(
          cs.getConstraintLocator(expr, ConstraintLocator::ConstructorMember));

      if (!selectedOverload)
        return nullptr;

      auto fnType =
          simplifyType(selectedOverload->openedType)->castTo<FunctionType>();

      auto newArg = coerceCallArguments(
          expr->getArg(), fnType, witness,
          /*applyExpr=*/nullptr, expr->getArgumentLabels(),
          cs.getConstraintLocator(expr, ConstraintLocator::ApplyArgument));

      expr->setInitializer(witness);
      expr->setArg(newArg);
      return expr;
    }

    // Add a forced unwrap of an expression which either has type Optional<T>
    // or is a function that returns an Optional<T>. The latter turns into a
    // conversion expression that we will hoist above the ApplyExpr
    // that needs to be forced during the process of rewriting the expression.
    //
    // forForcedOptional is used to indicate that we will further need
    // to hoist this result above an explicit force of an optional that is
    // in place for something like an @optional protocol member from
    // Objective C that we might otherwise mistake for the thing we mean to
    // force here.
    Expr *forceUnwrapResult(Expr *expr, bool forForcedOptional =false) {
      auto ty = simplifyType(cs.getType(expr));

      if (forForcedOptional)
        ty = ty->getOptionalObjectType();

      if (auto *fnTy = ty->getAs<AnyFunctionType>()) {
        auto underlyingType = cs.replaceFinalResultTypeWithUnderlying(fnTy);

        auto &ctx = cs.getASTContext();
        return cs.cacheType(new (ctx) ImplicitlyUnwrappedFunctionConversionExpr(
            expr, underlyingType));
      } else {
        return coerceImplicitlyUnwrappedOptionalToValue(
            expr, ty->getWithoutSpecifierType()->getOptionalObjectType());
      }
    }

    bool shouldForceUnwrapResult(OverloadChoice choice,
                                 ConstraintLocatorBuilder locator) {
      if (!choice.isImplicitlyUnwrappedValueOrReturnValue())
        return false;

      auto *choiceLocator = cs.getConstraintLocator(locator.withPathElement(
          ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice));

      return solution.getDisjunctionChoice(choiceLocator);
    }

    Expr *forceUnwrapIfExpected(Expr *expr, OverloadChoice choice,
                                ConstraintLocatorBuilder locator,
                                bool forForcedOptional = false) {
      if (!shouldForceUnwrapResult(choice, locator))
        return expr;

      // Force the expression if required for the solution.
      return forceUnwrapResult(expr, forForcedOptional);
    }

    Expr *visitDeclRefExpr(DeclRefExpr *expr) {
      auto locator = cs.getConstraintLocator(expr);

      // Find the overload choice used for this declaration reference.
      auto selected = solution.getOverloadChoice(locator);
      return buildDeclRef(selected, expr->getNameLoc(), locator,
                          expr->isImplicit());
    }

    Expr *visitSuperRefExpr(SuperRefExpr *expr) {
      simplifyExprType(expr);
      return expr;
    }

    Expr *visitTypeExpr(TypeExpr *expr) {
      auto toType = simplifyType(cs.getType(expr));
      assert(toType->is<MetatypeType>());
      cs.setType(expr, toType);
      return expr;
    }

    Expr *visitOtherConstructorDeclRefExpr(OtherConstructorDeclRefExpr *expr) {
      cs.setType(expr, expr->getDecl()->getInitializerInterfaceType());
      return expr;
    }

    Expr *visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *expr) {
      return simplifyExprType(expr);
    }

    Expr *visitOverloadedDeclRefExpr(OverloadedDeclRefExpr *expr) {
      // Determine the declaration selected for this overloaded reference.
      auto locator = cs.getConstraintLocator(expr);
      auto selected = solution.getOverloadChoice(locator);

      return buildDeclRef(selected, expr->getNameLoc(), locator,
                          expr->isImplicit());
    }

    Expr *visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *expr) {
      // FIXME: We should have generated an overload set from this, in which
      // case we can emit a typo-correction error here but recover well.
      return nullptr;
    }

    Expr *visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *expr) {
      // Our specializations should have resolved the subexpr to the right type.
      return expr->getSubExpr();
    }

    Expr *visitMemberRefExpr(MemberRefExpr *expr) {
      auto memberLocator = cs.getConstraintLocator(expr,
                                                   ConstraintLocator::Member);
      auto selected = solution.getOverloadChoice(memberLocator);
      return buildMemberRef(
          expr->getBase(), expr->getDotLoc(), selected, expr->getNameLoc(),
          cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
          expr->getAccessSemantics());
    }

    Expr *visitDynamicMemberRefExpr(DynamicMemberRefExpr *expr) {
      llvm_unreachable("already type-checked?");
    }

    Expr *visitUnresolvedMemberExpr(UnresolvedMemberExpr *expr) {
      // If constraint solving resolved this to an UnresolvedType, then we're in
      // an ambiguity tolerant mode used for diagnostic generation.  Just leave
      // this as an unresolved member reference.
      Type resultTy = simplifyType(cs.getType(expr));
      if (resultTy->hasUnresolvedType()) {
        cs.setType(expr, resultTy);
        return expr;
      }

      auto &ctx = cs.getASTContext();
      // Find the selected member and base type.
      auto memberLocator = cs.getConstraintLocator(
                             expr, ConstraintLocator::UnresolvedMember);
      auto selected = solution.getOverloadChoice(memberLocator);

      // Unresolved member lookup always happens in a metatype so dig out the
      // instance type.
      auto baseTy = selected.choice.getBaseType()->getMetatypeInstanceType();
      baseTy = simplifyType(baseTy);

      // The base expression is simply the metatype of the base type.
      // FIXME: This location info is bogus.
      auto base = TypeExpr::createImplicitHack(expr->getDotLoc(), baseTy, ctx);
      cs.cacheExprTypes(base);

      // Build the member reference.
      auto *exprLoc = cs.getConstraintLocator(expr);
      auto result = buildMemberRef(
          base, expr->getDotLoc(), selected, expr->getNameLoc(), exprLoc,
          memberLocator, expr->isImplicit(), AccessSemantics::Ordinary);
      if (!result)
        return nullptr;

      return coerceToType(result, resultTy, cs.getConstraintLocator(expr));
    }

  private:
    /// A list of "suspicious" optional injections that come from
    /// forced downcasts.
    SmallVector<InjectIntoOptionalExpr *, 4> SuspiciousOptionalInjections;

    /// Create a member reference to the given constructor.
    Expr *applyCtorRefExpr(Expr *expr, Expr *base, SourceLoc dotLoc,
                           DeclNameLoc nameLoc, bool implicit,
                           ConstraintLocator *ctorLocator,
                           SelectedOverload overload) {
      auto choice = overload.choice;
      assert(choice.getKind() != OverloadChoiceKind::DeclViaDynamic);
      auto *ctor = cast<ConstructorDecl>(choice.getDecl());

      // If the subexpression is a metatype, build a direct reference to the
      // constructor.
      if (cs.getType(base)->is<AnyMetatypeType>()) {
        return buildMemberRef(
            base, dotLoc, overload, nameLoc, cs.getConstraintLocator(expr),
            ctorLocator, implicit, AccessSemantics::Ordinary);
      }

      // The subexpression must be either 'self' or 'super'.
      if (!base->isSuperExpr()) {
        // 'super' references have already been fully checked; handle the
        // 'self' case below.
        auto &de = cs.getASTContext().Diags;
        bool diagnoseBadInitRef = true;
        auto arg = base->getSemanticsProvidingExpr();
        if (auto dre = dyn_cast<DeclRefExpr>(arg)) {
          if (dre->getDecl()->getName() == cs.getASTContext().Id_self) {
            // We have a reference to 'self'.
            diagnoseBadInitRef = false;
            // Make sure the reference to 'self' occurs within an initializer.
            if (!dyn_cast_or_null<ConstructorDecl>(
                   cs.DC->getInnermostMethodContext())) {
              if (!SuppressDiagnostics)
                de.diagnose(dotLoc, diag::init_delegation_outside_initializer);
              return nullptr;
            }
          }
        }

        // If we need to diagnose this as a bad reference to an initializer,
        // do so now.
        if (diagnoseBadInitRef) {
          // Determine whether 'super' would have made sense as a base.
          bool hasSuper = false;
          if (auto func = cs.DC->getInnermostMethodContext()) {
            if (auto classDecl = func->getDeclContext()->getSelfClassDecl()) {
              hasSuper = classDecl->hasSuperclass();
            }
          }

          if (SuppressDiagnostics)
            return nullptr;

          de.diagnose(dotLoc, diag::bad_init_ref_base, hasSuper);
        }
      }

      // Build a partial application of the delegated initializer.
      auto callee = resolveConcreteDeclRef(ctor, ctorLocator);
      Expr *ctorRef = buildOtherConstructorRef(overload.openedFullType, callee,
                                               base, nameLoc, ctorLocator,
                                               implicit);
      auto *call = new (cs.getASTContext()) DotSyntaxCallExpr(ctorRef, dotLoc,
                                                              base);

      return finishApply(call, cs.getType(expr), cs.getConstraintLocator(expr),
                         ctorLocator);
    }

    /// Give the deprecation warning for referring to a global function
    /// when there's a method from a conditional conformance in a smaller/closer
    /// scope.
    void
    diagnoseDeprecatedConditionalConformanceOuterAccess(UnresolvedDotExpr *UDE,
                                                        ValueDecl *choice) {
      auto getBaseName = [](DeclContext *context) -> DeclName {
        if (auto generic = context->getSelfNominalTypeDecl()) {
          return generic->getName();
        } else if (context->isModuleScopeContext())
          return context->getParentModule()->getName();
        else
          llvm_unreachable("Unsupported base");
      };

      auto result =
          TypeChecker::lookupUnqualified(cs.DC, UDE->getName(), UDE->getLoc());
      assert(result && "names can't just disappear");
      // These should all come from the same place.
      auto exampleInner = result.front();
      auto innerChoice = exampleInner.getValueDecl();
      auto innerDC = exampleInner.getDeclContext()->getInnermostTypeContext();
      auto innerParentDecl = innerDC->getSelfNominalTypeDecl();
      auto innerBaseName = getBaseName(innerDC);

      auto choiceKind = choice->getDescriptiveKind();
      auto choiceDC = choice->getDeclContext();
      auto choiceBaseName = getBaseName(choiceDC);
      auto choiceParentDecl = choiceDC->getAsDecl();
      auto choiceParentKind = choiceParentDecl
                                  ? choiceParentDecl->getDescriptiveKind()
                                  : DescriptiveDeclKind::Module;

      auto &DE = cs.getASTContext().Diags;
      DE.diagnose(UDE->getLoc(),
                  diag::warn_deprecated_conditional_conformance_outer_access,
                  UDE->getName(), choiceKind, choiceParentKind, choiceBaseName,
                  innerChoice->getDescriptiveKind(),
                  innerParentDecl->getDescriptiveKind(), innerBaseName);

      auto name = choiceBaseName.getBaseIdentifier();
      SmallString<32> namePlusDot = name.str();
      namePlusDot.push_back('.');

      DE.diagnose(UDE->getLoc(),
                  diag::fix_deprecated_conditional_conformance_outer_access,
                  namePlusDot, choiceKind, name)
          .fixItInsert(UDE->getStartLoc(), namePlusDot);
    }

    Expr *applyMemberRefExpr(Expr *expr, Expr *base, SourceLoc dotLoc,
                             DeclNameLoc nameLoc, bool implicit) {
      // If we have a constructor member, handle it as a constructor.
      auto ctorLocator = cs.getConstraintLocator(
                           expr,
                           ConstraintLocator::ConstructorMember);
      if (auto selected = solution.getOverloadChoiceIfAvailable(ctorLocator)) {
        return applyCtorRefExpr(
            expr, base, dotLoc, nameLoc, implicit, ctorLocator, *selected);
      }

      // Determine the declaration selected for this overloaded reference.
      auto memberLocator = cs.getConstraintLocator(expr,
                                                   ConstraintLocator::Member);
      auto selectedElt = solution.getOverloadChoiceIfAvailable(memberLocator);

      if (!selectedElt) {
        // If constraint solving resolved this to an UnresolvedType, then we're
        // in an ambiguity tolerant mode used for diagnostic generation.  Just
        // leave this as whatever type of member reference it already is.
        Type resultTy = simplifyType(cs.getType(expr));
        cs.setType(expr, resultTy);
        return expr;
      }

      auto selected = *selectedElt;
      if (!selected.choice.getBaseType()) {
        // This is one of the "outer alternatives", meaning the innermost
        // methods didn't work out.
        //
        // The only way to get here is via an UnresolvedDotExpr with outer
        // alternatives.
        auto UDE = cast<UnresolvedDotExpr>(expr);
        diagnoseDeprecatedConditionalConformanceOuterAccess(
            UDE, selected.choice.getDecl());

        return buildDeclRef(selected, nameLoc, memberLocator, implicit);
      }

      switch (selected.choice.getKind()) {
      case OverloadChoiceKind::DeclViaBridge: {
        base = cs.coerceToRValue(base);

        // Look through an implicitly unwrapped optional.
        auto baseTy = cs.getType(base);
        auto &ctx = cs.getASTContext();
        auto baseMetaTy = baseTy->getAs<MetatypeType>();
        auto baseInstTy = (baseMetaTy ? baseMetaTy->getInstanceType() : baseTy);
        auto classTy = ctx.getBridgedToObjC(cs.DC, baseInstTy);

        if (baseMetaTy) {
          // FIXME: We're dropping side effects in the base here!
          base = TypeExpr::createImplicitHack(base->getLoc(), classTy, ctx);
          cs.cacheExprTypes(base);
        } else {
          // Bridge the base to its corresponding Objective-C object.
          base = bridgeToObjectiveC(base, classTy);
        }

        // Fall through to build the member reference.
        LLVM_FALLTHROUGH;
      }

      case OverloadChoiceKind::Decl:
      case OverloadChoiceKind::DeclViaUnwrappedOptional:
      case OverloadChoiceKind::DeclViaDynamic:
        return buildMemberRef(base, dotLoc, selected, nameLoc,
                              cs.getConstraintLocator(expr), memberLocator,
                              implicit, AccessSemantics::Ordinary);

      case OverloadChoiceKind::TupleIndex: {
        Type toType = simplifyType(cs.getType(expr));

        auto baseTy = cs.getType(base);
        // If the base type is not a tuple l-value, access to
        // its elements supposed to be r-value as well.
        //
        // This is modeled in constraint system in a way
        // that when member type is resolved by `resolveOverload`
        // it would take r-value type of the element at
        // specified index, but if it's a type variable it
        // could still be bound to l-value later.
        if (!baseTy->is<LValueType>())
          toType = toType->getRValueType();

        // If the result type is an rvalue and the base contains lvalues,
        // need a full tuple coercion to properly load & set access kind
        // on all underlying elements before taking a single element.
        if (!toType->hasLValueType() && baseTy->hasLValueType())
          base = coerceToType(base, baseTy->getRValueType(),
                              cs.getConstraintLocator(base));

        return cs.cacheType(new (cs.getASTContext())
                            TupleElementExpr(base, dotLoc,
                                             selected.choice.getTupleIndex(),
                                             nameLoc.getBaseNameLoc(), toType));
      }

      case OverloadChoiceKind::KeyPathApplication:
        llvm_unreachable("should only happen in a subscript");

      case OverloadChoiceKind::DynamicMemberLookup:
      case OverloadChoiceKind::KeyPathDynamicMemberLookup: {
        return buildDynamicMemberLookupRef(
            expr, base, dotLoc, nameLoc.getStartLoc(), selected, memberLocator);
      }
      }

      llvm_unreachable("Unhandled OverloadChoiceKind in switch.");
    }

    /// Form a type checked expression for the index of a @dynamicMemberLookup
    /// subscript index parameter.
    Expr *buildDynamicMemberLookupIndexExpr(StringRef name, SourceLoc loc,
                                            Type literalTy) {
      // Build and type check the string literal index value to the specific
      // string type expected by the subscript.
      auto &ctx = cs.getASTContext();
      auto *nameExpr = new (ctx) StringLiteralExpr(name, loc, /*implicit*/true);
      cs.setType(nameExpr, literalTy);
      return handleStringLiteralExpr(nameExpr);
    }

    Expr *buildDynamicMemberLookupRef(Expr *expr, Expr *base, SourceLoc dotLoc,
                                      SourceLoc nameLoc,
                                      const SelectedOverload &overload,
                                      ConstraintLocator *memberLocator) {
      // Application of a DynamicMemberLookup result turns
      // a member access of `x.foo` into x[dynamicMember: "foo"], or
      // x[dynamicMember: KeyPath<T, U>]
      auto &ctx = cs.getASTContext();

      // Figure out the expected type of the lookup parameter. We know the
      // openedFullType will be "xType -> indexType -> resultType".  Dig out
      // its index type.
      auto paramTy = getTypeOfDynamicMemberIndex(overload);

      Expr *argExpr = nullptr;
      if (overload.choice.getKind() ==
          OverloadChoiceKind::DynamicMemberLookup) {
        // Build and type check the string literal index value to the specific
        // string type expected by the subscript.
        auto fieldName = overload.choice.getName().getBaseIdentifier().str();
        argExpr = buildDynamicMemberLookupIndexExpr(fieldName, nameLoc,
                                                    paramTy);
      } else {
        argExpr = buildKeyPathDynamicMemberIndexExpr(
            paramTy->castTo<BoundGenericType>(), dotLoc, memberLocator);
      }

      if (!argExpr)
        return nullptr;

      // Build a tuple so that the argument has a label.
      auto tupleTy =
          TupleType::get(TupleTypeElt(paramTy, ctx.Id_dynamicMember), ctx);

      Expr *index =
          TupleExpr::createImplicit(ctx, argExpr, ctx.Id_dynamicMember);
      index->setType(tupleTy);
      cs.cacheType(index);

      // Build and return a subscript that uses this string as the index.
      return buildSubscript(
          base, index, ctx.Id_dynamicMember,
          /*trailingClosure*/ false, cs.getConstraintLocator(expr),
          /*isImplicit*/ true, AccessSemantics::Ordinary, overload);
    }

    Type getTypeOfDynamicMemberIndex(const SelectedOverload &overload) {
      assert(overload.choice.getKind() ==
                 OverloadChoiceKind::DynamicMemberLookup ||
             overload.choice.getKind() ==
                 OverloadChoiceKind::KeyPathDynamicMemberLookup);

      auto declTy = solution.simplifyType(overload.openedFullType);
      auto subscriptTy = declTy->castTo<FunctionType>()->getResult();
      auto refFnType = subscriptTy->castTo<FunctionType>();
      assert(refFnType->getParams().size() == 1 &&
             "subscript always has one arg");
      return refFnType->getParams()[0].getPlainType();
    }

  public:
    Expr *visitUnresolvedDotExpr(UnresolvedDotExpr *expr) {
      return applyMemberRefExpr(expr, expr->getBase(), expr->getDotLoc(),
                                expr->getNameLoc(), expr->isImplicit());
    }

    Expr *visitSequenceExpr(SequenceExpr *expr) {
      llvm_unreachable("Expression wasn't parsed?");
    }

    Expr *visitArrowExpr(ArrowExpr *expr) {
      llvm_unreachable("Arrow expr wasn't converted to type?");
    }

    Expr *visitIdentityExpr(IdentityExpr *expr) {
      cs.setType(expr, cs.getType(expr->getSubExpr()));
      return expr;
    }

    Expr *visitAnyTryExpr(AnyTryExpr *expr) {
      cs.setType(expr, cs.getType(expr->getSubExpr()));
      return expr;
    }

    Expr *visitOptionalTryExpr(OptionalTryExpr *expr) {
      // Prior to Swift 5, 'try?' simply wraps the type of its sub-expression
      // in an Optional, regardless of the sub-expression type.
      //
      // In Swift 5+, the type of a 'try?' expression of static type T is:
      //  - Equal to T if T is optional
      //  - Equal to T? if T is not optional
      //
      // The result is that in Swift 5, 'try?' avoids producing nested optionals.
      
      if (!cs.getASTContext().LangOpts.isSwiftVersionAtLeast(5)) {
        // Nothing to do for Swift 4 and earlier!
        return simplifyExprType(expr);
      }
      
      Type exprType = simplifyType(cs.getType(expr));

      auto subExpr = coerceToType(expr->getSubExpr(), exprType,
                                  cs.getConstraintLocator(expr));
      if (!subExpr) return nullptr;
      expr->setSubExpr(subExpr);

      cs.setType(expr, exprType);
      return expr;
    }

    Expr *visitParenExpr(ParenExpr *expr) {
      return simplifyExprType(expr);
    }

    Expr *visitUnresolvedMemberChainResultExpr(
        UnresolvedMemberChainResultExpr *expr) {
      // Since this expression only exists to give the result type of an
      // unresolved member chain visibility in the AST, remove it from the AST
      // now that we have a solution and coerce the subexpr to the resulting
      // type.
      auto *subExpr = expr->getSubExpr();
      auto type = simplifyType(cs.getType(expr));
      subExpr = coerceToType(subExpr, type, cs.getConstraintLocator(subExpr));
      cs.setType(subExpr, type);
      return subExpr;
    }

    Expr *visitTupleExpr(TupleExpr *expr) {
      return simplifyExprType(expr);
    }

    Expr *visitSubscriptExpr(SubscriptExpr *expr) {
      auto *memberLocator =
          cs.getConstraintLocator(expr, ConstraintLocator::SubscriptMember);
      auto overload = solution.getOverloadChoiceIfAvailable(memberLocator);

      // Handles situation where there was a solution available but it didn't
      // have a proper overload selected from subscript call, might be because
      // solver was allowed to return free or unresolved types, which can
      // happen while running diagnostics on one of the expressions.
      if (!overload) {
        auto *base = expr->getBase();
        auto &de = cs.getASTContext().Diags;
        auto baseType = cs.getType(base);

        if (auto errorType = baseType->getAs<ErrorType>()) {
          de.diagnose(base->getLoc(), diag::cannot_subscript_base,
                      errorType->getOriginalType())
              .highlight(base->getSourceRange());
        } else {
          de.diagnose(base->getLoc(), diag::cannot_subscript_ambiguous_base)
              .highlight(base->getSourceRange());
        }

        return nullptr;
      }

      if (overload->choice.getKind() ==
              OverloadChoiceKind::KeyPathDynamicMemberLookup) {
        return buildDynamicMemberLookupRef(
            expr, expr->getBase(), expr->getIndex()->getStartLoc(), SourceLoc(),
            *overload, memberLocator);
      }

      return buildSubscript(
          expr->getBase(), expr->getIndex(), expr->getArgumentLabels(),
          expr->hasTrailingClosure(), cs.getConstraintLocator(expr),
          expr->isImplicit(), expr->getAccessSemantics(), *overload);
    }

    /// "Finish" an array expression by filling in the semantic expression.
    ArrayExpr *finishArrayExpr(ArrayExpr *expr) {
      Type arrayTy = cs.getType(expr);
      auto &ctx = cs.getASTContext();

      ProtocolDecl *arrayProto = TypeChecker::getProtocol(
          ctx, expr->getLoc(), KnownProtocolKind::ExpressibleByArrayLiteral);
      assert(arrayProto && "type-checked array literal w/o protocol?!");

      auto conformance =
        TypeChecker::conformsToProtocol(arrayTy, arrayProto, cs.DC);
      assert(conformance && "Type does not conform to protocol?");

      DeclName name(ctx, DeclBaseName::createConstructor(),
                    {ctx.Id_arrayLiteral});
      ConcreteDeclRef witness =
          conformance.getWitnessByName(arrayTy->getRValueType(), name);
      if (!witness || !isa<AbstractFunctionDecl>(witness.getDecl()))
        return nullptr;
      expr->setInitializer(witness);

      auto elementType = expr->getElementType();

      for (auto &element : expr->getElements()) {
        element = coerceToType(element, elementType,
                               cs.getConstraintLocator(element));
      }

      return expr;
    }

    Expr *visitArrayExpr(ArrayExpr *expr) {
      Type openedType = cs.getType(expr);
      Type arrayTy = simplifyType(openedType);
      cs.setType(expr, arrayTy);
      if (!finishArrayExpr(expr)) return nullptr;

      // If the array element type was defaulted, note that in the expression.
      if (solution.DefaultedConstraints.count(cs.getConstraintLocator(expr)))
        expr->setIsTypeDefaulted();

      return expr;
    }

    /// "Finish" a dictionary expression by filling in the semantic expression.
    DictionaryExpr *finishDictionaryExpr(DictionaryExpr *expr) {
      Type dictionaryTy = cs.getType(expr);

      auto &ctx = cs.getASTContext();
      ProtocolDecl *dictionaryProto = TypeChecker::getProtocol(
          cs.getASTContext(), expr->getLoc(),
          KnownProtocolKind::ExpressibleByDictionaryLiteral);

      auto conformance =
        TypeChecker::conformsToProtocol(dictionaryTy, dictionaryProto, cs.DC);
      if (conformance.isInvalid())
        return nullptr;

      DeclName name(ctx, DeclBaseName::createConstructor(),
                    {ctx.Id_dictionaryLiteral});
      ConcreteDeclRef witness =
          conformance.getWitnessByName(dictionaryTy->getRValueType(), name);
      if (!witness || !isa<AbstractFunctionDecl>(witness.getDecl()))
        return nullptr;
      expr->setInitializer(witness);

      auto elementType = expr->getElementType();
      for (auto &element : expr->getElements()) {
        element = coerceToType(element, elementType,
                               cs.getConstraintLocator(element));
      }

      return expr;
    }

    Expr *visitDictionaryExpr(DictionaryExpr *expr) {
      Type openedType = cs.getType(expr);
      Type dictionaryTy = simplifyType(openedType);
      cs.setType(expr, dictionaryTy);
      if (!finishDictionaryExpr(expr)) return nullptr;

      // If the dictionary key or value type was defaulted, note that in the
      // expression.
      if (solution.DefaultedConstraints.count(cs.getConstraintLocator(expr)))
        expr->setIsTypeDefaulted();

      return expr;
    }

    Expr *visitDynamicSubscriptExpr(DynamicSubscriptExpr *expr) {
      auto *memberLocator =
          cs.getConstraintLocator(expr, ConstraintLocator::SubscriptMember);
      return buildSubscript(expr->getBase(), expr->getIndex(),
                            expr->getArgumentLabels(),
                            expr->hasTrailingClosure(),
                            cs.getConstraintLocator(expr),
                            expr->isImplicit(), AccessSemantics::Ordinary,
                            solution.getOverloadChoice(memberLocator));
    }

    Expr *visitTupleElementExpr(TupleElementExpr *expr) {
      simplifyExprType(expr);
      return expr;
    }

    Expr *visitCaptureListExpr(CaptureListExpr *expr) {
      // The type of the capture list is the type of the closure contained
      // inside it.
      cs.setType(expr, cs.getType(expr->getClosureBody()));
      return expr;
    }

    Expr *visitClosureExpr(ClosureExpr *expr) {
      llvm_unreachable("Handled by the walker directly");
    }

    Expr *visitAutoClosureExpr(AutoClosureExpr *expr) {
      llvm_unreachable("Already type-checked");
    }

    Expr *visitInOutExpr(InOutExpr *expr) {
      auto objectTy = cs.getType(expr->getSubExpr())->getRValueType();

      // The type is simply inout of whatever the lvalue's object type was.
      cs.setType(expr, InOutType::get(objectTy));
      return expr;
    }

    Expr *visitVarargExpansionExpr(VarargExpansionExpr *expr) {
      simplifyExprType(expr);

      auto arrayTy = cs.getType(expr);
      expr->setSubExpr(coerceToType(expr->getSubExpr(), arrayTy,
                                    cs.getConstraintLocator(expr)));
      return expr;
    }

    Expr *visitDynamicTypeExpr(DynamicTypeExpr *expr) {
      Expr *base = expr->getBase();
      base = cs.coerceToRValue(base);
      expr->setBase(base);

      return simplifyExprType(expr);
    }

    Expr *visitOpaqueValueExpr(OpaqueValueExpr *expr) {
      assert(expr->isPlaceholder() && "Already type-checked");
      return expr;
    }

    Expr *visitPropertyWrapperValuePlaceholderExpr(
        PropertyWrapperValuePlaceholderExpr *expr) {
      return expr;
    }

    Expr *visitDefaultArgumentExpr(DefaultArgumentExpr *expr) {
      llvm_unreachable("Already type-checked");
    }

    Expr *visitApplyExpr(ApplyExpr *expr) {
      auto *calleeLoc = CalleeLocators[expr];
      assert(calleeLoc);
      return finishApply(expr, cs.getType(expr), cs.getConstraintLocator(expr),
                         calleeLoc);
    }

    Expr *visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *expr) {
      // A non-failable initializer cannot delegate to a failable
      // initializer.
      Expr *unwrappedSubExpr = expr->getSubExpr()->getSemanticsProvidingExpr();
      Type valueTy = cs.getType(unwrappedSubExpr)->getOptionalObjectType();
      auto inCtor = cast<ConstructorDecl>(cs.DC->getInnermostMethodContext());
      if (valueTy && !inCtor->isFailable()) {
        bool isChaining;
        auto *otherCtorRef = expr->getCalledConstructor(isChaining);
        ConstructorDecl *ctor = otherCtorRef->getDecl();
        assert(ctor);

        // If the initializer we're calling is not declared as
        // checked, it's an error.
        bool isError = !ctor->isImplicitlyUnwrappedOptional();

        // If we're suppressing diagnostics, just fail.
        if (isError && SuppressDiagnostics)
          return nullptr;

        auto &ctx = cs.getASTContext();

        auto &de = cs.getASTContext().Diags;
        if (isError) {
          if (auto *optTry = dyn_cast<OptionalTryExpr>(unwrappedSubExpr)) {
            de.diagnose(optTry->getTryLoc(),
                        diag::delegate_chain_nonoptional_to_optional_try,
                        isChaining);
            de.diagnose(optTry->getTryLoc(), diag::init_delegate_force_try)
                .fixItReplace({optTry->getTryLoc(), optTry->getQuestionLoc()},
                              "try!");
            de.diagnose(inCtor->getLoc(), diag::init_propagate_failure)
                .fixItInsertAfter(inCtor->getLoc(), "?");
          } else {
            // Give the user the option of adding '!' or making the enclosing
            // initializer failable.
            de.diagnose(otherCtorRef->getLoc(),
                        diag::delegate_chain_nonoptional_to_optional,
                        isChaining, ctor->getName());
            de.diagnose(otherCtorRef->getLoc(), diag::init_force_unwrap)
                .fixItInsertAfter(expr->getEndLoc(), "!");
            de.diagnose(inCtor->getLoc(), diag::init_propagate_failure)
                .fixItInsertAfter(inCtor->getLoc(), "?");
          }
        }

        // Recover by injecting the force operation (the first option).
        Expr *newSub = new (ctx) ForceValueExpr(expr->getSubExpr(),
                                                expr->getEndLoc());
        cs.setType(newSub, valueTy);
        newSub->setImplicit();
        expr->setSubExpr(newSub);
      }

      return expr;
    }

    Expr *visitIfExpr(IfExpr *expr) {
      auto resultTy = simplifyType(cs.getType(expr));
      cs.setType(expr, resultTy);

      auto cond = cs.coerceToRValue(expr->getCondExpr());
      expr->setCondExpr(cond);

      // Coerce the then/else branches to the common type.
      expr->setThenExpr(coerceToType(expr->getThenExpr(), resultTy,
                               cs.getConstraintLocator(expr->getThenExpr())));
      expr->setElseExpr(coerceToType(expr->getElseExpr(), resultTy,
                                 cs.getConstraintLocator(expr->getElseExpr())));

      return expr;
    }
    
    Expr *visitImplicitConversionExpr(ImplicitConversionExpr *expr) {
      llvm_unreachable("Already type-checked");
    }

    Expr *visitIsExpr(IsExpr *expr) {
      // Turn the subexpression into an rvalue.
      auto &ctx = cs.getASTContext();
      auto sub = cs.coerceToRValue(expr->getSubExpr());
      expr->setSubExpr(sub);

      // Simplify and update the type we checked against.
      auto *const castTypeRepr = expr->getCastTypeRepr();

      const auto fromType = cs.getType(sub);
      const auto toType = simplifyType(cs.getType(castTypeRepr));
      expr->setCastType(toType);
      cs.setType(castTypeRepr, toType);

      auto castContextKind =
          SuppressDiagnostics ? CheckedCastContextKind::None
                              : CheckedCastContextKind::IsExpr;
      auto castKind = TypeChecker::typeCheckCheckedCast(
          fromType, toType, castContextKind, cs.DC, expr->getLoc(), sub,
          castTypeRepr->getSourceRange());

      switch (castKind) {
      case CheckedCastKind::Unresolved:
        expr->setCastKind(CheckedCastKind::ValueCast);
        break;
          
      case CheckedCastKind::Coercion:
      case CheckedCastKind::BridgingCoercion:
        // Check is trivially true.
        ctx.Diags.diagnose(expr->getLoc(), diag::isa_is_always_true, "is");
        expr->setCastKind(castKind);
        break;
      case CheckedCastKind::ValueCast:
        // Check the cast target is a non-foreign type
        if (auto cls = toType->getAs<ClassType>()) {
          if (cls->getDecl()->getForeignClassKind() ==
                ClassDecl::ForeignKind::CFType) {
            ctx.Diags.diagnose(expr->getLoc(), diag::isa_is_foreign_check,
                               toType);
          }
        }
        expr->setCastKind(castKind);
        break;
      case CheckedCastKind::ArrayDowncast:
      case CheckedCastKind::DictionaryDowncast:
      case CheckedCastKind::SetDowncast:
        // Valid checks.
        expr->setCastKind(castKind);
        break;
      }

      // SIL-generation magically turns this into a Bool; make sure it can.
      if (!ctx.getBoolBuiltinInitDecl()) {
        ctx.Diags.diagnose(expr->getLoc(), diag::broken_bool);
        // Continue anyway.
      }

      // Dig through the optionals in the from/to types.
      SmallVector<Type, 2> fromOptionals;
      fromType->lookThroughAllOptionalTypes(fromOptionals);
      SmallVector<Type, 2> toOptionals;
      toType->lookThroughAllOptionalTypes(toOptionals);

      // If we have an imbalance of optionals or a collection
      // downcast, handle this as a checked cast followed by a
      // a 'hasValue' check.
      if (fromOptionals.size() != toOptionals.size() ||
          castKind == CheckedCastKind::ArrayDowncast ||
          castKind == CheckedCastKind::DictionaryDowncast ||
          castKind == CheckedCastKind::SetDowncast) {
        auto *const cast =
            ConditionalCheckedCastExpr::createImplicit(ctx, sub, toType);
        cast->setType(OptionalType::get(toType));
        cast->setCastType(toType);
        cs.setType(cast, cast->getType());

        // Type-check this conditional case.
        Expr *result = handleConditionalCheckedCastExpr(cast, castTypeRepr);
        if (!result)
          return nullptr;

        // Extract a Bool from the resulting expression.
        TypeChecker::requireOptionalIntrinsics(ctx, expr->getLoc());

        // Match the optional value against its `Some` case.
        auto *someDecl = ctx.getOptionalSomeDecl();
        auto isSomeExpr =
            new (ctx) EnumIsCaseExpr(result, castTypeRepr, someDecl);
        auto boolDecl = ctx.getBoolDecl();

        if (!boolDecl) {
          ctx.Diags.diagnose(SourceLoc(), diag::broken_bool);
        }

        cs.setType(isSomeExpr,
                   boolDecl
                   ? boolDecl->getDeclaredInterfaceType()
                   : Type());
        return isSomeExpr;
      }

      return expr;
    }

    /// The kind of cast we're working with for handling optional bindings.
    enum class OptionalBindingsCastKind {
      /// An explicit bridging conversion, spelled "as".
      Bridged,
      /// A forced cast, spelled "as!".
      Forced,
      /// A conditional cast, spelled "as?".
      Conditional,
    };

    /// Handle optional operands and results in an explicit cast.
    Expr *handleOptionalBindingsForCast(ExplicitCastExpr *cast, 
                                        Type finalResultType,
                                        OptionalBindingsCastKind castKind) {
      return handleOptionalBindings(cast->getSubExpr(), finalResultType,
                                    castKind,
        [&](Expr *sub, Type resultType) -> Expr* {

        // Complain about conditional casts to CF class types; they can't
        // actually be conditionally checked.
        if (castKind == OptionalBindingsCastKind::Conditional) {
          Type destValueType = resultType->getOptionalObjectType();
          auto destObjectType = destValueType;
          if (auto metaTy = destObjectType->getAs<MetatypeType>())
            destObjectType = metaTy->getInstanceType();
          if (auto destClass = destObjectType->getClassOrBoundGenericClass()) {
            if (destClass->getForeignClassKind() ==
                  ClassDecl::ForeignKind::CFType) {
              if (SuppressDiagnostics)
                return nullptr;

              auto &de = cs.getASTContext().Diags;
              de.diagnose(cast->getLoc(), diag::conditional_downcast_foreign,
                          destValueType);
              ConcreteDeclRef refDecl = sub->getReferencedDecl();
              if (refDecl) {
                de.diagnose(cast->getLoc(),
                            diag::note_explicitly_compare_cftypeid,
                            refDecl.getDecl()->getBaseName(), destValueType);
              }
            }
          }
        }

        // Set the expression as the sub-expression of the cast, then
        // use the cast as the inner operation.
        cast->setSubExpr(sub);
        cs.setType(cast, resultType);
        return cast;
      });
    }

    /// A helper function to build an operation.  The inner result type
    /// is the expected type of the operation; it will be a non-optional
    /// type unless the castKind is Conditional.
    using OperationBuilderRef =
      llvm::function_ref<Expr*(Expr *subExpr, Type innerResultType)>;

    /// Handle optional operands and results in an explicit cast.
    Expr *handleOptionalBindings(Expr *subExpr, Type finalResultType,
                                 OptionalBindingsCastKind castKind,
                                 OperationBuilderRef buildInnerOperation) {
      auto &ctx = cs.getASTContext();

      unsigned destExtraOptionals;
      bool forceExtraSourceOptionals;
      switch (castKind) {
      case OptionalBindingsCastKind::Bridged:
        destExtraOptionals = 0;
        forceExtraSourceOptionals = true;
        break;

      case OptionalBindingsCastKind::Forced:
        destExtraOptionals = 0;
        forceExtraSourceOptionals = true;
        break;

      case OptionalBindingsCastKind::Conditional:
        destExtraOptionals = 1;
        forceExtraSourceOptionals = false;
        break;
      }

      // FIXME: some of this work needs to be delayed until runtime to
      // properly account for archetypes dynamically being optional
      // types.  For example, if we're casting T to NSView?, that
      // should succeed if T=NSObject? and its value is actually nil.
      Type srcType = cs.getType(subExpr);

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

      SmallVector<Type, 4> destOptionals;
      auto destValueType
        = finalResultType->lookThroughAllOptionalTypes(destOptionals);

      auto isBridgeToAnyObject =
        castKind == OptionalBindingsCastKind::Bridged &&
        destValueType->isAnyObject();

      // If the destination value type is 'AnyObject' when performing a
      // bridging operation, or if the destination value type could dynamically
      // be an optional type, leave any extra optionals on the source in place.
      // Only apply the latter condition in Swift 5 mode to best preserve
      // compatibility with Swift 4.1's casting behaviour.
      if (isBridgeToAnyObject || (ctx.isSwiftVersionAtLeast(5) &&
                                  destValueType->canDynamicallyBeOptionalType(
                                      /*includeExistential*/ false))) {
        auto destOptionalsCount = destOptionals.size() - destExtraOptionals;
        if (srcOptionals.size() > destOptionalsCount) {
          srcType = srcOptionals[destOptionalsCount];
          srcOptionals.erase(srcOptionals.begin() + destOptionalsCount,
                             srcOptionals.end());
        }
      }

      // When performing a bridging operation, if the destination type
      // is more optional than the source, we'll add extra optional injections
      // at the end.
      SmallVector<Type, 4> destOptionalInjections;
      if (castKind == OptionalBindingsCastKind::Bridged &&
          destOptionals.size() > srcOptionals.size()) {
        // Remove the extra optionals from destOptionals, but keep them around
        // separately so we can perform the injections on the final result of
        // the cast.
        auto cutPoint = destOptionals.end() - srcOptionals.size();
        destOptionalInjections.append(destOptionals.begin(), cutPoint);
        destOptionals.erase(destOptionals.begin(), cutPoint);

        finalResultType = destOptionals.empty() ? destValueType
                                                : destOptionals.front();
      }

      // Local function to add the optional injections to final result.
      auto addFinalOptionalInjections = [&](Expr *result) {
        for (auto destType : llvm::reverse(destOptionalInjections)) {
          result =
              cs.cacheType(new (ctx) InjectIntoOptionalExpr(result, destType));
        }

        return result;
      };

      // There's nothing special to do if the operand isn't optional
      // (or is insufficiently optional) and we don't need any bridging.
      if (srcOptionals.empty()
          || (srcOptionals.size() < destOptionals.size() - destExtraOptionals)) {
        Expr *result = buildInnerOperation(subExpr, finalResultType);
        if (!result) return nullptr;
        return addFinalOptionalInjections(result);
      }

      // The outermost N levels of optionals on the operand must all
      // be present or the cast fails.  The innermost M levels of
      // optionals on the operand are reflected in the requested
      // destination type, so we should map these nils into the result.
      unsigned numRequiredOptionals =
        srcOptionals.size() - (destOptionals.size() - destExtraOptionals);

      // The number of OptionalEvaluationExprs between the point of the
      // inner cast and the enclosing OptionalEvaluationExpr (exclusive)
      // which represents failure for the entire operation.
      unsigned failureDepth = destOptionals.size() - destExtraOptionals;

      // Drill down on the operand until it's non-optional.
      SourceLoc fakeQuestionLoc = subExpr->getEndLoc();
      for (unsigned i : indices(srcOptionals)) {
        Type valueType =
          (i + 1 == srcOptionals.size() ? srcType : srcOptionals[i+1]);

        // As we move into the range of mapped optionals, start
        // lowering the depth.
        unsigned depth = failureDepth;
        if (i >= numRequiredOptionals) {
          depth -= (i - numRequiredOptionals) + 1;
        } else if (forceExtraSourceOptionals) {
          // For a forced cast, force the required optionals.
          subExpr = new (ctx) ForceValueExpr(subExpr, fakeQuestionLoc);
          cs.setType(subExpr, valueType);
          subExpr->setImplicit(true);
          continue;
        }

        subExpr = cs.cacheType(new (ctx) BindOptionalExpr(
            subExpr, fakeQuestionLoc, depth, valueType));
        subExpr->setImplicit(true);
      }

      // If this is a conditional cast, the result type will always
      // have at least one level of optional, which should become the
      // type of the checked-cast expression.
      Expr *result;
      if (castKind == OptionalBindingsCastKind::Conditional) {
        assert(!destOptionals.empty() &&
               "result of checked cast is not an optional type");
        result = buildInnerOperation(subExpr, destOptionals.back());
      } else {
        result = buildInnerOperation(subExpr, destValueType);
      }
      if (!result) return nullptr;

      // If we're casting to an optional type, we need to capture the
      // final M bindings.

      if (destOptionals.size() > destExtraOptionals) {
        if (castKind == OptionalBindingsCastKind::Conditional) {
          // If the innermost cast fails, the entire expression fails.  To
          // get this behavior, we have to bind and then re-inject the result.
          // (SILGen should know how to peephole this.)
          result = cs.cacheType(new (ctx) BindOptionalExpr(
              result, result->getEndLoc(), failureDepth, destValueType));
          result->setImplicit(true);
        }

        for (unsigned i = destOptionals.size(); i != 0; --i) {
          Type destType = destOptionals[i-1];
          result =
              cs.cacheType(new (ctx) InjectIntoOptionalExpr(result, destType));
          result =
              cs.cacheType(new (ctx) OptionalEvaluationExpr(result, destType));
        }

      // Otherwise, we just need to capture the failure-depth binding.
      } else if (!forceExtraSourceOptionals) {
        result = cs.cacheType(
            new (ctx) OptionalEvaluationExpr(result, finalResultType));
      }

      return addFinalOptionalInjections(result);
    }

    bool hasForcedOptionalResult(ExplicitCastExpr *expr) {
      const auto *const TR = expr->getCastTypeRepr();
      if (TR && TR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional) {
        auto *locator = cs.getConstraintLocator(
            expr, ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice);
        return solution.getDisjunctionChoice(locator);
      }
      return false;
    }

    Expr *visitCoerceExpr(CoerceExpr *expr) {
      // If we need to insert a force-unwrap for coercions of the form
      // 'as T!', do so now.
      if (hasForcedOptionalResult(expr)) {
        auto *coerced = visitCoerceExpr(expr, None);
        if (!coerced)
          return nullptr;

        return coerceImplicitlyUnwrappedOptionalToValue(
            coerced, cs.getType(coerced)->getOptionalObjectType());
      }

      return visitCoerceExpr(expr, None);
    }

    Expr *visitCoerceExpr(CoerceExpr *expr, Optional<unsigned> choice) {
      // Simplify and update the type we're coercing to.
      assert(expr->getCastTypeRepr());
      const auto toType = simplifyType(cs.getType(expr->getCastTypeRepr()));
      expr->setCastType(toType);
      cs.setType(expr->getCastTypeRepr(), toType);

      // If this is a literal that got converted into constructor call
      // lets put proper source information in place.
      if (expr->isLiteralInit()) {
        auto *literalInit = expr->getSubExpr();
        if (auto *call = dyn_cast<CallExpr>(literalInit)) {
          forEachExprInConstraintSystem(call->getFn(),
                                        [&](Expr *subExpr) -> Expr * {
            auto *TE = dyn_cast<TypeExpr>(subExpr);
            if (!TE)
              return subExpr;

            auto type = cs.getInstanceType(TE);

            assert(!type->hasError());

            if (!type->isEqual(toType))
              return subExpr;

            return cs.cacheType(TypeExpr::createImplicitHack(
                expr->getLoc(), toType, cs.getASTContext()));
          });
        }

        if (auto *literal = dyn_cast<NumberLiteralExpr>(literalInit)) {
          literal->setExplicitConversion();
        } else {
          literalInit->setImplicit(false);
        }

        cs.setType(expr, toType);
        // Keep the coercion around, because it contains the source range
        // for the original constructor call.
        return expr;
      }

      // Turn the subexpression into an rvalue.
      auto rvalueSub = cs.coerceToRValue(expr->getSubExpr());
      expr->setSubExpr(rvalueSub);

      // If we weren't explicitly told by the caller which disjunction choice,
      // get it from the solution to determine whether we've picked a coercion
      // or a bridging conversion.
      auto *locator = cs.getConstraintLocator(expr);

      if (!choice) {
        choice = solution.getDisjunctionChoice(locator);
      }

      // Handle the coercion/bridging of the underlying subexpression, where
      // optionality has been removed.
      if (*choice == 0) {
        // Convert the subexpression.
        Expr *sub = expr->getSubExpr();

        sub = solution.coerceToType(sub, toType, cs.getConstraintLocator(sub));
        if (!sub)
          return nullptr;

        expr->setSubExpr(sub);
        cs.setType(expr, toType);
        return expr;
      }

      // Bridging conversion.
      assert(*choice == 1 && "should be bridging");

      // Handle optional bindings.
      Expr *sub = handleOptionalBindings(expr->getSubExpr(), toType,
                                         OptionalBindingsCastKind::Bridged,
                                         [&](Expr *sub, Type toInstanceType) {
        return buildObjCBridgeExpr(sub, toInstanceType, locator);
      });

      if (!sub) return nullptr;
      expr->setSubExpr(sub);
      cs.setType(expr, toType);
      return expr;
    }

    // Rewrite ForcedCheckedCastExpr based on what the solver computed.
    Expr *visitForcedCheckedCastExpr(ForcedCheckedCastExpr *expr) {
      // The subexpression is always an rvalue.
      auto &ctx = cs.getASTContext();
      auto sub = cs.coerceToRValue(expr->getSubExpr());
      expr->setSubExpr(sub);

      // Simplify and update the type we're casting to.
      auto *const castTypeRepr = expr->getCastTypeRepr();

      const auto fromType = cs.getType(sub);
      auto toType = simplifyType(cs.getType(castTypeRepr));
      if (hasForcedOptionalResult(expr))
        toType = toType->getOptionalObjectType();

      expr->setCastType(toType);
      cs.setType(castTypeRepr, toType);

      auto castContextKind =
          SuppressDiagnostics ? CheckedCastContextKind::None
                              : CheckedCastContextKind::ForcedCast;

      const auto castKind = TypeChecker::typeCheckCheckedCast(
          fromType, toType, castContextKind, cs.DC, expr->getLoc(), sub,
          castTypeRepr->getSourceRange());
      switch (castKind) {
        /// Invalid cast.
      case CheckedCastKind::Unresolved:
        return nullptr;
      case CheckedCastKind::Coercion:
      case CheckedCastKind::BridgingCoercion: {
        if (cs.getType(sub)->isEqual(toType)) {
          ctx.Diags.diagnose(expr->getLoc(), diag::forced_downcast_noop, toType)
              .fixItRemove(SourceRange(expr->getLoc(),
                                       castTypeRepr->getSourceRange().End));

        } else {
          ctx.Diags
              .diagnose(expr->getLoc(), diag::forced_downcast_coercion,
                        cs.getType(sub), toType)
              .fixItReplace(SourceRange(expr->getLoc(), expr->getExclaimLoc()),
                            "as");
        }

        expr->setCastKind(castKind);
        cs.setType(expr, toType);
        return expr;
      }

      // Valid casts.
      case CheckedCastKind::ArrayDowncast:
      case CheckedCastKind::DictionaryDowncast:
      case CheckedCastKind::SetDowncast:
      case CheckedCastKind::ValueCast:
        expr->setCastKind(castKind);
        break;
      }
      
      return handleOptionalBindingsForCast(expr, simplifyType(cs.getType(expr)),
                                           OptionalBindingsCastKind::Forced);
    }

    Expr *visitConditionalCheckedCastExpr(ConditionalCheckedCastExpr *expr) {
      // Simplify and update the type we're casting to.
      auto *const castTypeRepr = expr->getCastTypeRepr();
      const auto toType = simplifyType(cs.getType(castTypeRepr));
      expr->setCastType(toType);
      cs.setType(castTypeRepr, toType);

      // If we need to insert a force-unwrap for coercions of the form
      // 'as! T!', do so now.
      if (hasForcedOptionalResult(expr)) {
        auto *coerced = handleConditionalCheckedCastExpr(expr, castTypeRepr);
        if (!coerced)
          return nullptr;

        return coerceImplicitlyUnwrappedOptionalToValue(
            coerced, cs.getType(coerced)->getOptionalObjectType());
      }

      return handleConditionalCheckedCastExpr(expr, castTypeRepr);
    }

    Expr *handleConditionalCheckedCastExpr(ConditionalCheckedCastExpr *expr,
                                           TypeRepr *castTypeRepr) {
      assert(castTypeRepr &&
             "cast requires TypeRepr; implicit casts are superfluous");

      // The subexpression is always an rvalue.
      auto &ctx = cs.getASTContext();
      auto sub = cs.coerceToRValue(expr->getSubExpr());
      expr->setSubExpr(sub);

      // Simplify and update the type we're casting to.
      const auto fromType = cs.getType(sub);
      const auto toType = expr->getCastType();

      bool isSubExprLiteral = isa<LiteralExpr>(sub);
      auto castContextKind =
          (SuppressDiagnostics || expr->isImplicit() || isSubExprLiteral)
              ? CheckedCastContextKind::None
              : CheckedCastContextKind::ConditionalCast;

      auto castKind = TypeChecker::typeCheckCheckedCast(
          fromType, toType, castContextKind, cs.DC, expr->getLoc(), sub,
          castTypeRepr->getSourceRange());
      switch (castKind) {
      // Invalid cast.
      case CheckedCastKind::Unresolved:
        // FIXME: This literal diagnostics needs to be revisited by a proposal
        // to unify casting semantics for literals.
        // https://bugs.swift.org/browse/SR-12093
        if (isSubExprLiteral) {
          auto protocol = TypeChecker::getLiteralProtocol(ctx, sub);
          // Special handle for literals conditional checked cast when they can
          // be statically coerced to the cast type.
          if (protocol && TypeChecker::conformsToProtocol(
                              toType, protocol, cs.DC)) {
            ctx.Diags
                .diagnose(expr->getLoc(),
                          diag::literal_conditional_downcast_to_coercion,
                          toType);
          } else {
            ctx.Diags
                .diagnose(expr->getLoc(), diag::downcast_to_unrelated, fromType,
                          toType)
                .highlight(sub->getSourceRange())
                .highlight(castTypeRepr->getSourceRange());
          }
        }
        expr->setCastKind(CheckedCastKind::ValueCast);
        break;

      case CheckedCastKind::Coercion:
      case CheckedCastKind::BridgingCoercion: {
        ctx.Diags.diagnose(expr->getLoc(), diag::conditional_downcast_coercion,
                           fromType, toType);
        expr->setCastKind(castKind);
        cs.setType(expr, OptionalType::get(toType));
        return expr;
      }

      // Valid casts.
      case CheckedCastKind::ArrayDowncast:
      case CheckedCastKind::DictionaryDowncast:
      case CheckedCastKind::SetDowncast:
      case CheckedCastKind::ValueCast:
        expr->setCastKind(castKind);
        break;
      }

      return handleOptionalBindingsForCast(expr, simplifyType(cs.getType(expr)),
                                         OptionalBindingsCastKind::Conditional);
    }

    Expr *visitAssignExpr(AssignExpr *expr) {
      // Convert the source to the simplified destination type.
      auto destTy = simplifyType(cs.getType(expr->getDest()));
      auto locator =
        ConstraintLocatorBuilder(cs.getConstraintLocator(expr->getSrc()));
      Expr *src = coerceToType(expr->getSrc(), destTy->getRValueType(), locator);
      if (!src)
        return nullptr;

      expr->setSrc(src);

      if (!SuppressDiagnostics) {
        // If we're performing an assignment to a weak or unowned variable from
        // a constructor call, emit a warning that the instance will be
        // immediately deallocated.
        diagnoseUnownedImmediateDeallocation(cs.getASTContext(), expr);
      }
      return expr;
    }
    
    Expr *visitDiscardAssignmentExpr(DiscardAssignmentExpr *expr) {
      return simplifyExprType(expr);
    }
    
    Expr *visitUnresolvedPatternExpr(UnresolvedPatternExpr *expr) {
      // If we end up here, we should have diagnosed somewhere else
      // already.
      Expr *simplified = simplifyExprType(expr);
      // Invalidate 'VarDecl's inside the pattern.
      expr->getSubPattern()->forEachVariable([](VarDecl *VD) {
        VD->setInvalid();
      });
      if (!SuppressDiagnostics
          && !cs.getType(simplified)->is<UnresolvedType>()) {
        auto &de = cs.getASTContext().Diags;
        de.diagnose(simplified->getLoc(), diag::pattern_in_expr,
                    expr->getSubPattern()->getKind());
      }
      return simplified;
    }
    
    Expr *visitBindOptionalExpr(BindOptionalExpr *expr) {
      return simplifyExprType(expr);
    }

    Expr *visitOptionalEvaluationExpr(OptionalEvaluationExpr *expr) {
      Type optType = simplifyType(cs.getType(expr));

      // If this is an optional chain that isn't chaining anything, and if the
      // subexpression is already optional (not IUO), then this is a noop:
      // reject it.  This avoids confusion of the model (where the programmer
      // thought it was doing something) and keeps pointless ?'s out of the
      // code.
      if (!SuppressDiagnostics) {
        auto &de = cs.getASTContext().Diags;
        if (auto *Bind = dyn_cast<BindOptionalExpr>(
                        expr->getSubExpr()->getSemanticsProvidingExpr())) {
          if (cs.getType(Bind->getSubExpr())->isEqual(optType)) {
            de.diagnose(expr->getLoc(), diag::optional_chain_noop, optType)
                .fixItRemove(Bind->getQuestionLoc());
          } else {
            de.diagnose(expr->getLoc(), diag::optional_chain_isnt_chaining);
          }
        }
      }

      Expr *subExpr = coerceToType(expr->getSubExpr(), optType,
                                   cs.getConstraintLocator(expr));
      if (!subExpr) return nullptr;

      expr->setSubExpr(subExpr);
      cs.setType(expr, optType);
      return expr;
    }

    Expr *visitForceValueExpr(ForceValueExpr *expr) {
      // Check to see if we are forcing an
      // ImplicitlyUnwrappedFunctionConversionExpr.  This can happen
      // in cases where we had a ForceValueExpr of an optional for a
      // declaration for a function whose result type we need to
      // implicitly force after applying. We need to hoist the function
      // conversion above the ForceValueExpr, so that we may ultimately
      // hoist it above the ApplyExpr where we will eventually rewrite the
      // function conversion into a force of the result.
      Expr *replacement = expr;
      if (auto fnConv =
          dyn_cast<ImplicitlyUnwrappedFunctionConversionExpr>(expr->getSubExpr())) {
        auto fnConvSubExpr = fnConv->getSubExpr();
        auto fnConvSubObjTy =
          cs.getType(fnConvSubExpr)->getOptionalObjectType();
        cs.setType(expr, fnConvSubObjTy);
        expr->setSubExpr(fnConvSubExpr);
        fnConv->setSubExpr(expr);
        replacement = fnConv;
      }

      Type valueType = simplifyType(cs.getType(expr));
      cs.setType(expr, valueType);

      // Coerce the object type, if necessary.
      auto subExpr = expr->getSubExpr();
      if (auto objectTy = cs.getType(subExpr)->getOptionalObjectType()) {
        if (objectTy && !objectTy->isEqual(valueType)) {
          auto coercedSubExpr = coerceToType(subExpr,
                                             OptionalType::get(valueType),
                                             cs.getConstraintLocator(subExpr));
          
          expr->setSubExpr(coercedSubExpr);
        }
      }
      
      return replacement;
    }

    Expr *visitOpenExistentialExpr(OpenExistentialExpr *expr) {
      llvm_unreachable("Already type-checked");
    }
    
    Expr *visitMakeTemporarilyEscapableExpr(MakeTemporarilyEscapableExpr *expr){
      llvm_unreachable("Already type-checked");
    }

    Expr *visitKeyPathApplicationExpr(KeyPathApplicationExpr *expr){
      // This should already be type-checked, but we may have had to re-
      // check it for failure diagnosis.
      return simplifyExprType(expr);
    }
    
    Expr *visitEnumIsCaseExpr(EnumIsCaseExpr *expr) {
      // Should already be type-checked.
      return simplifyExprType(expr);
    }

    Expr *visitLazyInitializerExpr(LazyInitializerExpr *expr) {
      llvm_unreachable("Already type-checked");
    }
    
    Expr *visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) {
      simplifyExprType(E);
      auto valueType = cs.getType(E);
      assert(!valueType->hasUnresolvedType());

      auto &ctx = cs.getASTContext();
      // Synthesize a call to _undefined() of appropriate type.
      FuncDecl *undefinedDecl = ctx.getUndefined();
      if (!undefinedDecl) {
        ctx.Diags.diagnose(E->getLoc(), diag::missing_undefined_runtime);
        return nullptr;
      }
      DeclRefExpr *fnRef = new (ctx) DeclRefExpr(undefinedDecl, DeclNameLoc(),
                                                 /*Implicit=*/true);
      fnRef->setFunctionRefKind(FunctionRefKind::SingleApply);

      StringRef msg = "attempt to evaluate editor placeholder";
      Expr *argExpr = new (ctx) StringLiteralExpr(msg, E->getLoc(),
                                                  /*implicit*/true);

      Expr *callExpr = CallExpr::createImplicit(ctx, fnRef, { argExpr },
                                                { Identifier() });

      auto resultTy = TypeChecker::typeCheckExpression(
          callExpr, cs.DC, /*contextualInfo=*/{valueType, CTP_CannotFail});
      assert(resultTy && "Conversion cannot fail!");
      (void)resultTy;

      cs.cacheExprTypes(callExpr);
      E->setSemanticExpr(callExpr);
      return E;
    }

    Expr *visitObjCSelectorExpr(ObjCSelectorExpr *E) {
      // Dig out the reference to a declaration.
      Expr *subExpr = E->getSubExpr();
      ValueDecl *foundDecl = nullptr;
      while (subExpr) {
        // Declaration reference.
        if (auto declRef = dyn_cast<DeclRefExpr>(subExpr)) {
          foundDecl = declRef->getDecl();
          break;
        }

        // Constructor reference.
        if (auto ctorRef = dyn_cast<OtherConstructorDeclRefExpr>(subExpr)) {
          foundDecl = ctorRef->getDecl();
          break;
        }

        // Member reference.
        if (auto memberRef = dyn_cast<MemberRefExpr>(subExpr)) {
          foundDecl = memberRef->getMember().getDecl();
          break;
        }

        // Dynamic member reference.
        if (auto dynMemberRef = dyn_cast<DynamicMemberRefExpr>(subExpr)) {
          foundDecl = dynMemberRef->getMember().getDecl();
          break;
        }

        // Look through parentheses.
        if (auto paren = dyn_cast<ParenExpr>(subExpr)) {
          subExpr = paren->getSubExpr();
          continue;
        }

        // Look through "a.b" to "b".
        if (auto dotSyntax = dyn_cast<DotSyntaxBaseIgnoredExpr>(subExpr)) {
          subExpr = dotSyntax->getRHS();
          continue;
        }

        // Look through self-rebind expression.
        if (auto rebindSelf = dyn_cast<RebindSelfInConstructorExpr>(subExpr)) {
          subExpr = rebindSelf->getSubExpr();
          continue;
        }

        // Look through optional binding within the monadic "?".
        if (auto bind = dyn_cast<BindOptionalExpr>(subExpr)) {
          subExpr = bind->getSubExpr();
          continue;
        }

        // Look through optional evaluation of the monadic "?".
        if (auto optEval = dyn_cast<OptionalEvaluationExpr>(subExpr)) {
          subExpr = optEval->getSubExpr();
          continue;
        }

        // Look through an implicit force-value.
        if (auto force = dyn_cast<ForceValueExpr>(subExpr)) {
          subExpr = force->getSubExpr();
          continue;
        }

        // Look through implicit open-existential operations.
        if (auto open = dyn_cast<OpenExistentialExpr>(subExpr)) {
          if (open->isImplicit()) {
            subExpr = open->getSubExpr();
            continue;
          }
          break;
        }

        // Look to the referenced member in a self-application.
        if (auto selfApply = dyn_cast<SelfApplyExpr>(subExpr)) {
          subExpr = selfApply->getFn();
          continue;
        }

        // Look through implicit conversions.
        if (auto conversion = dyn_cast<ImplicitConversionExpr>(subExpr)) {
          subExpr = conversion->getSubExpr();
          continue;
        }

        // Look through explicit coercions.
        if (auto coercion = dyn_cast<CoerceExpr>(subExpr)) {
          subExpr = coercion->getSubExpr();
          continue;
        }

        break;
      }

      if (!subExpr) return nullptr;

      // If we didn't find any declaration at all, we're stuck.
      auto &de = cs.getASTContext().Diags;
      if (!foundDecl) {
        de.diagnose(E->getLoc(), diag::expr_selector_no_declaration)
            .highlight(subExpr->getSourceRange());
        return E;
      }

      // Check whether we found an entity that #selector could refer to.
      // If we found a method or initializer, check it.
      AbstractFunctionDecl *method = nullptr;
      if (auto func = dyn_cast<AbstractFunctionDecl>(foundDecl)) {
        // Methods and initializers.

        // If this isn't a method, complain.
        if (!func->getDeclContext()->isTypeContext()) {
          de.diagnose(E->getLoc(), diag::expr_selector_not_method,
                      func->getDeclContext()->isModuleScopeContext(),
                      func->getName())
              .highlight(subExpr->getSourceRange());
          de.diagnose(func, diag::decl_declared_here, func->getName());
          return E;
        }

        // Check that we requested a method.
        switch (E->getSelectorKind()) {
        case ObjCSelectorExpr::Method:
          break;

        case ObjCSelectorExpr::Getter:
        case ObjCSelectorExpr::Setter:
          // Complain that we cannot ask for the getter or setter of a
          // method.
          de.diagnose(E->getModifierLoc(),
                      diag::expr_selector_expected_property,
                      E->getSelectorKind() == ObjCSelectorExpr::Setter,
                      foundDecl->getDescriptiveKind(), foundDecl->getName())
              .fixItRemoveChars(E->getModifierLoc(),
                                E->getSubExpr()->getStartLoc());

          // Update the AST to reflect the fix.
          E->overrideObjCSelectorKind(ObjCSelectorExpr::Method, SourceLoc());
          break;
        }

        // Note the method we're referring to.
        method = func;
      } else if (auto var = dyn_cast<VarDecl>(foundDecl)) {
        // Properties.

        // If this isn't a property on a type, complain.
        if (!var->getDeclContext()->isTypeContext()) {
          de.diagnose(E->getLoc(), diag::expr_selector_not_property,
                      isa<ParamDecl>(var), var->getName())
              .highlight(subExpr->getSourceRange());
          de.diagnose(var, diag::decl_declared_here, var->getName());
          return E;
        }

        // Check that we requested a property getter or setter.
        switch (E->getSelectorKind()) {
        case ObjCSelectorExpr::Method: {
          bool isSettable = var->isSettable(cs.DC) &&
            var->isSetterAccessibleFrom(cs.DC);
          auto primaryDiag =
              de.diagnose(E->getLoc(), diag::expr_selector_expected_method,
                          isSettable, var->getName());
          primaryDiag.highlight(subExpr->getSourceRange());

          // The point at which we will insert the modifier.
          SourceLoc modifierLoc = E->getSubExpr()->getStartLoc();

          // If the property is settable, we don't know whether the
          // user wanted the getter or setter. Provide notes for each.
          if (isSettable) {
            // Flush the primary diagnostic. We have notes to add.
            primaryDiag.flush();

            // Add notes for the getter and setter, respectively.
            de.diagnose(modifierLoc, diag::expr_selector_add_modifier, false,
                        var->getName())
                .fixItInsert(modifierLoc, "getter: ");
            de.diagnose(modifierLoc, diag::expr_selector_add_modifier, true,
                        var->getName())
                .fixItInsert(modifierLoc, "setter: ");

            // Bail out now. We don't know what the user wanted, so
            // don't fill in the details.
            return E;
          }

          // The property is non-settable, so add "getter:".
          primaryDiag.fixItInsert(modifierLoc, "getter: ");
          E->overrideObjCSelectorKind(ObjCSelectorExpr::Getter, modifierLoc);
          method = var->getOpaqueAccessor(AccessorKind::Get);
          break;
        }

        case ObjCSelectorExpr::Getter:
          method = var->getOpaqueAccessor(AccessorKind::Get);
          break;

        case ObjCSelectorExpr::Setter:
          // Make sure we actually have a setter.
          if (!var->isSettable(cs.DC)) {
            de.diagnose(E->getLoc(), diag::expr_selector_property_not_settable,
                        var->getDescriptiveKind(), var->getName());
            de.diagnose(var, diag::decl_declared_here, var->getName());
            return E;
          }

          // Make sure the setter is accessible.
          if (!var->isSetterAccessibleFrom(cs.DC)) {
            de.diagnose(E->getLoc(),
                        diag::expr_selector_property_setter_inaccessible,
                        var->getDescriptiveKind(), var->getName());
            de.diagnose(var, diag::decl_declared_here, var->getName());
            return E;
          }

          method = var->getOpaqueAccessor(AccessorKind::Set);
          break;
        }
      } else {
        // Cannot reference with #selector.
        de.diagnose(E->getLoc(), diag::expr_selector_no_declaration)
            .highlight(subExpr->getSourceRange());
        de.diagnose(foundDecl, diag::decl_declared_here,
                    foundDecl->getName());
        return E;
      }
      assert(method && "Didn't find a method?");

      // The declaration we found must be exposed to Objective-C.
      if (!method->isObjC()) {
        // If the method declaration lies in a protocol and we're providing
        // a default implementation of the method through a protocol extension
        // and using it as a selector, then bail out as adding @objc to the
        // protocol might not be the right thing to do and could lead to
        // problems.
        if (auto protocolDecl = dyn_cast<ProtocolDecl>(foundDecl->getDeclContext())) {
          de.diagnose(E->getLoc(), diag::expr_selector_cannot_be_used,
                      foundDecl->getBaseName(), protocolDecl->getName());
          return E;
        }

        de.diagnose(E->getLoc(), diag::expr_selector_not_objc,
                    foundDecl->getDescriptiveKind(), foundDecl->getName())
            .highlight(subExpr->getSourceRange());
        de.diagnose(foundDecl, diag::make_decl_objc,
                    foundDecl->getDescriptiveKind())
            .fixItInsert(foundDecl->getAttributeInsertionLoc(false), "@objc ");
        return E;
      } else if (auto attr = foundDecl->getAttrs().getAttribute<ObjCAttr>()) {
        // If this attribute was inferred based on deprecated Swift 3 rules,
        // complain.
        if (attr->isSwift3Inferred() &&
            cs.getASTContext().LangOpts.WarnSwift3ObjCInference ==
                Swift3ObjCInferenceWarnings::Minimal) {
          de.diagnose(E->getLoc(), diag::expr_selector_swift3_objc_inference,
                      foundDecl->getDescriptiveKind(), foundDecl->getName(),
                      foundDecl->getDeclContext()
                          ->getSelfNominalTypeDecl()
                          ->getName())
              .highlight(subExpr->getSourceRange());
          de.diagnose(foundDecl, diag::make_decl_objc,
                      foundDecl->getDescriptiveKind())
              .fixItInsert(foundDecl->getAttributeInsertionLoc(false),
                           "@objc ");
        }
      }

      // Note which method we're referencing.
      E->setMethod(method);
      return E;
    }

    Expr *visitKeyPathExpr(KeyPathExpr *E) {
      if (E->isObjC()) {
        cs.setType(E, cs.getType(E->getObjCStringLiteralExpr()));
        return E;
      }

      simplifyExprType(E);
      
      if (cs.getType(E)->hasError())
        return E;

      // If a component is already resolved, then all of them should be
      // resolved, and we can let the expression be. This might happen when
      // re-checking a failed system for diagnostics.
      if (!E->getComponents().empty()
          && E->getComponents().front().isResolved()) {
        assert([&]{
          for (auto &c : E->getComponents())
            if (!c.isResolved())
              return false;
          return true;
        }());
        return E;
      }

      SmallVector<KeyPathExpr::Component, 4> resolvedComponents;

      // Resolve each of the components.
      bool didOptionalChain = false;
      bool isFunctionType = false;
      Type baseTy, leafTy;
      Type exprType = cs.getType(E);
      if (auto fnTy = exprType->getAs<FunctionType>()) {
        baseTy = fnTy->getParams()[0].getParameterType();
        leafTy = fnTy->getResult();
        isFunctionType = true;
      } else {
        auto keyPathTy = exprType->castTo<BoundGenericType>();
        baseTy = keyPathTy->getGenericArgs()[0];
        leafTy = keyPathTy->getGenericArgs()[1];
      }

      // Track the type of the current component. Once we finish projecting
      // through each component of the key path, we should reach the leafTy.
      auto componentTy = baseTy;
      for (unsigned i : indices(E->getComponents())) {
        auto &origComponent = E->getMutableComponents()[i];
        
        // If there were unresolved types, we may end up with a null base for
        // following components.
        if (!componentTy) {
          resolvedComponents.push_back(origComponent);
          continue;
        }

        auto kind = origComponent.getKind();
        auto locator = cs.getConstraintLocator(
            E, LocatorPathElt::KeyPathComponent(i));

        // Adjust the locator such that it includes any additional elements to
        // point to the component's callee, e.g a SubscriptMember for a
        // subscript component.
        locator = cs.getCalleeLocator(locator);

        bool isDynamicMember = false;
        // If this is an unresolved link, make sure we resolved it.
        if (kind == KeyPathExpr::Component::Kind::UnresolvedProperty ||
            kind == KeyPathExpr::Component::Kind::UnresolvedSubscript) {
          auto foundDecl = solution.getOverloadChoiceIfAvailable(locator);
          if (!foundDecl) {
            // If we couldn't resolve the component, leave it alone.
            resolvedComponents.push_back(origComponent);
            componentTy = origComponent.getComponentType();
            continue;
          }

          isDynamicMember =
              foundDecl->choice.getKind() ==
                  OverloadChoiceKind::DynamicMemberLookup ||
              foundDecl->choice.getKind() ==
                  OverloadChoiceKind::KeyPathDynamicMemberLookup;

          // If this was a @dynamicMemberLookup property, then we actually
          // form a subscript reference, so switch the kind.
          if (isDynamicMember) {
            kind = KeyPathExpr::Component::Kind::UnresolvedSubscript;
          }
        }

        switch (kind) {
        case KeyPathExpr::Component::Kind::UnresolvedProperty: {
          buildKeyPathPropertyComponent(solution.getOverloadChoice(locator),
                                        origComponent.getLoc(),
                                        locator, resolvedComponents);
          break;
        }
        case KeyPathExpr::Component::Kind::UnresolvedSubscript: {
          ArrayRef<Identifier> subscriptLabels;
          if (!isDynamicMember)
            subscriptLabels = origComponent.getSubscriptLabels();

          buildKeyPathSubscriptComponent(
              solution.getOverloadChoice(locator),
              origComponent.getLoc(), origComponent.getIndexExpr(),
              subscriptLabels, locator, resolvedComponents);
          break;
        }
        case KeyPathExpr::Component::Kind::OptionalChain: {
          didOptionalChain = true;
          // Chaining always forces the element to be an rvalue.
          auto objectTy =
              componentTy->getWithoutSpecifierType()->getOptionalObjectType();
          if (componentTy->hasUnresolvedType() && !objectTy) {
            objectTy = componentTy;
          }
          assert(objectTy);
          
          auto loc = origComponent.getLoc();
          resolvedComponents.push_back(
              KeyPathExpr::Component::forOptionalChain(objectTy, loc));
          break;
        }
        case KeyPathExpr::Component::Kind::OptionalForce: {
          // Handle force optional when it is the first component e.g.
          // \String?.!.count
          if (resolvedComponents.empty()) {
            auto loc = origComponent.getLoc();
            auto objectTy = componentTy->getOptionalObjectType();
            assert(objectTy);

            resolvedComponents.push_back(
                KeyPathExpr::Component::forOptionalForce(objectTy, loc));
          } else {
            buildKeyPathOptionalForceComponent(resolvedComponents);
          }
          break;
        }
        case KeyPathExpr::Component::Kind::Invalid: {
          auto component = origComponent;
          component.setComponentType(leafTy);
          resolvedComponents.push_back(component);
          break;
        }
        case KeyPathExpr::Component::Kind::Identity: {
          auto component = origComponent;
          component.setComponentType(componentTy);
          resolvedComponents.push_back(component);
          break;
        }
        case KeyPathExpr::Component::Kind::Property:
        case KeyPathExpr::Component::Kind::Subscript:
        case KeyPathExpr::Component::Kind::OptionalWrap:
        case KeyPathExpr::Component::Kind::TupleElement:
          llvm_unreachable("already resolved");
          break;
        case KeyPathExpr::Component::Kind::DictionaryKey:
          llvm_unreachable("DictionaryKey only valid in #keyPath");
          break;
        }

        // Update "componentTy" with the result type of the last component.
        assert(!resolvedComponents.empty());
        componentTy = resolvedComponents.back().getComponentType();
      }
      
      // Wrap a non-optional result if there was chaining involved.
      if (didOptionalChain && componentTy &&
          !componentTy->hasUnresolvedType() &&
          !componentTy->getWithoutSpecifierType()->isEqual(leafTy)) {
        assert(leafTy->getOptionalObjectType()->isEqual(
            componentTy->getWithoutSpecifierType()));
        auto component = KeyPathExpr::Component::forOptionalWrap(leafTy);
        resolvedComponents.push_back(component);
        componentTy = leafTy;
      }

      // Set the resolved components, and cache their types.
      E->resolveComponents(cs.getASTContext(), resolvedComponents);
      cs.cacheExprTypes(E);

      // See whether there's an equivalent ObjC key path string we can produce
      // for interop purposes.
      checkAndSetObjCKeyPathString(E);
      
      // The final component type ought to line up with the leaf type of the
      // key path.
      assert(!componentTy || componentTy->hasUnresolvedType()
             || componentTy->getWithoutSpecifierType()->isEqual(leafTy));

      if (!isFunctionType)
        return E;

      // If we've gotten here, the user has used key path literal syntax to form
      // a closure. The type checker has given E a function type to indicate
      // this; we're going to change E's type to KeyPath<baseTy, leafTy> and
      // then wrap it in a larger closure expression with the appropriate type.

      // Compute KeyPath<baseTy, leafTy> and set E's type back to it.
      auto kpDecl = cs.getASTContext().getKeyPathDecl();
      auto keyPathTy =
          BoundGenericType::get(kpDecl, nullptr, { baseTy, leafTy });
      E->setType(keyPathTy);
      cs.cacheType(E);

      // To ensure side effects of the key path expression (mainly indices in
      // subscripts) are only evaluated once, we construct an outer closure,
      // which is immediately evaluated, and an inner closure, which it returns.
      // The result looks like this:
      //
      //     return "{ $kp$ in { $0[keyPath: $kp$] } }( \(E) )"

      auto &ctx = cs.getASTContext();
      auto discriminator = AutoClosureExpr::InvalidDiscriminator;

      // The inner closure.
      //
      //     let closure = "{ $0[keyPath: $kp$] }"
      auto closureTy =
          FunctionType::get({ FunctionType::Param(baseTy) }, leafTy);
      auto closure = new (ctx)
          AutoClosureExpr(/*set body later*/nullptr, leafTy,
                          discriminator, cs.DC);
      auto param = new (ctx) ParamDecl(
          SourceLoc(),
          /*argument label*/ SourceLoc(), Identifier(),
          /*parameter name*/ SourceLoc(), ctx.getIdentifier("$0"), closure);
      param->setInterfaceType(baseTy->mapTypeOutOfContext());
      param->setSpecifier(ParamSpecifier::Default);

      // The outer closure.
      //
      //    let outerClosure = "{ $kp$ in \(closure) }"
      auto outerClosureTy =
          FunctionType::get({ FunctionType::Param(keyPathTy) }, closureTy);
      auto outerClosure = new (ctx)
          AutoClosureExpr(/*set body later*/nullptr, closureTy,
                          discriminator, cs.DC);
      auto outerParam =
          new (ctx) ParamDecl(SourceLoc(),
                              /*argument label*/ SourceLoc(), Identifier(),
                              /*parameter name*/ SourceLoc(),
                              ctx.getIdentifier("$kp$"), outerClosure);
      outerParam->setInterfaceType(keyPathTy->mapTypeOutOfContext());
      outerParam->setSpecifier(ParamSpecifier::Default);

      // let paramRef = "$0"
      auto *paramRef = new (ctx)
          DeclRefExpr(param, DeclNameLoc(E->getLoc()), /*Implicit=*/true);
      paramRef->setType(baseTy);
      cs.cacheType(paramRef);

      // let outerParamRef = "$kp$"
      auto outerParamRef = new (ctx)
          DeclRefExpr(outerParam, DeclNameLoc(E->getLoc()), /*Implicit=*/true);
      outerParamRef->setType(keyPathTy);
      cs.cacheType(outerParamRef);

      // let application = "\(paramRef)[keyPath: \(outerParamRef)]"
      auto *application = new (ctx)
          KeyPathApplicationExpr(paramRef,
                                 E->getStartLoc(), outerParamRef, E->getEndLoc(),
                                 leafTy, /*implicit=*/true);
      cs.cacheType(application);

      // Finish up the inner closure.
      closure->setParameterList(ParameterList::create(ctx, {param}));
      closure->setBody(application);
      closure->setType(closureTy);
      cs.cacheType(closure);

      // Finish up the outer closure.
      outerClosure->setParameterList(ParameterList::create(ctx, {outerParam}));
      outerClosure->setBody(closure);
      outerClosure->setType(outerClosureTy);
      cs.cacheType(outerClosure);

      // let outerApply = "\( outerClosure )( \(E) )"
      auto outerApply = CallExpr::createImplicit(ctx, outerClosure, {E}, {});
      outerApply->setType(closureTy);
      cs.cacheExprTypes(outerApply);

      return coerceToType(outerApply, exprType, cs.getConstraintLocator(E));
    }

    void buildKeyPathOptionalForceComponent(
        SmallVectorImpl<KeyPathExpr::Component> &components) {
      assert(!components.empty());

      // Unwrap the last component type, preserving @lvalue-ness.
      auto optionalTy = components.back().getComponentType();
      Type objectTy;
      if (auto lvalue = optionalTy->getAs<LValueType>()) {
        objectTy = lvalue->getObjectType()->getOptionalObjectType();
        if (optionalTy->hasUnresolvedType() && !objectTy) {
          objectTy = optionalTy;
        }
        objectTy = LValueType::get(objectTy);
      } else {
        objectTy = optionalTy->getOptionalObjectType();
        if (optionalTy->hasUnresolvedType() && !objectTy) {
          objectTy = optionalTy;
        }
      }
      assert(objectTy);

      auto loc = components.back().getLoc();
      components.push_back(
          KeyPathExpr::Component::forOptionalForce(objectTy, loc));
    }

    void buildKeyPathPropertyComponent(
        const SelectedOverload &overload, SourceLoc componentLoc,
        ConstraintLocator *locator,
        SmallVectorImpl<KeyPathExpr::Component> &components) {
      auto resolvedTy = simplifyType(overload.openedType);
      if (auto *property = overload.choice.getDeclOrNull()) {
        // Key paths can only refer to properties currently.
        auto varDecl = cast<VarDecl>(property);
        // Key paths don't work with mutating-get properties.
        assert(!varDecl->isGetterMutating());
        // Key paths don't currently support static members.
        // There is a fix which diagnoses such situation already.
        assert(!varDecl->isStatic());

        // Compute the concrete reference to the member.
        auto ref = resolveConcreteDeclRef(property, locator);
        components.push_back(
            KeyPathExpr::Component::forProperty(ref, resolvedTy, componentLoc));
      } else {
        auto fieldIndex = overload.choice.getTupleIndex();
        components.push_back(KeyPathExpr::Component::forTupleElement(
            fieldIndex, resolvedTy, componentLoc));
      }

      if (shouldForceUnwrapResult(overload.choice, locator))
        buildKeyPathOptionalForceComponent(components);
    }

    void buildKeyPathSubscriptComponent(
        const SelectedOverload &overload,
        SourceLoc componentLoc, Expr *indexExpr,
        ArrayRef<Identifier> labels, ConstraintLocator *locator,
        SmallVectorImpl<KeyPathExpr::Component> &components) {
      auto subscript = cast<SubscriptDecl>(overload.choice.getDecl());
      assert(!subscript->isGetterMutating());

      // Compute substitutions to refer to the member.
      auto ref = resolveConcreteDeclRef(subscript, locator);

      // If this is a @dynamicMemberLookup reference to resolve a property
      // through the subscript(dynamicMember:) member, restore the
      // openedType and origComponent to its full reference as if the user
      // wrote out the subscript manually.
      bool forDynamicLookup =
          overload.choice.getKind() ==
              OverloadChoiceKind::DynamicMemberLookup ||
          overload.choice.getKind() ==
              OverloadChoiceKind::KeyPathDynamicMemberLookup;

      if (forDynamicLookup) {
        labels = cs.getASTContext().Id_dynamicMember;

        auto indexType = getTypeOfDynamicMemberIndex(overload);
        if (overload.choice.getKind() ==
            OverloadChoiceKind::KeyPathDynamicMemberLookup) {
          indexExpr = buildKeyPathDynamicMemberIndexExpr(
              indexType->castTo<BoundGenericType>(), componentLoc, locator);
        } else {
          auto fieldName = overload.choice.getName().getBaseIdentifier().str();
          indexExpr = buildDynamicMemberLookupIndexExpr(fieldName, componentLoc,
                                                        indexType);
        }
      }

      auto subscriptType =
          simplifyType(overload.openedType)->castTo<AnyFunctionType>();
      auto resolvedTy = subscriptType->getResult();

      // Coerce the indices to the type the subscript expects.
      auto *newIndexExpr =
          coerceCallArguments(indexExpr, subscriptType, ref,
                              /*applyExpr*/ nullptr, labels,
                              locator);

      // We need to be able to hash the captured index values in order for
      // KeyPath itself to be hashable, so check that all of the subscript
      // index components are hashable and collect their conformances here.
      SmallVector<ProtocolConformanceRef, 4> conformances;

      auto hashable =
          cs.getASTContext().getProtocol(KnownProtocolKind::Hashable);

      auto fnType = overload.openedType->castTo<FunctionType>();
      SmallVector<Identifier, 4> newLabels;
      for (auto &param : fnType->getParams()) {
        newLabels.push_back(param.getLabel());

        auto indexType = simplifyType(param.getParameterType());
        // Index type conformance to Hashable protocol has been
        // verified by the solver, we just need to get it again
        // with all of the generic parameters resolved.
        auto hashableConformance =
          TypeChecker::conformsToProtocol(indexType, hashable, cs.DC);
        assert(hashableConformance);

        conformances.push_back(hashableConformance);
      }

      auto comp = KeyPathExpr::Component::forSubscriptWithPrebuiltIndexExpr(
          ref, newIndexExpr, cs.getASTContext().AllocateCopy(newLabels),
          resolvedTy, componentLoc,
          cs.getASTContext().AllocateCopy(conformances));
      components.push_back(comp);

      if (shouldForceUnwrapResult(overload.choice, locator))
        buildKeyPathOptionalForceComponent(components);
    }

    Expr *visitKeyPathDotExpr(KeyPathDotExpr *E) {
      llvm_unreachable("found KeyPathDotExpr in CSApply");
    }

    Expr *visitOneWayExpr(OneWayExpr *E) {
      auto type = simplifyType(cs.getType(E));
      return coerceToType(E->getSubExpr(), type, cs.getConstraintLocator(E));
    }

    Expr *visitTapExpr(TapExpr *E) {
      auto type = simplifyType(cs.getType(E));

      E->getVar()->setInterfaceType(type->mapTypeOutOfContext());

      cs.setType(E, type);
      E->setType(type);

      return E;
    }

    /// Interface for ExprWalker
    void walkToExprPre(Expr *expr) {
      // If we have an apply, make a note of its callee locator prior to
      // rewriting.
      if (auto *apply = dyn_cast<ApplyExpr>(expr)) {
        auto *calleeLoc = cs.getCalleeLocator(cs.getConstraintLocator(expr));
        CalleeLocators[apply] = calleeLoc;
      }
      ExprStack.push_back(expr);
    }

    Expr *walkToExprPost(Expr *expr) {
      Expr *result = visit(expr);

      assert(expr == ExprStack.back());
      ExprStack.pop_back();

      return result;
    }

    void finalize() {
      assert(ExprStack.empty());
      assert(OpenedExistentials.empty());

      auto &ctx = cs.getASTContext();

      // Look at all of the suspicious optional injections
      for (auto injection : SuspiciousOptionalInjections) {
        auto *cast = findForcedDowncast(ctx, injection->getSubExpr());
        if (!cast)
          continue;

        if (isa<ParenExpr>(injection->getSubExpr()))
          continue;

        ctx.Diags.diagnose(
            injection->getLoc(), diag::inject_forced_downcast,
            cs.getType(injection->getSubExpr())->getRValueType());
        auto exclaimLoc = cast->getExclaimLoc();
        ctx.Diags
            .diagnose(exclaimLoc, diag::forced_to_conditional_downcast,
                      cs.getType(injection)->getOptionalObjectType())
            .fixItReplace(exclaimLoc, "?");
        ctx.Diags
            .diagnose(cast->getStartLoc(), diag::silence_inject_forced_downcast)
            .fixItInsert(cast->getStartLoc(), "(")
            .fixItInsertAfter(cast->getEndLoc(), ")");
      }
    }

    /// Diagnose an optional injection that is probably not what the
    /// user wanted, because it comes from a forced downcast.
    void diagnoseOptionalInjection(InjectIntoOptionalExpr *injection) {
      // Check whether we have a forced downcast.
      auto *cast =
          findForcedDowncast(cs.getASTContext(), injection->getSubExpr());
      if (!cast)
        return;
      
      SuspiciousOptionalInjections.push_back(injection);
    }
  };
} // end anonymous namespace

ConcreteDeclRef
Solution::resolveLocatorToDecl(ConstraintLocator *locator) const {
  // Get the callee locator without looking through applies, ensuring we only
  // return a decl for a direct reference.
  auto *calleeLoc =
      constraintSystem->getCalleeLocator(locator, /*lookThroughApply*/ false);
  auto overload = getOverloadChoiceIfAvailable(calleeLoc);
  if (!overload)
    return ConcreteDeclRef();

  return resolveConcreteDeclRef(overload->choice.getDeclOrNull(), locator);
}

/// Returns the concrete callee which 'owns' the default argument at a given
/// index. This looks through inheritance for inherited default args.
static ConcreteDeclRef getDefaultArgOwner(ConcreteDeclRef owner,
                                          unsigned index) {
  auto *param = getParameterAt(owner.getDecl(), index);
  if (param->getDefaultArgumentKind() == DefaultArgumentKind::Inherited) {
    return getDefaultArgOwner(owner.getOverriddenDecl(), index);
  }
  return owner;
}

static bool canPeepholeTupleConversion(Expr *expr,
                                       ArrayRef<unsigned> sources) {
  if (!isa<TupleExpr>(expr))
    return false;

  for (unsigned i = 0, e = sources.size(); i != e; ++i) {
    if (sources[i] != i)
      return false;
  }

  return true;
}

Expr *ExprRewriter::coerceTupleToTuple(Expr *expr,
                                       TupleType *fromTuple,
                                       TupleType *toTuple,
                                       ConstraintLocatorBuilder locator,
                                       ArrayRef<unsigned> sources) {
  auto &ctx = cs.getASTContext();

  // If the input expression is a tuple expression, we can convert it in-place.
  if (canPeepholeTupleConversion(expr, sources)) {
    auto *tupleExpr = cast<TupleExpr>(expr);

    for (unsigned i = 0, e = tupleExpr->getNumElements(); i != e; ++i) {
      auto *fromElt = tupleExpr->getElement(i);

      // Actually convert the source element.
      auto toEltType = toTuple->getElementType(i);

      auto *toElt
        = coerceToType(fromElt, toEltType,
                      locator.withPathElement(
                        LocatorPathElt::TupleElement(i)));
      if (!toElt)
        return nullptr;

      tupleExpr->setElement(i, toElt);
    }

    tupleExpr->setType(toTuple);
    cs.cacheType(tupleExpr);

    return tupleExpr;
  }

  // Build a list of OpaqueValueExprs that matches the structure
  // of expr's type.
  //
  // Each OpaqueValueExpr's type is equal to the type of the
  // corresponding element of fromTuple.
  SmallVector<OpaqueValueExpr *, 4> destructured;
  for (unsigned i = 0, e = sources.size(); i != e; ++i) {
    auto fromEltType = fromTuple->getElementType(i);
    auto *opaqueElt =
        new (ctx) OpaqueValueExpr(expr->getSourceRange(), fromEltType);
    cs.cacheType(opaqueElt);
    destructured.push_back(opaqueElt);
  }

  // Convert each OpaqueValueExpr to the correct type.
  SmallVector<Expr *, 4> converted;
  SmallVector<Identifier, 4> labels;
  SmallVector<TupleTypeElt, 4> convertedElts;

  bool anythingShuffled = false;
  for (unsigned i = 0, e = sources.size(); i != e; ++i) {
    unsigned source = sources[i];
    auto *fromElt = destructured[source];

    // Actually convert the source element.
    auto toEltType = toTuple->getElementType(i);
    auto toLabel = toTuple->getElement(i).getName();

    // If we're shuffling positions and labels, we have to warn about this
    // conversion.
    if (i != sources[i] &&
        fromTuple->getElement(i).getName() != toLabel)
      anythingShuffled = true;

    auto *toElt
      = coerceToType(fromElt, toEltType,
                     locator.withPathElement(
                       LocatorPathElt::TupleElement(source)));
    if (!toElt)
      return nullptr;

    converted.push_back(toElt);
    labels.push_back(toLabel);
    convertedElts.emplace_back(toEltType, toLabel, ParameterTypeFlags());
  }

  // Shuffling tuple elements is an anti-pattern worthy of a diagnostic.  We
  // will form the shuffle for now, but a future compiler should decline to
  // do so and begin the process of removing them altogether.
  if (anythingShuffled) {
    cs.getASTContext().Diags.diagnose(
        expr->getLoc(), diag::warn_reordering_tuple_shuffle_deprecated);
  }

  // Create the result tuple, written in terms of the destructured
  // OpaqueValueExprs.
  auto *result = TupleExpr::createImplicit(ctx, converted, labels);
  result->setType(TupleType::get(convertedElts, ctx));
  cs.cacheType(result);

  // Create the tuple conversion.
  return cs.cacheType(
      DestructureTupleExpr::create(ctx, destructured, expr, result, toTuple));
}

static Type getMetatypeSuperclass(Type t) {
  if (auto *metaTy = t->getAs<MetatypeType>())
    return MetatypeType::get(getMetatypeSuperclass(
                               metaTy->getInstanceType()));

  if (auto *metaTy = t->getAs<ExistentialMetatypeType>())
    return ExistentialMetatypeType::get(getMetatypeSuperclass(
                                          metaTy->getInstanceType()));

  return t->getSuperclass();
}

Expr *ExprRewriter::coerceSuperclass(Expr *expr, Type toType) {
  auto &ctx = cs.getASTContext();

  auto fromType = cs.getType(expr);

  auto fromInstanceType = fromType;
  auto toInstanceType = toType;

  while (fromInstanceType->is<AnyMetatypeType>() &&
         toInstanceType->is<MetatypeType>()) {
    fromInstanceType = fromInstanceType->castTo<AnyMetatypeType>()
      ->getInstanceType();
    toInstanceType = toInstanceType->castTo<MetatypeType>()
      ->getInstanceType();
  }

  if (fromInstanceType->is<ArchetypeType>()) {
    // Coercion from archetype to its (concrete) superclass.
    auto superclass = getMetatypeSuperclass(fromType);

    expr =
      cs.cacheType(
        new (ctx) ArchetypeToSuperExpr(expr, superclass));

    if (!superclass->isEqual(toType))
      return coerceSuperclass(expr, toType);

    return expr;

  }

  if (fromInstanceType->isExistentialType()) {
    // Coercion from superclass-constrained existential to its
    // concrete superclass.
    auto fromArchetype = OpenedArchetypeType::getAny(fromType);

    auto *archetypeVal = cs.cacheType(new (ctx) OpaqueValueExpr(
        expr->getSourceRange(), fromArchetype));

    auto *result = coerceSuperclass(archetypeVal, toType);

    return cs.cacheType(
      new (ctx) OpenExistentialExpr(expr, archetypeVal, result,
                                           toType));
  }

  // Coercion from subclass to superclass.
  if (toType->is<MetatypeType>()) {
    return cs.cacheType(
      new (ctx) MetatypeConversionExpr(expr, toType));
  }

  return cs.cacheType(
    new (ctx) DerivedToBaseExpr(expr, toType));
}

/// Collect the conformances for all the protocols of an existential type.
/// If the source type is also existential, we don't want to check conformance
/// because most protocols do not conform to themselves -- however we still
/// allow the conversion here, except the ErasureExpr ends up with trivial
/// conformances.
static ArrayRef<ProtocolConformanceRef>
collectExistentialConformances(Type fromType, Type toType,
                               DeclContext *DC) {
  auto layout = toType->getExistentialLayout();

  SmallVector<ProtocolConformanceRef, 4> conformances;
  for (auto proto : layout.getProtocols()) {
    conformances.push_back(TypeChecker::containsProtocol(
        fromType, proto->getDecl(), DC));
  }

  return toType->getASTContext().AllocateCopy(conformances);
}

Expr *ExprRewriter::coerceExistential(Expr *expr, Type toType) {
  Type fromType = cs.getType(expr);
  Type fromInstanceType = fromType;
  Type toInstanceType = toType;

  // Look through metatypes
  while ((fromInstanceType->is<UnresolvedType>() ||
          fromInstanceType->is<AnyMetatypeType>()) &&
         toInstanceType->is<ExistentialMetatypeType>()) {
    if (!fromInstanceType->is<UnresolvedType>())
      fromInstanceType = fromInstanceType->castTo<AnyMetatypeType>()->getInstanceType();
    toInstanceType = toInstanceType->castTo<ExistentialMetatypeType>()->getInstanceType();
  }

  ASTContext &ctx = cs.getASTContext();

  auto conformances =
    collectExistentialConformances(fromInstanceType, toInstanceType, cs.DC);

  // For existential-to-existential coercions, open the source existential.
  if (fromType->isAnyExistentialType()) {
    fromType = OpenedArchetypeType::getAny(fromType);

    auto *archetypeVal = cs.cacheType(
        new (ctx) OpaqueValueExpr(expr->getSourceRange(), fromType));

    auto *result = cs.cacheType(ErasureExpr::create(ctx, archetypeVal, toType,
                                                    conformances));
    return cs.cacheType(
        new (ctx) OpenExistentialExpr(expr, archetypeVal, result,
                                      cs.getType(result)));
  }

  // Load tuples with lvalue elements.
  if (auto tupleType = fromType->getAs<TupleType>()) {
    if (tupleType->hasLValueType()) {
      expr = cs.coerceToRValue(expr);
    }
  }

  return cs.cacheType(ErasureExpr::create(ctx, expr, toType, conformances));
}

/// Given that the given expression is an implicit conversion added
/// to the target by coerceToType, find out how many OptionalEvaluationExprs
/// it includes and the target.
static unsigned getOptionalEvaluationDepth(Expr *expr, Expr *target) {
  unsigned depth = 0;
  while (true) {
    // Look through sugar expressions.
    expr = expr->getSemanticsProvidingExpr();

    // If we find the target expression, we're done.
    if (expr == target) return depth;

    // If we see an optional evaluation, the depth goes up.
    if (auto optEval = dyn_cast<OptionalEvaluationExpr>(expr)) {
      ++depth;
      expr = optEval->getSubExpr();

    // We have to handle any other expressions that can be introduced by
    // coerceToType.
    } else if (auto bind = dyn_cast<BindOptionalExpr>(expr)) {
      expr = bind->getSubExpr();
    } else if (auto force = dyn_cast<ForceValueExpr>(expr)) {
      expr = force->getSubExpr();
    } else if (auto open = dyn_cast<OpenExistentialExpr>(expr)) {
      depth += getOptionalEvaluationDepth(open->getSubExpr(),
                                          open->getOpaqueValue());
      expr = open->getExistentialValue();

    // Otherwise, look through implicit conversions.
    } else {
      expr = cast<ImplicitConversionExpr>(expr)->getSubExpr();
    }
  }
}

Expr *ExprRewriter::coerceOptionalToOptional(Expr *expr, Type toType,
                                             ConstraintLocatorBuilder locator,
                                          Optional<Pattern*> typeFromPattern) {
  auto &ctx = cs.getASTContext();
  Type fromType = cs.getType(expr);

  TypeChecker::requireOptionalIntrinsics(ctx, expr->getLoc());

  SmallVector<Type, 4> fromOptionals;
  (void)fromType->lookThroughAllOptionalTypes(fromOptionals);

  SmallVector<Type, 4> toOptionals;
  (void)toType->lookThroughAllOptionalTypes(toOptionals);

  assert(!toOptionals.empty());
  assert(!fromOptionals.empty());

  // If we are adding optionals but the types are equivalent up to the common
  // depth, peephole the optional-to-optional conversion into a series of nested
  // injections.
  auto toDepth = toOptionals.size();
  auto fromDepth = fromOptionals.size();
  if (toDepth > fromDepth &&
      toOptionals[toOptionals.size() - fromDepth]->isEqual(fromType)) {
    auto diff = toDepth - fromDepth;
    while (diff--) {
      Type type = toOptionals[diff];
      expr = cs.cacheType(new (ctx) InjectIntoOptionalExpr(expr, type));
      diagnoseOptionalInjection(cast<InjectIntoOptionalExpr>(expr));
    }

    return expr;
  }

  Type fromValueType = fromType->getOptionalObjectType();
  Type toValueType = toType->getOptionalObjectType();

  // The depth we use here will get patched after we apply the coercion.
  auto bindOptional =
      new (ctx) BindOptionalExpr(expr, expr->getSourceRange().End,
                                 /*depth*/ 0, fromValueType);

  expr = cs.cacheType(bindOptional);
  expr->setImplicit(true);
  expr = coerceToType(expr, toValueType, locator, typeFromPattern);
  if (!expr) return nullptr;

  unsigned depth = getOptionalEvaluationDepth(expr, bindOptional);
  bindOptional->setDepth(depth);

  expr = cs.cacheType(new (ctx) InjectIntoOptionalExpr(expr, toType));

  expr = cs.cacheType(new (ctx) OptionalEvaluationExpr(expr, toType));
  expr->setImplicit(true);
  return expr;
}

Expr *ExprRewriter::coerceImplicitlyUnwrappedOptionalToValue(Expr *expr, Type objTy) {
  auto optTy = cs.getType(expr);
  // Preserve l-valueness of the result.
  if (optTy->is<LValueType>())
    objTy = LValueType::get(objTy);

  expr = new (cs.getASTContext()) ForceValueExpr(expr, expr->getEndLoc(),
                                                 /* forcedIUO=*/ true);
  cs.setType(expr, objTy);
  expr->setImplicit();
  return expr;
}

/// Determine whether the given expression is a reference to an
/// unbound instance member of a type.
static bool isReferenceToMetatypeMember(ConstraintSystem &cs, Expr *expr) {
  expr = expr->getSemanticsProvidingExpr();
  if (auto dotIgnored = dyn_cast<DotSyntaxBaseIgnoredExpr>(expr))
    return cs.getType(dotIgnored->getLHS())->is<AnyMetatypeType>();
  if (auto dotSyntax = dyn_cast<DotSyntaxCallExpr>(expr))
    return cs.getType(dotSyntax->getBase())->is<AnyMetatypeType>();
  return false;
}

static bool hasCurriedSelf(ConstraintSystem &cs, ConcreteDeclRef callee,
                           ApplyExpr *apply) {
  // If we do not have a callee, return false.
  if (!callee) {
    return false;
  }

  // Only calls to members of types can have curried 'self'.
  auto calleeDecl = callee.getDecl();
  if (!calleeDecl->getDeclContext()->isTypeContext()) {
    return false;
  }

  // Would have `self`, if we're not applying it.
  if (auto *call = dyn_cast<CallExpr>(apply)) {
    if (!calleeDecl->isInstanceMember() ||
        !isReferenceToMetatypeMember(cs, call->getDirectCallee())) {
      return true;
    }
    return false;
  }

  // Operators have curried self.
  if (isa<PrefixUnaryExpr>(apply) || isa<PostfixUnaryExpr>(apply) ||
      isa<BinaryExpr>(apply)) {
    return true;
  }

  // Otherwise, we have a normal application.
  return false;
}

Expr *ExprRewriter::coerceCallArguments(
    Expr *arg, AnyFunctionType *funcType,
    ConcreteDeclRef callee,
    ApplyExpr *apply,
    ArrayRef<Identifier> argLabels,
    ConstraintLocatorBuilder locator) {
  auto &ctx = getConstraintSystem().getASTContext();
  auto params = funcType->getParams();

  // Local function to produce a locator to refer to the given parameter.
  auto getArgLocator =
      [&](unsigned argIdx, unsigned paramIdx,
          ParameterTypeFlags flags) -> ConstraintLocatorBuilder {
    return locator.withPathElement(
        LocatorPathElt::ApplyArgToParam(argIdx, paramIdx, flags));
  };

  bool matchCanFail =
      llvm::any_of(params, [](const AnyFunctionType::Param &param) {
        return param.getPlainType()->hasUnresolvedType();
      });

  // Determine whether this application has curried self.
  bool skipCurriedSelf = apply ? hasCurriedSelf(cs, callee, apply) : true;
  // Determine the parameter bindings.
  ParameterListInfo paramInfo(params, callee.getDecl(), skipCurriedSelf);

  SmallVector<AnyFunctionType::Param, 8> args;
  AnyFunctionType::decomposeInput(cs.getType(arg), args);

  // If this application is an init(wrappedValue:) call that needs an injected
  // wrapped value placeholder, the first non-defaulted argument must be
  // wrapped in an OpaqueValueExpr.
  bool shouldInjectWrappedValuePlaceholder =
     target->shouldInjectWrappedValuePlaceholder(apply);

  auto injectWrappedValuePlaceholder =
      [&](Expr *arg, bool isAutoClosure = false) -> Expr * {
        auto *placeholder = PropertyWrapperValuePlaceholderExpr::create(
            ctx, arg->getSourceRange(), cs.getType(arg),
            target->propertyWrapperHasInitialWrappedValue() ? arg : nullptr,
            isAutoClosure);
        cs.cacheType(placeholder);
        cs.cacheType(placeholder->getOpaqueValuePlaceholder());
        shouldInjectWrappedValuePlaceholder = false;
        return placeholder;
      };

  // Quickly test if any further fix-ups for the argument types are necessary.
  if (AnyFunctionType::equalParams(args, params) &&
      !shouldInjectWrappedValuePlaceholder)
    return arg;

  // Apply labels to arguments.
  AnyFunctionType::relabelParams(args, argLabels);

  MatchCallArgumentListener listener;
  auto unlabeledTrailingClosureIndex =
      arg->getUnlabeledTrailingClosureIndexOfPackedArgument();

  // Determine the trailing closure matching rule that was applied. This
  // is only relevant for explicit calls and subscripts.
  auto trailingClosureMatching = TrailingClosureMatching::Forward;
  {
    SmallVector<LocatorPathElt, 4> path;
    auto anchor = locator.getLocatorParts(path);
    if (!path.empty() && path.back().is<LocatorPathElt::ApplyArgument>() &&
        !anchor.isExpr(ExprKind::UnresolvedDot)) {
      auto locatorPtr = cs.getConstraintLocator(locator);
      assert(solution.trailingClosureMatchingChoices.count(locatorPtr) == 1);
      trailingClosureMatching = solution.trailingClosureMatchingChoices.find(
          locatorPtr)->second;
    }
  }

  auto callArgumentMatch = constraints::matchCallArguments(
      args, params, paramInfo, unlabeledTrailingClosureIndex,
      /*allowFixes=*/false, listener, trailingClosureMatching);

  assert((matchCanFail || callArgumentMatch) &&
         "Call arguments did not match up?");
  (void)matchCanFail;

  auto parameterBindings = std::move(callArgumentMatch->parameterBindings);

  // We should either have parentheses or a tuple.
  auto *argTuple = dyn_cast<TupleExpr>(arg);
  auto *argParen = dyn_cast<ParenExpr>(arg);
  // FIXME: Eventually, we want to enforce that we have either argTuple or
  // argParen here.

  SourceLoc lParenLoc, rParenLoc;
  if (argTuple) {
    lParenLoc = argTuple->getLParenLoc();
    rParenLoc = argTuple->getRParenLoc();
  } else if (argParen) {
    lParenLoc = argParen->getLParenLoc();
    rParenLoc = argParen->getRParenLoc();
  }

  // Local function to extract the ith argument expression, which papers
  // over some of the weirdness with tuples vs. parentheses.
  auto getArg = [&](unsigned i) -> Expr * {
    if (argTuple)
      return argTuple->getElement(i);
    assert(i == 0 && "Scalar only has a single argument");

    if (argParen)
      return argParen->getSubExpr();

    return arg;
  };

  auto getLabelLoc = [&](unsigned i) -> SourceLoc {
    if (argTuple)
      return argTuple->getElementNameLoc(i);

    assert(i == 0 && "Scalar only has a single argument");
    return SourceLoc();
  };

  SmallVector<Expr *, 4> newArgs;
  SmallVector<Identifier, 4> newLabels;
  SmallVector<SourceLoc, 4> newLabelLocs;
  SmallVector<AnyFunctionType::Param, 4> newParams;

  for (unsigned paramIdx = 0, numParams = parameterBindings.size();
       paramIdx != numParams; ++paramIdx) {
    // Extract the parameter.
    const auto &param = params[paramIdx];
    newLabels.push_back(param.getLabel());

    // Handle variadic parameters.
    if (param.isVariadic()) {
      assert(!param.isInOut());

      SmallVector<Expr *, 4> variadicArgs;

      // The first argument of this vararg parameter may have had a label;
      // save its location.
      auto &varargIndices = parameterBindings[paramIdx];
      if (!varargIndices.empty())
        newLabelLocs.push_back(getLabelLoc(varargIndices[0]));
      else
        newLabelLocs.push_back(SourceLoc());

      // Convert the arguments.
      for (auto argIdx : varargIndices) {
        auto arg = getArg(argIdx);
        auto argType = cs.getType(arg);

        // If the argument type exactly matches, this just works.
        if (argType->isEqual(param.getPlainType())) {
          variadicArgs.push_back(arg);
          continue;
        }

        // Convert the argument.
        auto convertedArg = coerceToType(
            arg, param.getPlainType(),
            getArgLocator(argIdx, paramIdx, param.getParameterFlags()));
        if (!convertedArg)
          return nullptr;

        // Add the converted argument.
        variadicArgs.push_back(convertedArg);
      }

      SourceLoc start, end;
      if (!variadicArgs.empty()) {
        start = variadicArgs.front()->getStartLoc();
        end = variadicArgs.back()->getEndLoc();
      }

      // Collect them into an ArrayExpr.
      auto *arrayExpr = ArrayExpr::create(ctx, start, variadicArgs, {}, end,
                                          param.getParameterType());
      arrayExpr->setImplicit();
      cs.cacheType(arrayExpr);

      // Wrap the ArrayExpr in a VarargExpansionExpr.
      auto *varargExpansionExpr = new (ctx)
          VarargExpansionExpr(arrayExpr,
                              /*implicit=*/true, arrayExpr->getType());
      cs.cacheType(varargExpansionExpr);

      newArgs.push_back(varargExpansionExpr);
      newParams.push_back(param);
      continue;
    }

    // Handle default arguments.
    if (parameterBindings[paramIdx].empty()) {
      auto owner = getDefaultArgOwner(callee, paramIdx);
      auto paramTy = param.getParameterType();
      auto *defArg = new (ctx)
          DefaultArgumentExpr(owner, paramIdx, arg->getStartLoc(), paramTy, dc);

      cs.cacheType(defArg);
      newArgs.push_back(defArg);
      newParams.push_back(param);
      newLabelLocs.push_back(SourceLoc());
      continue;
    }

    // Otherwise, we have a plain old ordinary argument.

    // Extract the argument used to initialize this parameter.
    assert(parameterBindings[paramIdx].size() == 1);
    unsigned argIdx = parameterBindings[paramIdx].front();
    auto arg = getArg(argIdx);
    auto argType = cs.getType(arg);

    // Save the original label location.
    newLabelLocs.push_back(getLabelLoc(argIdx));

    // If the types exactly match, this is easy.
    auto paramType = param.getOldType();
    if (argType->isEqual(paramType) && !shouldInjectWrappedValuePlaceholder) {
      newArgs.push_back(arg);
      newParams.push_back(param);
      continue;
    }

    Expr *convertedArg = nullptr;
    auto argRequiresAutoClosureExpr = [&](const AnyFunctionType::Param &param,
                                          Type argType) {
      if (!param.isAutoClosure())
        return false;

      // Since it was allowed to pass function types to @autoclosure
      // parameters in Swift versions < 5, it has to be handled as
      // a regular function coversion by `coerceToType`.
      if (isAutoClosureArgument(arg)) {
        // In Swift >= 5 mode we only allow `@autoclosure` arguments
        // to be used by value if parameter would return a function
        // type (it just needs to get wrapped into autoclosure expr),
        // otherwise argument must always form a call.
        return cs.getASTContext().isSwiftVersionAtLeast(5);
      }

      return true;
    };

    if (argRequiresAutoClosureExpr(param, argType)) {
      assert(!param.isInOut());

      // If parameter is an autoclosure, we need to make sure that:
      //   - argument type is coerced to parameter result type
      //   - impilict autoclosure is created to wrap argument expression
      //   - new types are propagated to constraint system
      auto *closureType = param.getPlainType()->castTo<FunctionType>();

      auto argLoc = getArgLocator(argIdx, paramIdx, param.getParameterFlags());

      arg = coerceToType(
          arg, closureType->getResult(),
          argLoc.withPathElement(ConstraintLocator::AutoclosureResult));

      if (shouldInjectWrappedValuePlaceholder) {
        // If init(wrappedValue:) takes an autoclosure, then we want
        // the effect of autoclosure forwarding of the placeholder
        // autoclosure. The only way to do this is to call the placeholder
        // autoclosure when passing it to the init.
        bool isDefaultWrappedValue =
            target->propertyWrapperHasInitialWrappedValue();
        auto *placeholder = injectWrappedValuePlaceholder(
            cs.buildAutoClosureExpr(arg, closureType, isDefaultWrappedValue),
            /*isAutoClosure=*/true);
        arg = CallExpr::createImplicit(ctx, placeholder, {}, {});
        arg->setType(closureType->getResult());
        cs.cacheType(arg);
      }

      convertedArg = cs.buildAutoClosureExpr(arg, closureType);
    } else {
      convertedArg = coerceToType(
          arg, paramType,
          getArgLocator(argIdx, paramIdx, param.getParameterFlags()));
    }

    // Perform the wrapped value placeholder injection
    if (shouldInjectWrappedValuePlaceholder)
      convertedArg = injectWrappedValuePlaceholder(convertedArg);

    if (!convertedArg)
      return nullptr;

    newArgs.push_back(convertedArg);

    // Make an effort to preserve the sugared type of the argument in the
    // case where there was no conversion, instead of using the parameter
    // type.
    newParams.emplace_back(cs.getType(convertedArg)->getInOutObjectType(),
                           param.getLabel(),
                           param.getParameterFlags());
  }

  assert(newArgs.size() == newParams.size());
  assert(newArgs.size() == newLabels.size());
  assert(newArgs.size() == newLabelLocs.size());

  // This is silly. SILGen gets confused if a 'self' parameter is wrapped
  // in a ParenExpr sometimes.
  if (!argTuple && !argParen &&
      (params[0].getValueOwnership() == ValueOwnership::Default ||
       params[0].getValueOwnership() == ValueOwnership::InOut)) {
    assert(newArgs.size() == 1);
    assert(!unlabeledTrailingClosureIndex);
    return newArgs[0];
  }

  // Rebuild the argument list, sharing as much structure as possible.
  auto paramType = AnyFunctionType::composeInput(ctx, newParams,
                                                 /*canonicalVararg=*/false);
  if (isa<ParenType>(paramType.getPointer())) {
    if (argParen) {
      // We already had a ParenExpr, so replace it's sub-expression.
      argParen->setSubExpr(newArgs[0]);
    } else {
      bool isImplicit = arg->isImplicit();
      arg = new (ctx) ParenExpr(
          lParenLoc, newArgs[0], rParenLoc,
          static_cast<bool>(unlabeledTrailingClosureIndex));
      arg->setImplicit(isImplicit);
    }
  } else {
    assert(isa<TupleType>(paramType.getPointer()));

    if (argTuple && newArgs.size() == argTuple->getNumElements()) {
      // The existing TupleExpr has the right number of elements,
      // replace them.
      for (unsigned i = 0, e = newArgs.size(); i != e; ++i) {
        argTuple->setElement(i, newArgs[i]);
      }
    } else {
      // Build a new TupleExpr, re-using source location information.
      arg = TupleExpr::create(ctx, lParenLoc, rParenLoc, newArgs, newLabels,
                              newLabelLocs, unlabeledTrailingClosureIndex,
                              /*implicit=*/arg->isImplicit());
    }
  }

  arg->setType(paramType);
  return cs.cacheType(arg);
}

static bool isClosureLiteralExpr(Expr *expr) {
  expr = expr->getSemanticsProvidingExpr();
  return (isa<CaptureListExpr>(expr) || isa<ClosureExpr>(expr));
}

/// If the expression is an explicit closure expression (potentially wrapped in
/// IdentityExprs), change the type of the closure and identities to the
/// specified type and return true.  Otherwise, return false with no effect.
static bool applyTypeToClosureExpr(ConstraintSystem &cs,
                                   Expr *expr, Type toType) {
  // Look through identity expressions, like parens.
  if (auto IE = dyn_cast<IdentityExpr>(expr)) {
    if (!applyTypeToClosureExpr(cs, IE->getSubExpr(), toType)) return false;
    cs.setType(IE, toType);
    return true;
  }

  // Look through capture lists.
  if (auto CLE = dyn_cast<CaptureListExpr>(expr)) {
    if (!applyTypeToClosureExpr(cs, CLE->getClosureBody(), toType)) return false;
    cs.setType(CLE, toType);
    return true;
  }

  // If we found an explicit ClosureExpr, update its type.
  if (auto CE = dyn_cast<ClosureExpr>(expr)) {
    cs.setType(CE, toType);

    // If this closure isn't type-checked in its enclosing expression, write
    // the type into the ClosureExpr directly here, since the visitor won't.
    if (!shouldTypeCheckInEnclosingExpression(CE))
      CE->setType(toType);

    return true;
  }

  // Otherwise fail.
  return false;
}

// Look through sugar and DotSyntaxBaseIgnoredExprs.
static Expr *
getSemanticExprForDeclOrMemberRef(Expr *expr) {
  auto semanticExpr = expr->getSemanticsProvidingExpr();
  while (auto ignoredBase = dyn_cast<DotSyntaxBaseIgnoredExpr>(semanticExpr)){
    semanticExpr = ignoredBase->getRHS()->getSemanticsProvidingExpr();
  }
  return semanticExpr;
}

static void
maybeDiagnoseUnsupportedDifferentiableConversion(ConstraintSystem &cs,
                                                 Expr *expr,
                                                 AnyFunctionType *toType) {
  ASTContext &ctx = cs.getASTContext();
  Type fromType = cs.getType(expr);
  auto fromFnType = fromType->getAs<AnyFunctionType>();
  auto isToTypeLinear =
      toType->getDifferentiabilityKind() == DifferentiabilityKind::Linear;
  // Conversion from a `@differentiable` function to a `@differentiable(linear)`
  // function is not allowed, because the from-expression will never be a
  // closure expression or a declaration/member reference.
  if (fromFnType->getDifferentiabilityKind() == DifferentiabilityKind::Normal &&
      toType->getDifferentiabilityKind() == DifferentiabilityKind::Linear) {
    ctx.Diags.diagnose(expr->getLoc(),
                       diag::invalid_differentiable_function_conversion_expr,
                       isToTypeLinear);
    return;
  }
  // Conversion from a non-`@differentiable` function to a `@differentiable` is
  // only allowed from a closure expression or a declaration/member reference.
  if (!fromFnType->isDifferentiable() && toType->isDifferentiable()) {
    std::function<void(Expr *)> maybeDiagnoseFunctionRef;
    maybeDiagnoseFunctionRef = [&](Expr *semanticExpr) {
      if (auto *capture = dyn_cast<CaptureListExpr>(semanticExpr))
        semanticExpr = capture->getClosureBody();
      if (isa<ClosureExpr>(semanticExpr)) return;
      if (auto *declRef = dyn_cast<DeclRefExpr>(semanticExpr)) {
        if (isa<AbstractFunctionDecl>(declRef->getDecl())) return;
        // If the referenced decl is a function parameter, the user may want
        // to change the declaration to be a '@differentiable' closure. Emit a
        // note with a fix-it.
        if (auto *paramDecl = dyn_cast<ParamDecl>(declRef->getDecl())) {
          ctx.Diags.diagnose(
              expr->getLoc(),
              diag::invalid_differentiable_function_conversion_expr,
              isToTypeLinear);
          if (paramDecl->getType()->is<AnyFunctionType>()) {
            auto *typeRepr = paramDecl->getTypeRepr();
            while (auto *attributed = dyn_cast<AttributedTypeRepr>(typeRepr))
              typeRepr = attributed->getTypeRepr();
            std::string attributeString = "@differentiable";
            if (isToTypeLinear)
              attributeString += "(linear)";
            auto *funcTypeRepr = cast<FunctionTypeRepr>(typeRepr);
            auto paramListLoc = funcTypeRepr->getArgsTypeRepr()->getStartLoc();
            ctx.Diags.diagnose(paramDecl->getLoc(),
                    diag::invalid_differentiable_function_conversion_parameter,
                    attributeString)
                .highlight(paramDecl->getTypeRepr()->getSourceRange())
                .fixItInsert(paramListLoc, attributeString + " ");
          }
          return;
        }
      } else if (auto *memberRef = dyn_cast<MemberRefExpr>(semanticExpr)) {
        if (isa<FuncDecl>(memberRef->getMember().getDecl())) return;
      } else if (auto *dotSyntaxCall =
                     dyn_cast<DotSyntaxCallExpr>(semanticExpr)) {
        // Recurse on the function expression.
        auto *fnExpr = dotSyntaxCall->getFn()->getSemanticsProvidingExpr();
        maybeDiagnoseFunctionRef(fnExpr);
        return;
      } else if (auto *autoclosureExpr = dyn_cast<AutoClosureExpr>(semanticExpr)) {
        // Peer through curry thunks.
        if (auto *unwrappedFnExpr = autoclosureExpr->getUnwrappedCurryThunkExpr()) {
          maybeDiagnoseFunctionRef(unwrappedFnExpr);
          return;
        }
      }
      ctx.Diags.diagnose(expr->getLoc(),
                         diag::invalid_differentiable_function_conversion_expr,
                         isToTypeLinear);
    };
    maybeDiagnoseFunctionRef(getSemanticExprForDeclOrMemberRef(expr));
  }
}

static void
maybeDiagnoseUnsupportedFunctionConversion(ConstraintSystem &cs, Expr *expr,
                                           AnyFunctionType *toType) {
  auto &de = cs.getASTContext().Diags;
  Type fromType = cs.getType(expr);
  auto fromFnType = fromType->getAs<AnyFunctionType>();
  
  // Conversions to C function pointer type are limited. Since a C function
  // pointer captures no context, we can only do the necessary thunking or
  // codegen if the original function is a direct reference to a global function
  // or context-free closure or local function.
  if (toType->getRepresentation()
       == AnyFunctionType::Representation::CFunctionPointer) {
    // Can convert from an ABI-compatible C function pointer.
    if (fromFnType
        && fromFnType->getRepresentation()
            == AnyFunctionType::Representation::CFunctionPointer)
      return;
    
    // Can convert a decl ref to a global or local function that doesn't
    // capture context. Look through ignored bases too.
    // TODO: Look through static method applications to the type.
    auto semanticExpr = getSemanticExprForDeclOrMemberRef(expr);
    auto maybeDiagnoseFunctionRef = [&](FuncDecl *fn) {
      // TODO: We could allow static (or class final) functions too by
      // "capturing" the metatype in a thunk.
      if (fn->getDeclContext()->isTypeContext()) {
        de.diagnose(expr->getLoc(), diag::c_function_pointer_from_method);
      } else if (fn->getGenericParams()) {
        de.diagnose(expr->getLoc(),
                    diag::c_function_pointer_from_generic_function);
      }
    };
    
    if (auto declRef = dyn_cast<DeclRefExpr>(semanticExpr)) {
      if (auto fn = dyn_cast<FuncDecl>(declRef->getDecl())) {
        return maybeDiagnoseFunctionRef(fn);
      }
    }
    
    if (auto memberRef = dyn_cast<MemberRefExpr>(semanticExpr)) {
      if (auto fn = dyn_cast<FuncDecl>(memberRef->getMember().getDecl())) {
        return maybeDiagnoseFunctionRef(fn);
      }
    }

    // Unwrap closures with explicit capture lists.
    if (auto capture = dyn_cast<CaptureListExpr>(semanticExpr))
      semanticExpr = capture->getClosureBody();
    
    // Can convert a literal closure that doesn't capture context.
    if (auto closure = dyn_cast<ClosureExpr>(semanticExpr))
      return;

    de.diagnose(expr->getLoc(),
                diag::invalid_c_function_pointer_conversion_expr);
  }
}

/// Build the conversion of an element in a collection upcast.
static Expr *buildElementConversion(ExprRewriter &rewriter,
                                    SourceRange srcRange, Type srcType,
                                    Type destType, bool bridged,
                                    ConstraintLocatorBuilder locator,
                                    Expr *element) {
  auto &cs = rewriter.getConstraintSystem();
  if (bridged &&
      TypeChecker::typeCheckCheckedCast(srcType, destType,
                                        CheckedCastContextKind::None, cs.DC,
                                        SourceLoc(), nullptr, SourceRange())
        != CheckedCastKind::Coercion) {
    if (auto conversion =
          rewriter.buildObjCBridgeExpr(element, destType, locator))
        return conversion;
  }

  return rewriter.coerceToType(element, destType, locator);
}

static CollectionUpcastConversionExpr::ConversionPair
buildOpaqueElementConversion(ExprRewriter &rewriter, SourceRange srcRange,
                             Type srcCollectionType, Type destCollectionType,
                             bool bridged, ConstraintLocatorBuilder locator,
                             unsigned typeArgIndex) {
  // We don't need this stuff unless we've got generalized casts.
  Type srcType = srcCollectionType->castTo<BoundGenericType>()
                                  ->getGenericArgs()[typeArgIndex];
  Type destType = destCollectionType->castTo<BoundGenericType>()
                                    ->getGenericArgs()[typeArgIndex];

  // Build the conversion.
  auto &cs = rewriter.getConstraintSystem();
  ASTContext &ctx = cs.getASTContext();
  auto opaque =
      rewriter.cs.cacheType(new (ctx) OpaqueValueExpr(srcRange, srcType));

  Expr *conversion = buildElementConversion(
      rewriter, srcRange, srcType, destType, bridged,
      locator.withPathElement(LocatorPathElt::GenericArgument(typeArgIndex)),
      opaque);

  return { opaque, conversion };
}

void ExprRewriter::peepholeArrayUpcast(ArrayExpr *expr, Type toType,
                                       bool bridged, Type elementType,
                                       ConstraintLocatorBuilder locator) {
  // Update the type of the array literal.
  cs.setType(expr, toType);
  // FIXME: finish{Array,Dictionary}Expr invoke cacheExprTypes after forming
  // the semantic expression for the dictionary literal, which will undo the
  // type we set here if this dictionary literal is nested unless we update
  // the expr type as well.
  expr->setType(toType);

  // Convert the elements.
  ConstraintLocatorBuilder innerLocator =
    locator.withPathElement(LocatorPathElt::GenericArgument(0));
  for (auto &element : expr->getElements()) {
    if (auto newElement = buildElementConversion(*this, expr->getLoc(),
                                                 cs.getType(element),
                                                 elementType,
                                                 bridged, innerLocator,
                                                 element)) {
      element = newElement;
    }
  }

  (void)finishArrayExpr(expr);
}

void ExprRewriter::peepholeDictionaryUpcast(DictionaryExpr *expr,
                                            Type toType, bool bridged,
                                            Type keyType, Type valueType,
                                            ConstraintLocatorBuilder locator) {
  // Update the type of the dictionary literal.
  cs.setType(expr, toType);
  // FIXME: finish{Array,Dictionary}Expr invoke cacheExprTypes after forming
  // the semantic expression for the dictionary literal, which will undo the
  // type we set here if this dictionary literal is nested unless we update
  // the expr type as well.
  expr->setType(toType);

  ConstraintLocatorBuilder valueLocator =
    locator.withPathElement(LocatorPathElt::GenericArgument(1));

  // Convert the elements.
  TupleTypeElt tupleTypeElts[2] = { keyType, valueType };
  auto tupleType = TupleType::get(tupleTypeElts, cs.getASTContext());
  for (auto element : expr->getElements()) {
    if (auto tuple = dyn_cast<TupleExpr>(element)) {
      auto key = tuple->getElement(0);
      if (auto newKey = buildElementConversion(*this, expr->getLoc(),
                                               cs.getType(key), keyType,
                                               bridged, valueLocator, key))
        tuple->setElement(0, newKey);

      auto value = tuple->getElement(1);
      if (auto newValue = buildElementConversion(*this, expr->getLoc(),
                                                 cs.getType(value), valueType,
                                                 bridged, valueLocator,
                                                 value)) {
        tuple->setElement(1, newValue);
      }

      cs.setType(tuple, tupleType);
      // FIXME: finish{Array,Dictionary}Expr invoke cacheExprTypes after forming
      // the semantic expression for the dictionary literal, which will undo the
      // type we set here if this dictionary literal is nested unless we update
      // the expr type as well.
      tuple->setType(tupleType);
    }
  }

  (void)finishDictionaryExpr(expr);
}

bool ExprRewriter::peepholeCollectionUpcast(Expr *expr, Type toType,
                                            bool bridged,
                                            ConstraintLocatorBuilder locator) {
  // Recur into parenthesized expressions.
  if (auto paren = dyn_cast<ParenExpr>(expr)) {
    // If we can't peephole the subexpression, we're done.
    if (!peepholeCollectionUpcast(paren->getSubExpr(), toType, bridged,
                                  locator))
      return false;

    // Update the type of this expression.
    auto parenTy = ParenType::get(cs.getASTContext(),
                                  cs.getType(paren->getSubExpr()));
    cs.setType(paren, parenTy);
    // FIXME: finish{Array,Dictionary}Expr invoke cacheExprTypes after forming
    // the semantic expression for the dictionary literal, which will undo the
    // type we set here if this dictionary literal is nested unless we update
    // the expr type as well.
    paren->setType(parenTy);
    return true;
  }

  // Array literals.
  if (auto arrayLiteral = dyn_cast<ArrayExpr>(expr)) {
    if (Optional<Type> elementType = ConstraintSystem::isArrayType(toType)) {
      peepholeArrayUpcast(arrayLiteral, toType, bridged, *elementType, locator);
      return true;
    }

    if (Optional<Type> elementType = ConstraintSystem::isSetType(toType)) {
      peepholeArrayUpcast(arrayLiteral, toType, bridged, *elementType, locator);
      return true;
    }

    return false;
  }

  // Dictionary literals.
  if (auto dictLiteral = dyn_cast<DictionaryExpr>(expr)) {
    if (auto elementType = ConstraintSystem::isDictionaryType(toType)) {
      peepholeDictionaryUpcast(dictLiteral, toType, bridged,
                               elementType->first, elementType->second,
                               locator);
      return true;
    }

    return false;
  }

  return false;
}

Expr *ExprRewriter::buildCollectionUpcastExpr(
                                            Expr *expr, Type toType,
                                            bool bridged,
                                            ConstraintLocatorBuilder locator) {
  if (peepholeCollectionUpcast(expr, toType, bridged, locator))
    return expr;

  ASTContext &ctx = cs.getASTContext();
  // Build the first value conversion.
  auto conv =
    buildOpaqueElementConversion(*this, expr->getLoc(), cs.getType(expr),
                                 toType, bridged, locator, 0);

  // For single-parameter collections, form the upcast.
  if (ConstraintSystem::isArrayType(toType) ||
      ConstraintSystem::isSetType(toType)) {
    return cs.cacheType(
              new (ctx) CollectionUpcastConversionExpr(expr, toType, {}, conv));
  }

  assert(ConstraintSystem::isDictionaryType(toType) &&
         "Unhandled collection upcast");

  // Build the second value conversion.
  auto conv2 =
    buildOpaqueElementConversion(*this, expr->getLoc(), cs.getType(expr),
                                 toType, bridged, locator, 1);

  return cs.cacheType(
           new (ctx) CollectionUpcastConversionExpr(expr, toType, conv, conv2));

}

Expr *ExprRewriter::buildObjCBridgeExpr(Expr *expr, Type toType,
                                        ConstraintLocatorBuilder locator) {
  Type fromType = cs.getType(expr);

  // Bridged collection casts always succeed, so we treat them as
  // collection "upcasts".
  if ((ConstraintSystem::isArrayType(fromType) &&
       ConstraintSystem::isArrayType(toType)) ||
      (ConstraintSystem::isDictionaryType(fromType) &&
       ConstraintSystem::isDictionaryType(toType)) ||
      (ConstraintSystem::isSetType(fromType) &&
       ConstraintSystem::isSetType(toType))) {
    return buildCollectionUpcastExpr(expr, toType, /*bridged=*/true, locator);
  }

  // Bridging from a Swift type to an Objective-C class type.
  if (toType->isAnyObject() ||
      (fromType->getRValueType()->isPotentiallyBridgedValueType() &&
       (toType->isBridgeableObjectType() || toType->isExistentialType()))) {
    // Bridging to Objective-C.
    Expr *objcExpr = bridgeToObjectiveC(expr, toType);
    if (!objcExpr)
      return nullptr;

    // We might have a coercion of a Swift type to a CF type toll-free
    // bridged to Objective-C.
    //
    // FIXME: Ideally we would instead have already recorded a restriction
    // when solving the constraint, and we wouldn't need to duplicate this
    // part of coerceToType() here.
    if (auto foreignClass = toType->getClassOrBoundGenericClass()) {
      if (foreignClass->getForeignClassKind() ==
            ClassDecl::ForeignKind::CFType) {
        return cs.cacheType(new (cs.getASTContext())
                                ForeignObjectConversionExpr(objcExpr, toType));
      }
    }

    return coerceToType(objcExpr, toType, locator);
  }

  // Bridging from an Objective-C class type to a Swift type.
  return forceBridgeFromObjectiveC(expr, toType);
}

Expr *ConstraintSystem::addImplicitLoadExpr(Expr *expr) {
  return TypeChecker::addImplicitLoadExpr(
      getASTContext(), expr, [this](Expr *expr) { return getType(expr); },
      [this](Expr *expr, Type type) { setType(expr, type); });
}

Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
                                 ConstraintLocatorBuilder locator,
                                 Optional<Pattern*> typeFromPattern) {
  auto &ctx = cs.getASTContext();

  // The type we're converting from.
  Type fromType = cs.getType(expr);

  // If the types are already equivalent, we don't have to do anything.
  if (fromType->isEqual(toType))
    return expr;

  // If the solver recorded what we should do here, just do it immediately.
  auto knownRestriction = solution.ConstraintRestrictions.find(
                            { fromType->getCanonicalType(),
                              toType->getCanonicalType() });
  if (knownRestriction != solution.ConstraintRestrictions.end()) {
    switch (knownRestriction->second) {
    case ConversionRestrictionKind::DeepEquality: {
      if (toType->hasUnresolvedType())
        break;

      // HACK: Fix problem related to Swift 4 mode (with assertions),
      // since Swift 4 mode allows passing arguments with extra parens
      // to parameters which don't expect them, it should be supported
      // by "deep equality" type - Optional<T> e.g.
      // ```swift
      // func foo(_: (() -> Void)?) {}
      // func bar() -> ((()) -> Void)? { return nil }
      // foo(bar) // This expression should compile in Swift 3 mode
      // ```
      //
      // See also: https://bugs.swift.org/browse/SR-6796
      if (cs.getASTContext().isSwiftVersionAtLeast(4) &&
          !cs.getASTContext().isSwiftVersionAtLeast(5)) {
        auto obj1 = fromType->getOptionalObjectType();
        auto obj2 = toType->getOptionalObjectType();

        if (obj1 && obj2) {
          auto *fn1 = obj1->getAs<AnyFunctionType>();
          auto *fn2 = obj2->getAs<AnyFunctionType>();

          if (fn1 && fn2) {
            auto params1 = fn1->getParams();
            auto params2 = fn2->getParams();

            // This handles situations like argument: (()), parameter: ().
            if (params1.size() == 1 && params2.empty()) {
              auto tupleTy = params1.front().getOldType()->getAs<TupleType>();
              if (tupleTy && tupleTy->getNumElements() == 0)
                break;
            }
          }
        }
      }

      auto &err = llvm::errs();
      err << "fromType->getCanonicalType() = ";
      fromType->getCanonicalType()->dump(err);
      err << "toType->getCanonicalType() = ";
      toType->getCanonicalType()->dump(err);
      llvm_unreachable("Should be handled above");
    }

    case ConversionRestrictionKind::Superclass:
    case ConversionRestrictionKind::ExistentialMetatypeToMetatype:
      return coerceSuperclass(expr, toType);

    case ConversionRestrictionKind::Existential:
    case ConversionRestrictionKind::MetatypeToExistentialMetatype:
      return coerceExistential(expr, toType);

    case ConversionRestrictionKind::ClassMetatypeToAnyObject: {
      assert(ctx.LangOpts.EnableObjCInterop &&
             "metatypes can only be cast to objects w/ objc runtime!");
      return cs.cacheType(new (ctx) ClassMetatypeToObjectExpr(expr, toType));
    }
    case ConversionRestrictionKind::ExistentialMetatypeToAnyObject: {
      assert(ctx.LangOpts.EnableObjCInterop &&
             "metatypes can only be cast to objects w/ objc runtime!");
      return cs.cacheType(new (ctx)
                              ExistentialMetatypeToObjectExpr(expr, toType));
    }
    case ConversionRestrictionKind::ProtocolMetatypeToProtocolClass: {
      return cs.cacheType(new (ctx) ProtocolMetatypeToObjectExpr(expr, toType));
    }
        
    case ConversionRestrictionKind::ValueToOptional: {
      auto toGenericType = toType->castTo<BoundGenericType>();
      assert(toGenericType->getDecl()->isOptionalDecl());
      TypeChecker::requireOptionalIntrinsics(cs.getASTContext(),
                                             expr->getLoc());

      Type valueType = toGenericType->getGenericArgs()[0];
      expr = coerceToType(expr, valueType, locator);
      if (!expr) return nullptr;

      auto *result =
          cs.cacheType(new (ctx) InjectIntoOptionalExpr(expr, toType));
      diagnoseOptionalInjection(result);
      return result;
    }

    case ConversionRestrictionKind::OptionalToOptional:
      return coerceOptionalToOptional(expr, toType, locator, typeFromPattern);

    case ConversionRestrictionKind::ArrayUpcast: {
      // Build the value conversion.
      return buildCollectionUpcastExpr(expr, toType, /*bridged=*/false,
                                       locator);
    }

    case ConversionRestrictionKind::HashableToAnyHashable: {
      // We want to check conformance on the rvalue, as that's what has
      // the Hashable conformance
      expr = cs.coerceToRValue(expr);

      // Find the conformance of the source type to Hashable.
      auto hashable = ctx.getProtocol(KnownProtocolKind::Hashable);
      auto conformance =
        TypeChecker::conformsToProtocol(
                        cs.getType(expr), hashable, cs.DC);
      assert(conformance && "must conform to Hashable");

      return cs.cacheType(
          new (ctx) AnyHashableErasureExpr(expr, toType, conformance));
    }

    case ConversionRestrictionKind::DictionaryUpcast: {
      // Build the value conversion.
      return buildCollectionUpcastExpr(expr, toType, /*bridged=*/false,
                                       locator);
    }

    case ConversionRestrictionKind::SetUpcast: {
      // Build the value conversion.
      return buildCollectionUpcastExpr(expr, toType, /*bridged=*/false, locator);
    }

    case ConversionRestrictionKind::InoutToPointer: {
      bool isOptional = false;
      Type unwrappedTy = toType;
      if (Type unwrapped = toType->getOptionalObjectType()) {
        isOptional = true;
        unwrappedTy = unwrapped;
      }
      PointerTypeKind pointerKind;
      auto toEltType = unwrappedTy->getAnyPointerElementType(pointerKind);
      assert(toEltType && "not a pointer type?"); (void) toEltType;

      TypeChecker::requirePointerArgumentIntrinsics(ctx, expr->getLoc());
      Expr *result =
          cs.cacheType(new (ctx) InOutToPointerExpr(expr, unwrappedTy));
      if (isOptional)
        result = cs.cacheType(new (ctx) InjectIntoOptionalExpr(result, toType));
      return result;
    }
    
    case ConversionRestrictionKind::ArrayToPointer: {
      bool isOptional = false;
      Type unwrappedTy = toType;
      if (Type unwrapped = toType->getOptionalObjectType()) {
        isOptional = true;
        unwrappedTy = unwrapped;
      }

      TypeChecker::requirePointerArgumentIntrinsics(ctx, expr->getLoc());
      Expr *result =
          cs.cacheType(new (ctx) ArrayToPointerExpr(expr, unwrappedTy));
      if (isOptional)
        result = cs.cacheType(new (ctx) InjectIntoOptionalExpr(result, toType));
      return result;
    }
    
    case ConversionRestrictionKind::StringToPointer: {
      bool isOptional = false;
      Type unwrappedTy = toType;
      if (Type unwrapped = toType->getOptionalObjectType()) {
        isOptional = true;
        unwrappedTy = unwrapped;
      }

      TypeChecker::requirePointerArgumentIntrinsics(ctx, expr->getLoc());
      Expr *result =
          cs.cacheType(new (ctx) StringToPointerExpr(expr, unwrappedTy));
      if (isOptional)
        result = cs.cacheType(new (ctx) InjectIntoOptionalExpr(result, toType));
      return result;
    }
    
    case ConversionRestrictionKind::PointerToPointer: {
      TypeChecker::requirePointerArgumentIntrinsics(ctx, expr->getLoc());
      Type unwrappedToTy = toType->getOptionalObjectType();

      // Optional to optional.
      if (Type unwrappedFromTy = cs.getType(expr)->getOptionalObjectType()) {
        assert(unwrappedToTy && "converting optional to non-optional");
        Expr *boundOptional = cs.cacheType(
            new (ctx) BindOptionalExpr(expr, SourceLoc(),
                                       /*depth*/ 0, unwrappedFromTy));
        Expr *converted = cs.cacheType(
            new (ctx) PointerToPointerExpr(boundOptional, unwrappedToTy));
        Expr *rewrapped =
            cs.cacheType(new (ctx) InjectIntoOptionalExpr(converted, toType));
        return cs.cacheType(new (ctx)
                                OptionalEvaluationExpr(rewrapped, toType));
      }

      // Non-optional to optional.
      if (unwrappedToTy) {
        Expr *converted =
            cs.cacheType(new (ctx) PointerToPointerExpr(expr, unwrappedToTy));
        return cs.cacheType(new (ctx)
                                InjectIntoOptionalExpr(converted, toType));
      }

      // Non-optional to non-optional.
      return cs.cacheType(new (ctx) PointerToPointerExpr(expr, toType));
    }

    case ConversionRestrictionKind::CFTollFreeBridgeToObjC: {
      auto foreignClass = fromType->getClassOrBoundGenericClass();
      auto objcType = foreignClass->getAttrs().getAttribute<ObjCBridgedAttr>()
                        ->getObjCClass()->getDeclaredInterfaceType();
      auto asObjCClass =
          cs.cacheType(new (ctx) ForeignObjectConversionExpr(expr, objcType));
      return coerceToType(asObjCClass, toType, locator);
    }

    case ConversionRestrictionKind::ObjCTollFreeBridgeToCF: {
      auto foreignClass = toType->getClassOrBoundGenericClass();
      auto objcType = foreignClass->getAttrs().getAttribute<ObjCBridgedAttr>()
                        ->getObjCClass()->getDeclaredInterfaceType();
      Expr *result = coerceToType(expr, objcType, locator);
      if (!result)
        return nullptr;

      return cs.cacheType(new (ctx)
                              ForeignObjectConversionExpr(result, toType));
    }
    }
  }

  // Handle "from specific" coercions before "catch all" coercions.
  auto desugaredFromType = fromType->getDesugaredType();
  switch (desugaredFromType->getKind()) {
  // Coercions from an lvalue: load or perform implicit address-of. We perform
  // these coercions first because they are often the first step in a multi-step
  // coercion.
  case TypeKind::LValue: {
    auto fromLValue = cast<LValueType>(desugaredFromType);
    auto toIO = toType->getAs<InOutType>();
    if (!toIO)
      return coerceToType(cs.addImplicitLoadExpr(expr), toType, locator);

    // In an 'inout' operator like "i += 1", the operand is converted from
    // an implicit lvalue to an inout argument.
    assert(toIO->getObjectType()->isEqual(fromLValue->getObjectType()));
    return cs.cacheType(new (ctx) InOutExpr(expr->getStartLoc(), expr,
                                            toIO->getObjectType(),
                                            /*isImplicit*/ true));
  }

  // Coerce from a tuple to a tuple.
  case TypeKind::Tuple: {
    auto fromTuple = cast<TupleType>(desugaredFromType);
    auto toTuple = toType->getAs<TupleType>();
    if (!toTuple)
      break;

    if (fromTuple->hasLValueType() && !toTuple->hasLValueType())
      return coerceToType(cs.coerceToRValue(expr), toType, locator);

    SmallVector<unsigned, 4> sources;
    if (!computeTupleShuffle(fromTuple, toTuple, sources)) {
      return coerceTupleToTuple(expr, fromTuple, toTuple,
                                locator, sources);
    }
    break;
  }

  case TypeKind::PrimaryArchetype:
  case TypeKind::OpenedArchetype:
  case TypeKind::NestedArchetype:
  case TypeKind::OpaqueTypeArchetype:
    if (!cast<ArchetypeType>(desugaredFromType)->requiresClass())
      break;
    LLVM_FALLTHROUGH;

  // Coercion from a subclass to a superclass.
  //
  // FIXME: Can we rig things up so that we always have a Superclass
  // conversion restriction in this case?
  case TypeKind::DynamicSelf:
  case TypeKind::BoundGenericClass:
  case TypeKind::Class: {
    if (!toType->getClassOrBoundGenericClass())
      break;
    for (auto fromSuperClass = fromType->getSuperclass();
         fromSuperClass;
         fromSuperClass = fromSuperClass->getSuperclass()) {
      if (fromSuperClass->isEqual(toType)) {
        return coerceSuperclass(expr, toType);
      }
    }
    break;
  }

  // Coercion from one function type to another, this produces a
  // FunctionConversionExpr in its full generality.
  case TypeKind::Function: {
    auto fromFunc = cast<FunctionType>(desugaredFromType);
    auto toFunc = toType->getAs<FunctionType>();
    if (!toFunc)
      break;

    // Default argument generator must return escaping functions. Therefore, we
    // leave an explicit escape to noescape cast here such that SILGen can skip
    // the cast and emit a code for the escaping function.
    bool isInDefaultArgumentContext = false;
    if (auto initalizerCtx = dyn_cast<Initializer>(cs.DC))
      isInDefaultArgumentContext = (initalizerCtx->getInitializerKind() ==
                                    InitializerKind::DefaultArgument);
    auto toEI = toFunc->getExtInfo();
    assert(toType->is<FunctionType>());

    // Handle implicit conversions between non-@differentiable and
    // @differentiable functions.
    {
      auto fromEI = fromFunc->getExtInfo();
      auto isFromDifferentiable = fromEI.isDifferentiable();
      auto isToDifferentiable = toEI.isDifferentiable();
      // Handle implicit conversion from @differentiable.
      if (isFromDifferentiable && !isToDifferentiable) {
        fromFunc = fromFunc->getWithoutDifferentiability()
            ->castTo<FunctionType>();
        switch (fromEI.getDifferentiabilityKind()) {
        case DifferentiabilityKind::Normal:
          expr = cs.cacheType(new (ctx)
              DifferentiableFunctionExtractOriginalExpr(expr, fromFunc));
          break;
        case DifferentiabilityKind::Linear:
          expr = cs.cacheType(new (ctx)
              LinearFunctionExtractOriginalExpr(expr, fromFunc));
          break;
        case DifferentiabilityKind::NonDifferentiable:
          llvm_unreachable("Cannot be NonDifferentiable");
        }
      }
      // Handle implicit conversion from @differentiable(linear) to
      // @differentiable.
      else if (fromEI.getDifferentiabilityKind() ==
                   DifferentiabilityKind::Linear &&
               toEI.getDifferentiabilityKind() == DifferentiabilityKind::Normal) {
        // TODO(TF-908): Create a `LinearToDifferentiableFunctionExpr` and SILGen
        // it as thunk application. Remove the diagnostic.
        ctx.Diags.diagnose(expr->getLoc(),
                           diag::unsupported_linear_to_differentiable_conversion);
      }
      // Handle implicit conversion from non-@differentiable to @differentiable.
      maybeDiagnoseUnsupportedDifferentiableConversion(cs, expr, toFunc);
      if (!isFromDifferentiable && isToDifferentiable) {
        auto newEI =
            fromEI.intoBuilder()
                .withDifferentiabilityKind(toEI.getDifferentiabilityKind())
                .build();
        fromFunc = FunctionType::get(toFunc->getParams(), fromFunc->getResult())
            ->withExtInfo(newEI)
            ->castTo<FunctionType>();
        switch (toEI.getDifferentiabilityKind()) {
        case DifferentiabilityKind::Normal:
          expr = cs.cacheType(new (ctx)
                              DifferentiableFunctionExpr(expr, fromFunc));
          break;
        case DifferentiabilityKind::Linear:
          expr = cs.cacheType(new (ctx)
                              LinearFunctionExpr(expr, fromFunc));
          break;
        case DifferentiabilityKind::NonDifferentiable:
          llvm_unreachable("Cannot be NonDifferentiable");
        }
      }
    }

    // If we have a ClosureExpr, then we can safely propagate the 'no escape'
    // bit to the closure without invalidating prior analysis.
    auto fromEI = fromFunc->getExtInfo();
    if (toEI.isNoEscape() && !fromEI.isNoEscape()) {
      auto newFromFuncType = fromFunc->withExtInfo(fromEI.withNoEscape());
      if (!isInDefaultArgumentContext &&
          applyTypeToClosureExpr(cs, expr, newFromFuncType)) {
        fromFunc = newFromFuncType->castTo<FunctionType>();
        // Propagating the 'no escape' bit might have satisfied the entire
        // conversion.  If so, we're done, otherwise keep converting.
        if (fromFunc->isEqual(toType))
          return expr;
      } else if (isInDefaultArgumentContext) {
        // First apply the conversion *without* noescape attribute.
        if (!newFromFuncType->isEqual(toType)) {
          auto escapingToFuncTy =
              toFunc->withExtInfo(toEI.withNoEscape(false));
          maybeDiagnoseUnsupportedFunctionConversion(cs, expr, toFunc);
          expr = cs.cacheType(
              new (ctx) FunctionConversionExpr(expr, escapingToFuncTy));
        }
        // Apply an explict function conversion *only* for the escape to
        // noescape conversion. This conversion will be stripped by the
        // default argument generator. (We can't return a @noescape function)
        auto newExpr =
            cs.cacheType(new (ctx) FunctionConversionExpr(expr, toFunc));
        return newExpr;
      }
    }

    maybeDiagnoseUnsupportedFunctionConversion(cs, expr, toFunc);

    return cs.cacheType(new (ctx) FunctionConversionExpr(expr, toType));
  }

  // Coercions from one metatype to another.
  case TypeKind::Metatype: {
    if (auto toMeta = toType->getAs<MetatypeType>())
      return cs.cacheType(new (ctx) MetatypeConversionExpr(expr, toMeta));
    LLVM_FALLTHROUGH;
  }
  // Coercions from metatype to objects.
  case TypeKind::ExistentialMetatype: {
    auto fromMeta = cast<AnyMetatypeType>(desugaredFromType);
    if (toType->isAnyObject()) {
      assert(cs.getASTContext().LangOpts.EnableObjCInterop
             && "metatype-to-object conversion requires objc interop");
      if (fromMeta->is<MetatypeType>()) {
        assert(fromMeta->getInstanceType()->mayHaveSuperclass()
               && "metatype-to-object input should be a class metatype");
        return cs.cacheType(new (ctx) ClassMetatypeToObjectExpr(expr, toType));
      }
      
      if (fromMeta->is<ExistentialMetatypeType>()) {
        assert(fromMeta->getInstanceType()->getCanonicalType()
                       ->getExistentialLayout().requiresClass()
               && "metatype-to-object input should be a class metatype");
        return cs.cacheType(new (ctx)
                                ExistentialMetatypeToObjectExpr(expr, toType));
      }
      
      llvm_unreachable("unhandled metatype kind");
    }
    
    if (auto toClass = toType->getClassOrBoundGenericClass()) {
      if (toClass->getName() == cs.getASTContext().Id_Protocol
          && toClass->getModuleContext()->getName()
              == cs.getASTContext().Id_ObjectiveC) {
        assert(cs.getASTContext().LangOpts.EnableObjCInterop
               && "metatype-to-object conversion requires objc interop");
        assert(fromMeta->is<MetatypeType>()
               && fromMeta->getInstanceType()->is<ProtocolType>()
               && "protocol-metatype-to-Protocol only works for single "
                  "protocols");
        return cs.cacheType(new (ctx)
                                ProtocolMetatypeToObjectExpr(expr, toType));
      }
    }

    break;
  }

#define SUGARED_TYPE(Name, Parent) case TypeKind::Name:
#define BUILTIN_TYPE(Name, Parent) case TypeKind::Name:
#define UNCHECKED_TYPE(Name, Parent) case TypeKind::Name:
#define ARTIFICIAL_TYPE(Name, Parent) case TypeKind::Name:
#define TYPE(Name, Parent)
#include "swift/AST/TypeNodes.def"
  case TypeKind::Error:
  case TypeKind::InOut:
  case TypeKind::Module:
  case TypeKind::Enum:
  case TypeKind::Struct:
  case TypeKind::Protocol:
  case TypeKind::ProtocolComposition:
  case TypeKind::BoundGenericEnum:
  case TypeKind::BoundGenericStruct:
  case TypeKind::GenericFunction:
  case TypeKind::GenericTypeParam:
  case TypeKind::DependentMember:
    break;
  }

  // "Catch all" coercions.
  auto desugaredToType = toType->getDesugaredType();
  switch (desugaredToType->getKind()) {
  // Coercions from a type to an existential type.
  case TypeKind::ExistentialMetatype:
  case TypeKind::ProtocolComposition:
  case TypeKind::Protocol:
    return coerceExistential(expr, toType);

  // Coercion to Optional<T>.
  case TypeKind::BoundGenericEnum: {
    auto toGenericType = cast<BoundGenericEnumType>(desugaredToType);
    if (!toGenericType->getDecl()->isOptionalDecl())
      break;
    TypeChecker::requireOptionalIntrinsics(ctx, expr->getLoc());

    if (cs.getType(expr)->getOptionalObjectType())
      return coerceOptionalToOptional(expr, toType, locator, typeFromPattern);

    Type valueType = toGenericType->getGenericArgs()[0];
    expr = coerceToType(expr, valueType, locator);
    if (!expr) return nullptr;

    auto *result = cs.cacheType(new (ctx) InjectIntoOptionalExpr(expr, toType));
    diagnoseOptionalInjection(result);
    return result;
  }

#define SUGARED_TYPE(Name, Parent) case TypeKind::Name:
#define BUILTIN_TYPE(Name, Parent) case TypeKind::Name:
#define UNCHECKED_TYPE(Name, Parent) case TypeKind::Name:
#define ARTIFICIAL_TYPE(Name, Parent) case TypeKind::Name:
#define TYPE(Name, Parent)
#include "swift/AST/TypeNodes.def"
  case TypeKind::Error:
  case TypeKind::Module:
  case TypeKind::Tuple:
  case TypeKind::Enum:
  case TypeKind::Struct:
  case TypeKind::Class:
  case TypeKind::BoundGenericClass:
  case TypeKind::BoundGenericStruct:
  case TypeKind::Metatype:
  case TypeKind::DynamicSelf:
  case TypeKind::PrimaryArchetype:
  case TypeKind::OpenedArchetype:
  case TypeKind::NestedArchetype:
  case TypeKind::OpaqueTypeArchetype:
  case TypeKind::GenericTypeParam:
  case TypeKind::DependentMember:
  case TypeKind::Function:
  case TypeKind::GenericFunction:
  case TypeKind::LValue:
  case TypeKind::InOut:
    break;
  }

  // Unresolved types come up in diagnostics for lvalue and inout types.
  if (fromType->hasUnresolvedType() || toType->hasUnresolvedType())
    return cs.cacheType(new (ctx) UnresolvedTypeConversionExpr(expr, toType));

  // Use an opaque type to abstract a value of the underlying concrete type.
  if (toType->getAs<OpaqueTypeArchetypeType>()) {
    return cs.cacheType(new (ctx) UnderlyingToOpaqueExpr(expr, toType));
  }
  
  llvm_unreachable("Unhandled coercion");
}

/// Detect if the expression is an assignment to a `self` wrapped property that
/// has a nonmutating setter, inside a constructor.
///
/// We use this to decide when to produce an inout_expr instead of a load_expr
/// for the sake of emitting a reference required by the assign_by_wrapper
/// instruction.
static bool isNonMutatingSetterPWAssignInsideInit(Expr *baseExpr,
                                                  ValueDecl *member,
                                                  DeclContext *UseDC) {
  // Setter is mutating
  if (cast<AbstractStorageDecl>(member)->isSetterMutating())
    return false;
  // Member is not a wrapped property
  auto *VD = dyn_cast<VarDecl>(member);
  if (!(VD && VD->hasAttachedPropertyWrapper()))
    return false;
  // This is not an expression inside a constructor
  auto *CD = dyn_cast<ConstructorDecl>(UseDC);
  if (!CD)
    return false;
  // This is not an assignment on self
  if (!baseExpr->isSelfExprOf(CD))
    return false;

  return true;
}

/// Adjust the given type to become the self type when referring to
/// the given member.
static Type adjustSelfTypeForMember(Expr *baseExpr,
                                    Type baseTy, ValueDecl *member,
                                    DeclContext *UseDC) {
  assert(!baseTy->is<LValueType>());

  auto inOutTy = baseTy->getAs<InOutType>();
  if (!inOutTy)
    return baseTy;

  auto baseObjectTy = inOutTy->getObjectType();

  if (isa<ConstructorDecl>(member))
    return baseObjectTy;

  if (auto func = dyn_cast<FuncDecl>(member)) {
    // If 'self' is an inout type, turn the base type into an lvalue
    // type with the same qualifiers.
    if (func->isMutating())
      return baseTy;

    // Otherwise, return the rvalue type.
    return baseObjectTy;
  }

  // If the base of the access is mutable, then we may be invoking a getter or
  // setter that requires the base to be mutable.
  auto *SD = cast<AbstractStorageDecl>(member);
  bool isSettableFromHere =
      SD->isSettable(UseDC) && SD->isSetterAccessibleFrom(UseDC);

  // If neither the property's getter nor its setter are mutating, and
  // this is not a nonmutating property wrapper setter,
  // the base can be an rvalue.
  // With the exception of assignments to a wrapped property inside a
  // constructor, where we need to produce a reference to be used on
  // the assign_by_wrapper instruction. 
  if (!SD->isGetterMutating() && 
      (!isSettableFromHere || !SD->isSetterMutating()) &&
      !isNonMutatingSetterPWAssignInsideInit(baseExpr, member, UseDC))
    return baseObjectTy;

  if (isa<SubscriptDecl>(member))
    return baseTy;

  return LValueType::get(baseObjectTy);
}

Expr *
ExprRewriter::coerceSelfArgumentToType(Expr *expr,
                                       Type baseTy, ValueDecl *member,
                                       ConstraintLocatorBuilder locator) {
  Type toType = adjustSelfTypeForMember(expr, baseTy, member, dc);

  // If our expression already has the right type, we're done.
  Type fromType = cs.getType(expr);
  if (fromType->isEqual(toType))
    return expr;

  // If we're coercing to an rvalue type, just do it.
  auto toInOutTy = toType->getAs<InOutType>();
  if (!toInOutTy)
    return coerceToType(expr, toType, locator);

  assert(fromType->is<LValueType>() && "Can only convert lvalues to inout");

  auto &ctx = cs.getASTContext();

  // Use InOutExpr to convert it to an explicit inout argument for the
  // receiver.
  return cs.cacheType(new (ctx) InOutExpr(expr->getStartLoc(), expr, 
                                          toInOutTy->getInOutObjectType(),
                                          /*isImplicit*/ true));
}

Expr *ExprRewriter::convertLiteralInPlace(
    LiteralExpr *literal, Type type, ProtocolDecl *protocol,
    Identifier literalType, DeclName literalFuncName,
    ProtocolDecl *builtinProtocol, DeclName builtinLiteralFuncName,
    Diag<> brokenProtocolDiag, Diag<> brokenBuiltinProtocolDiag) {
  // If coercing a literal to an unresolved type, we don't try to look up the
  // witness members, just do it.
  if (type->is<UnresolvedType>()) {
    cs.setType(literal, type);
    return literal;
  }

  // Check whether this literal type conforms to the builtin protocol. If so,
  // initialize via the builtin protocol.
  if (builtinProtocol) {
    auto builtinConformance = TypeChecker::conformsToProtocol(
        type, builtinProtocol, cs.DC);
    if (builtinConformance) {
      // Find the witness that we'll use to initialize the type via a builtin
      // literal.
      auto witness = builtinConformance.getWitnessByName(
          type->getRValueType(), builtinLiteralFuncName);
      if (!witness || !isa<AbstractFunctionDecl>(witness.getDecl()))
        return nullptr;

      // Form a reference to the builtin conversion function.

      // Set the builtin initializer.
      dyn_cast<BuiltinLiteralExpr>(literal)->setBuiltinInitializer(witness);

      // The literal expression has this type.
      cs.setType(literal, type);

      return literal;
    }
  }

  // This literal type must conform to the (non-builtin) protocol.
  assert(protocol && "requirements should have stopped recursion");
  auto conformance = TypeChecker::conformsToProtocol(type, protocol, cs.DC);
  assert(conformance && "must conform to literal protocol");

  // Dig out the literal type and perform a builtin literal conversion to it.
  if (!literalType.empty()) {
    // Extract the literal type.
    Type builtinLiteralType =
        conformance.getTypeWitnessByName(type, literalType);
    if (builtinLiteralType->hasError())
      return nullptr;

    // Perform the builtin conversion.
    if (!convertLiteralInPlace(literal, builtinLiteralType, nullptr,
                               Identifier(), DeclName(), builtinProtocol,
                               builtinLiteralFuncName, brokenProtocolDiag,
                               brokenBuiltinProtocolDiag))
      return nullptr;
  }

  // Find the witness that we'll use to initialize the literal value.
  auto witness =
      conformance.getWitnessByName(type->getRValueType(), literalFuncName);
  if (!witness || !isa<AbstractFunctionDecl>(witness.getDecl()))
    return nullptr;

  // Set the initializer.
  literal->setInitializer(witness);

  // The literal expression has this type.
  cs.setType(literal, type);

  return literal;
}

// Returns true if the given method and method type are a valid
// `@dynamicCallable` required `func dynamicallyCall` method.
static bool isValidDynamicCallableMethod(FuncDecl *method,
                                         AnyFunctionType *methodType) {
  auto &ctx = method->getASTContext();
  if (method->getBaseIdentifier() != ctx.Id_dynamicallyCall)
    return false;
  if (methodType->getParams().size() != 1)
    return false;
  auto argumentLabel = methodType->getParams()[0].getLabel();
  if (argumentLabel != ctx.Id_withArguments &&
      argumentLabel != ctx.Id_withKeywordArguments)
    return false;
  return true;
}

// Build a reference to a `callAsFunction` method.
static Expr *buildCallAsFunctionMethodRef(
    ExprRewriter &rewriter, ApplyExpr *apply, SelectedOverload selected,
    ConstraintLocator *calleeLoc) {
  assert(calleeLoc->isLastElement<LocatorPathElt::ImplicitCallAsFunction>());
  assert(cast<FuncDecl>(selected.choice.getDecl())->isCallAsFunctionMethod());

  // Create direct reference to `callAsFunction` method.
  auto *fn = apply->getFn();
  auto *arg = apply->getArg();

  // HACK: Temporarily push the fn expr onto the expr stack to make sure we
  // don't try to prematurely close an existential when applying the curried
  // member ref. This can be removed once existential opening is refactored not
  // to rely on the shape of the AST prior to rewriting.
  rewriter.ExprStack.push_back(fn);
  SWIFT_DEFER {
    rewriter.ExprStack.pop_back();
  };

  auto *declRef = rewriter.buildMemberRef(
      fn, /*dotLoc*/ SourceLoc(), selected, DeclNameLoc(arg->getStartLoc()),
      calleeLoc, calleeLoc, /*implicit*/ true, AccessSemantics::Ordinary);
  if (!declRef)
    return nullptr;
  declRef->setImplicit(apply->isImplicit());
  return declRef;
}

// Resolve `@dynamicCallable` applications.
std::pair<Expr *, Expr *>
ExprRewriter::buildDynamicCallable(ApplyExpr *apply, SelectedOverload selected,
                                   FuncDecl *method,
                                   AnyFunctionType *methodType,
                                   ConstraintLocatorBuilder loc) {
  auto &ctx = cs.getASTContext();
  auto *fn = apply->getFn();

  TupleExpr *arg = dyn_cast<TupleExpr>(apply->getArg());
  if (auto parenExpr = dyn_cast<ParenExpr>(apply->getArg()))
    arg = TupleExpr::createImplicit(ctx, parenExpr->getSubExpr(), {});

  // Get resolved `dynamicallyCall` method and verify it.
  assert(isValidDynamicCallableMethod(method, methodType));
  auto params = methodType->getParams();
  auto argumentType = params[0].getParameterType();

  // Determine which method was resolved: a `withArguments` method or a
  // `withKeywordArguments` method.
  auto argumentLabel = methodType->getParams()[0].getLabel();
  bool useKwargsMethod = argumentLabel == ctx.Id_withKeywordArguments;

  // HACK: Temporarily push the fn expr onto the expr stack to make sure we
  // don't try to prematurely close an existential when applying the curried
  // member ref. This can be removed once existential opening is refactored not
  // to rely on the shape of the AST prior to rewriting.
  ExprStack.push_back(fn);
  SWIFT_DEFER {
    ExprStack.pop_back();
  };

  // Construct expression referencing the `dynamicallyCall` method.
  auto member = buildMemberRef(fn, SourceLoc(), selected,
                               DeclNameLoc(), loc, loc,
                               /*implicit=*/true, AccessSemantics::Ordinary);

  // Construct argument to the method (either an array or dictionary
  // expression).
  Expr *argument = nullptr;
  if (!useKwargsMethod) {
    argument = ArrayExpr::create(ctx, SourceLoc(), arg->getElements(),
                                 {}, SourceLoc());
    cs.setType(argument, argumentType);
    finishArrayExpr(cast<ArrayExpr>(argument));
  } else {
    auto dictLitProto =
        ctx.getProtocol(KnownProtocolKind::ExpressibleByDictionaryLiteral);
    auto conformance =
        TypeChecker::conformsToProtocol(argumentType, dictLitProto, cs.DC);
    auto keyType = conformance.getTypeWitnessByName(argumentType, ctx.Id_Key);
    auto valueType =
        conformance.getTypeWitnessByName(argumentType, ctx.Id_Value);
    SmallVector<Identifier, 4> names;
    SmallVector<Expr *, 4> dictElements;
    for (unsigned i = 0, n = arg->getNumElements(); i < n; ++i) {
      Expr *labelExpr =
        new (ctx) StringLiteralExpr(arg->getElementName(i).get(),
                                    arg->getElementNameLoc(i),
                                    /*Implicit*/ true);
      cs.setType(labelExpr, keyType);
      handleStringLiteralExpr(cast<LiteralExpr>(labelExpr));

      Expr *valueExpr = coerceToType(arg->getElement(i), valueType, loc);
      assert(valueExpr && "Failed to coerce?");
      Expr *pair = TupleExpr::createImplicit(ctx, {labelExpr, valueExpr}, {});
      auto eltTypes = { TupleTypeElt(keyType), TupleTypeElt(valueType) };
      cs.setType(pair, TupleType::get(eltTypes, ctx));
      dictElements.push_back(pair);
    }
    argument = DictionaryExpr::create(ctx, SourceLoc(), dictElements, {},
                                      SourceLoc());
    cs.setType(argument, argumentType);
    finishDictionaryExpr(cast<DictionaryExpr>(argument));
  }
  argument->setImplicit();

  // Build the argument list expr.
  argument = TupleExpr::createImplicit(ctx, {argument}, {argumentLabel});
  cs.setType(argument,
             TupleType::get({TupleTypeElt(argumentType, argumentLabel)}, ctx));

  return std::make_pair(member, argument);
}

Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
                                ConstraintLocatorBuilder locator,
                                ConstraintLocatorBuilder calleeLocator) {
  auto &ctx = cs.getASTContext();

  auto *arg = apply->getArg();
  auto *fn = apply->getFn();

  auto finishApplyOfDeclWithSpecialTypeCheckingSemantics
    = [&](ApplyExpr *apply,
          ConcreteDeclRef declRef,
          Type openedType) -> Expr* {
      switch (TypeChecker::getDeclTypeCheckingSemantics(declRef.getDecl())) {
      case DeclTypeCheckingSemantics::TypeOf: {
        // Resolve into a DynamicTypeExpr.
        auto arg = apply->getArg();

        SmallVector<Identifier, 2> argLabelsScratch;

        auto fnType = cs.getType(fn)->getAs<FunctionType>();
        arg = coerceCallArguments(arg, fnType, declRef,
                                  apply,
                                  apply->getArgumentLabels(argLabelsScratch),
                                  locator.withPathElement(
                                    ConstraintLocator::ApplyArgument));
        if (!arg) {
          return nullptr;
        }

        if (auto tuple = dyn_cast<TupleExpr>(arg))
          arg = tuple->getElements()[0];

        auto replacement = new (ctx)
          DynamicTypeExpr(apply->getFn()->getLoc(),
                          apply->getArg()->getStartLoc(),
                          arg,
                          apply->getArg()->getEndLoc(),
                          Type());
        cs.setType(replacement, simplifyType(openedType));
        return replacement;
      }
      
      case DeclTypeCheckingSemantics::WithoutActuallyEscaping: {
        // Resolve into a MakeTemporarilyEscapableExpr.
        auto arg = cast<TupleExpr>(apply->getArg());
        assert(arg->getNumElements() == 2 && "should have two arguments");
        auto nonescaping = arg->getElements()[0];
        auto body = arg->getElements()[1];
        auto bodyTy = cs.getType(body)->getWithoutSpecifierType();
        auto bodyFnTy = bodyTy->castTo<FunctionType>();
        auto escapableParams = bodyFnTy->getParams();
        auto resultType = bodyFnTy->getResult();
        
        // The body is immediately called, so is obviously noescape.
        bodyFnTy = cast<FunctionType>(
          bodyFnTy->withExtInfo(bodyFnTy->getExtInfo().withNoEscape()));
        body = coerceToType(body, bodyFnTy, locator);
        assert(body && "can't make nonescaping?!");

        auto escapable = new (ctx)
            OpaqueValueExpr(apply->getFn()->getSourceRange(), Type());
        cs.setType(escapable, escapableParams[0].getOldType());

        auto getType = [&](Expr *E) -> Type { return cs.getType(E); };

        auto callSubExpr = CallExpr::createImplicit(ctx, body,
                                                    {escapable}, {}, getType);
        cs.cacheSubExprTypes(callSubExpr);
        cs.setType(callSubExpr->getArg(),
                   AnyFunctionType::composeInput(ctx,
                                                 escapableParams, false));
        cs.setType(callSubExpr, resultType);
        
        auto replacement = new (ctx)
          MakeTemporarilyEscapableExpr(apply->getFn()->getLoc(),
                                       apply->getArg()->getStartLoc(),
                                       nonescaping,
                                       callSubExpr,
                                       apply->getArg()->getEndLoc(),
                                       escapable,
                                       apply);
        cs.setType(replacement, resultType);
        return replacement;
      }
      
      case DeclTypeCheckingSemantics::OpenExistential: {
        // Resolve into an OpenExistentialExpr.
        auto arg = cast<TupleExpr>(apply->getArg());
        assert(arg->getNumElements() == 2 && "should have two arguments");

        auto existential = cs.coerceToRValue(arg->getElements()[0]);
        auto body = cs.coerceToRValue(arg->getElements()[1]);

        auto bodyFnTy = cs.getType(body)->castTo<FunctionType>();
        auto openedTy = getBaseType(bodyFnTy, /*wantsRValue*/ false);
        auto resultTy = bodyFnTy->getResult();

        // The body is immediately called, so is obviously noescape.
        bodyFnTy = cast<FunctionType>(
          bodyFnTy->withExtInfo(bodyFnTy->getExtInfo().withNoEscape()));
        body = coerceToType(body, bodyFnTy, locator);
        assert(body && "can't make nonescaping?!");

        auto openedInstanceTy = openedTy;
        auto existentialInstanceTy = cs.getType(existential);
        if (auto metaTy = openedTy->getAs<MetatypeType>()) {
          openedInstanceTy = metaTy->getInstanceType();
          existentialInstanceTy = existentialInstanceTy
            ->castTo<ExistentialMetatypeType>()
            ->getInstanceType();
        }
        assert(openedInstanceTy->castTo<OpenedArchetypeType>()
                   ->getOpenedExistentialType()
                   ->isEqual(existentialInstanceTy));

        auto opaqueValue =
            new (ctx) OpaqueValueExpr(apply->getSourceRange(), openedTy);
        cs.setType(opaqueValue, openedTy);

        auto getType = [&](Expr *E) -> Type { return cs.getType(E); };

        auto callSubExpr = CallExpr::createImplicit(ctx, body, {opaqueValue}, {}, getType);
        cs.cacheSubExprTypes(callSubExpr);
        cs.setType(callSubExpr, resultTy);
        
        auto replacement = new (ctx)
          OpenExistentialExpr(existential, opaqueValue, callSubExpr,
                              resultTy);
        cs.setType(replacement, resultTy);
        return replacement;
      }
      
      case DeclTypeCheckingSemantics::Normal:
        return nullptr;
      }

      llvm_unreachable("Unhandled DeclTypeCheckingSemantics in switch.");
    };

  // Resolve the callee for the application if we have one.
  ConcreteDeclRef callee;
  auto *calleeLoc = cs.getConstraintLocator(calleeLocator);
  auto overload = solution.getOverloadChoiceIfAvailable(calleeLoc);
  if (overload) {
    auto *decl = overload->choice.getDeclOrNull();
    callee = resolveConcreteDeclRef(decl, calleeLoc);
  }

  // If this is an implicit call to a `callAsFunction` method, build the
  // appropriate member reference.
  if (cs.getType(fn)->getRValueType()->isCallableNominalType(dc)) {
    fn = buildCallAsFunctionMethodRef(*this, apply, *overload, calleeLoc);
    if (!fn)
      return nullptr;
  }

  // Resolve a `@dynamicCallable` application.
  auto applyFunctionLoc =
      locator.withPathElement(ConstraintLocator::ApplyFunction);
  if (auto selected = solution.getOverloadChoiceIfAvailable(
          cs.getConstraintLocator(applyFunctionLoc))) {
    auto *method = dyn_cast<FuncDecl>(selected->choice.getDecl());
    auto methodType =
        simplifyType(selected->openedType)->getAs<AnyFunctionType>();
    if (method && methodType) {
      // Handle a call to a @dynamicCallable method.
      if (isValidDynamicCallableMethod(method, methodType))
        std::tie(fn, arg) = buildDynamicCallable(
            apply, *selected, method, methodType, applyFunctionLoc);
    }
  }

  // The function is always an rvalue.
  fn = cs.coerceToRValue(fn);

  // Resolve applications of decls with special semantics.
  if (auto declRef =
      dyn_cast<DeclRefExpr>(getSemanticExprForDeclOrMemberRef(fn))) {
    if (auto special =
        finishApplyOfDeclWithSpecialTypeCheckingSemantics(apply,
                                                          declRef->getDeclRef(),
                                                          openedType)) {
      return special;
    }
  }
  
  bool unwrapResult = false;
  if (auto *IUOFnTy = dyn_cast<ImplicitlyUnwrappedFunctionConversionExpr>(fn)) {
    unwrapResult = true;
    fn = IUOFnTy->getSubExpr();
  }

  // If we're applying a function that resulted from a covariant
  // function conversion, strip off that conversion.
  // FIXME: It would be nicer if we could build the ASTs properly in the
  // first shot.
  Type covariantResultType;
  if (auto covariant = dyn_cast<CovariantFunctionConversionExpr>(fn)) {
    // Strip off one layer of application from the covariant result.
    covariantResultType
      = cs.getType(covariant)->castTo<AnyFunctionType>()->getResult();
   
    // Use the subexpression as the function.
    fn = covariant->getSubExpr();
  }

  // An immediate application of a closure literal is always noescape.
  if (isClosureLiteralExpr(fn)) {
    if (auto fnTy = cs.getType(fn)->getAs<FunctionType>()) {
      fnTy = cast<FunctionType>(
        fnTy->withExtInfo(fnTy->getExtInfo().withNoEscape()));
      fn = coerceToType(fn, fnTy, locator);
    }
  }

  apply->setFn(fn);

  // Check whether the argument is 'super'.
  bool isSuper = apply->getArg()->isSuperExpr();

  // For function application, convert the argument to the input type of
  // the function.
  SmallVector<Identifier, 2> argLabelsScratch;
  if (auto fnType = cs.getType(fn)->getAs<FunctionType>()) {
    arg = coerceCallArguments(arg, fnType, callee, apply,
                              apply->getArgumentLabels(argLabelsScratch),
                              locator.withPathElement(
                                  ConstraintLocator::ApplyArgument));
    if (!arg) {
      return nullptr;
    }

    apply->setArg(arg);
    cs.setType(apply, fnType->getResult());
    apply->setIsSuper(isSuper);

    solution.setExprTypes(apply);
    Expr *result = TypeChecker::substituteInputSugarTypeForResult(apply);
    cs.cacheExprTypes(result);

    // If we have a covariant result type, perform the conversion now.
    if (covariantResultType) {
      if (covariantResultType->is<FunctionType>())
        result = cs.cacheType(new (ctx) CovariantFunctionConversionExpr(
            result, covariantResultType));
      else
        result = cs.cacheType(new (ctx) CovariantReturnConversionExpr(
            result, covariantResultType));
    }

    // Try closing the existential, if there is one.
    closeExistential(result, locator);

    if (unwrapResult)
      return forceUnwrapResult(result);

    return result;
  }

  // FIXME: handle unwrapping everywhere else
  assert(!unwrapResult);

  // If this is an UnresolvedType in the system, preserve it.
  if (cs.getType(fn)->is<UnresolvedType>()) {
    cs.setType(apply, cs.getType(fn));
    return apply;
  }

  // We have a type constructor.
  auto metaTy = cs.getType(fn)->castTo<AnyMetatypeType>();
  auto ty = metaTy->getInstanceType();

  // If we're "constructing" a tuple type, it's simply a conversion.
  if (auto tupleTy = ty->getAs<TupleType>()) {
    // FIXME: Need an AST to represent this properly.
    return coerceToType(apply->getArg(), tupleTy, locator);
  }

  // We're constructing a value of nominal type. Look for the constructor or
  // enum element to use.
  auto *ctorLocator =
      cs.getConstraintLocator(locator, {ConstraintLocator::ApplyFunction,
                                        ConstraintLocator::ConstructorMember});
  auto selected = solution.getOverloadChoiceIfAvailable(ctorLocator);
  if (!selected) {
    assert(ty->hasError() || ty->hasUnresolvedType());
    cs.setType(apply, ty);
    return apply;
  }

  assert(ty->getNominalOrBoundGenericNominal() || ty->is<DynamicSelfType>() ||
         ty->isExistentialType() || ty->is<ArchetypeType>());

  // Consider the constructor decl reference expr 'implicit', but the
  // constructor call expr itself has the apply's 'implicitness'.
  Expr *declRef = buildMemberRef(fn, /*dotLoc=*/SourceLoc(), *selected,
                                 DeclNameLoc(fn->getEndLoc()), locator,
                                 ctorLocator, /*implicit=*/true,
                                 AccessSemantics::Ordinary);
  if (!declRef)
    return nullptr;
  declRef->setImplicit(apply->isImplicit());
  apply->setFn(declRef);

  // Tail-recur to actually call the constructor.
  return finishApply(apply, openedType, locator, ctorLocator);
}

// Return the precedence-yielding parent of 'expr', along with the index of
// 'expr' as the child of that parent. The precedence-yielding parent is the
// nearest ancestor of 'expr' which imposes a minimum precedence on 'expr'.
// Right now that just means skipping over TupleExpr instances that only exist
// to hold arguments to binary operators.
static std::pair<Expr *, unsigned> getPrecedenceParentAndIndex(Expr *expr,
                                                               Expr *rootExpr)
{
  auto parentMap = rootExpr->getParentMap();
  auto it = parentMap.find(expr);
  if (it == parentMap.end()) {
    return { nullptr, 0 };
  }
  Expr *parent = it->second;

  // Handle all cases where the answer isn't just going to be { parent, 0 }.
  if (auto tuple = dyn_cast<TupleExpr>(parent)) {
    // Get index of expression in tuple.
    auto tupleElems = tuple->getElements();
    auto elemIt = std::find(tupleElems.begin(), tupleElems.end(), expr);
    assert(elemIt != tupleElems.end() && "expr not found in parent TupleExpr");
    unsigned index = elemIt - tupleElems.begin();

    it = parentMap.find(parent);
    if (it != parentMap.end()) {
      Expr *gparent = it->second;

      // Was this tuple just constructed for a binop?
      if (isa<BinaryExpr>(gparent)) {
        return { gparent, index };
      }
    }

    // Must be a tuple literal, function arg list, collection, etc.
    return { parent, index };
  } else if (auto ifExpr = dyn_cast<IfExpr>(parent)) {
    unsigned index;
    if (expr == ifExpr->getCondExpr()) {
      index = 0;
    } else if (expr == ifExpr->getThenExpr()) {
      index = 1;
    } else if (expr == ifExpr->getElseExpr()) {
      index = 2;
    } else {
      llvm_unreachable("expr not found in parent IfExpr");
    }
    return { ifExpr, index };
  } else if (auto assignExpr = dyn_cast<AssignExpr>(parent)) {
    unsigned index;
    if (expr == assignExpr->getSrc()) {
      index = 0;
    } else if (expr == assignExpr->getDest()) {
      index = 1;
    } else {
      llvm_unreachable("expr not found in parent AssignExpr");
    }
    return { assignExpr, index };
  }

  return { parent, 0 };
}

/// Return true if, when replacing "<expr>" with "<expr> op <something>",
/// parentheses must be added around "<expr>" to allow the new operator
/// to bind correctly.
bool swift::exprNeedsParensInsideFollowingOperator(
    DeclContext *DC, Expr *expr,
    PrecedenceGroupDecl *followingPG) {
  if (expr->isInfixOperator()) {
    auto exprPG = TypeChecker::lookupPrecedenceGroupForInfixOperator(DC, expr);
    if (!exprPG) return true;

    return DC->getASTContext().associateInfixOperators(exprPG, followingPG)
             != Associativity::Left;
  }

  // We want to parenthesize a 'try?' on the LHS, but we don't care about
  // capturing the new operator inside a 'try' or 'try!'.
  if (isa<OptionalTryExpr>(expr))
    return true;

  return false;
}

/// Return true if, when replacing "<expr>" with "<expr> op <something>"
/// within the given root expression, parentheses must be added around
/// the new operator to prevent it from binding incorrectly in the
/// surrounding context.
bool swift::exprNeedsParensOutsideFollowingOperator(
    DeclContext *DC, Expr *expr, Expr *rootExpr,
    PrecedenceGroupDecl *followingPG) {
  Expr *parent;
  unsigned index;
  std::tie(parent, index) = getPrecedenceParentAndIndex(expr, rootExpr);
  if (!parent || isa<TupleExpr>(parent)) {
    return false;
  }

  if (auto parenExp = dyn_cast<ParenExpr>(parent))
    if (!parenExp->isImplicit())
      return false;

  if (parent->isInfixOperator()) {
    auto parentPG = TypeChecker::lookupPrecedenceGroupForInfixOperator(DC,
                                                                       parent);
    if (!parentPG) return true;

    // If the index is 0, this is on the LHS of the parent.
    auto &Context = DC->getASTContext();
    if (index == 0) {
      return Context.associateInfixOperators(followingPG, parentPG)
               != Associativity::Left;
    } else {
      return Context.associateInfixOperators(parentPG, followingPG)
               != Associativity::Right;
    }
  }

  return true;
}

bool swift::exprNeedsParensBeforeAddingNilCoalescing(DeclContext *DC,
                                                     Expr *expr) {
  auto &ctx = DC->getASTContext();
  auto asPG = TypeChecker::lookupPrecedenceGroup(
                  DC, ctx.Id_NilCoalescingPrecedence, SourceLoc())
                  .getSingle();
  if (!asPG)
    return true;
  return exprNeedsParensInsideFollowingOperator(DC, expr, asPG);
}

bool swift::exprNeedsParensAfterAddingNilCoalescing(DeclContext *DC,
                                                    Expr *expr,
                                                    Expr *rootExpr) {
  auto &ctx = DC->getASTContext();
  auto asPG = TypeChecker::lookupPrecedenceGroup(
                  DC, ctx.Id_NilCoalescingPrecedence, SourceLoc())
                  .getSingle();
  if (!asPG)
    return true;
  return exprNeedsParensOutsideFollowingOperator(DC, expr, rootExpr, asPG);
}

namespace {
  class SetExprTypes : public ASTWalker {
    const Solution &solution;

  public:
    explicit SetExprTypes(const Solution &solution)
        : solution(solution) {}

    Expr *walkToExprPost(Expr *expr) override {
      auto &cs = solution.getConstraintSystem();
      auto exprType = cs.getType(expr);
      exprType = solution.simplifyType(exprType);
      // assert((!expr->getType() || expr->getType()->isEqual(exprType)) &&
      //       "Mismatched types!");
      assert(!exprType->hasTypeVariable() &&
             "Should not write type variable into expression!");
      assert(!exprType->hasHole() &&
             "Should not write type holes into expression!");
      expr->setType(exprType);

      if (auto kp = dyn_cast<KeyPathExpr>(expr)) {
        for (auto i : indices(kp->getComponents())) {
          Type componentType;
          if (cs.hasType(kp, i)) {
            componentType = solution.simplifyType(cs.getType(kp, i));
            assert(!componentType->hasTypeVariable() &&
                   "Should not write type variable into key-path component");
            assert(!componentType->hasHole() &&
                   "Should not write type hole into key-path component");
            kp->getMutableComponents()[i].setComponentType(componentType);
          }
        }
      }

      return expr;
    }

    /// Ignore statements.
    std::pair<bool, Stmt *> walkToStmtPre(Stmt *stmt) override {
      return { false, stmt };
    }

    /// Ignore declarations.
    bool walkToDeclPre(Decl *decl) override { return false; }
  };

  class ExprWalker : public ASTWalker {
    ExprRewriter &Rewriter;
    SmallVector<ClosureExpr *, 4> ClosuresToTypeCheck;
    SmallVector<std::pair<TapExpr *, DeclContext *>, 4> TapsToTypeCheck;

  public:
    ExprWalker(ExprRewriter &Rewriter) : Rewriter(Rewriter) { }

    const SmallVectorImpl<ClosureExpr *> &getClosuresToTypeCheck() const {
      return ClosuresToTypeCheck;
    }

    const SmallVectorImpl<std::pair<TapExpr *, DeclContext *>> &getTapsToTypeCheck() const {
      return TapsToTypeCheck;
    }

    std::pair<bool, Expr *> walkToExprPre(Expr *expr) override {
      // For closures, update the parameter types and check the body.
      if (auto closure = dyn_cast<ClosureExpr>(expr)) {
        rewriteFunction(closure);
        return { false, closure };
      }

      if (auto tap = dyn_cast_or_null<TapExpr>(expr)) {
        // We remember the DeclContext because the code to handle
        // single-expression-body closures above changes it.
        TapsToTypeCheck.push_back(std::make_pair(tap, Rewriter.dc));
      }

      if (auto captureList = dyn_cast<CaptureListExpr>(expr)) {
        // Rewrite captures.
        for (const auto &capture : captureList->getCaptureList()) {
          (void)rewriteTarget(SolutionApplicationTarget(capture.Init));
        }
      }

      Rewriter.walkToExprPre(expr);
      return { true, expr };
    }

    Expr *walkToExprPost(Expr *expr) override {
      return Rewriter.walkToExprPost(expr);
    }

    /// Ignore statements.
    std::pair<bool, Stmt *> walkToStmtPre(Stmt *stmt) override {
      return { false, stmt };
    }

    /// Ignore declarations.
    bool walkToDeclPre(Decl *decl) override { return false; }

    /// Rewrite the target, producing a new target.
    Optional<SolutionApplicationTarget>
    rewriteTarget(SolutionApplicationTarget target);

    /// Rewrite the function for the given solution.
    ///
    /// \returns true if an error occurred.
    bool rewriteFunction(AnyFunctionRef fn) {
      auto result = Rewriter.cs.applySolution(
          Rewriter.solution, fn, Rewriter.dc,
          [&](SolutionApplicationTarget target) {
            auto resultTarget = rewriteTarget(target);
            if (resultTarget) {
              if (auto expr = resultTarget->getAsExpr())
                Rewriter.solution.setExprTypes(expr);
            }

            return resultTarget;
          });

      switch (result) {
      case SolutionApplicationToFunctionResult::Success:
        return false;

      case SolutionApplicationToFunctionResult::Failure:
        return true;

      case SolutionApplicationToFunctionResult::Delay: {
        if (!Rewriter.cs.Options
                .contains(ConstraintSystemFlags::LeaveClosureBodyUnchecked)) {
          auto closure = cast<ClosureExpr>(fn.getAbstractClosureExpr());
          ClosuresToTypeCheck.push_back(closure);
        }
        return false;
      }
      }
    }
  };
} // end anonymous namespace

Expr *ConstraintSystem::coerceToRValue(Expr *expr) {
  return TypeChecker::coerceToRValue(
      getASTContext(), expr, [&](Expr *expr) { return getType(expr); },
      [&](Expr *expr, Type type) { setType(expr, type); });
}

namespace {
  /// Function object to compare source locations, putting invalid
  /// locations at the end.
  class CompareExprSourceLocs {
    SourceManager &sourceMgr;

  public:
    explicit CompareExprSourceLocs(SourceManager &sourceMgr)
      : sourceMgr(sourceMgr) { }

    bool operator()(ASTNode lhs, ASTNode rhs) const {
      if (static_cast<bool>(lhs) != static_cast<bool>(rhs)) {
        return static_cast<bool>(lhs);
      }

      auto lhsLoc = getLoc(lhs);
      auto rhsLoc = getLoc(rhs);
      if (lhsLoc.isValid() != rhsLoc.isValid())
        return lhsLoc.isValid();

      return sourceMgr.isBeforeInBuffer(lhsLoc, rhsLoc);
    }
  };

}

/// Emit the fixes computed as part of the solution, returning true if we were
/// able to emit an error message, or false if none of the fixits worked out.
bool ConstraintSystem::applySolutionFixes(const Solution &solution) {
  /// Collect the fixes on a per-expression basis.
  llvm::SmallDenseMap<ASTNode, SmallVector<ConstraintFix *, 4>> fixesPerAnchor;
  for (auto *fix : solution.Fixes) {
    fixesPerAnchor[fix->getAnchor()].push_back(fix);
  }

  // Collect all of the expressions that have fixes, and sort them by
  // source ordering.
  SmallVector<ASTNode, 4> orderedAnchors;
  for (const auto &fix : fixesPerAnchor) {
    orderedAnchors.push_back(fix.getFirst());
  }
  std::sort(orderedAnchors.begin(), orderedAnchors.end(),
            CompareExprSourceLocs(Context.SourceMgr));

  // Walk over each of the expressions, diagnosing fixes.
  bool diagnosedAnyErrors = false;

  for (auto anchor : orderedAnchors) {
    // Coalesce fixes with the same locator to avoid duplicating notes.
    auto fixes = fixesPerAnchor[anchor];

    using ConstraintFixVector = llvm::SmallVector<ConstraintFix *, 4>;
    llvm::SmallMapVector<ConstraintLocator *,
        llvm::SmallMapVector<FixKind, ConstraintFixVector, 4>, 4> aggregatedFixes;
    for (auto *fix : fixes)
      aggregatedFixes[fix->getLocator()][fix->getKind()].push_back(fix);

    for (auto fixesPerLocator : aggregatedFixes) {
      for (auto fixesPerKind : fixesPerLocator.second) {
        auto fixes = fixesPerKind.second;
        auto *primaryFix = fixes[0];
        ArrayRef<ConstraintFix *> secondaryFixes{fixes.begin() + 1, fixes.end()};

        auto diagnosed =
            primaryFix->coalesceAndDiagnose(solution, secondaryFixes);
        if (primaryFix->isWarning()) {
          assert(diagnosed && "warnings should always be diagnosed");
          (void)diagnosed;
        } else {
          diagnosedAnyErrors |= diagnosed;
        }
      }
    }
  }

  return diagnosedAnyErrors;
}

/// For the initializer of an `async let`, wrap it in an autoclosure and then
/// a call to that autoclosure, so that the code for the child task is captured
/// entirely within the autoclosure. This captures the semantics of the
/// operation but not the timing, e.g., the call itself will actually occur
/// when one of the variables in the async let is referenced.
static Expr *wrapAsyncLetInitializer(
      ConstraintSystem &cs, Expr *initializer, DeclContext *dc) {
  // Form the autoclosure type. It is always 'async', and will be 'throws'.
  Type initializerType = initializer->getType();
  bool throws = TypeChecker::canThrow(initializer);
  auto extInfo = ASTExtInfoBuilder()
    .withAsync()
    .withThrows(throws)
    .build();

  // Form the autoclosure expression. The actual closure here encapsulates the
  // child task.
  auto closureType = FunctionType::get({ }, initializerType, extInfo);
  ASTContext &ctx = dc->getASTContext();
  Expr *autoclosureExpr = cs.buildAutoClosureExpr(
      initializer, closureType, /*isDefaultWrappedValue=*/false,
      /*isAsyncLetWrapper=*/true);

  // Call the autoclosure so that the AST types line up. SILGen will ignore the
  // actual calls and translate them into a different mechanism.
  auto autoclosureCall = CallExpr::createImplicit(
      ctx, autoclosureExpr, { }, { });
  autoclosureCall->setType(initializerType);
  autoclosureCall->setThrows(throws);

  // For a throwing expression, wrap the call in a 'try'.
  Expr *resultInit = autoclosureCall;
  if (throws) {
    resultInit = new (ctx) TryExpr(
        SourceLoc(), resultInit, initializerType, /*implicit=*/true);
  }

  // Wrap the call in an 'await'.
  resultInit = new (ctx) AwaitExpr(
      SourceLoc(), resultInit, initializerType, /*implicit=*/true);

  cs.cacheExprTypes(resultInit);
  return resultInit;
}

/// Apply the given solution to the initialization target.
///
/// \returns the resulting initialization expression.
static Optional<SolutionApplicationTarget> applySolutionToInitialization(
    Solution &solution, SolutionApplicationTarget target,
    Expr *initializer) {
  auto wrappedVar = target.getInitializationWrappedVar();
  Type initType;
  if (wrappedVar) {
    initType = solution.getType(initializer);
  } else {
    initType = solution.getType(target.getInitializationPattern());
  }

  {
    // Figure out what type the constraints decided on.
    auto ty = solution.simplifyType(initType);
    initType = ty->getRValueType()->reconstituteSugar(/*recursive =*/false);
  }

  // Convert the initializer to the type of the pattern.
  auto &cs = solution.getConstraintSystem();
  auto locator =
      cs.getConstraintLocator(initializer, LocatorPathElt::ContextualType());
  initializer = solution.coerceToType(initializer, initType, locator);
  if (!initializer)
    return None;

  SolutionApplicationTarget resultTarget = target;
  resultTarget.setExpr(initializer);

  // Record the property wrapper type and note that the initializer has
  // been subsumed by the backing property.
  if (wrappedVar) {
    ASTContext &ctx = cs.getASTContext();
    wrappedVar->getParentPatternBinding()->setInitializerSubsumed(0);
    ctx.setSideCachedPropertyWrapperBackingPropertyType(
        wrappedVar, initType->mapTypeOutOfContext());

    // Record the semantic initializer on the outermost property wrapper.
    wrappedVar->getAttachedPropertyWrappers().front()
        ->setSemanticInit(initializer);
  }

  // Coerce the pattern to the type of the initializer.
  TypeResolutionOptions options =
      isa<EditorPlaceholderExpr>(initializer->getSemanticsProvidingExpr())
      ? TypeResolverContext::EditorPlaceholderExpr
      : target.getInitializationPatternBindingDecl()
        ? TypeResolverContext::PatternBindingDecl
        : TypeResolverContext::InExpression;
  options |= TypeResolutionFlags::OverrideType;

  // Determine the type of the pattern.
  Type finalPatternType = initializer->getType();
  if (wrappedVar) {
    if (!finalPatternType->hasError() && !finalPatternType->is<TypeVariableType>())
      finalPatternType = computeWrappedValueType(wrappedVar, finalPatternType);
  }

  if (finalPatternType->hasDependentMember())
    return None;

  finalPatternType = finalPatternType->reconstituteSugar(/*recursive =*/false);

  // Apply the solution to the pattern as well.
  auto contextualPattern = target.getContextualPattern();
  if (auto coercedPattern = TypeChecker::coercePatternToType(
          contextualPattern, finalPatternType, options)) {
    resultTarget.setPattern(coercedPattern);
  } else {
    return None;
  }

  // For an async let, wrap the initializer appropriately to make it a child
  // task.
  if (auto patternBinding = target.getInitializationPatternBindingDecl()) {
    if (patternBinding->isAsyncLet()) {
      resultTarget.setExpr(
          wrapAsyncLetInitializer(
            cs, resultTarget.getAsExpr(), resultTarget.getDeclContext()));
    }
  }

  return resultTarget;
}

/// Apply the given solution to the for-each statement target.
///
/// \returns the resulting initialization expression.
static Optional<SolutionApplicationTarget> applySolutionToForEachStmt(
    Solution &solution, SolutionApplicationTarget target, Expr *sequence) {
  auto resultTarget = target;
  auto &forEachStmtInfo = resultTarget.getForEachStmtInfo();

  // Simplify the various types.
  forEachStmtInfo.elementType =
      solution.simplifyType(forEachStmtInfo.elementType);
  forEachStmtInfo.iteratorType =
      solution.simplifyType(forEachStmtInfo.iteratorType);
  forEachStmtInfo.initType =
      solution.simplifyType(forEachStmtInfo.initType);
  forEachStmtInfo.sequenceType =
      solution.simplifyType(forEachStmtInfo.sequenceType);

  // Coerce the sequence to the sequence type.
  auto &cs = solution.getConstraintSystem();
  auto locator = cs.getConstraintLocator(target.getAsExpr());
  sequence = solution.coerceToType(
     sequence, forEachStmtInfo.sequenceType, locator);
  if (!sequence)
    return None;

  resultTarget.setExpr(sequence);

  // Get the conformance of the sequence type to the Sequence protocol.
  auto stmt = forEachStmtInfo.stmt;
  auto sequenceProto = TypeChecker::getProtocol(
      cs.getASTContext(), stmt->getForLoc(), KnownProtocolKind::Sequence);
  auto contextualLocator = cs.getConstraintLocator(
      target.getAsExpr(), LocatorPathElt::ContextualType());
  auto sequenceConformance = solution.resolveConformance(
      contextualLocator, sequenceProto);
  assert(!sequenceConformance.isInvalid() &&
         "Couldn't find sequence conformance");

  // Coerce the pattern to the element type.
  TypeResolutionOptions options(TypeResolverContext::ForEachStmt);
  options |= TypeResolutionFlags::OverrideType;

  // Apply the solution to the pattern as well.
  auto contextualPattern = target.getContextualPattern();
  if (auto coercedPattern = TypeChecker::coercePatternToType(
          contextualPattern, forEachStmtInfo.initType, options)) {
    resultTarget.setPattern(coercedPattern);
  } else {
    return None;
  }

  // Apply the solution to the filtering condition, if there is one.
  auto dc = target.getDeclContext();
  if (forEachStmtInfo.whereExpr) {
    auto *boolDecl = dc->getASTContext().getBoolDecl();
    assert(boolDecl);
    Type boolType = boolDecl->getDeclaredInterfaceType();
    assert(boolType);

    SolutionApplicationTarget whereTarget(
        forEachStmtInfo.whereExpr, dc, CTP_Condition, boolType,
        /*isDiscarded=*/false);
    auto newWhereTarget = cs.applySolution(solution, whereTarget);
    if (!newWhereTarget)
      return None;

    forEachStmtInfo.whereExpr = newWhereTarget->getAsExpr();
  }

  // Invoke iterator() to get an iterator from the sequence.
  ASTContext &ctx = cs.getASTContext();
  VarDecl *iterator;
  Type nextResultType = OptionalType::get(forEachStmtInfo.elementType);
  {
    // Create a local variable to capture the iterator.
    std::string name;
    if (auto np = dyn_cast_or_null<NamedPattern>(stmt->getPattern()))
      name = "$"+np->getBoundName().str().str();
    name += "$generator";

    iterator = new (ctx) VarDecl(
        /*IsStatic*/ false, VarDecl::Introducer::Var, stmt->getInLoc(),
        ctx.getIdentifier(name), dc);
    iterator->setInterfaceType(
        forEachStmtInfo.iteratorType->mapTypeOutOfContext());
    iterator->setImplicit();

    auto genPat = new (ctx) NamedPattern(iterator);
    genPat->setImplicit();

    // TODO: test/DebugInfo/iteration.swift requires this extra info to
    // be around.
    PatternBindingDecl::createImplicit(
        ctx, StaticSpellingKind::None, genPat,
        new (ctx) OpaqueValueExpr(stmt->getInLoc(), nextResultType),
        dc, /*VarLoc*/ stmt->getForLoc());
  }

  // Create the iterator variable.
  auto *varRef = TypeChecker::buildCheckedRefExpr(
      iterator, dc, DeclNameLoc(stmt->getInLoc()), /*implicit*/ true);

  // Convert that Optional<Element> value to the type of the pattern.
  auto optPatternType = OptionalType::get(forEachStmtInfo.initType);
  if (!optPatternType->isEqual(nextResultType)) {
    OpaqueValueExpr *elementExpr =
        new (ctx) OpaqueValueExpr(stmt->getInLoc(), nextResultType,
                                  /*isPlaceholder=*/true);
    Expr *convertElementExpr = elementExpr;
    if (TypeChecker::typeCheckExpression(
            convertElementExpr, dc,
            /*contextualInfo=*/{optPatternType, CTP_CoerceOperand})
            .isNull()) {
      return None;
    }
    elementExpr->setIsPlaceholder(false);
    stmt->setElementExpr(elementExpr);
    stmt->setConvertElementExpr(convertElementExpr);
  }

  // Write the result back into the AST.
  stmt->setSequence(resultTarget.getAsExpr());
  stmt->setPattern(resultTarget.getContextualPattern().getPattern());
  stmt->setSequenceConformance(sequenceConformance);
  stmt->setWhere(forEachStmtInfo.whereExpr);
  stmt->setIteratorVar(iterator);
  stmt->setIteratorVarRef(varRef);

  return resultTarget;
}

Optional<SolutionApplicationTarget>
ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
  auto &solution = Rewriter.solution;

  // Apply the solution to the target.
  SolutionApplicationTarget result = target;
  if (auto expr = target.getAsExpr()) {
    Expr *rewrittenExpr = expr->walk(*this);
    if (!rewrittenExpr)
      return None;

    /// Handle special cases for expressions.
    switch (target.getExprContextualTypePurpose()) {
    case CTP_Initialization: {
      auto initResultTarget = applySolutionToInitialization(
          solution, target, rewrittenExpr);
      if (!initResultTarget)
        return None;

      result = *initResultTarget;
      break;
    }

    case CTP_ForEachStmt: {
      auto forEachResultTarget = applySolutionToForEachStmt(
          solution, target, rewrittenExpr);
      if (!forEachResultTarget)
        return None;

      result = *forEachResultTarget;
      break;
    }

    case CTP_Unused:
    case CTP_ReturnStmt:
    case swift::CTP_ReturnSingleExpr:
    case swift::CTP_YieldByValue:
    case swift::CTP_YieldByReference:
    case swift::CTP_ThrowStmt:
    case swift::CTP_EnumCaseRawValue:
    case swift::CTP_DefaultParameter:
    case swift::CTP_AutoclosureDefaultParameter:
    case swift::CTP_CalleeResult:
    case swift::CTP_CallArgument:
    case swift::CTP_ClosureResult:
    case swift::CTP_ArrayElement:
    case swift::CTP_DictionaryKey:
    case swift::CTP_DictionaryValue:
    case swift::CTP_CoerceOperand:
    case swift::CTP_AssignSource:
    case swift::CTP_SubscriptAssignSource:
    case swift::CTP_Condition:
    case swift::CTP_WrappedProperty:
    case swift::CTP_ComposedPropertyWrapper:
    case swift::CTP_CannotFail:
      result.setExpr(rewrittenExpr);
      break;
    }
  } else if (auto stmtCondition = target.getAsStmtCondition()) {
    for (auto &condElement : *stmtCondition) {
      switch (condElement.getKind()) {
      case StmtConditionElement::CK_Availability:
        continue;

      case StmtConditionElement::CK_Boolean: {
        auto condExpr = condElement.getBoolean();
        auto finalCondExpr = condExpr->walk(*this);
        if (!finalCondExpr)
          return None;

        // Load the condition if needed.
        solution.setExprTypes(finalCondExpr);
        if (finalCondExpr->getType()->hasLValueType()) {
          ASTContext &ctx = solution.getConstraintSystem().getASTContext();
          finalCondExpr = TypeChecker::addImplicitLoadExpr(ctx, finalCondExpr);
        }

        condElement.setBoolean(finalCondExpr);
        continue;
      }

      case StmtConditionElement::CK_PatternBinding: {
        ConstraintSystem &cs = solution.getConstraintSystem();
        auto target = *cs.getSolutionApplicationTarget(&condElement);
        auto resolvedTarget = rewriteTarget(target);
        if (!resolvedTarget)
          return None;

        solution.setExprTypes(resolvedTarget->getAsExpr());
        condElement.setInitializer(resolvedTarget->getAsExpr());
        condElement.setPattern(resolvedTarget->getInitializationPattern());
        continue;
      }
      }
    }

    return target;
  } else if (auto caseLabelItem = target.getAsCaseLabelItem()) {
    ConstraintSystem &cs = solution.getConstraintSystem();
    auto info = *cs.getCaseLabelItemInfo(*caseLabelItem);

    // Figure out the pattern type.
    Type patternType = solution.simplifyType(solution.getType(info.pattern));
    patternType = patternType->reconstituteSugar(/*recursive=*/false);

    // Coerce the pattern to its appropriate type.
    TypeResolutionOptions patternOptions(TypeResolverContext::InExpression);
    patternOptions |= TypeResolutionFlags::OverrideType;
    auto contextualPattern =
        ContextualPattern::forRawPattern(info.pattern,
                                         target.getDeclContext());
    if (auto coercedPattern = TypeChecker::coercePatternToType(
            contextualPattern, patternType, patternOptions)) {
      (*caseLabelItem)->setPattern(coercedPattern, /*resolved=*/true);
    } else {
      return None;
    }

    // If there is a guard expression, coerce that.
    if (auto guardExpr = info.guardExpr) {
      guardExpr = guardExpr->walk(*this);
      if (!guardExpr)
        return None;

      // FIXME: Feels like we could leverage existing code more.
      Type boolType = cs.getASTContext().getBoolDecl()->getDeclaredInterfaceType();
      guardExpr = solution.coerceToType(
          guardExpr, boolType, cs.getConstraintLocator(info.guardExpr));
      if (!guardExpr)
        return None;

      (*caseLabelItem)->setGuardExpr(guardExpr);
      solution.setExprTypes(guardExpr);
    }

    return target;
  } else if (auto patternBinding = target.getAsPatternBinding()) {
    ConstraintSystem &cs = solution.getConstraintSystem();
    for (unsigned index : range(patternBinding->getNumPatternEntries())) {
      // Find the solution application target for this.
      auto knownTarget = *cs.getSolutionApplicationTarget(
          {patternBinding, index});

      // Rewrite the target.
      auto resultTarget = rewriteTarget(knownTarget);
      if (!resultTarget)
        return None;

      patternBinding->setPattern(
          index, resultTarget->getInitializationPattern(),
          resultTarget->getDeclContext());
      patternBinding->setInit(index, resultTarget->getAsExpr());
    }

    return target;
  } else if (auto *wrappedVar = target.getAsUninitializedWrappedVar()) {
    // Get the outermost wrapper type from the solution
    auto outermostWrapper = wrappedVar->getAttachedPropertyWrappers().front();
    auto backingType = solution.simplifyType(
        solution.getType(outermostWrapper->getTypeRepr()));

    auto &ctx = solution.getConstraintSystem().getASTContext();
    ctx.setSideCachedPropertyWrapperBackingPropertyType(
        wrappedVar, backingType->mapTypeOutOfContext());

    return target;
  } else {
    auto fn = *target.getAsFunction();
    if (rewriteFunction(fn))
      return None;

    result.setFunctionBody(fn.getBody());
  }

  // Follow-up tasks.
  auto &cs = solution.getConstraintSystem();
  if (auto resultExpr = result.getAsExpr()) {
    Expr *expr = target.getAsExpr();
    assert(expr && "Can't have expression result without expression target");

    // We are supposed to use contextual type only if it is present and
    // this expression doesn't represent the implicit return of the single
    // expression function which got deduced to be `Never`.
    Type convertType = target.getExprConversionType();
    auto shouldCoerceToContextualType = [&]() {
      return convertType &&
          !target.isOptionalSomePatternInit() &&
          !(solution.getType(resultExpr)->isUninhabited() &&
            cs.getContextualTypePurpose(target.getAsExpr())
              == CTP_ReturnSingleExpr);
    };

    // If we're supposed to convert the expression to some particular type,
    // do so now.
    if (shouldCoerceToContextualType()) {
      resultExpr = Rewriter.coerceToType(resultExpr,
                                         solution.simplifyType(convertType),
                                         cs.getConstraintLocator(expr));
    } else if (cs.getType(resultExpr)->hasLValueType() &&
               !target.isDiscardedExpr()) {
      // We referenced an lvalue. Load it.
      resultExpr = Rewriter.coerceToType(
          resultExpr,
          cs.getType(resultExpr)->getRValueType(),
          cs.getConstraintLocator(expr));
    }

    if (!resultExpr)
      return None;

    // For an @autoclosure default parameter type, add the autoclosure
    // conversion.
    if (FunctionType *autoclosureParamType =
            target.getAsAutoclosureParamType()) {
      resultExpr = cs.buildAutoClosureExpr(resultExpr, autoclosureParamType);
    }

    solution.setExprTypes(resultExpr);
    result.setExpr(resultExpr);

    if (cs.isDebugMode()) {
      auto &log = llvm::errs();
      log << "---Type-checked expression---\n";
      resultExpr->dump(log);
      log << "\n";
    }
  }

  return result;
}

/// Apply a given solution to the expression, producing a fully
/// type-checked expression.
Optional<SolutionApplicationTarget> ConstraintSystem::applySolution(
    Solution &solution, SolutionApplicationTarget target) {
  // If any fixes needed to be applied to arrive at this solution, resolve
  // them to specific expressions.
  if (!solution.Fixes.empty()) {
    if (shouldSuppressDiagnostics())
      return None;

    bool diagnosedErrorsViaFixes = applySolutionFixes(solution);
    // If all of the available fixes would result in a warning,
    // we can go ahead and apply this solution to AST.
    if (!llvm::all_of(solution.Fixes, [](const ConstraintFix *fix) {
          return fix->isWarning();
        })) {
      // If we already diagnosed any errors via fixes, that's it.
      if (diagnosedErrorsViaFixes)
        return None;

      // If we didn't manage to diagnose anything well, so fall back to
      // diagnosing mining the system to construct a reasonable error message.
      diagnoseFailureFor(target);
      return None;
    }
  }

  // If there are no fixes recorded but score indicates that there
  // should have been at least one, let's fail application and
  // produce a fallback diagnostic to highlight the problem.
  {
    const auto &score = solution.getFixedScore();
    if (score.Data[SK_Fix] > 0 || score.Data[SK_Hole] > 0) {
      maybeProduceFallbackDiagnostic(target);
      return None;
    }
  }

  ExprRewriter rewriter(*this, solution, target, shouldSuppressDiagnostics());
  ExprWalker walker(rewriter);
  auto resultTarget = walker.rewriteTarget(target);
  if (!resultTarget)
    return None;

  // Visit closures that have non-single expression bodies.
  bool hadError = false;

  for (auto *closure : walker.getClosuresToTypeCheck())
    hadError |= TypeChecker::typeCheckClosureBody(closure);

  // Tap expressions too; they should or should not be
  // type-checked under the same conditions as closure bodies.
  for (auto tuple : walker.getTapsToTypeCheck()) {
    auto tap = std::get<0>(tuple);
    auto tapDC = std::get<1>(tuple);
    hadError |= TypeChecker::typeCheckTapBody(tap, tapDC);
  }

  // If any of them failed to type check, bail.
  if (hadError)
    return None;

  rewriter.finalize();

  return resultTarget;
}

Expr *Solution::coerceToType(Expr *expr, Type toType,
                             ConstraintLocator *locator,
                             Optional<Pattern*> typeFromPattern) {
  auto &cs = getConstraintSystem();
  ExprRewriter rewriter(cs, *this, None, /*suppressDiagnostics=*/false);
  Expr *result = rewriter.coerceToType(expr, toType, locator, typeFromPattern);
  if (!result)
    return nullptr;

  setExprTypes(result);
  rewriter.finalize();
  return result;
}

ProtocolConformanceRef Solution::resolveConformance(
    ConstraintLocator *locator, ProtocolDecl *proto) {
  for (const auto &conformance : Conformances) {
    if (conformance.first != locator)
      continue;
    if (conformance.second.getRequirement() != proto)
      continue;

    // If the conformance doesn't require substitution, return it immediately.
    auto conformanceRef = conformance.second;
    if (conformanceRef.isAbstract())
      return conformanceRef;

    auto concrete = conformanceRef.getConcrete();
    auto conformingType = concrete->getType();
    if (!conformingType->hasTypeVariable())
      return conformanceRef;

    // Substitute into the conformance type, then look for a conformance
    // again.
    // FIXME: Should be able to perform the substitution using the Solution
    // itself rather than another conforms-to-protocol check.
    Type substConformingType = simplifyType(conformingType);
    return TypeChecker::conformsToProtocol(
        substConformingType, proto, constraintSystem->DC);
  }

  return ProtocolConformanceRef::forInvalid();
}

bool Solution::hasType(ASTNode node) const {
  auto result = nodeTypes.find(node);
  if (result != nodeTypes.end())
    return true;

  auto &cs = getConstraintSystem();
  return cs.hasType(node);
}

Type Solution::getType(ASTNode node) const {
  auto result = nodeTypes.find(node);
  if (result != nodeTypes.end())
    return result->second;

  auto &cs = getConstraintSystem();
  return cs.getType(node);
}

Type Solution::getResolvedType(ASTNode node) const {
  return simplifyType(getType(node));
}

void Solution::setExprTypes(Expr *expr) const {
  if (!expr)
    return;

  SetExprTypes SET(*this);
  expr->walk(SET);
}

/// MARK: SolutionResult implementation.

SolutionResult SolutionResult::forSolved(Solution &&solution) {
  SolutionResult result(Kind::Success);
  void *memory = malloc(sizeof(Solution));
  result.solutions = new (memory) Solution(std::move(solution));
  result.numSolutions = 1;
  return result;
}

SolutionResult SolutionResult::forAmbiguous(
    MutableArrayRef<Solution> solutions) {
  assert(solutions.size() > 1 && "Not actually ambiguous");
  SolutionResult result(Kind::Ambiguous);
  result.solutions =
      (Solution *)malloc(sizeof(Solution) * solutions.size());
  result.numSolutions = solutions.size();
  std::uninitialized_copy(std::make_move_iterator(solutions.begin()),
                          std::make_move_iterator(solutions.end()),
                          result.solutions);
  return result;
}

SolutionResult::~SolutionResult() {
  assert((!requiresDiagnostic() || emittedDiagnostic) &&
         "SolutionResult was destroyed without emitting a diagnostic");

  for (unsigned i : range(numSolutions)) {
    solutions[i].~Solution();
  }
  free(solutions);
}

const Solution &SolutionResult::getSolution() const {
  assert(numSolutions == 1 && "Wrong number of solutions");
  return solutions[0];
}

Solution &&SolutionResult::takeSolution() && {
  assert(numSolutions == 1 && "Wrong number of solutions");
  return std::move(solutions[0]);
}

ArrayRef<Solution> SolutionResult::getAmbiguousSolutions() const {
  assert(getKind() == Ambiguous);
  return makeArrayRef(solutions, numSolutions);
}

MutableArrayRef<Solution> SolutionResult::takeAmbiguousSolutions() && {
  assert(getKind() == Ambiguous);
  markAsDiagnosed();
  return MutableArrayRef<Solution>(solutions, numSolutions);
}

SolutionApplicationTarget SolutionApplicationTarget::walk(ASTWalker &walker) {
  switch (kind) {
  case Kind::expression: {
    SolutionApplicationTarget result = *this;
    result.setExpr(getAsExpr()->walk(walker));
    return result;
  }

  case Kind::function:
    return SolutionApplicationTarget(
        *getAsFunction(),
        cast_or_null<BraceStmt>(getFunctionBody()->walk(walker)));

  case Kind::stmtCondition:
    for (auto &condElement : stmtCondition.stmtCondition) {
      condElement = *condElement.walk(walker);
    }
    return *this;

  case Kind::caseLabelItem:
    if (auto newPattern =
            caseLabelItem.caseLabelItem->getPattern()->walk(walker)) {
      caseLabelItem.caseLabelItem->setPattern(
          newPattern, caseLabelItem.caseLabelItem->isPatternResolved());
    }
    if (auto guardExpr = caseLabelItem.caseLabelItem->getGuardExpr()) {
      if (auto newGuardExpr = guardExpr->walk(walker))
        caseLabelItem.caseLabelItem->setGuardExpr(newGuardExpr);
    }

    return *this;

  case Kind::patternBinding:
    return *this;

  case Kind::uninitializedWrappedVar:
    return *this;
  }

  llvm_unreachable("invalid target kind");
}
