text: //===--- 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 "ConstraintSystem.h"
  #include "CodeSynthesis.h"
  #include "CSDiagnostics.h"
  #include "MiscDiagnostics.h"
  #include "SolutionResult.h"
  #include "TypeCheckProtocol.h"
  #include "TypeCheckType.h"
  #include "swift/AST/ASTVisitor.h"
  #include "swift/AST/ASTWalker.h"
  #include "swift/AST/ExistentialLayout.h"
  #include "swift/AST/Initializer.h"
  #include "swift/AST/GenericEnvironment.h"
  #include "swift/AST/GenericSignature.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 "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);
  }
  
  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();
    return ConcreteDeclRef(decl, computeSubstitutions(sig, locator));
  }
  
  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,
                         AccessSemantics semantics) {
        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();
        
        // 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);
  
        assert(ref.getDecl() == decl);
        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:
          // Ensure that the argument type matches up exactly.
          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;
        auto openedFullType = overload.openedFullType;
  
        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;
        }
  
        // 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, simplifyType(openedFullType));
          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);
  
        auto refTy = simplifyType(openedFullType);
  
        // 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 = coerceObjectArgumentToType(
                   base, selfParamTy, member, semantics,
                   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 (isa<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 memberRefExpr
            = new (context) MemberRefExpr(base, dotLoc, memberRef,
                                          memberLoc, Implicit, semantics);
          memberRefExpr->setIsSuper(isSuper);
  
          cs.setType(memberRefExpr, simplifyType(openedType));
          Expr *result = memberRefExpr;
          closeExistential(result, locator);
  
          if (cast<VarDecl>(member)->getValueInterfaceType()
                                   ->hasDynamicSelfType()) {
            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(Expr *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 object 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 semantics The kind of access we've been asked to perform.
      ///
      /// \param locator Locator used to describe where in this expression we are.
      Expr *coerceObjectArgumentToType(Expr *expr,
                                       Type baseTy, ValueDecl *member,
                                       AccessSemantics semantics,
                                       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 = coerceObjectArgumentToType(base, baseTy, subscript,
                                            AccessSemantics::Ordinary, 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 = coerceObjectArgumentToType(
            base, containerTy, subscript, AccessSemantics::Ordinary,
            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->setResultInit(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->getAccessSemantics());
      }
  
      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(), AccessSemantics::Ordinary);
      }
  
      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;
  
        // Check for ambiguous member if the base is an Optional
        if (baseTy->getOptionalObjectType()) {
          diagnoseAmbiguousNominalMember(baseTy, result);
        }
  
        return coerceToType(result, resultTy, cs.getConstraintLocator(expr));
      }
      
      /// Diagnose if the base type is optional, we're referring to a nominal
      /// type member via the dot syntax and the member name matches
      /// Optional<T>.{member name}
      void diagnoseAmbiguousNominalMember(Type baseTy, Expr *result) {
        if (auto baseTyUnwrapped = baseTy->lookThroughAllOptionalTypes()) {
          // Return if the base type doesn't have a nominal type decl
          if (!baseTyUnwrapped->getNominalOrBoundGenericNominal()) {
            return;
          }
          
          // Otherwise, continue digging
          if (auto DSCE = dyn_cast<DotSyntaxCallExpr>(result)) {
            auto calledValue = DSCE->getCalledValue();
            auto isOptional = false;
            Identifier memberName;
            
            // Try cast the assigned value to an enum case
            //
            // This will always succeed if the base is Optional<T> & the
            // assigned case comes from Optional<T>
            if (auto EED = dyn_cast<EnumElementDecl>(calledValue)) {
              isOptional = EED->getParentEnum()->isOptionalDecl();
              memberName = EED->getBaseIdentifier();
            }
            
            // Return if the enum case doesn't come from Optional<T>
            if (!isOptional) {
              return;
            }
            
            // Look up the enum case in the unwrapped type to check if it exists
            // as a member
            auto baseTyNominalDecl = baseTyUnwrapped
                                     ->getNominalOrBoundGenericNominal();
            auto results = TypeChecker::lookupMember(
                baseTyNominalDecl->getModuleContext(), baseTyUnwrapped,
                DeclNameRef(memberName), defaultMemberLookupOptions);
  
            // Filter out any functions, instance members, enum cases with
            // associated values or variables whose type does not match the
            // contextual type.
            results.filter([&](const LookupResultEntry entry, bool isOuter) {
              if (auto member = entry.getValueDecl()) {
                if (isa<FuncDecl>(member))
                  return false;
                if (member->isInstanceMember())
                  return false;
                if (auto EED = dyn_cast<EnumElementDecl>(member)) {
                  return !EED->hasAssociatedValues();
                }
                if (auto VD = dyn_cast<VarDecl>(member)) {
                  auto baseType = DSCE->getType()->lookThroughAllOptionalTypes();
                  return VD->getInterfaceType()->isEqual(baseType);
                }
              }
  
              // Filter out anything that's not one of the above. We don't care
              // if we have a typealias named 'none' or a struct/class named
              // 'none'.
              return false;
            });
  
            if (results.empty()) {
              return;
            }
  
            auto &de = cs.getASTContext().Diags;
            if (auto member = results.front().getValueDecl()) {
              // Emit a diagnostic with some fix-its
              auto baseTyName = baseTy->getCanonicalType().getString();
              auto baseTyUnwrappedName = baseTyUnwrapped->getString();
              auto loc = DSCE->getLoc();
              auto startLoc = DSCE->getStartLoc();
              de.diagnoseWithNotes(
                  de.diagnose(loc, swift::diag::optional_ambiguous_case_ref,
                              baseTyName, baseTyUnwrappedName, memberName.str()),
                  [&]() {
                    de.diagnose(loc,
                                swift::diag::optional_fixit_ambiguous_case_ref)
                        .fixItInsert(startLoc, "Optional");
                    de.diagnose(
                          loc,
                          swift::diag::type_fixit_optional_ambiguous_case_ref,
                          baseTyUnwrappedName, memberName.str())
                        .fixItInsert(startLoc, baseTyUnwrappedName);
                  });
            }
          }
        }
      }
      
    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,
                              AccessSemantics::Ordinary);
        }
  
        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, 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>();
  
        arg = coerceToType(
            arg, closureType->getResult(),
            locator.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,
                                      AccessSemantics semantics,
                                      DeclContext *UseDC) {
    auto baseObjectTy = baseTy->getWithoutSpecifierType();
  
    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 InOutType::get(baseObjectTy);
  
      // 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 we're calling an accessor, keep the base as an inout type, because the
    // getter may be mutating.
    auto strategy = SD->getAccessStrategy(semantics,
                                          isSettableFromHere
                                            ? AccessKind::ReadWrite
                                            : AccessKind::Read,
                                          UseDC->getParentModule(),
                                          UseDC->getResilienceExpansion());
    if (baseTy->is<InOutType>() && strategy.getKind() != AccessStrategy::Storage)
      return InOutType::get(baseObjectTy);
  
    // Accesses to non-function members in value types are done through an @lvalue
    // type.
    if (baseTy->is<InOutType>())
      return LValueType::get(baseObjectTy);
    
    // Accesses to members in values of reference type (classes, metatypes) are
    // always done through a the reference to self.  Accesses to value types with
    // a non-mutable self are also done through the base type.
    return baseTy;
  }
  
  Expr *
  ExprRewriter::coerceObjectArgumentToType(Expr *expr,
                                           Type baseTy, ValueDecl *member,
                                           AccessSemantics semantics,
                                           ConstraintLocatorBuilder locator) {
    Type toType = adjustSelfTypeForMember(expr, baseTy, member, semantics, 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(Expr *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.
        if (auto stringLiteral = dyn_cast<StringLiteralExpr>(literal))
          stringLiteral->setBuiltinInitializer(witness);
        else if (auto booleanLiteral = dyn_cast<BooleanLiteralExpr>(literal))
          booleanLiteral->setBuiltinInitializer(witness);
        else if (auto numberLiteral = dyn_cast<NumberLiteralExpr>(literal))
          numberLiteral->setBuiltinInitializer(witness);
        else {
          cast<MagicIdentifierLiteralExpr>(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.
    if (auto nilLiteral = dyn_cast<NilLiteralExpr>(literal))
      nilLiteral->setInitializer(witness);
    else if (auto stringLiteral = dyn_cast<StringLiteralExpr>(literal))
      stringLiteral->setInitializer(witness);
    else if (auto booleanLiteral = dyn_cast<BooleanLiteralExpr>(literal))
      booleanLiteral->setInitializer(witness);
    else if (auto numberLiteral = dyn_cast<NumberLiteralExpr>(literal))
      numberLiteral->setInitializer(witness);
    else
      cast<MagicIdentifierLiteralExpr>(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;
  }
  
  /// 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;
    }
  
    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,
              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");
  }
  