//===--- TypeCheckError.cpp - Type Checking for Error Coverage ------------===//
//
// 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 semantic analysis to ensure that errors are
// caught.
//
//===----------------------------------------------------------------------===//

#include "TypeChecker.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/DiagnosticsSema.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/PrettyStackTrace.h"

using namespace swift;

namespace {

/// A function reference.
class AbstractFunction {
public:
  enum Kind : uint8_t {
    Opaque, Function, Closure, Parameter,
  };

private:
  union {
    AbstractFunctionDecl *TheFunction;
    AbstractClosureExpr *TheClosure;
    ParamDecl *TheParameter;
    Expr *TheExpr;
  };
  unsigned TheKind : 2;
  unsigned IsRethrows : 1;
  unsigned ParamCount : 2;

public:
  explicit AbstractFunction(Kind kind, Expr *fn)
    : TheKind(kind),
      IsRethrows(false),
      ParamCount(1) {
    TheExpr = fn;
  }

  explicit AbstractFunction(AbstractFunctionDecl *fn)
    : TheKind(Kind::Function),
      IsRethrows(fn->getAttrs().hasAttribute<RethrowsAttr>()),
      ParamCount(fn->hasImplicitSelfDecl() ? 2 : 1) {
    TheFunction = fn;
  }

  explicit AbstractFunction(AbstractClosureExpr *closure)
    : TheKind(Kind::Closure),
      IsRethrows(false),
      ParamCount(1) {
    TheClosure = closure;
  }

  explicit AbstractFunction(ParamDecl *parameter)
    : TheKind(Kind::Parameter),
      IsRethrows(false),
      ParamCount(1) {
    TheParameter = parameter;
  }

  Kind getKind() const { return Kind(TheKind); }

  /// Whether the function is marked 'rethrows'.
  bool isBodyRethrows() const { return IsRethrows; }

  unsigned getNumArgumentsForFullApply() const {
    return ParamCount;
  }

  Type getType() const {
    switch (getKind()) {
    case Kind::Opaque: return getOpaqueFunction()->getType();
    case Kind::Function: return getFunction()->getInterfaceType();
    case Kind::Closure: return getClosure()->getType();
    case Kind::Parameter: return getParameter()->getType();
    }
    llvm_unreachable("bad kind");
  }

  bool isAutoClosure() const {
    if (getKind() == Kind::Closure)
      return isa<AutoClosureExpr>(getClosure());
    return false;
  }

  AbstractFunctionDecl *getFunction() const {
    assert(getKind() == Kind::Function);
    return TheFunction;
  }
  AbstractClosureExpr *getClosure() const {
    assert(getKind() == Kind::Closure);
    return TheClosure;
  }
  ParamDecl *getParameter() const {
    assert(getKind() == Kind::Parameter);
    return TheParameter;
  }
  Expr *getOpaqueFunction() const {
    assert(getKind() == Kind::Opaque);
    return TheExpr;
  }

  static AbstractFunction decomposeApply(ApplyExpr *apply,
                                         SmallVectorImpl<Expr*> &args) {
    Expr *fn;
    do {
      args.push_back(apply->getArg());
      fn = apply->getFn()->getValueProvidingExpr();
    } while ((apply = dyn_cast<ApplyExpr>(fn)));

    return decomposeFunction(fn);
  }

  static AbstractFunction decomposeFunction(Expr *fn) {
    assert(fn->getValueProvidingExpr() == fn);

    while (true) {
      // Look through Optional unwraps.
      if (auto conversion = dyn_cast<ForceValueExpr>(fn)) {
        fn = conversion->getSubExpr()->getValueProvidingExpr();
      } else if (auto conversion = dyn_cast<BindOptionalExpr>(fn)) {
        fn = conversion->getSubExpr()->getValueProvidingExpr();
      // Look through optional injections.
      } else if (auto injection = dyn_cast<InjectIntoOptionalExpr>(fn)) {
        fn = injection->getSubExpr()->getValueProvidingExpr();
      // Look through function conversions.
      } else if (auto conversion = dyn_cast<FunctionConversionExpr>(fn)) {
        fn = conversion->getSubExpr()->getValueProvidingExpr();
      // Look through base-ignored qualified references (Module.methodName).
      } else if (auto baseIgnored = dyn_cast<DotSyntaxBaseIgnoredExpr>(fn)) {
        fn = baseIgnored->getRHS();
      // Look through closure capture lists.
      } else if (auto captureList = dyn_cast<CaptureListExpr>(fn)) {
        fn = captureList->getClosureBody();
        // Look through optional evaluations.
      } else if (auto optionalEval = dyn_cast<OptionalEvaluationExpr>(fn)) {
        fn = optionalEval->getSubExpr()->getValueProvidingExpr();
      } else {
        break;
      }
    }
    
    // Constructor delegation.
    if (auto otherCtorDeclRef = dyn_cast<OtherConstructorDeclRefExpr>(fn)) {
      return AbstractFunction(otherCtorDeclRef->getDecl());
    }

    // Normal function references.
    if (auto declRef = dyn_cast<DeclRefExpr>(fn)) {
      ValueDecl *decl = declRef->getDecl();
      if (auto fn = dyn_cast<AbstractFunctionDecl>(decl)) {
        return AbstractFunction(fn);
      } else if (auto param = dyn_cast<ParamDecl>(decl)) {
        return AbstractFunction(param);
      }

    // Closures.
    } else if (auto closure = dyn_cast<AbstractClosureExpr>(fn)) {
      return AbstractFunction(closure);
    }

    // Everything else is opaque.
    return AbstractFunction(Kind::Opaque, fn);
  }
};

enum ShouldRecurse_t : bool {
  ShouldNotRecurse = false, ShouldRecurse = true
};

/// A CRTP ASTWalker implementation that looks for interesting
/// nodes for error handling.
template <class Impl>
class ErrorHandlingWalker : public ASTWalker {
  Impl &asImpl() { return *static_cast<Impl*>(this); }
public:
  bool walkToDeclPre(Decl *D) override {
    ShouldRecurse_t recurse = ShouldRecurse;
    // Skip the implementations of all local declarations... except
    // PBD.  We should really just have a PatternBindingStmt.
    if (auto ic = dyn_cast<IfConfigDecl>(D))
      recurse = asImpl().checkIfConfig(ic);
    else if (!isa<PatternBindingDecl>(D))
      recurse = ShouldNotRecurse;
    return bool(recurse);
  }

  std::pair<bool, Expr*> walkToExprPre(Expr *E) override {
    ShouldRecurse_t recurse = ShouldRecurse;
    if (isa<ErrorExpr>(E)) {
      asImpl().flagInvalidCode();
    } else if (auto closure = dyn_cast<ClosureExpr>(E)) {
      recurse = asImpl().checkClosure(closure);
    } else if (auto autoclosure = dyn_cast<AutoClosureExpr>(E)) {
      recurse = asImpl().checkAutoClosure(autoclosure);
    } else if (auto tryExpr = dyn_cast<TryExpr>(E)) {
      recurse = asImpl().checkTry(tryExpr);
    } else if (auto forceTryExpr = dyn_cast<ForceTryExpr>(E)) {
      recurse = asImpl().checkForceTry(forceTryExpr);
    } else if (auto optionalTryExpr = dyn_cast<OptionalTryExpr>(E)) {
      recurse = asImpl().checkOptionalTry(optionalTryExpr);
    } else if (auto apply = dyn_cast<ApplyExpr>(E)) {
      recurse = asImpl().checkApply(apply);
    } else if (auto interpolated = dyn_cast<InterpolatedStringLiteralExpr>(E)) {
      recurse = asImpl().checkInterpolatedStringLiteral(interpolated);
    }
    // Error handling validation (via checkTopLevelErrorHandling) happens after
    // type checking. If an unchecked expression is still around, the code was
    // invalid.
#define UNCHECKED_EXPR(KIND, BASE) \
    else if (isa<KIND##Expr>(E)) return {false, nullptr};
#include "swift/AST/ExprNodes.def"

    return {bool(recurse), E};
  }

  std::pair<bool, Stmt*> walkToStmtPre(Stmt *S) override {
    ShouldRecurse_t recurse = ShouldRecurse;
    if (auto doCatch = dyn_cast<DoCatchStmt>(S)) {
      recurse = asImpl().checkDoCatch(doCatch);
    } else if (auto thr = dyn_cast<ThrowStmt>(S)) {
      recurse = asImpl().checkThrow(thr);
    } else {
      assert(!isa<CatchStmt>(S));
    }
    return {bool(recurse), S};
  }

  ShouldRecurse_t checkDoCatch(DoCatchStmt *S) {
    auto bodyResult = (S->isSyntacticallyExhaustive()
        ? asImpl().checkExhaustiveDoBody(S)
        : asImpl().checkNonExhaustiveDoBody(S));
    for (auto clause : S->getCatches()) {
      asImpl().checkCatch(clause, bodyResult);
    }
    return ShouldNotRecurse;
  }
};

/// A potential reason why something might throw.
class PotentialReason {
public:
  enum class Kind : uint8_t {
    /// The function throws unconditionally.
    Throw,

    /// The function calls an unconditionally throwing function.
    CallThrows,

    /// The function is 'rethrows', and it was passed an explicit
    /// argument that was not rethrowing-only in this context.
    CallRethrowsWithExplicitThrowingArgument,

    /// The function is 'rethrows', and it was passed a default
    /// argument that was not rethrowing-only in this context.
    CallRethrowsWithDefaultThrowingArgument,
  };

private:
  Expr *TheExpression;
  Kind TheKind;

  explicit PotentialReason(Kind kind) : TheKind(kind) {}
public:
  static PotentialReason forRethrowsArgument(Expr *E) {
    PotentialReason result(Kind::CallRethrowsWithExplicitThrowingArgument);
    result.TheExpression = E;
    return result;
  }
  static PotentialReason forDefaultArgument() {
    return PotentialReason(Kind::CallRethrowsWithDefaultThrowingArgument);
  }
  static PotentialReason forThrowingApply() {
    return PotentialReason(Kind::CallThrows);
  }
  static PotentialReason forThrow() {
    return PotentialReason(Kind::Throw);
  }

  Kind getKind() const { return TheKind; }

  /// Is this a throw expression?
  bool isThrow() const { return getKind() == Kind::Throw; }
  bool isRethrowsCall() const {
    return (getKind() == Kind::CallRethrowsWithExplicitThrowingArgument ||
            getKind() == Kind::CallRethrowsWithDefaultThrowingArgument);
  }

  /// If this was built with forRethrowsArgument, return the expression.
  Expr *getThrowingArgument() const {
    assert(getKind() == Kind::CallRethrowsWithExplicitThrowingArgument);
    return TheExpression;
  }
};

enum class ThrowingKind {
  /// The call/function can't throw.
  None,

  /// The call/function contains invalid code.
  Invalid,

  /// The call/function can only throw if one of the parameters in
  /// the current rethrows context can throw.
  RethrowingOnly,

  /// The call/function can throw.
  Throws,
};

/// A type expressing the result of classifying whether a call or function
/// throws.
class Classification {
  ThrowingKind Result;
  Optional<PotentialReason> Reason;

public:
  Classification() : Result(ThrowingKind::None) {}
  explicit Classification(ThrowingKind result, PotentialReason reason)
      : Result(result) {
    if (result == ThrowingKind::Throws ||
        result == ThrowingKind::RethrowingOnly) {
      Reason = reason;
    }
  }

  /// Return a classification saying that there's an unconditional
  /// throw site.
  static Classification forThrow(PotentialReason reason) {
    Classification result;
    result.Result = ThrowingKind::Throws;
    result.Reason = reason;
    return result;
  }

  static Classification forInvalidCode() {
    Classification result;
    result.Result = ThrowingKind::Invalid;
    return result;
  }

  static Classification forRethrowingOnly(PotentialReason reason) {
    Classification result;
    result.Result = ThrowingKind::RethrowingOnly;
    result.Reason = reason;
    return result;
  }

  void merge(Classification other) {
    if (other.getResult() > getResult()) {
      *this = other;
    }
  }

  ThrowingKind getResult() const { return Result; }
  PotentialReason getThrowsReason() const {
    assert(getResult() == ThrowingKind::Throws ||
           getResult() == ThrowingKind::RethrowingOnly);
    return *Reason;
  }
};

/// Given the type of a function, classify whether calling it with the
/// given number of arguments would throw.
static ThrowingKind
classifyFunctionByType(Type type, unsigned numArgs) {
  if (!type) return ThrowingKind::Invalid;

  assert(numArgs > 0);
  while (true) {
    auto fnType = type->getAs<AnyFunctionType>();
    if (!fnType) return ThrowingKind::Invalid;
    if (--numArgs == 0) {
      return fnType->getExtInfo().throws()
        ? ThrowingKind::Throws : ThrowingKind::None;
    }

    type = fnType->getResult();
  }
}

/// A class for collecting information about rethrowing functions.
class ApplyClassifier {
  llvm::DenseMap<void*, ThrowingKind> Cache;

public:
  DeclContext *RethrowsDC = nullptr;
  bool inRethrowsContext() const { return RethrowsDC != nullptr; }

  /// Check to see if the given function application throws.
  Classification classifyApply(ApplyExpr *E) {
    // An apply expression is a potential throw site if the function throws.
    // But if the expression didn't type-check, suppress diagnostics.
    if (!E->getType() || E->getType()->hasError())
      return Classification::forInvalidCode();

    auto type = E->getFn()->getType();
    if (!type) return Classification::forInvalidCode();
    auto fnType = type->getAs<AnyFunctionType>();
    if (!fnType) return Classification::forInvalidCode();

    // If the function doesn't throw at all, we're done here.
    if (!fnType->throws()) return Classification();

    // Decompose the application.
    SmallVector<Expr*, 4> args;
    auto fnRef = AbstractFunction::decomposeApply(E, args);

    // If any of the arguments didn't type check, fail.
    for (auto arg : args) {
      if (!arg->getType() || arg->getType()->hasError())
        return Classification::forInvalidCode();
    }

    // If we're applying more arguments than the natural argument
    // count, then this is a call to the opaque value returned from
    // the function.
    if (args.size() != fnRef.getNumArgumentsForFullApply()) {
      // Special case: a reference to an operator within a type might be
      // missing 'self'.
      // FIXME: The issue here is that this is an ill-formed expression, but
      // we don't know it from the structure of the expression.
      if (args.size() == 1 && fnRef.getKind() == AbstractFunction::Function &&
          isa<FuncDecl>(fnRef.getFunction()) &&
          cast<FuncDecl>(fnRef.getFunction())->isOperator() &&
          fnRef.getNumArgumentsForFullApply() == 2 &&
          fnRef.getFunction()->getDeclContext()->isTypeContext()) {
        // Can only happen with invalid code.
        assert(fnRef.getFunction()->getASTContext().Diags.hadAnyError());
        return Classification::forInvalidCode();
      }

      assert(args.size() > fnRef.getNumArgumentsForFullApply() &&
             "partial application was throwing?");
      return Classification::forThrow(PotentialReason::forThrowingApply());
    }

    // If the function's body is 'rethrows' for the number of
    // arguments we gave it, apply the rethrows logic.
    if (fnRef.isBodyRethrows()) {
      // We need to walk the original parameter types in parallel
      // because it only counts for 'rethrows' purposes if it lines up
      // with a throwing function parameter in the original type.
      Type type = fnRef.getType();
      if (!type) return Classification::forInvalidCode();

      // Use the most significant result from the arguments.
      Classification result;
      for (auto arg : reversed(args)) {
        auto fnType = type->getAs<AnyFunctionType>();
        if (!fnType) return Classification::forInvalidCode();

        auto paramType = FunctionType::composeInput(fnType->getASTContext(),
                                                    fnType->getParams(), false);
        result.merge(classifyRethrowsArgument(arg, paramType));
        type = fnType->getResult();
      }
      return result;
    }

    // Try to classify the implementation of functions that we have
    // local knowledge of.
    Classification result =
      classifyThrowingFunctionBody(fnRef, PotentialReason::forThrowingApply());
    assert(result.getResult() != ThrowingKind::None &&
           "body classification decided function was no-throw");
    return result;
  }

private:
  /// Classify a throwing function according to our local knowledge of
  /// its implementation.
  ///
  /// For the most part, this only distinguishes between Throws and
  /// RethrowingOnly.  But it can return Invalid if a type-checking
  /// failure prevents it from deciding that, and it can return None
  /// if the function is an autoclosure that simply doesn't throw at all.
  Classification
  classifyThrowingFunctionBody(const AbstractFunction &fn,
                               PotentialReason reason) {
    // If we're not checking a 'rethrows' context, we don't need to
    // distinguish between 'throws' and 'rethrows'.  But don't even
    // trust 'throws' for autoclosures.
    if (!inRethrowsContext() && !fn.isAutoClosure())
      return Classification::forThrow(reason);

    switch (fn.getKind()) {
    case AbstractFunction::Opaque:
      return Classification::forThrow(reason);
    case AbstractFunction::Parameter:
      return classifyThrowingParameterBody(fn.getParameter(), reason);
    case AbstractFunction::Function:
      return classifyThrowingFunctionBody(fn.getFunction(), reason);
    case AbstractFunction::Closure:
      return classifyThrowingFunctionBody(fn.getClosure(), reason);
    }
    llvm_unreachable("bad abstract function kind");
  }

  Classification classifyThrowingParameterBody(ParamDecl *param,
                                               PotentialReason reason) {
    assert(param->getType()->lookThroughAllOptionalTypes()->castTo<AnyFunctionType>()->throws());

    // If we're currently doing rethrows-checking on the body of the
    // function which declares the parameter, it's rethrowing-only.
    if (param->getDeclContext() == RethrowsDC)
      return Classification::forRethrowingOnly(reason);

    // Otherwise, it throws unconditionally.
    return Classification::forThrow(reason);
  }

  bool isLocallyDefinedInRethrowsContext(DeclContext *DC) {
    while (true) {
      assert(DC->isLocalContext());
      if (DC == RethrowsDC) return true;
      DC = DC->getParent();
      if (!DC->isLocalContext()) return false;
    }
  }

  Classification classifyThrowingFunctionBody(AbstractFunctionDecl *fn,
                                              PotentialReason reason) {
    // Functions can't be rethrowing-only unless they're defined
    // within the rethrows context.
    if (!isLocallyDefinedInRethrowsContext(fn) || !fn->hasBody())
      return Classification::forThrow(reason);

    auto kind = classifyThrowingFunctionBodyImpl(fn, fn->getBody(),
                                                 /*allowNone*/ false);
    return Classification(kind, reason);
  }

  Classification classifyThrowingFunctionBody(AbstractClosureExpr *closure,
                                              PotentialReason reason) {
    bool isAutoClosure = isa<AutoClosureExpr>(closure);

    // Closures can't be rethrowing-only unless they're defined
    // within the rethrows context.
    if (!isAutoClosure && !isLocallyDefinedInRethrowsContext(closure))
      return Classification::forThrow(reason);

    BraceStmt *body;
    if (auto autoclosure = dyn_cast<AutoClosureExpr>(closure)) {
      body = autoclosure->getBody();
    } else {
      body = cast<ClosureExpr>(closure)->getBody();
    }
    if (!body) return Classification::forInvalidCode();

    auto kind = classifyThrowingFunctionBodyImpl(closure, body,
                                                 /*allowNone*/ isAutoClosure);
    return Classification(kind, reason);
  }

  class FunctionBodyClassifier
      : public ErrorHandlingWalker<FunctionBodyClassifier> {
    ApplyClassifier &Self;
  public:
    ThrowingKind Result = ThrowingKind::None;
    FunctionBodyClassifier(ApplyClassifier &self) : Self(self) {}

    void flagInvalidCode() {
      Result = std::max(Result, ThrowingKind::Invalid);
    }

    ShouldRecurse_t checkClosure(ClosureExpr *closure) {
      return ShouldNotRecurse;
    }
    ShouldRecurse_t checkAutoClosure(AutoClosureExpr *closure) {
      return ShouldNotRecurse;
    }
    ShouldRecurse_t checkTry(TryExpr *E) {
      return ShouldRecurse;
    }
    ShouldRecurse_t checkForceTry(ForceTryExpr *E) {
      return ShouldNotRecurse;
    }
    ShouldRecurse_t checkOptionalTry(OptionalTryExpr *E) {
      return ShouldNotRecurse;
    }
    ShouldRecurse_t checkApply(ApplyExpr *E) {
      Result = std::max(Result, Self.classifyApply(E).getResult());
      return ShouldRecurse;
    }
    ShouldRecurse_t checkThrow(ThrowStmt *E) {
      Result = ThrowingKind::Throws;
      return ShouldRecurse;
    }
    ShouldRecurse_t checkInterpolatedStringLiteral(InterpolatedStringLiteralExpr *E) {
      return ShouldRecurse;
    }

    ShouldRecurse_t checkIfConfig(IfConfigDecl *D) {
      return ShouldRecurse;
    }

    ThrowingKind checkExhaustiveDoBody(DoCatchStmt *S) {
      // All errors thrown by the do body are caught, but any errors thrown
      // by the catch bodies are bounded by the throwing kind of the do body.
      auto savedResult = Result;
      Result = ThrowingKind::None;
      S->getBody()->walk(*this);
      auto doThrowingKind = Result;
      Result = savedResult;
      return doThrowingKind;
    }

    ThrowingKind checkNonExhaustiveDoBody(DoCatchStmt *S) {
      S->getBody()->walk(*this);
      // Because catch bodies can only be executed if the do body throws an
      // error, and because the do is non-exhaustive, we can skip checking the
      // catch bodies entirely.
      return ThrowingKind::None;
    }

    void checkCatch(CatchStmt *S, ThrowingKind doThrowingKind) {
      if (doThrowingKind != ThrowingKind::None) {
        // This was an exhaustive do body, so bound our throwing kind by its
        // throwing kind.
        auto savedResult = Result;
        Result = ThrowingKind::None;
        S->getBody()->walk(*this);
        auto boundedResult = std::min(doThrowingKind, Result);
        Result = std::max(savedResult, boundedResult);
      } else {
        // We can skip the catch body, since bounding the result by None is
        // guaranteed to give back None, which leaves our Result unchanged.
      }
    }
  };

  ThrowingKind classifyThrowingFunctionBodyImpl(void *key, BraceStmt *body,
                                                bool allowNone) {
    // Look for the key in the cache.
    auto existingIter = Cache.find(key);
    if (existingIter != Cache.end())
      return existingIter->second;

    // For the purposes of finding a fixed point, consider the
    // function to be rethrowing-only within its body.  Autoclosures
    // aren't recursively referenceable, so their special treatment
    // isn't a problem for this.
    Cache.insert({key, ThrowingKind::RethrowingOnly});

    // Walk the body.
    ThrowingKind result; {
      FunctionBodyClassifier classifier(*this);
      body->walk(classifier);
      result = classifier.Result;
    }

    // The body result cannot be 'none' unless it's an autoclosure.
    if (!allowNone) {
      result = ThrowingKind::RethrowingOnly;
    }

    // Remember the result.
    Cache[key] = result;
    return result;
  }

  /// Classify an argument being passed to a rethrows function.
  Classification classifyRethrowsArgument(Expr *arg, Type paramType) {
    arg = arg->getValueProvidingExpr();

    // If the parameter was structurally a tuple, try to look through the
    // various tuple operations.
    if (auto paramTupleType = dyn_cast<TupleType>(paramType.getPointer())) {
      if (auto tuple = dyn_cast<TupleExpr>(arg)) {
        return classifyTupleRethrowsArgument(tuple, paramTupleType);
      } else if (auto shuffle = dyn_cast<TupleShuffleExpr>(arg)) {
        return classifyShuffleRethrowsArgument(shuffle, paramTupleType);
      }

      if (paramTupleType->getNumElements() != 1) {
        // Otherwise, we're passing an opaque tuple expression, and we
        // should treat it as contributing to 'rethrows' if the original
        // parameter type included a throwing function type.
        return classifyArgumentByType(
                                    paramType,
                                    PotentialReason::forRethrowsArgument(arg));
      }

      // FIXME: There's a case where we can end up with an ApplyExpr that
      // has a single-element-tuple argument type, but the argument is just
      // a ClosureExpr and not a TupleExpr/TupleShuffleExpr.
      paramType = paramTupleType->getElementType(0);
    }

    // Otherwise, if the original parameter type was not a throwing
    // function type, it does not contribute to 'rethrows'.
    auto paramFnType = paramType->lookThroughAllOptionalTypes()->getAs<AnyFunctionType>();
    if (!paramFnType || !paramFnType->throws())
      return Classification();

    PotentialReason reason = PotentialReason::forRethrowsArgument(arg);

    // TODO: partial applications?

    // Decompose the function reference, then consider the type
    // of the decomposed function.
    AbstractFunction fn = AbstractFunction::decomposeFunction(arg);

    // If it doesn't have function type, we must have invalid code.
    Type argType = fn.getType();
    if (!argType) return Classification::forInvalidCode();

    auto argFnType =
        argType->lookThroughAllOptionalTypes()->getAs<AnyFunctionType>();
    if (!argFnType) return Classification::forInvalidCode();

    // If it doesn't throw, this argument does not cause the call to throw.
    if (!argFnType->throws()) return Classification();

    // Otherwise, classify the function implementation.
    return classifyThrowingFunctionBody(fn, reason);
  }

  /// Classify an argument to a 'rethrows' function that's a tuple literal.
  Classification classifyTupleRethrowsArgument(TupleExpr *tuple,
                                               TupleType *paramTupleType) {
    if (paramTupleType->getNumElements() != tuple->getNumElements())
      return Classification::forInvalidCode();

    Classification result;
    for (unsigned i : indices(tuple->getElements())) {
      result.merge(classifyRethrowsArgument(tuple->getElement(i),
                                            paramTupleType->getElementType(i)));
    }
    return result;
  }

  /// Classify an argument to a 'rethrows' function that's a tuple shuffle.
  Classification classifyShuffleRethrowsArgument(TupleShuffleExpr *shuffle,
                                                 TupleType *paramTupleType) {
    auto reversedParamType =
      reverseShuffleParamType(shuffle, paramTupleType);

    // Classify the operand.
    auto result = classifyRethrowsArgument(shuffle->getSubExpr(),
                                           reversedParamType);

    // Check for default arguments in the shuffle.
    for (auto i : indices(shuffle->getElementMapping())) {
      // If this element comes from the sub-expression, we've already
      // analyzed it.  (Variadic arguments also end up here, which is
      // correct for our purposes.)
      auto elt = shuffle->getElementMapping()[i];
      if (elt >= 0) {
        // Ignore.

      // Otherwise, it might come from a default argument.  It still
      // might contribute to 'rethrows', but treat it as an opaque source.
      } else if (elt == TupleShuffleExpr::DefaultInitialize ||
                 elt == TupleShuffleExpr::CallerDefaultInitialize) {
        result.merge(classifyArgumentByType(paramTupleType->getElementType(i),
                                       PotentialReason::forDefaultArgument()));
      }
    }

    return result;
  }

  /// Given a tuple shuffle and an original parameter type, construct
  /// the type of the source of the tuple shuffle preserving as much
  /// information as possible from the original parameter type.
  Type reverseShuffleParamType(TupleShuffleExpr *shuffle,
                               TupleType *origParamTupleType) {
    SmallVector<TupleTypeElt, 4> origSrcElts;
    if (shuffle->isSourceScalar()) {
      origSrcElts.append(1, TupleTypeElt());
    } else {
      auto srcTupleType = shuffle->getSubExpr()->getType()->castTo<TupleType>();
      origSrcElts.append(srcTupleType->getNumElements(), TupleTypeElt());
    }

    auto mapping = shuffle->getElementMapping();
    for (unsigned destIndex = 0; destIndex != mapping.size(); ++destIndex) {
      auto srcIndex = mapping[destIndex];
      if (srcIndex >= 0) {
        origSrcElts[srcIndex] = origParamTupleType->getElement(destIndex);
      } else if (srcIndex == TupleShuffleExpr::DefaultInitialize ||
                 srcIndex == TupleShuffleExpr::CallerDefaultInitialize) {
        // Nothing interesting from the source expression.
      } else if (srcIndex == TupleShuffleExpr::Variadic) {
        // Variadic arguments never contribute to 'rethrows'.
        // Assign the rest of the source elements parameter types that will
        // cause the recursive walker to ignore them.
        for (unsigned srcIndex : shuffle->getVariadicArgs()) {
          assert(srcIndex >= 0 && "default-initialized variadic argument?");
          origSrcElts[srcIndex] =
            origParamTupleType->getASTContext().TheRawPointerType;
        }
      } else {
        llvm_unreachable("bad source-element mapping!");
      }
    }

    if (shuffle->isSourceScalar()) {
      return origSrcElts[0].getType();
    } else {
      return TupleType::get(origSrcElts, origParamTupleType->getASTContext());
    }
  }

  /// Given the type of an argument, try to determine if it contains
  /// a throwing function in a way that is permitted to cause a
  /// 'rethrows' function to throw.
  static Classification classifyArgumentByType(Type paramType,
                                               PotentialReason reason) {
    if (!paramType || paramType->hasError())
      return Classification::forInvalidCode();
    if (auto fnType = paramType->getAs<AnyFunctionType>()) {
      if (fnType->throws()) {
        return Classification::forThrow(reason);
      } else {
        return Classification();
      }
    }
    if (auto tupleType = paramType->getAs<TupleType>()) {
      Classification result;
      for (auto eltType : tupleType->getElementTypes()) {
        result.merge(classifyArgumentByType(eltType, reason));
      }
      return result;
    }

    // No other types include throwing functions for now.
    return Classification();
  }
};

/// An error-handling context.
class Context {
public:
  enum class Kind : uint8_t {
    /// A context that handles errors.
    Handled,

    /// A non-throwing function.
    NonThrowingFunction,

    /// A rethrowing function.
    RethrowingFunction,

    /// A non-throwing autoclosure.
    NonThrowingAutoClosure,

    /// A non-exhaustive catch within a non-throwing function.
    NonExhaustiveCatch,

    /// A default argument expression.
    DefaultArgument,

    /// The initializer for an instance variable.
    IVarInitializer,

    /// The initializer for a global variable.
    GlobalVarInitializer,

    /// The initializer for an enum element.
    EnumElementInitializer,

    /// The pattern of a catch.
    CatchPattern,

    /// The pattern of a catch.
    CatchGuard,
  };

private:
  static Kind getKindForFunctionBody(Type type, unsigned numArgs) {
    switch (classifyFunctionByType(type, numArgs)) {
    case ThrowingKind::None:
      return Kind::NonThrowingFunction;
    case ThrowingKind::Invalid:
    case ThrowingKind::RethrowingOnly:
    case ThrowingKind::Throws:
      return Kind::Handled;
    }
    llvm_unreachable("invalid classify result");
  }

  static Context getContextForPatternBinding(PatternBindingDecl *pbd) {
    if (!pbd->isStatic() && pbd->getDeclContext()->isTypeContext()) {
      return Context(Kind::IVarInitializer);
    } else {
      return Context(Kind::GlobalVarInitializer);
    }
  }

  Kind TheKind;
  bool DiagnoseErrorOnTry = false;
  DeclContext *RethrowsDC = nullptr;
  InterpolatedStringLiteralExpr *InterpolatedString = nullptr;

  explicit Context(Kind kind) : TheKind(kind) {}

public:
  static Context getHandled() {
    return Context(Kind::Handled);
  }

  static Context forTopLevelCode(TopLevelCodeDecl *D) {
    // Top-level code implicitly handles errors.
    return Context(Kind::Handled);
  }

  static Context forFunction(AbstractFunctionDecl *D) {
    if (D->getAttrs().hasAttribute<RethrowsAttr>()) {
      Context result(Kind::RethrowingFunction);
      result.RethrowsDC = D;
      return result;
    }

    // HACK: If the decl is the synthesized getter for a 'lazy' property, then
    // treat the context as a property initializer in order to produce a better
    // diagnostic; the only code we should be diagnosing on is within the
    // initializer expression that has been transplanted from the var's pattern
    // binding decl. We don't perform the analysis on the initializer while it's
    // still a part of that PBD, as it doesn't get a solution applied there.
    if (auto *accessor = dyn_cast<AccessorDecl>(D)) {
      if (auto *var = dyn_cast<VarDecl>(accessor->getStorage())) {
        if (accessor->isGetter() && var->getAttrs().hasAttribute<LazyAttr>()) {
          auto *pbd = var->getParentPatternBinding();
          assert(pbd && "lazy var didn't have a pattern binding decl");
          return getContextForPatternBinding(pbd);
        }
      }
    }

    return Context(getKindForFunctionBody(
        D->getInterfaceType(), D->hasImplicitSelfDecl() ? 2 : 1));
  }

  static Context forInitializer(Initializer *init) {
    if (isa<DefaultArgumentInitializer>(init)) {
      return Context(Kind::DefaultArgument);
    }

    auto *binding = cast<PatternBindingInitializer>(init)->getBinding();
    assert(!binding->getDeclContext()->isLocalContext() &&
           "setting up error context for local pattern binding?");
    return getContextForPatternBinding(binding);
  }

  static Context forEnumElementInitializer(EnumElementDecl *elt) {
    return Context(Kind::EnumElementInitializer);
  }

  static Context forClosure(AbstractClosureExpr *E) {
    auto kind = getKindForFunctionBody(E->getType(), 1);
    if (kind != Kind::Handled && isa<AutoClosureExpr>(E))
      kind = Kind::NonThrowingAutoClosure;
    return Context(kind);
  }

  static Context forNonExhaustiveCatch(DoCatchStmt *S) {
    return Context(Kind::NonExhaustiveCatch);
  }

  static Context forCatchPattern(CatchStmt *S) {
    return Context(Kind::CatchPattern);
  }

  static Context forCatchGuard(CatchStmt *S) {
    return Context(Kind::CatchGuard);
  }

  Context withInterpolatedString(InterpolatedStringLiteralExpr *E) const {
    Context copy = *this;
    copy.InterpolatedString = E;
    return copy;
  }

  Kind getKind() const { return TheKind; }

  bool handlesNothing() const {
    return getKind() != Kind::Handled &&
           getKind() != Kind::RethrowingFunction;
  }
  bool handles(ThrowingKind errorKind) const {
    switch (errorKind) {
    case ThrowingKind::None:
    case ThrowingKind::Invalid:
      return true;

    // A call that's rethrowing-only can be handled by 'rethrows'.
    case ThrowingKind::RethrowingOnly:
      return !handlesNothing();

    // An operation that always throws can only be handled by an
    // all-handling context.
    case ThrowingKind::Throws:
      return getKind() == Kind::Handled;
    }
    llvm_unreachable("bad error kind");
  }

  DeclContext *getRethrowsDC() const { return RethrowsDC; }
  InterpolatedStringLiteralExpr * getInterpolatedString() const {
    return InterpolatedString;
  }

  static void diagnoseThrowInIllegalContext(TypeChecker &TC, ASTNode node,
                                            StringRef description) {
    if (auto *e = node.dyn_cast<Expr*>())
      if (isa<ApplyExpr>(e)) {
        TC.diagnose(e->getLoc(), diag::throwing_call_in_illegal_context,
                    description);
        return;
      }
    TC.diagnose(node.getStartLoc(), diag::throw_in_illegal_context,
                description);
  }

  static void maybeAddRethrowsNote(TypeChecker &TC, SourceLoc loc,
                                   const PotentialReason &reason) {
    switch (reason.getKind()) {
    case PotentialReason::Kind::Throw:
      llvm_unreachable("should already have been covered");
    case PotentialReason::Kind::CallThrows:
      // Already fully diagnosed.
      return;
    case PotentialReason::Kind::CallRethrowsWithExplicitThrowingArgument:
      TC.diagnose(reason.getThrowingArgument()->getLoc(),
                  diag::because_rethrows_argument_throws);
      return;
    case PotentialReason::Kind::CallRethrowsWithDefaultThrowingArgument:
      TC.diagnose(loc, diag::because_rethrows_default_argument_throws);
      return;
    }
    llvm_unreachable("bad reason kind");
  }

  void diagnoseUncoveredThrowSite(TypeChecker &TC, ASTNode E,
                                  const PotentialReason &reason) {
    auto message = diag::throwing_call_without_try;
    auto loc = E.getStartLoc();
    SourceLoc insertLoc;
    SourceRange highlight;
    
    // Generate more specific messages in some cases.
    if (auto e = dyn_cast_or_null<ApplyExpr>(E.dyn_cast<Expr*>())) {
      if (isa<PrefixUnaryExpr>(e) || isa<PostfixUnaryExpr>(e) ||
          isa<BinaryExpr>(e)) {
        loc = e->getFn()->getStartLoc();
        message = diag::throwing_operator_without_try;
      }
      insertLoc = loc;
      highlight = e->getSourceRange();
      
      if (InterpolatedString &&
          e->getCalledValue() &&
          e->getCalledValue()->getBaseName() ==
          TC.Context.Id_appendInterpolation) {
        message = diag::throwing_interpolation_without_try;
        insertLoc = InterpolatedString->getLoc();
      }
    }
    
    TC.diagnose(loc, message).highlight(highlight);
    maybeAddRethrowsNote(TC, loc, reason);

    // If this is a call without expected 'try[?|!]', like this:
    //
    // func foo() throws {}
    // [let _ = ]foo()
    //
    // Let's suggest couple of alternative fix-its
    // because complete context is unavailable.
    if (reason.getKind() != PotentialReason::Kind::CallThrows)
      return;

    TC.diagnose(loc, diag::note_forgot_try)
        .fixItInsert(insertLoc, "try ");
    TC.diagnose(loc, diag::note_error_to_optional)
        .fixItInsert(insertLoc, "try? ");
    TC.diagnose(loc, diag::note_disable_error_propagation)
        .fixItInsert(insertLoc, "try! ");
  }

  void diagnoseThrowInLegalContext(TypeChecker &TC, ASTNode node,
                                   bool isTryCovered,
                                   const PotentialReason &reason,
                                   Diag<> diagForThrow,
                                   Diag<> diagForThrowingCall,
                                   Diag<> diagForTrylessThrowingCall) {
    auto loc = node.getStartLoc();
    if (reason.isThrow()) {
      TC.diagnose(loc, diagForThrow);
      return;
    }

    // Allow the diagnostic to fire on the 'try' if we don't have
    // anything else to say.
    if (isTryCovered && !reason.isRethrowsCall() &&
        (getKind() == Kind::NonThrowingFunction ||
         getKind() == Kind::NonExhaustiveCatch)) {
      DiagnoseErrorOnTry = true;
      return;
    }

    if (isTryCovered) {
      TC.diagnose(loc, diagForThrowingCall);
    } else {
      TC.diagnose(loc, diagForTrylessThrowingCall);
    }
    maybeAddRethrowsNote(TC, loc, reason);
  }

  void diagnoseUnhandledThrowSite(TypeChecker &TC, ASTNode E, bool isTryCovered,
                                  const PotentialReason &reason) {
    switch (getKind()) {
    case Kind::Handled:
      llvm_unreachable("throw site is handled!");

    // TODO: Doug suggested that we could generate one error per
    // non-throwing function with throw sites within it, possibly with
    // notes for the throw sites.

    case Kind::RethrowingFunction:
      diagnoseThrowInLegalContext(TC, E, isTryCovered, reason,
                                  diag::throw_in_rethrows_function,
                                  diag::throwing_call_in_rethrows_function,
                          diag::tryless_throwing_call_in_rethrows_function);
      return;

    case Kind::NonThrowingFunction:
      diagnoseThrowInLegalContext(TC, E, isTryCovered, reason,
                                  diag::throw_in_nonthrowing_function,
                                  diag::throwing_call_unhandled,
                                  diag::tryless_throwing_call_unhandled);
      return;

    case Kind::NonThrowingAutoClosure:
      diagnoseThrowInLegalContext(TC, E, isTryCovered, reason,
                                  diag::throw_in_nonthrowing_autoclosure,
                            diag::throwing_call_in_nonthrowing_autoclosure,
                    diag::tryless_throwing_call_in_nonthrowing_autoclosure);
      return;

    case Kind::NonExhaustiveCatch:
      diagnoseThrowInLegalContext(TC, E, isTryCovered, reason,
                                  diag::throw_in_nonexhaustive_catch,
                                  diag::throwing_call_in_nonexhaustive_catch,
                          diag::tryless_throwing_call_in_nonexhaustive_catch);
      return;

    case Kind::EnumElementInitializer:
      diagnoseThrowInIllegalContext(TC, E, "an enum case raw value");
      return;

    case Kind::GlobalVarInitializer:
      diagnoseThrowInIllegalContext(TC, E, "a global variable initializer");
      return;

    case Kind::IVarInitializer:
      diagnoseThrowInIllegalContext(TC, E, "a property initializer");
      return;

    case Kind::DefaultArgument:
      diagnoseThrowInIllegalContext(TC, E, "a default argument");
      return;

    case Kind::CatchPattern:
      diagnoseThrowInIllegalContext(TC, E, "a catch pattern");
      return;

    case Kind::CatchGuard:
      diagnoseThrowInIllegalContext(TC, E, "a catch guard expression");
      return;
    }
    llvm_unreachable("bad context kind");
  }

  void diagnoseUnhandledTry(TypeChecker &TC, TryExpr *E) {
    switch (getKind()) {
    case Kind::Handled:
    case Kind::RethrowingFunction:
      llvm_unreachable("try is handled!");

    case Kind::NonThrowingFunction:
      if (DiagnoseErrorOnTry)
        TC.diagnose(E->getTryLoc(), diag::try_unhandled);
      return;

    case Kind::NonExhaustiveCatch:
      if (DiagnoseErrorOnTry)
        TC.diagnose(E->getTryLoc(), diag::try_unhandled_in_nonexhaustive_catch);
      return;

    case Kind::NonThrowingAutoClosure:
    case Kind::EnumElementInitializer:
    case Kind::GlobalVarInitializer:
    case Kind::IVarInitializer:
    case Kind::DefaultArgument:
    case Kind::CatchPattern:
    case Kind::CatchGuard:
      assert(!DiagnoseErrorOnTry);
      // Diagnosed at the call sites.
      return;
    }
    llvm_unreachable("bad context kind");
  }
};

/// A class to walk over a local context and validate the correctness
/// of its error coverage.
class CheckErrorCoverage : public ErrorHandlingWalker<CheckErrorCoverage> {
  friend class ErrorHandlingWalker<CheckErrorCoverage>;

  TypeChecker &TC;

  ApplyClassifier Classifier;

  Context CurContext;

  class ContextFlags {
  public:
    enum ContextFlag : unsigned {
      /// Is the current context considered 'try'-covered?
      IsTryCovered = 0x1,

      /// Is the current context within a 'try' expression?
      IsInTry = 0x2,

      /// Is the current context top-level in a debugger function?  This
      /// causes 'try' suppression to apply recursively within a single
      /// level of do/catch.
      IsTopLevelDebuggerFunction = 0x4,

      /// Do we have any throw site in this context?
      HasAnyThrowSite = 0x8,

      /// Do we have a throw site using 'try' in this context?
      HasTryThrowSite = 0x10,
    };
  private:
    unsigned Bits;
  public:
    ContextFlags() : Bits(0) {}

    void reset() { Bits = 0; }
    bool has(ContextFlag flag) const { return Bits & flag; }
    void set(ContextFlag flag) { Bits |= flag; }
    void clear(ContextFlag flag) { Bits &= ~flag; }
    void mergeFrom(ContextFlag flag, ContextFlags other) {
      Bits |= (other.Bits & flag);
    }
  };

  ContextFlags Flags;

  /// The maximum combined value of all throwing expressions in the current
  /// context.
  ThrowingKind MaxThrowingKind;

  void flagInvalidCode() {
    // Suppress warnings about useless try or catch.
    Flags.set(ContextFlags::HasAnyThrowSite);
    Flags.set(ContextFlags::HasTryThrowSite);
  }

  /// An RAII object for restoring all the interesting state in an
  /// error-coverage.
  class ContextScope {
    CheckErrorCoverage &Self;
    Context OldContext;
    DeclContext *OldRethrowsDC;
    ContextFlags OldFlags;
    ThrowingKind OldMaxThrowingKind;
  public:
    ContextScope(CheckErrorCoverage &self, Optional<Context> newContext)
      : Self(self), OldContext(self.CurContext),
        OldRethrowsDC(self.Classifier.RethrowsDC),
        OldFlags(self.Flags),
        OldMaxThrowingKind(self.MaxThrowingKind) {
      if (newContext) self.CurContext = *newContext;
    }

    ContextScope(const ContextScope &) = delete;
    ContextScope &operator=(const ContextScope &) = delete;

    void enterSubFunction() {
      Self.Classifier.RethrowsDC = nullptr;
    }

    void enterTry() {
      Self.Flags.set(ContextFlags::IsInTry);
      Self.Flags.set(ContextFlags::IsTryCovered);
      Self.Flags.clear(ContextFlags::HasTryThrowSite);
    }

    void refineLocalContext(Context newContext) {
      Self.CurContext = newContext;
    }

    void resetCoverage() {
      Self.Flags.reset();
      Self.MaxThrowingKind = ThrowingKind::None;
    }

    void resetCoverageForDoCatch() {
      Self.Flags.reset();
      Self.MaxThrowingKind = ThrowingKind::None;

      // Suppress 'try' coverage checking within a single level of
      // do/catch in debugger functions.
      if (OldFlags.has(ContextFlags::IsTopLevelDebuggerFunction))
        Self.Flags.set(ContextFlags::IsTryCovered);
    }

    void preserveCoverageFromAutoclosureBody() {
      // An autoclosure body is the part of the enclosing function
      // body for the purposes of deciding whether a try contained
      // a throwing call.
      OldFlags.mergeFrom(ContextFlags::HasTryThrowSite, Self.Flags);
    }

    void preserveCoverageFromNonExhaustiveCatch() {
      OldFlags.mergeFrom(ContextFlags::HasAnyThrowSite, Self.Flags);
      OldMaxThrowingKind = std::max(OldMaxThrowingKind, Self.MaxThrowingKind);
    }

    void preserveCoverageFromTryOperand() {
      OldFlags.mergeFrom(ContextFlags::HasAnyThrowSite, Self.Flags);
      OldMaxThrowingKind = std::max(OldMaxThrowingKind, Self.MaxThrowingKind);
    }

    void preserveCoverageFromInterpolatedString() {
      OldFlags.mergeFrom(ContextFlags::HasAnyThrowSite, Self.Flags);
      OldFlags.mergeFrom(ContextFlags::HasTryThrowSite, Self.Flags);
      OldMaxThrowingKind = std::max(OldMaxThrowingKind, Self.MaxThrowingKind);
    }
    
    bool wasTopLevelDebuggerFunction() const {
      return OldFlags.has(ContextFlags::IsTopLevelDebuggerFunction);
    }

    ~ContextScope() {
      Self.CurContext = OldContext;
      Self.Classifier.RethrowsDC = OldRethrowsDC;
      Self.Flags = OldFlags;
      Self.MaxThrowingKind = OldMaxThrowingKind;
    }
  };

public:
  CheckErrorCoverage(TypeChecker &tc, Context initialContext)
    : TC(tc), CurContext(initialContext),
      MaxThrowingKind(ThrowingKind::None) {

    if (auto rethrowsDC = initialContext.getRethrowsDC()) {
      Classifier.RethrowsDC = rethrowsDC;
    }
  }

  /// Mark that the current context is top-level code with
  /// throw-without-try enabled.
  void setTopLevelThrowWithoutTry() {
    Flags.set(ContextFlags::IsTryCovered);
  }

  /// Mark that the current context is covered by a 'try', as
  /// appropriate for a debugger function.
  ///
  /// Top level code in the debugger is actually implicitly wrapped in
  /// a function with a do/catch block.
  void setTopLevelDebuggerFunction() {
    Flags.set(ContextFlags::IsTryCovered);
    Flags.set(ContextFlags::IsTopLevelDebuggerFunction);
  }

private:
  ShouldRecurse_t checkClosure(ClosureExpr *E) {
    ContextScope scope(*this, Context::forClosure(E));
    scope.enterSubFunction();
    scope.resetCoverage();
    E->getBody()->walk(*this);
    return ShouldNotRecurse;
  }

  ShouldRecurse_t checkAutoClosure(AutoClosureExpr *E) {
    ContextScope scope(*this, Context::forClosure(E));
    scope.enterSubFunction();
    E->getBody()->walk(*this);
    scope.preserveCoverageFromAutoclosureBody();
    return ShouldNotRecurse;
  }

  ThrowingKind checkExhaustiveDoBody(DoCatchStmt *S) {
    // This is a handled context.
    ContextScope scope(*this, Context::getHandled());
    assert(!Flags.has(ContextFlags::IsInTry) && "do/catch within try?");
    scope.resetCoverageForDoCatch();

    S->getBody()->walk(*this);

    diagnoseNoThrowInDo(S, scope);

    return MaxThrowingKind;
  }

  ThrowingKind checkNonExhaustiveDoBody(DoCatchStmt *S) {
    ContextScope scope(*this, None);
    assert(!Flags.has(ContextFlags::IsInTry) && "do/catch within try?");
    scope.resetCoverageForDoCatch();

    // If the enclosing context doesn't handle anything, use a
    // specialized diagnostic about non-exhaustive catches.
    if (CurContext.handlesNothing()) {
      scope.refineLocalContext(Context::forNonExhaustiveCatch(S));
    }

    S->getBody()->walk(*this);

    diagnoseNoThrowInDo(S, scope);

    scope.preserveCoverageFromNonExhaustiveCatch();
    return MaxThrowingKind;
  }

  void diagnoseNoThrowInDo(DoCatchStmt *S, ContextScope &scope) {
    // Warn if nothing threw within the body, unless this is the
    // implicit do/catch in a debugger function.
    if (!Flags.has(ContextFlags::HasAnyThrowSite) &&
        !scope.wasTopLevelDebuggerFunction()) {
      TC.diagnose(S->getCatches().front()->getCatchLoc(),
                  diag::no_throw_in_do_with_catch);
    }
  }

  void checkCatch(CatchStmt *S, ThrowingKind doThrowingKind) {
    // The pattern and guard aren't allowed to throw.
    {
      ContextScope scope(*this, Context::forCatchPattern(S));
      S->getErrorPattern()->walk(*this);
    }
    if (auto guard = S->getGuardExpr()) {
      ContextScope scope(*this, Context::forCatchGuard(S));
      guard->walk(*this);
    }

    auto savedContext = CurContext;
    if (doThrowingKind != ThrowingKind::Throws &&
        CurContext.getKind() == Context::Kind::RethrowingFunction) {
      // If this catch clause is reachable at all, it's because a function
      // parameter throws. So let's temporarily set our context to Handled so
      // the catch body is allowed to throw.
      CurContext = Context::getHandled();
    }

    // The catch body just happens in the enclosing context.
    S->getBody()->walk(*this);

    CurContext = savedContext;
  }

  ShouldRecurse_t checkApply(ApplyExpr *E) {
    // An apply expression is a potential throw site if the function throws.
    // But if the expression didn't type-check, suppress diagnostics.
    auto classification = Classifier.classifyApply(E);

    checkThrowSite(E, /*requiresTry*/ true, classification);

    // HACK: functions can get queued multiple times in
    // definedFunctions, so be sure to be idempotent.
    if (!E->isThrowsSet() &&
        classification.getResult() != ThrowingKind::Invalid) {
      E->setThrows(classification.getResult() == ThrowingKind::RethrowingOnly ||
                   classification.getResult() == ThrowingKind::Throws);
    }

    // If current apply expression did not type-check, don't attempt
    // walking inside of it. This accounts for the fact that we don't
    // erase types without type variables to enable better code complication,
    // so DeclRefExpr(s) or ApplyExpr with DeclRefExpr as function contained
    // inside would have their types preserved, which makes classification
    // incorrect.
    auto type = E->getType();
    return !type || type->hasError() ? ShouldNotRecurse : ShouldRecurse;
  }

  ShouldRecurse_t
  checkInterpolatedStringLiteral(InterpolatedStringLiteralExpr *E) {
    ContextScope scope(*this, CurContext.withInterpolatedString(E));
    if (E->getSemanticExpr())
      E->getSemanticExpr()->walk(*this);
    scope.preserveCoverageFromInterpolatedString();
    return ShouldNotRecurse;
  }

  ShouldRecurse_t checkIfConfig(IfConfigDecl *ICD) {
    // Check the inactive regions of a #if block to disable warnings that may
    // be due to platform specific code.
    struct ConservativeThrowChecker : public ASTWalker {
      CheckErrorCoverage &CEC;
      ConservativeThrowChecker(CheckErrorCoverage &CEC) : CEC(CEC) {}
      
      Expr *walkToExprPost(Expr *E) override {
        if (isa<TryExpr>(E))
          CEC.Flags.set(ContextFlags::HasAnyThrowSite);
        return E;
      }
      
      Stmt *walkToStmtPost(Stmt *S) override {
        if (isa<ThrowStmt>(S))
          CEC.Flags.set(ContextFlags::HasAnyThrowSite);

        return S;
      }
    };

    for (auto &clause : ICD->getClauses()) {
      // Active clauses are handled by the normal AST walk.
      if (clause.isActive) continue;
      
      for (auto elt : clause.Elements)
        elt.walk(ConservativeThrowChecker(*this));
    }
    return ShouldRecurse;
  }

  ShouldRecurse_t checkThrow(ThrowStmt *S) {
    checkThrowSite(S, /*requiresTry*/ false,
                   Classification::forThrow(PotentialReason::forThrow()));
    return ShouldRecurse;
  }

  void checkThrowSite(ASTNode E, bool requiresTry,
                      const Classification &classification) {
    MaxThrowingKind = std::max(MaxThrowingKind, classification.getResult());

    switch (classification.getResult()) {
    // Completely ignores sites that don't throw.
    case ThrowingKind::None:
      return;

    // Suppress all diagnostics when there's an un-analyzable throw site.
    case ThrowingKind::Invalid:
      Flags.set(ContextFlags::HasAnyThrowSite);
      if (requiresTry) Flags.set(ContextFlags::HasTryThrowSite);
      return;

    // For the purposes of handling and try-coverage diagnostics,
    // being rethrowing-only still makes this a throw site.
    case ThrowingKind::RethrowingOnly:
    case ThrowingKind::Throws:
      Flags.set(ContextFlags::HasAnyThrowSite);
      if (requiresTry) Flags.set(ContextFlags::HasTryThrowSite);

      // We set the throwing bit of an apply expr after performing this
      // analysis, so ensure we don't emit duplicate diagnostics for functions
      // that have been queued multiple times.
      if (auto expr = E.dyn_cast<Expr*>())
        if (auto apply = dyn_cast<ApplyExpr>(expr))
          if (apply->isThrowsSet())
            return;

      bool isTryCovered =
        (!requiresTry || Flags.has(ContextFlags::IsTryCovered));
      if (!CurContext.handles(classification.getResult())) {
        CurContext.diagnoseUnhandledThrowSite(TC, E, isTryCovered,
                                              classification.getThrowsReason());
      } else if (!isTryCovered) {
        CurContext.diagnoseUncoveredThrowSite(TC, E,
                                              classification.getThrowsReason());
      }
      return;
    }
    llvm_unreachable("bad throwing kind");
  }

  ShouldRecurse_t checkTry(TryExpr *E) {
    // Walk the operand.
    ContextScope scope(*this, None);
    scope.enterTry();

    E->getSubExpr()->walk(*this);

    // Warn about 'try' expressions that weren't actually needed.
    if (!Flags.has(ContextFlags::HasTryThrowSite)) {
      if (!E->isImplicit())
        TC.diagnose(E->getTryLoc(), diag::no_throw_in_try);

    // Diagnose all the call sites within a single unhandled 'try'
    // at the same time.
    } else if (CurContext.handlesNothing()) {
      CurContext.diagnoseUnhandledTry(TC, E);
    }

    scope.preserveCoverageFromTryOperand();
    return ShouldNotRecurse;
  }

  ShouldRecurse_t checkForceTry(ForceTryExpr *E) {
    // Walk the operand.  'try!' handles errors.
    ContextScope scope(*this, Context::getHandled());
    scope.enterTry();

    E->getSubExpr()->walk(*this);

    // Warn about 'try' expressions that weren't actually needed.
    if (!Flags.has(ContextFlags::HasTryThrowSite)) {
      TC.diagnose(E->getLoc(), diag::no_throw_in_try);
    }
    return ShouldNotRecurse;
  }

  ShouldRecurse_t checkOptionalTry(OptionalTryExpr *E) {
    // Walk the operand.  'try?' handles errors.
    ContextScope scope(*this, Context::getHandled());
    scope.enterTry();

    E->getSubExpr()->walk(*this);

    // Warn about 'try' expressions that weren't actually needed.
    if (!Flags.has(ContextFlags::HasTryThrowSite)) {
      TC.diagnose(E->getLoc(), diag::no_throw_in_try);
    }
    return ShouldNotRecurse;
  }
};

} // end anonymous namespace

void TypeChecker::checkTopLevelErrorHandling(TopLevelCodeDecl *code) {
  CheckErrorCoverage checker(*this, Context::forTopLevelCode(code));

  // In some language modes, we allow top-level code to omit 'try' marking.
  if (Context.LangOpts.EnableThrowWithoutTry)
    checker.setTopLevelThrowWithoutTry();

  code->getBody()->walk(checker);
}

void TypeChecker::checkFunctionErrorHandling(AbstractFunctionDecl *fn) {
  // In some cases, we won't have validated the signature
  // by the time we got here.
  if (!fn->hasInterfaceType()) return;

#ifndef NDEBUG
  PrettyStackTraceDecl debugStack("checking error handling for", fn);
#endif

  CheckErrorCoverage checker(*this, Context::forFunction(fn));

  // If this is a debugger function, suppress 'try' marking at the top level.
  if (fn->getAttrs().hasAttribute<LLDBDebuggerFunctionAttr>())
    checker.setTopLevelDebuggerFunction();

  if (auto body = fn->getBody()) {
    body->walk(checker);
  }
  if (auto ctor = dyn_cast<ConstructorDecl>(fn))
    if (auto superInit = ctor->getSuperInitCall())
      superInit->walk(checker);
}

void TypeChecker::checkInitializerErrorHandling(Initializer *initCtx,
                                                Expr *init) {
  CheckErrorCoverage checker(*this, Context::forInitializer(initCtx));
  init->walk(checker);
}

/// Check the correctness of error handling within the given enum
/// element's raw value expression.
///
/// The syntactic restrictions on such expressions should make it
/// impossible for errors to ever arise, but checking them anyway (1)
/// ensures correctness if those restrictions are ever loosened,
/// perhaps accidentally, and (2) allows the verifier to assert that
/// all calls have been checked.
void TypeChecker::checkEnumElementErrorHandling(EnumElementDecl *elt) {
  if (auto init = elt->getTypeCheckedRawValueExpr()) {
    CheckErrorCoverage checker(*this, Context::forEnumElementInitializer(elt));
    init->walk(checker);
  }
}
