//===--- TypeCheckOverride.cpp - Override Checking ------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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 for declaration overrides.
//
//===----------------------------------------------------------------------===//
#include "MiscDiagnostics.h"
#include "TypeCheckAvailability.h"
#include "TypeCheckDecl.h"
#include "TypeCheckObjC.h"
#include "TypeChecker.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/Availability.h"
#include "swift/AST/Decl.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/NameLookupRequests.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/TypeCheckRequests.h"
using namespace swift;

static void adjustFunctionTypeForOverride(Type &type) {
  // Drop 'throws'.
  // FIXME: Do we want to allow overriding a function returning a value
  // with one returning Never?
  auto fnType = type->castTo<AnyFunctionType>();
  auto extInfo = fnType->getExtInfo();
  extInfo = extInfo.withThrows(false);
  if (fnType->getExtInfo() != extInfo)
    type = fnType->withExtInfo(extInfo);
}

/// Drop the optionality of the result type of the given function type.
static Type dropResultOptionality(Type type, unsigned uncurryLevel) {
  // We've hit the result type.
  if (uncurryLevel == 0) {
    if (auto objectTy = type->getOptionalObjectType())
      return objectTy;

    return type;
  }

  // Determine the input and result types of this function.
  auto fnType = type->castTo<AnyFunctionType>();
  auto parameters = fnType->getParams();
  Type resultType =
      dropResultOptionality(fnType->getResult(), uncurryLevel - 1);

  // Produce the resulting function type.
  if (auto genericFn = dyn_cast<GenericFunctionType>(fnType)) {
    return GenericFunctionType::get(genericFn->getGenericSignature(),
                                    parameters, resultType,
                                    fnType->getExtInfo());
  }

  return FunctionType::get(parameters, resultType, fnType->getExtInfo());
}

Type swift::getMemberTypeForComparison(ASTContext &ctx, ValueDecl *member,
                                       ValueDecl *derivedDecl) {
  auto *method = dyn_cast<AbstractFunctionDecl>(member);
  ConstructorDecl *ctor = nullptr;
  if (method)
    ctor = dyn_cast<ConstructorDecl>(method);

  auto abstractStorage = dyn_cast<AbstractStorageDecl>(member);
  assert((method || abstractStorage) && "Not a method or abstractStorage?");
  SubscriptDecl *subscript = dyn_cast_or_null<SubscriptDecl>(abstractStorage);

  auto memberType = member->getInterfaceType();
  if (derivedDecl) {
    auto *dc = derivedDecl->getDeclContext();
    auto owningType = dc->getDeclaredInterfaceType();
    assert(owningType);

    memberType = owningType->adjustSuperclassMemberDeclType(member, derivedDecl,
                                                            memberType);
    if (memberType->hasError())
      return memberType;
  }

  if (method) {
    // For methods, strip off the 'Self' type.
    memberType = memberType->castTo<AnyFunctionType>()->getResult();
    adjustFunctionTypeForOverride(memberType);
  } else if (subscript) {
    // For subscripts, we don't have a 'Self' type, but turn it
    // into a monomorphic function type.
    auto funcTy = memberType->castTo<AnyFunctionType>();
    memberType = FunctionType::get(funcTy->getParams(), funcTy->getResult());
  } else {
    // For properties, strip off ownership.
    memberType = memberType->getReferenceStorageReferent();
  }

  // Ignore the optionality of initializers when comparing types;
  // we'll enforce this separately
  if (ctor) {
    memberType = dropResultOptionality(memberType, 1);
  }

  return memberType;
}

static bool areAccessorsOverrideCompatible(AbstractStorageDecl *storage,
                                           AbstractStorageDecl *parentStorage) {
  // It's okay for the storage to disagree about whether to use a getter or
  // a read accessor; we'll patch up any differences when setting overrides
  // for the accessors.  We don't want to diagnose anything involving
  // `@_borrowed` because it is not yet part of the language.

  // All the other checks are for non-static storage only.
  if (storage->isStatic())
    return true;

  // The storage must agree on whether reads are mutating.  For accessors,
  // this is sufficient to imply that they use the same SelfAccessKind
  // because we do not allow accessors to be consuming.
  if (storage->isGetterMutating() != parentStorage->isGetterMutating())
    return false;

  // We allow covariance about whether the storage itself is mutable, so we
  // can only check mutating-ness of setters if both have one.
  if (storage->supportsMutation() && parentStorage->supportsMutation()) {
    // The storage must agree on whether writes are mutating.
    if (storage->isSetterMutating() != parentStorage->isSetterMutating())
      return false;

    // Those together should imply that read-write accesses have the same
    // mutability.
  }

  return true;
}

bool swift::isOverrideBasedOnType(ValueDecl *decl, Type declTy,
                                  ValueDecl *parentDecl, Type parentDeclTy) {
  auto genericSig =
      decl->getInnermostDeclContext()->getGenericSignatureOfContext();

  auto canDeclTy = declTy->getCanonicalType(genericSig);
  auto canParentDeclTy = parentDeclTy->getCanonicalType(genericSig);

  auto declIUOAttr = decl->isImplicitlyUnwrappedOptional();
  auto parentDeclIUOAttr = parentDecl->isImplicitlyUnwrappedOptional();

  if (declIUOAttr != parentDeclIUOAttr)
    return false;

  // If the generic signatures don't match, then return false because we don't
  // want to complain if an overridden method matches multiple superclass
  // methods which differ in generic signature.
  //
  // We can still succeed with a subtype match later in
  // OverrideMatcher::match().
  auto declGenericCtx = decl->getAsGenericContext();
  auto &ctx = decl->getASTContext();
  auto sig = ctx.getOverrideGenericSignature(parentDecl, decl);

  if (sig && declGenericCtx &&
      declGenericCtx->getGenericSignature()->getCanonicalSignature() !=
          sig->getCanonicalSignature()) {
    return false;
  }

  // If this is a constructor, let's compare only parameter types.
  if (isa<ConstructorDecl>(decl)) {
    // Within a protocol context, check for a failability mismatch.
    if (isa<ProtocolDecl>(decl->getDeclContext())) {
      if (cast<ConstructorDecl>(decl)->isFailable() !=
          cast<ConstructorDecl>(parentDecl)->isFailable())
        return false;
      if (cast<ConstructorDecl>(decl)->isImplicitlyUnwrappedOptional() !=
          cast<ConstructorDecl>(parentDecl)->isImplicitlyUnwrappedOptional())
        return false;
    }

    auto fnType1 = declTy->castTo<AnyFunctionType>();
    auto fnType2 = parentDeclTy->castTo<AnyFunctionType>();
    return AnyFunctionType::equalParams(fnType1->getParams(),
                                        fnType2->getParams());

  // In a non-static protocol requirement, verify that the self access kind
  // matches.
  } else if (auto func = dyn_cast<FuncDecl>(decl)) {
    // We only compare `isMutating()` rather than `getSelfAccessKind()`
    // because we don't want to complain about `nonmutating` vs. `__consuming`
    // conflicts at this time, especially since `__consuming` is not yet
    // officially part of the language.
    if (!func->isStatic() &&
        func->isMutating() != cast<FuncDecl>(parentDecl)->isMutating())
      return false;

  // In abstract storage, verify that the accessor mutating-ness matches.
  } else if (auto storage = dyn_cast<AbstractStorageDecl>(decl)) {
    auto parentStorage = cast<AbstractStorageDecl>(parentDecl);
    if (!areAccessorsOverrideCompatible(storage, parentStorage))
      return false;
  }

  return canDeclTy == canParentDeclTy;
}

/// Perform basic checking to determine whether a declaration can override a
/// declaration in a superclass.
static bool areOverrideCompatibleSimple(ValueDecl *decl,
                                        ValueDecl *parentDecl) {
  // If the number of argument labels does not match, these overrides cannot
  // be compatible.
  if (decl->getFullName().getArgumentNames().size() !=
        parentDecl->getFullName().getArgumentNames().size())
    return false;

  // If the parent declaration is not in a class (or extension thereof) or
  // a protocol, we cannot override it.
  if (decl->getDeclContext()->getSelfClassDecl() &&
      parentDecl->getDeclContext()->getSelfClassDecl()) {
    // Okay: class override
  } else if (isa<ProtocolDecl>(decl->getDeclContext()) &&
             isa<ProtocolDecl>(parentDecl->getDeclContext())) {
    // Okay: protocol override.
  } else {
    // Cannot be an override.
    return false;
  }

  // The declarations must be of the same kind.
  if (decl->getKind() != parentDecl->getKind())
    return false;

  // Ignore invalid parent declarations.
  // FIXME: Do we really need this?
  if (parentDecl->isInvalid())
    return false;

  // If their staticness is different, they aren't compatible.
  if (decl->isStatic() != parentDecl->isStatic())
    return false;

  // If their genericity is different, they aren't compatible.
  if (auto genDecl = decl->getAsGenericContext()) {
    auto genParentDecl = parentDecl->getAsGenericContext();
    if (genDecl->isGeneric() != genParentDecl->isGeneric())
      return false;
  }

  // Factory initializers cannot be overridden.
  if (auto parentCtor = dyn_cast<ConstructorDecl>(parentDecl))
    if (parentCtor->isFactoryInit())
      return false;

  return true;
}

static bool
diagnoseMismatchedOptionals(const ValueDecl *member,
                            const ParameterList *params, TypeLoc resultTL,
                            const ValueDecl *parentMember,
                            const ParameterList *parentParams, Type owningTy,
                            bool treatIUOResultAsError) {
  auto &diags = member->getASTContext().Diags;

  bool emittedError = false;
  Type plainParentTy = owningTy->adjustSuperclassMemberDeclType(
      parentMember, member, parentMember->getInterfaceType());
  const auto *parentTy = plainParentTy->castTo<FunctionType>();
  if (isa<AbstractFunctionDecl>(parentMember))
    parentTy = parentTy->getResult()->castTo<FunctionType>();

  // Check the parameter types.
  auto checkParam = [&](const ParamDecl *decl, const ParamDecl *parentDecl) {
    Type paramTy = decl->getType();
    Type parentParamTy = parentDecl->getType();

    if (!paramTy || !parentParamTy)
      return;

    auto *repr = decl->getTypeRepr();
    if (!repr)
      return;

    bool paramIsOptional =  (bool) paramTy->getOptionalObjectType();
    bool parentIsOptional = (bool) parentParamTy->getOptionalObjectType();

    if (paramIsOptional == parentIsOptional)
      return;

    if (!paramIsOptional) {
      if (parentDecl->isImplicitlyUnwrappedOptional())
        if (!treatIUOResultAsError)
          return;

      emittedError = true;
      auto diag = diags.diagnose(decl->getStartLoc(),
                                 diag::override_optional_mismatch,
                                 member->getDescriptiveKind(),
                                 isa<SubscriptDecl>(member),
                                 parentParamTy, paramTy);
      if (repr->isSimple()) {
        diag.fixItInsertAfter(repr->getEndLoc(), "?");
      } else {
        diag.fixItInsert(repr->getStartLoc(), "(");
        diag.fixItInsertAfter(repr->getEndLoc(), ")?");
      }
      return;
    }

    if (!decl->isImplicitlyUnwrappedOptional())
      return;

    // Allow silencing this warning using parens.
    if (paramTy->hasParenSugar())
      return;

    diags
        .diagnose(decl->getStartLoc(), diag::override_unnecessary_IUO,
                  member->getDescriptiveKind(), parentParamTy, paramTy)
        .highlight(repr->getSourceRange());

    if (auto iuoRepr = dyn_cast<ImplicitlyUnwrappedOptionalTypeRepr>(repr)) {
      diags
          .diagnose(iuoRepr->getExclamationLoc(),
                    diag::override_unnecessary_IUO_remove)
          .fixItRemove(iuoRepr->getExclamationLoc());
    }

    diags.diagnose(repr->getStartLoc(), diag::override_unnecessary_IUO_silence)
        .fixItInsert(repr->getStartLoc(), "(")
        .fixItInsertAfter(repr->getEndLoc(), ")");
  };

  // FIXME: If we ever allow argument reordering, this is incorrect.
  ArrayRef<ParamDecl *> sharedParams = params->getArray();
  ArrayRef<ParamDecl *> sharedParentParams = parentParams->getArray();
  assert(sharedParams.size() == sharedParentParams.size());
  for_each(sharedParams, sharedParentParams, checkParam);

  if (!resultTL.getTypeRepr())
    return emittedError;

  auto checkResult = [&](TypeLoc resultTL, Type parentResultTy) {
    Type resultTy = resultTL.getType();
    if (!resultTy || !parentResultTy)
      return;

    if (!resultTy->getOptionalObjectType())
      return;

    TypeRepr *TR = resultTL.getTypeRepr();

    bool resultIsPlainOptional = true;
    if (member->isImplicitlyUnwrappedOptional())
      resultIsPlainOptional = false;

    if (resultIsPlainOptional || treatIUOResultAsError) {
      if (parentResultTy->getOptionalObjectType())
        return;
      emittedError = true;
      auto diag = diags.diagnose(resultTL.getSourceRange().Start,
                                 diag::override_optional_result_mismatch,
                                 member->getDescriptiveKind(),
                                 isa<SubscriptDecl>(member),
                                 parentResultTy, resultTy);
      if (auto optForm = dyn_cast<OptionalTypeRepr>(TR)) {
        diag.fixItRemove(optForm->getQuestionLoc());
      } else if (auto iuoForm =
          dyn_cast<ImplicitlyUnwrappedOptionalTypeRepr>(TR)) {
        diag.fixItRemove(iuoForm->getExclamationLoc());
      }
      return;
    }

    if (!parentResultTy->getOptionalObjectType())
      return;

    // Allow silencing this warning using parens.
    if (resultTy->hasParenSugar())
      return;

    diags.diagnose(resultTL.getSourceRange().Start,
                   diag::override_unnecessary_result_IUO,
                   member->getDescriptiveKind(), parentResultTy, resultTy)
      .highlight(resultTL.getSourceRange());

    auto sugaredForm = dyn_cast<ImplicitlyUnwrappedOptionalTypeRepr>(TR);
    if (sugaredForm) {
      diags.diagnose(sugaredForm->getExclamationLoc(),
                     diag::override_unnecessary_IUO_use_strict)
        .fixItReplace(sugaredForm->getExclamationLoc(), "?");
    }

    diags.diagnose(resultTL.getSourceRange().Start,
                   diag::override_unnecessary_IUO_silence)
      .fixItInsert(resultTL.getSourceRange().Start, "(")
      .fixItInsertAfter(resultTL.getSourceRange().End, ")");
  };

  checkResult(resultTL, parentTy->getResult());
  return emittedError;
}

/// Record that the \c overriding declarations overrides the
/// \c overridden declaration.
///
/// \returns true if an error occurred.
static bool checkSingleOverride(ValueDecl *override, ValueDecl *base);

/// If the difference between the types of \p decl and \p base is something
/// we feel confident about fixing (even partially), emit a note with fix-its
/// attached. Otherwise, no note will be emitted.
///
/// \returns true iff a diagnostic was emitted.
static bool noteFixableMismatchedTypes(ValueDecl *decl, const ValueDecl *base) {
  auto &ctx = decl->getASTContext();
  auto &diags = ctx.Diags;
  DiagnosticTransaction tentativeDiags(diags);

  {
    Type baseTy = base->getInterfaceType();
    if (baseTy->hasError())
      return false;

    Optional<InFlightDiagnostic> activeDiag;
    if (auto *baseInit = dyn_cast<ConstructorDecl>(base)) {
      // Special-case initializers, whose "type" isn't useful besides the
      // input arguments.
      auto *fnType = baseTy->getAs<AnyFunctionType>();
      baseTy = fnType->getResult();
      Type argTy = FunctionType::composeInput(ctx,
                                              baseTy->getAs<AnyFunctionType>()
                                                    ->getParams(),
                                              false);
      auto diagKind = diag::override_type_mismatch_with_fixits_init;
      unsigned numArgs = baseInit->getParameters()->size();
      activeDiag.emplace(diags.diagnose(decl, diagKind,
                                        /*plural*/std::min(numArgs, 2U),
                                        argTy));
    } else {
      if (isa<AbstractFunctionDecl>(base))
        baseTy = baseTy->getAs<AnyFunctionType>()->getResult();

      activeDiag.emplace(
        diags.diagnose(decl,
                       diag::override_type_mismatch_with_fixits,
                       base->getDescriptiveKind(), baseTy));
    }

    if (fixItOverrideDeclarationTypes(*activeDiag, decl, base))
      return true;
  }

  // There weren't any fixes we knew how to make. Drop this diagnostic.
  tentativeDiags.abort();
  return false;
}

namespace {
  enum class OverrideCheckingAttempt {
    PerfectMatch,
    MismatchedOptional,
    MismatchedTypes,
    BaseName,
    BaseNameWithMismatchedOptional,
    Final
  };

  OverrideCheckingAttempt &operator++(OverrideCheckingAttempt &attempt) {
    assert(attempt != OverrideCheckingAttempt::Final);
    attempt = static_cast<OverrideCheckingAttempt>(1+static_cast<int>(attempt));
    return attempt;
  }

  struct OverrideMatch {
    ValueDecl *Decl;
    bool IsExact;
  };
}

static void diagnoseGeneralOverrideFailure(ValueDecl *decl,
                                           ArrayRef<OverrideMatch> matches,
                                           OverrideCheckingAttempt attempt) {
  auto &diags = decl->getASTContext().Diags;

  switch (attempt) {
  case OverrideCheckingAttempt::PerfectMatch:
    diags.diagnose(decl, diag::override_multiple_decls_base,
                   decl->getFullName());
    break;
  case OverrideCheckingAttempt::BaseName:
    diags.diagnose(decl, diag::override_multiple_decls_arg_mismatch,
                   decl->getFullName());
    break;
  case OverrideCheckingAttempt::MismatchedOptional:
  case OverrideCheckingAttempt::MismatchedTypes:
  case OverrideCheckingAttempt::BaseNameWithMismatchedOptional:
    if (isa<ConstructorDecl>(decl))
      diags.diagnose(decl, diag::initializer_does_not_override);
    else if (isa<SubscriptDecl>(decl))
      diags.diagnose(decl, diag::subscript_does_not_override);
    else if (isa<VarDecl>(decl))
      diags.diagnose(decl, diag::property_does_not_override);
    else
      diags.diagnose(decl, diag::method_does_not_override);
    break;
  case OverrideCheckingAttempt::Final:
    llvm_unreachable("should have exited already");
  }

  for (auto match : matches) {
    auto matchDecl = match.Decl;
    if (attempt == OverrideCheckingAttempt::PerfectMatch) {
      diags.diagnose(matchDecl, diag::overridden_here);
      continue;
    }

    auto diag = diags.diagnose(matchDecl, diag::overridden_near_match_here,
                               matchDecl->getDescriptiveKind(),
                               matchDecl->getFullName());
    if (attempt == OverrideCheckingAttempt::BaseName) {
      fixDeclarationName(diag, decl, matchDecl->getFullName());
    }
  }
}

static bool parameterTypesMatch(const ValueDecl *derivedDecl,
                                const ValueDecl *baseDecl,
                                TypeMatchOptions matchMode) {
  const ParameterList *derivedParams;
  const ParameterList *baseParams;
  if (auto *derived = dyn_cast<AbstractFunctionDecl>(derivedDecl)) {
    auto *base = dyn_cast<AbstractFunctionDecl>(baseDecl);
    if (!base)
      return false;
    baseParams = base->getParameters();
    derivedParams = derived->getParameters();
  } else {
    auto *base = dyn_cast<SubscriptDecl>(baseDecl);
    if (!base)
      return false;
    baseParams = base->getIndices();
    derivedParams = cast<SubscriptDecl>(derivedDecl)->getIndices();
  }

  if (baseParams->size() != derivedParams->size())
    return false;

  auto subs = SubstitutionMap::getOverrideSubstitutions(baseDecl, derivedDecl,
                                                        /*derivedSubs=*/None);

  for (auto i : indices(baseParams->getArray())) {
    auto *baseParam = baseParams->get(i);
    auto *derivedParam = derivedParams->get(i);

    // Make sure inout-ness and varargs match.
    if (baseParam->isInOut() != derivedParam->isInOut() ||
        baseParam->isVariadic() != derivedParam->isVariadic()) {
      return false;
    }

    auto baseParamTy = baseParam->getInterfaceType();
    baseParamTy = baseParamTy.subst(subs);
    auto derivedParamTy = derivedParam->getInterfaceType();

    if (baseParam->isInOut() || baseParam->isVariadic()) {
      // Inout and vararg parameters must match exactly.
      if (baseParamTy->isEqual(derivedParamTy))
        continue;
    } else {
      // Attempt contravariant match.
      if (baseParamTy->matchesParameter(derivedParamTy, matchMode))
        continue;

      // Try once more for a match, using the underlying type of an
      // IUO if we're allowing that.
      if (baseParam->isImplicitlyUnwrappedOptional() &&
          matchMode.contains(TypeMatchFlags::AllowNonOptionalForIUOParam)) {
        baseParamTy = baseParamTy->getOptionalObjectType();
        if (baseParamTy->matches(derivedParamTy, matchMode))
          continue;
      }
    }

    // If there is no match, then we're done.
    return false;
  }

  return true;
}

// SWIFT_ENABLE_TENSORFLOW
static bool overridesDifferentiableAttribute(ValueDecl *derivedDecl,
                                             ValueDecl *baseDecl) {
  ASTContext &ctx = derivedDecl->getASTContext();
  auto &diags = ctx.Diags;

  auto *derivedAFD = dyn_cast<AbstractFunctionDecl>(derivedDecl);
  auto *baseAFD = dyn_cast<AbstractFunctionDecl>(baseDecl);

  if (!derivedAFD || !baseAFD)
    return false;

  auto derivedDAs = derivedAFD->getAttrs()
      .getAttributes<DifferentiableAttr, /*AllowInvalid*/ true>();
  auto baseDAs = baseAFD->getAttrs().getAttributes<DifferentiableAttr>();

  // Make sure all the `@differentiable` attributes in `baseDecl` are
  // also declared in `derivedDecl`.
  bool diagnosed = false;
  for (auto *baseDA : baseDAs) {
    auto baseParameters = baseDA->getParameterIndices();
    auto defined = false;
    for (auto derivedDA : derivedDAs) {
      auto derivedParameters = derivedDA->getParameterIndices();
      // If base and derived parameter indices are both defined, check whether
      // base parameter indices are a subset of derived parameter indices.
      if (derivedParameters && baseParameters &&
          baseParameters->isSubsetOf(derivedParameters)) {
        defined = true;
        break;
      }
      // Parameter indices may not be resolved because override matching happens
      // before attribute checking for declaration type-checking.
      // If parameter indices have not been resolved, avoid emitting diagnostic.
      // Assume that attributes are valid.
      if (!derivedParameters || !baseParameters) {
        defined = true;
        break;
      }
    }
    if (defined)
      continue;
    diagnosed = true;
    // Omit printing wrt clause if attribute differentiation parameters match
    // inferred differentiation parameters.
    auto *inferredParameters = TypeChecker::inferDifferentiableParameters(
        derivedAFD, nullptr);
    bool omitWrtClause = !baseParameters ||
        baseParameters->getNumIndices() == inferredParameters->getNumIndices();
    // Get `@differentiable` attribute description.
    std::string baseDAString;
    llvm::raw_string_ostream stream(baseDAString);
    baseDA->print(stream, derivedDecl, omitWrtClause,
                  /*omitDerivativeFunctions*/ true);
    diags.diagnose(
        derivedDecl, diag::overriding_decl_missing_differentiable_attr,
        StringRef(stream.str()).trim());
    diags.diagnose(baseDecl, diag::overridden_here);
  }
  // If a diagnostic was produced, return false.
  if (diagnosed)
    return false;

  // If there is no `@differentiable` attribute in `derivedDecl`, then
  // overriding is not allowed.
  auto *derivedDC = derivedDecl->getDeclContext();
  auto *baseDC = baseDecl->getDeclContext();
  if (derivedDC->getSelfClassDecl() && baseDC->getSelfClassDecl())
    return false;

  // Finally, go through all `@differentiable` attributes in `derivedDecl` and
  // check if they subsume any of the `@differentiable` attributes in
  // `baseDecl`.
  for (auto derivedDA : derivedDAs) {
    auto derivedParameters = derivedDA->getParameterIndices();
    auto overrides = true;
    for (auto baseDA : baseDAs) {
      auto baseParameters = baseDA->getParameterIndices();
      // If the parameter indices of `derivedDA` are a subset of those of
      // `baseDA`, then `baseDA` subsumes `derivedDA` and the function is
      // marked as overridden.
      if (derivedParameters && baseParameters &&
          derivedParameters->isSubsetOf(baseParameters)) {
        overrides = false;
        break;
      }
      if (!derivedParameters && !baseParameters) {
        assert(false);
      }
    }
    if (overrides)
      return true;
  }

  return false;
}
// SWIFT_ENABLE_TENSORFLOW END

/// Returns true if the given declaration is for the `NSObject.hashValue`
/// property.
static bool isNSObjectHashValue(ValueDecl *baseDecl) {
  ASTContext &ctx = baseDecl->getASTContext();

  if (auto baseVar = dyn_cast<VarDecl>(baseDecl)) {
    if (auto classDecl = baseVar->getDeclContext()->getSelfClassDecl()) {
      return baseVar->getName() == ctx.Id_hashValue &&
        classDecl->getName().is("NSObject") &&
        (classDecl->getModuleContext()->getName() == ctx.Id_Foundation ||
         classDecl->getModuleContext()->getName() == ctx.Id_ObjectiveC);
    }
  }
  return false;
}

namespace {
  /// Class that handles the checking of a particular declaration against
  /// superclass entities that it could override.
  class OverrideMatcher {
    ASTContext &ctx;
    ValueDecl *decl;

    /// The set of declarations in which we'll look for overridden
    /// methods.
    SmallVector<NominalTypeDecl *, 2> superContexts;

    /// Cached member lookup results.
    SmallVector<ValueDecl *, 4> members;

    /// The lookup name used to find \c members.
    DeclName membersName;

    /// The type of the declaration, cached here once it has been computed.
    Type cachedDeclType;

  public:
    OverrideMatcher(ValueDecl *decl);

    /// Returns true when it's possible to perform any override matching.
    explicit operator bool() const {
      return !superContexts.empty();
    }

    /// Whether this is an override of a class member.
    bool isClassOverride() const {
      return decl->getDeclContext()->getSelfClassDecl() != nullptr;
    }

    /// Whether this is an override of a protocol member.
    bool isProtocolOverride() const {
      return decl->getDeclContext()->getSelfProtocolDecl() != nullptr;
    }

    /// Match this declaration against potential members in the superclass,
    /// using the heuristics appropriate for the given \c attempt.
    SmallVector<OverrideMatch, 2> match(OverrideCheckingAttempt attempt);

    /// Check each of the given matches, returning only those that
    /// succeeded.
    TinyPtrVector<ValueDecl *> checkPotentialOverrides(
                                        SmallVectorImpl<OverrideMatch> &matches,
                                        OverrideCheckingAttempt attempt);

  private:
    /// We have determined that we have an override of the given \c baseDecl.
    ///
    /// Check that the override itself is valid.
    bool checkOverride(ValueDecl *baseDecl,
                       OverrideCheckingAttempt attempt);

    /// Retrieve the type of the declaration, to be used in comparisons.
    Type getDeclComparisonType() {
      if (!cachedDeclType) {
        cachedDeclType = getMemberTypeForComparison(ctx, decl);
      }

      return cachedDeclType;
    }

    /// Adjust the interface of the given declaration, which is found in
    /// a supertype of the given type.
    Type getSuperMemberDeclType(ValueDecl *baseDecl) const {
      auto selfType = decl->getDeclContext()->getSelfInterfaceType();
      if (selfType->getClassOrBoundGenericClass()) {
        selfType = selfType->getSuperclass();
        assert(selfType && "No superclass type?");
      }

      return selfType->adjustSuperclassMemberDeclType(
               baseDecl, decl, baseDecl->getInterfaceType());
    }
  };
}

OverrideMatcher::OverrideMatcher(ValueDecl *decl)
    : ctx(decl->getASTContext()), decl(decl) {
  // The final step for this constructor is to set up the superclass type,
  // without which we will not perform an matching. Early exits therefore imply
  // that there is no way we can match this declaration.
  if (decl->isInvalid())
    return;

  auto *dc = decl->getDeclContext();
  if (auto classDecl = dc->getSelfClassDecl()) {
    if (auto superclassDecl = classDecl->getSuperclassDecl())
      superContexts.push_back(superclassDecl);
  } else if (auto protocol = dyn_cast<ProtocolDecl>(dc)) {
    auto inheritedProtocols = protocol->getInheritedProtocols();
    superContexts.insert(superContexts.end(), inheritedProtocols.begin(),
                         inheritedProtocols.end());
  }
}

SmallVector<OverrideMatch, 2> OverrideMatcher::match(
                                             OverrideCheckingAttempt attempt) {
  // If there's no matching we can do, fail.
  if (!*this) return { };

  auto dc = decl->getDeclContext();

  // Determine what name we should look for.
  DeclName name;
  switch (attempt) {
  case OverrideCheckingAttempt::PerfectMatch:
  case OverrideCheckingAttempt::MismatchedOptional:
  case OverrideCheckingAttempt::MismatchedTypes:
    name = decl->getFullName();
    break;
  case OverrideCheckingAttempt::BaseName:
  case OverrideCheckingAttempt::BaseNameWithMismatchedOptional:
    name = decl->getBaseName();
    break;
  case OverrideCheckingAttempt::Final:
    // Give up.
    return { };
  }

  // If we don't have members available yet, or we looked them up based on a
  // different name, look them up now.
  if (members.empty() || name != membersName) {
    membersName = name;
    members.clear();
    dc->lookupQualified(superContexts, membersName,
                        NL_QualifiedDefault, members);
  }

  // Check each member we found.
  SmallVector<OverrideMatch, 2> matches;
  for (auto parentDecl : members) {
    // Check whether there are any obvious reasons why the two given
    // declarations do not have an overriding relationship.
    if (!areOverrideCompatibleSimple(decl, parentDecl))
      continue;

    // SWIFT_ENABLE_TENSORFLOW
    // Check whether the `@differentiable` attribute allows overriding.
    if (overridesDifferentiableAttribute(decl, parentDecl))
      continue;
    // SWIFT_ENABLE_TENSORFLOW END

    auto parentMethod = dyn_cast<AbstractFunctionDecl>(parentDecl);
    auto parentStorage = dyn_cast<AbstractStorageDecl>(parentDecl);
    assert(parentMethod || parentStorage);
    (void)parentMethod;
    (void)parentStorage;

    // Check whether the types are identical.
    auto parentDeclTy = getMemberTypeForComparison(ctx, parentDecl, decl);
    if (parentDeclTy->hasError())
      continue;

    Type declTy = getDeclComparisonType();
    if (isOverrideBasedOnType(decl, declTy, parentDecl, parentDeclTy)) {
      matches.push_back({parentDecl, true});
      continue;
    }

    // If this is a property, we accept the match and then reject it below
    // if the types don't line up, since you can't overload properties based
    // on types.
    if ((isa<VarDecl>(parentDecl) && isClassOverride()) ||
        attempt == OverrideCheckingAttempt::MismatchedTypes) {
      matches.push_back({parentDecl, false});
      continue;
    }

    // For a protocol override, we require an exact match.
    if (isProtocolOverride()) {
      continue;
    }

    // Failing that, check for subtyping.
    TypeMatchOptions matchMode = TypeMatchFlags::AllowOverride;
    if (attempt == OverrideCheckingAttempt::MismatchedOptional ||
        attempt == OverrideCheckingAttempt::BaseNameWithMismatchedOptional){
      matchMode |= TypeMatchFlags::AllowTopLevelOptionalMismatch;
    } else if (parentDecl->isObjC()) {
      matchMode |= TypeMatchFlags::AllowNonOptionalForIUOParam;
      matchMode |= TypeMatchFlags::IgnoreNonEscapingForOptionalFunctionParam;
    }

    auto declFnTy = getDeclComparisonType()->getAs<AnyFunctionType>();
    auto parentDeclFnTy = parentDeclTy->getAs<AnyFunctionType>();
    if (declFnTy && parentDeclFnTy) {
      auto paramsAndResultMatch = [=]() -> bool {
        return parameterTypesMatch(decl, parentDecl, matchMode) &&
               declFnTy->getResult()->matches(parentDeclFnTy->getResult(),
                                              matchMode);
      };

      if (declFnTy->matchesFunctionType(parentDeclFnTy, matchMode,
                                        paramsAndResultMatch)) {
        matches.push_back({parentDecl, false});
        continue;
      }
    } else if (getDeclComparisonType()->matches(parentDeclTy, matchMode)) {
      matches.push_back({parentDecl, false});
      continue;
    }
  }

  // If we have more than one match, and any of them was exact, remove all
  // non-exact matches.
  if (matches.size() > 1) {
    bool hadExactMatch = std::find_if(matches.begin(), matches.end(),
                                      [](const OverrideMatch &match) {
                                        return match.IsExact;
                                      }) != matches.end();
    if (hadExactMatch) {
      matches.erase(std::remove_if(matches.begin(), matches.end(),
                                   [&](const OverrideMatch &match) {
                                     return !match.IsExact;
                                   }),
                    matches.end());
    }
  }

  return matches;
}

static void checkOverrideAccessControl(ValueDecl *baseDecl, ValueDecl *decl,
                                       ASTContext &ctx) {
  if (ctx.isAccessControlDisabled())
    return;

  if (isa<ProtocolDecl>(decl->getDeclContext()))
    return;

  auto &diags = ctx.Diags;

  auto dc = decl->getDeclContext();
  auto classDecl = dc->getSelfClassDecl();
  assert(classDecl != nullptr && "Should have ruled out protocols above");

  bool isAccessor = isa<AccessorDecl>(decl);

  // Check that the override has the required access level.
  // Overrides have to be at least as accessible as what they
  // override, except:
  //   - they don't have to be more accessible than their class and
  //   - a final method may be public instead of open.
  // Also diagnose attempts to override a non-open method from outside its
  // defining module.  This is not required for constructors, which are
  // never really "overridden" in the intended sense here, because of
  // course derived classes will change how the class is initialized.
  bool baseHasOpenAccess = baseDecl->hasOpenAccess(dc);
  if (!isAccessor &&
      !baseHasOpenAccess &&
      baseDecl->getModuleContext() != decl->getModuleContext() &&
      !isa<ConstructorDecl>(decl)) {
    // NSObject.hashValue was made non-overridable in Swift 5; one should
    // override NSObject.hash instead.
    if (isNSObjectHashValue(baseDecl)) {
      diags.diagnose(decl, diag::override_nsobject_hashvalue_error)
        .fixItReplace(SourceRange(decl->getNameLoc()), "hash");
    } else {
      diags.diagnose(decl, diag::override_of_non_open,
                     decl->getDescriptiveKind());
    }
  } else if (baseHasOpenAccess &&
             classDecl->hasOpenAccess(dc) &&
             decl->getFormalAccess() < AccessLevel::Public &&
             !decl->isFinal()) {
    {
      auto diag = diags.diagnose(decl, diag::override_not_accessible,
                                 /*setter*/false,
                                 decl->getDescriptiveKind(),
                                 /*fromOverridden*/true);
      fixItAccess(diag, decl, AccessLevel::Open);
    }
    diags.diagnose(baseDecl, diag::overridden_here);

  } else if (!isa<ConstructorDecl>(decl)) {
    auto matchAccessScope =
      baseDecl->getFormalAccessScope(dc);
    auto classAccessScope =
      classDecl->getFormalAccessScope(dc);
    auto requiredAccessScope =
      matchAccessScope.intersectWith(classAccessScope);
    auto scopeDC = requiredAccessScope->getDeclContext();

    bool shouldDiagnose = !decl->isAccessibleFrom(scopeDC);

    bool shouldDiagnoseSetter = false;
    if (auto matchASD = dyn_cast<AbstractStorageDecl>(baseDecl)) {
      if (!shouldDiagnose && matchASD->isSettable(dc)){
        if (matchASD->isSetterAccessibleFrom(dc)) {
          auto matchSetterAccessScope =
            matchASD->getSetterFormalAccessScope(dc);
          auto requiredSetterAccessScope =
            matchSetterAccessScope.intersectWith(classAccessScope);
          auto setterScopeDC = requiredSetterAccessScope->getDeclContext();

          const auto *ASD = cast<AbstractStorageDecl>(decl);
          shouldDiagnoseSetter =
              ASD->isSettable(setterScopeDC) &&
              !ASD->isSetterAccessibleFrom(setterScopeDC);
        }
      }
    }

    if (shouldDiagnose || shouldDiagnoseSetter) {
      bool overriddenForcesAccess =
        (requiredAccessScope->hasEqualDeclContextWith(matchAccessScope) &&
         !baseHasOpenAccess);
      AccessLevel requiredAccess =
        requiredAccessScope->requiredAccessForDiagnostics();
      {
        auto diag = diags.diagnose(decl, diag::override_not_accessible,
                                   shouldDiagnoseSetter,
                                   decl->getDescriptiveKind(),
                                   overriddenForcesAccess);
        fixItAccess(diag, decl, requiredAccess, shouldDiagnoseSetter);
      }
      diags.diagnose(baseDecl, diag::overridden_here);
    }
  }
}

bool OverrideMatcher::checkOverride(ValueDecl *baseDecl,
                                    OverrideCheckingAttempt attempt) {
  auto &diags = ctx.Diags;
  auto baseTy = getMemberTypeForComparison(ctx, baseDecl, decl);
  bool emittedMatchError = false;

  // If the name of our match differs from the name we were looking for,
  // complain.
  if (decl->getFullName() != baseDecl->getFullName()) {
    auto diag = diags.diagnose(decl, diag::override_argument_name_mismatch,
                               isa<ConstructorDecl>(decl),
                               decl->getFullName(),
                               baseDecl->getFullName());
    fixDeclarationName(diag, decl, baseDecl->getFullName());
    emittedMatchError = true;
  }

  auto baseGenericCtx = baseDecl->getAsGenericContext();
  auto derivedGenericCtx = decl->getAsGenericContext();

  using Direction = ASTContext::OverrideGenericSignatureReqCheck;
  if (baseGenericCtx && derivedGenericCtx) {
    if (!ctx.overrideGenericSignatureReqsSatisfied(
            baseDecl, decl, Direction::DerivedReqSatisfiedByBase)) {
      auto newSig = ctx.getOverrideGenericSignature(baseDecl, decl);
      diags.diagnose(decl, diag::override_method_different_generic_sig,
                     decl->getBaseName(),
                     derivedGenericCtx->getGenericSignature()->getAsString(),
                     baseGenericCtx->getGenericSignature()->getAsString(),
                     newSig->getAsString());
      diags.diagnose(baseDecl, diag::overridden_here);
      emittedMatchError = true;
    }
  }

  // If we have an explicit ownership modifier and our parent doesn't,
  // complain.
  auto parentAttr =
      baseDecl->getAttrs().getAttribute<ReferenceOwnershipAttr>();
  if (auto ownershipAttr =
          decl->getAttrs().getAttribute<ReferenceOwnershipAttr>()) {
    ReferenceOwnership parentOwnership;
    if (parentAttr)
      parentOwnership = parentAttr->get();
    else
      parentOwnership = ReferenceOwnership::Strong;
    if (parentOwnership != ownershipAttr->get()) {
      diags.diagnose(decl, diag::override_ownership_mismatch,
                     parentOwnership, ownershipAttr->get());
      diags.diagnose(baseDecl, diag::overridden_here);
    }
  }

  // If a super method returns Self, and the subclass overrides it to
  // instead return the subclass type, complain.
  // This case gets this far because the type matching above specifically
  // strips out dynamic self via replaceCovariantResultType(), and that
  // is helpful in several cases - just not this one.
  auto dc = decl->getDeclContext();
  auto classDecl = dc->getSelfClassDecl();
  if (decl->getASTContext().isSwiftVersionAtLeast(5) &&
      baseDecl->getInterfaceType()->hasDynamicSelfType() &&
      !decl->getInterfaceType()->hasDynamicSelfType() &&
      !classDecl->isFinal()) {
    diags.diagnose(decl, diag::override_dynamic_self_mismatch);
    diags.diagnose(baseDecl, diag::overridden_here);
  }

  checkOverrideAccessControl(baseDecl, decl, ctx);

  bool mayHaveMismatchedOptionals =
      (attempt == OverrideCheckingAttempt::MismatchedOptional ||
       attempt == OverrideCheckingAttempt::BaseNameWithMismatchedOptional);

  auto declIUOAttr = decl->isImplicitlyUnwrappedOptional();
  auto matchDeclIUOAttr = baseDecl->isImplicitlyUnwrappedOptional();

  // If this is an exact type match, we're successful!
  Type declTy = getDeclComparisonType();
  Type owningTy = dc->getDeclaredInterfaceType();
  if (declIUOAttr == matchDeclIUOAttr && declTy->isEqual(baseTy)) {
    // Nothing to do.

  } else if (auto method = dyn_cast<AbstractFunctionDecl>(decl)) {
    if (attempt == OverrideCheckingAttempt::MismatchedTypes) {
      auto diagKind = diag::method_does_not_override;
      if (isa<ConstructorDecl>(method))
        diagKind = diag::initializer_does_not_override;
      diags.diagnose(decl, diagKind);
      noteFixableMismatchedTypes(decl, baseDecl);
      diags.diagnose(baseDecl, diag::overridden_near_match_here,
                     baseDecl->getDescriptiveKind(),
                     baseDecl->getFullName());
      emittedMatchError = true;

    } else if (!isa<AccessorDecl>(method) &&
               (baseDecl->isObjC() || mayHaveMismatchedOptionals)) {
      // Private migration help for overrides of Objective-C methods.
      TypeLoc resultTL;
      if (auto *methodAsFunc = dyn_cast<FuncDecl>(method))
        resultTL = methodAsFunc->getBodyResultTypeLoc();

      emittedMatchError |= diagnoseMismatchedOptionals(
          method, method->getParameters(), resultTL, baseDecl,
          cast<AbstractFunctionDecl>(baseDecl)->getParameters(),
          owningTy, mayHaveMismatchedOptionals);
    }
  } else if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
    // Otherwise, if this is a subscript, validate that covariance is ok.
    // If the parent is non-mutable, it's okay to be covariant.
    auto parentSubscript = cast<SubscriptDecl>(baseDecl);
    if (parentSubscript->supportsMutation()) {
      diags.diagnose(subscript, diag::override_mutable_covariant_subscript,
                     declTy, baseTy);
      diags.diagnose(baseDecl, diag::subscript_override_here);
      return true;
    }

    if (attempt == OverrideCheckingAttempt::MismatchedTypes) {
      diags.diagnose(decl, diag::subscript_does_not_override);
      noteFixableMismatchedTypes(decl, baseDecl);
      diags.diagnose(baseDecl, diag::overridden_near_match_here,
                     baseDecl->getDescriptiveKind(),
                     baseDecl->getFullName());
      emittedMatchError = true;

    } else if (mayHaveMismatchedOptionals) {
      emittedMatchError |= diagnoseMismatchedOptionals(
          subscript, subscript->getIndices(),
          subscript->getElementTypeLoc(), baseDecl,
          cast<SubscriptDecl>(baseDecl)->getIndices(), owningTy,
          mayHaveMismatchedOptionals);
    }
  } else if (auto property = dyn_cast<VarDecl>(decl)) {
    auto propertyTy = property->getInterfaceType();
    auto parentPropertyTy = getSuperMemberDeclType(baseDecl);

    CanType parentPropertyCanTy =
      parentPropertyTy->getCanonicalType(
        decl->getInnermostDeclContext()->getGenericSignatureOfContext());
    if (!propertyTy->matches(parentPropertyCanTy,
                             TypeMatchFlags::AllowOverride)) {
      diags.diagnose(property, diag::override_property_type_mismatch,
                     property->getName(), propertyTy, parentPropertyTy);
      noteFixableMismatchedTypes(decl, baseDecl);
      diags.diagnose(baseDecl, diag::property_override_here);
      return true;
    }

    // Differing only in Optional vs. ImplicitlyUnwrappedOptional is fine.
    bool IsSilentDifference = false;
    if (auto propertyTyNoOptional = propertyTy->getOptionalObjectType())
      if (auto parentPropertyTyNoOptional =
              parentPropertyTy->getOptionalObjectType())
        if (propertyTyNoOptional->isEqual(parentPropertyTyNoOptional))
          IsSilentDifference = true;

    // The overridden property must not be mutable.
    if (cast<AbstractStorageDecl>(baseDecl)->supportsMutation() &&
        !IsSilentDifference) {
      diags.diagnose(property, diag::override_mutable_covariant_property,
                  property->getName(), parentPropertyTy, propertyTy);
      diags.diagnose(baseDecl, diag::property_override_here);
      return true;
    }
  }

  if (emittedMatchError)
    return true;

  // Catch-all to make sure we don't silently accept something we shouldn't.
  if (attempt != OverrideCheckingAttempt::PerfectMatch) {
    OverrideMatch match{decl, /*isExact=*/false};
    diagnoseGeneralOverrideFailure(decl, match, attempt);
  }

  return checkSingleOverride(decl, baseDecl);
}

// Invalidate an existing "override" attribute or add a new invalid "override"
// attribute, which will suppress additional checking.
static void invalidateOverrideAttribute(ValueDecl *decl) {
  auto overrideAttr = decl->getAttrs().getAttribute<OverrideAttr>(true);
  if (!overrideAttr) {
    overrideAttr = new (decl->getASTContext()) OverrideAttr(true);
    decl->getAttrs().add(overrideAttr);
  }

  overrideAttr->setInvalid();
}

TinyPtrVector<ValueDecl *> OverrideMatcher::checkPotentialOverrides(
                                    SmallVectorImpl<OverrideMatch> &matches,
                                    OverrideCheckingAttempt attempt) {
  // If we override more than one declaration from a class, complain.
  if (matches.size() > 1 && decl->getDeclContext()->getSelfClassDecl()) {
    diagnoseGeneralOverrideFailure(decl, matches, attempt);
    return { };
  }

  // Check the matches. If any are ill-formed, drop them.
  TinyPtrVector<ValueDecl *> overridden;
  for (const auto &match : matches) {
    if (checkOverride(match.Decl, attempt))
      continue;

    overridden.push_back(match.Decl);
  }

  // If there were no overrides, invalidate the "override" attribute.
  if (overridden.empty())
    invalidateOverrideAttribute(decl);

  return overridden;
}

/// Determine which method or subscript this method or subscript overrides
/// (if any).
///
/// \returns true if an error occurred.
bool swift::checkOverrides(ValueDecl *decl) {
  // If there is a @_nonoverride attribute, this does not override anything.
  if (decl->getAttrs().hasAttribute<NonOverrideAttr>())
    return false;

  // If we already computed overridden declarations and either succeeded
  // or invalidated the attribute, there's nothing more to do.
  if (decl->overriddenDeclsComputed()) {
    // If we computed an overridden declaration successfully, we're done.
    if (decl->getOverriddenDecl())
      return false;

    // If we set the override attribute to "invalid", we already diagnosed
    // something here.
    if (decl->getAttrs().hasAttribute<OverrideAttr>(/*AllowInvalid=*/true) &&
        !decl->getAttrs().hasAttribute<OverrideAttr>())
      return true;

    // Otherwise, we have more checking to do.
  }

  // Accessor methods get overrides through their storage declaration, and
  // all checking can be performed via that mechanism.
  if (isa<AccessorDecl>(decl)) {
    (void)decl->getOverriddenDecls();
    return false;
  }

  // Set up matching, but bail out if there's nothing to match.
  OverrideMatcher matcher(decl);
  if (!matcher) return false;

  // Look for members with the same name and matching types as this
  // one.
  SmallVector<OverrideMatch, 2> matches;
  auto attempt = OverrideCheckingAttempt::PerfectMatch;
  do {
    // Determine whether we should attempt to perform matching now, or exit
    // early with a failure.
    switch (attempt) {
    case OverrideCheckingAttempt::PerfectMatch:
      break;
    case OverrideCheckingAttempt::MismatchedOptional:
      // Don't keep looking if the user didn't indicate it's an override.
      if (!decl->getAttrs().hasAttribute<OverrideAttr>())
        return false;
      break;
    case OverrideCheckingAttempt::MismatchedTypes:
      break;
    case OverrideCheckingAttempt::BaseName:
      // Don't keep looking if this is already a simple name, or if there
      // are no arguments.
      if (decl->getFullName() == decl->getBaseName() ||
          decl->getFullName().getArgumentNames().empty())
        return false;
      break;
    case OverrideCheckingAttempt::BaseNameWithMismatchedOptional:
      break;
    case OverrideCheckingAttempt::Final:
      // Give up.
      return false;
    }

    // Try to match with this attempt kind.
    matches = matcher.match(attempt);
    if (!matches.empty())
      break;

    // If we're computing implicit overrides for a protocol member, don't
    // look any further unless there's an `override` attribute.
    if (matcher.isProtocolOverride() &&
        !decl->getAttrs().hasAttribute<OverrideAttr>())
      return false;

    // Try the next version.
    ++attempt;
  } while (true);

  assert(!matches.empty());

  // FIXME: Check for missing 'override' keyword here?

  // We performed override checking, so record the overrides.
  // FIXME: It's weird to be pushing state here, but how do we say that
  // this check subsumes the normal 'override' check?
  auto overridden = matcher.checkPotentialOverrides(matches, attempt);
  if (overridden.empty())
    invalidateOverrideAttribute(decl);
  decl->setOverriddenDecls(overridden);
  return false;
}

namespace  {
  /// Attribute visitor that checks how the given attribute should be
  /// considered when overriding a declaration.
  ///
  /// Note that the attributes visited are those of the base
  /// declaration, so if you need to check that the overriding
  /// declaration doesn't have an attribute if the base doesn't have
  /// it, this isn't sufficient.
  class AttributeOverrideChecker
          : public AttributeVisitor<AttributeOverrideChecker> {
    ValueDecl *Base;
    ValueDecl *Override;
    DiagnosticEngine &Diags;

  public:
    AttributeOverrideChecker(ValueDecl *base, ValueDecl *override)
      : Base(base), Override(override), Diags(base->getASTContext().Diags) { }

    /// Deleting this ensures that all attributes are covered by the visitor
    /// below.
    void visitDeclAttribute(DeclAttribute *A) = delete;

#define UNINTERESTING_ATTR(CLASS)                                              \
    void visit##CLASS##Attr(CLASS##Attr *) {}

    // Please keep these alphabetical.
    UNINTERESTING_ATTR(AccessControl)
    UNINTERESTING_ATTR(Alignment)
    UNINTERESTING_ATTR(AlwaysEmitIntoClient)
    UNINTERESTING_ATTR(Borrowed)
    UNINTERESTING_ATTR(CDecl)
    UNINTERESTING_ATTR(Consuming)
    UNINTERESTING_ATTR(Dynamic)
    UNINTERESTING_ATTR(DynamicCallable)
    UNINTERESTING_ATTR(DynamicMemberLookup)
    UNINTERESTING_ATTR(SILGenName)
    UNINTERESTING_ATTR(Exported)
    UNINTERESTING_ATTR(ForbidSerializingReference)
    UNINTERESTING_ATTR(GKInspectable)
    UNINTERESTING_ATTR(IBAction)
    UNINTERESTING_ATTR(IBDesignable)
    UNINTERESTING_ATTR(IBInspectable)
    UNINTERESTING_ATTR(IBOutlet)
    UNINTERESTING_ATTR(IBSegueAction)
    UNINTERESTING_ATTR(Indirect)
    UNINTERESTING_ATTR(Inline)
    UNINTERESTING_ATTR(Optimize)
    UNINTERESTING_ATTR(Inlinable)
    UNINTERESTING_ATTR(Effects)
    UNINTERESTING_ATTR(Final)
    UNINTERESTING_ATTR(FixedLayout)
    UNINTERESTING_ATTR(Lazy)
    UNINTERESTING_ATTR(LLDBDebuggerFunction)
    UNINTERESTING_ATTR(Mutating)
    UNINTERESTING_ATTR(NonMutating)
    UNINTERESTING_ATTR(NonObjC)
    UNINTERESTING_ATTR(NonOverride)
    UNINTERESTING_ATTR(NSApplicationMain)
    UNINTERESTING_ATTR(NSCopying)
    UNINTERESTING_ATTR(NSManaged)
    UNINTERESTING_ATTR(ObjCBridged)
    UNINTERESTING_ATTR(Optional)
    UNINTERESTING_ATTR(Override)
    UNINTERESTING_ATTR(RawDocComment)
    UNINTERESTING_ATTR(Required)
    UNINTERESTING_ATTR(Convenience)
    UNINTERESTING_ATTR(Semantics)
    UNINTERESTING_ATTR(SetterAccess)
    UNINTERESTING_ATTR(HasStorage)
    UNINTERESTING_ATTR(UIApplicationMain)
    UNINTERESTING_ATTR(UsableFromInline)
    UNINTERESTING_ATTR(ObjCNonLazyRealization)
    UNINTERESTING_ATTR(UnsafeNoObjCTaggedPointer)
    UNINTERESTING_ATTR(SwiftNativeObjCRuntimeBase)
    UNINTERESTING_ATTR(ShowInInterface)
    UNINTERESTING_ATTR(Specialize)
    UNINTERESTING_ATTR(DynamicReplacement)
    UNINTERESTING_ATTR(PrivateImport)

    // SWIFT_ENABLE_TENSORFLOW
    UNINTERESTING_ATTR(Differentiable)
    UNINTERESTING_ATTR(Differentiating)
    UNINTERESTING_ATTR(CompilerEvaluable)
    UNINTERESTING_ATTR(NoDerivative)
    UNINTERESTING_ATTR(Transposing)

    // These can't appear on overridable declarations.
    UNINTERESTING_ATTR(Prefix)
    UNINTERESTING_ATTR(Postfix)
    UNINTERESTING_ATTR(Infix)
    UNINTERESTING_ATTR(ReferenceOwnership)

    UNINTERESTING_ATTR(SynthesizedProtocol)
    UNINTERESTING_ATTR(RequiresStoredPropertyInits)
    UNINTERESTING_ATTR(Transparent)
    UNINTERESTING_ATTR(Testable)

    UNINTERESTING_ATTR(WarnUnqualifiedAccess)
    UNINTERESTING_ATTR(DiscardableResult)

    UNINTERESTING_ATTR(ObjCMembers)
    UNINTERESTING_ATTR(ObjCRuntimeName)
    UNINTERESTING_ATTR(RestatedObjCConformance)
    UNINTERESTING_ATTR(Implements)
    UNINTERESTING_ATTR(StaticInitializeObjCMetadata)
    UNINTERESTING_ATTR(ClangImporterSynthesizedType)
    UNINTERESTING_ATTR(WeakLinked)
    UNINTERESTING_ATTR(Frozen)
    UNINTERESTING_ATTR(HasInitialValue)
    UNINTERESTING_ATTR(ImplementationOnly)
    UNINTERESTING_ATTR(Custom)
    UNINTERESTING_ATTR(PropertyWrapper)
    UNINTERESTING_ATTR(DisfavoredOverload)
    UNINTERESTING_ATTR(FunctionBuilder)
    UNINTERESTING_ATTR(ProjectedValueProperty)

    UNINTERESTING_ATTR(Quoted)
#undef UNINTERESTING_ATTR

    void visitAvailableAttr(AvailableAttr *attr) {
      // FIXME: Check that this declaration is at least as available as the
      // one it overrides.
    }

    void visitRethrowsAttr(RethrowsAttr *attr) {
      // 'rethrows' functions are a subtype of ordinary 'throws' functions.
      // Require 'rethrows' on the override if it was there on the base,
      // unless the override is completely non-throwing.
      if (!Override->getAttrs().hasAttribute<RethrowsAttr>() &&
          cast<AbstractFunctionDecl>(Override)->hasThrows()) {
        Diags.diagnose(Override, diag::override_rethrows_with_non_rethrows,
                       isa<ConstructorDecl>(Override));
        Diags.diagnose(Base, diag::overridden_here);
      }
    }

    void visitObjCAttr(ObjCAttr *attr) {
      // Checking for overrides of declarations that are implicitly @objc
      // and occur in class extensions, because overriding will no longer be
      // possible under the Swift 4 rules.

      // We only care about the storage declaration.
      if (isa<AccessorDecl>(Override)) return;

      // If @objc was explicit or handled elsewhere, nothing to do.
      if (!attr->isSwift3Inferred()) return;

      // If we aren't warning about Swift 3 @objc inference, we're done.
      if (Override->getASTContext().LangOpts.WarnSwift3ObjCInference ==
            Swift3ObjCInferenceWarnings::None)
        return;

      // If 'dynamic' was implicit, we'll already have warned about this.
      if (auto dynamicAttr = Base->getAttrs().getAttribute<DynamicAttr>()) {
        if (!dynamicAttr->isImplicit()) return;
      }

      // The overridden declaration needs to be in an extension.
      if (!isa<ExtensionDecl>(Base->getDeclContext())) return;

      // Complain.
      Diags.diagnose(Override, diag::override_swift3_objc_inference,
                     Override->getDescriptiveKind(),
                     Override->getFullName(),
                     Base->getDeclContext()
                       ->getSelfNominalTypeDecl()
                       ->getName());
      Diags.diagnose(Base, diag::make_decl_objc, Base->getDescriptiveKind())
        .fixItInsert(Base->getAttributeInsertionLoc(false),
                     "@objc ");
    }
  };
} // end anonymous namespace

/// Determine whether overriding the given declaration requires a keyword.
OverrideRequiresKeyword swift::overrideRequiresKeyword(ValueDecl *overridden) {
  if (isa<AccessorDecl>(overridden))
    return OverrideRequiresKeyword::Never;

  if (isa<ProtocolDecl>(overridden->getDeclContext())) {
    if (overridden->getASTContext().LangOpts.WarnImplicitOverrides)
      return OverrideRequiresKeyword::Implicit;

    return OverrideRequiresKeyword::Never;
  }

  if (auto ctor = dyn_cast<ConstructorDecl>(overridden)) {
    return !ctor->isDesignatedInit() || ctor->isRequired()
      ? OverrideRequiresKeyword::Never
      : OverrideRequiresKeyword::Always;
  }

  return OverrideRequiresKeyword::Always;
}

/// Returns true if the availability of the overriding declaration
/// makes it a safe override, given the availability of the base declaration.
static bool isAvailabilitySafeForOverride(ValueDecl *override,
                                          ValueDecl *base) {
  ASTContext &ctx = override->getASTContext();

  // API availability ranges are contravariant: make sure the version range
  // of an overridden declaration is fully contained in the range of the
  // overriding declaration.
  AvailabilityContext overrideInfo =
    AvailabilityInference::availableRange(override, ctx);
  AvailabilityContext baseInfo =
    AvailabilityInference::availableRange(base, ctx);

  return baseInfo.isContainedIn(overrideInfo);
}

/// Returns true if a diagnostic about an accessor being less available
/// than the accessor it overrides would be redundant because we will
/// already emit another diagnostic.
static bool
isRedundantAccessorOverrideAvailabilityDiagnostic(ValueDecl *override,
                                                  ValueDecl *base) {

  auto *overrideFn = dyn_cast<AccessorDecl>(override);
  auto *baseFn = dyn_cast<AccessorDecl>(base);
  if (!overrideFn || !baseFn)
    return false;

  AbstractStorageDecl *overrideASD = overrideFn->getStorage();
  AbstractStorageDecl *baseASD = baseFn->getStorage();
  if (overrideASD->getOverriddenDecl() != baseASD)
    return false;

  // If we have already emitted a diagnostic about an unsafe override
  // for the property, don't complain about the accessor.
  if (!isAvailabilitySafeForOverride(overrideASD, baseASD)) {
    return true;
  }

  // Returns true if we will already diagnose a bad override
  // on the property's accessor of the given kind.
  auto accessorOverrideAlreadyDiagnosed = [&](AccessorKind kind) {
    FuncDecl *overrideAccessor = overrideASD->getOpaqueAccessor(kind);
    FuncDecl *baseAccessor = baseASD->getOpaqueAccessor(kind);
    if (overrideAccessor && baseAccessor &&
        !isAvailabilitySafeForOverride(overrideAccessor, baseAccessor)) {
      return true;
    }
    return false;
  };

  // If we have already emitted a diagnostic about an unsafe override
  // for a getter or a setter, no need to complain about the read or
  // modify coroutines, which are synthesized to be as available as either
  // the getter and the setter.
  switch (overrideFn->getAccessorKind()) {
  case AccessorKind::Get:
  case AccessorKind::Set:
    break;

  case AccessorKind::Read:
    if (accessorOverrideAlreadyDiagnosed(AccessorKind::Get))
      return true;
    break;

  case AccessorKind::Modify:
    if (accessorOverrideAlreadyDiagnosed(AccessorKind::Get) ||
        accessorOverrideAlreadyDiagnosed(AccessorKind::Set)) {
      return true;
    }
    break;

#define OPAQUE_ACCESSOR(ID, KEYWORD)
#define ACCESSOR(ID) \
  case AccessorKind::ID:
#include "swift/AST/AccessorKinds.def"
    llvm_unreachable("checking override for non-opaque accessor");
  }

  return false;
}

/// Diagnose an override for potential availability. Returns true if
/// a diagnostic was emitted and false otherwise.
static bool diagnoseOverrideForAvailability(ValueDecl *override,
                                            ValueDecl *base) {
  if (isAvailabilitySafeForOverride(override, base))
    return false;

  // Suppress diagnostics about availability overrides for accessors
  // if they would be redundant with other diagnostics.
  if (isRedundantAccessorOverrideAvailabilityDiagnostic(override, base))
    return false;

  auto &diags = override->getASTContext().Diags;
  if (auto *accessor = dyn_cast<AccessorDecl>(override)) {
    diags.diagnose(override, diag::override_accessor_less_available,
                   accessor->getDescriptiveKind(),
                   accessor->getStorage()->getBaseName());
    diags.diagnose(base, diag::overridden_here);
    return true;
  }

  diags.diagnose(override, diag::override_less_available,
                 override->getBaseName());
  diags.diagnose(base, diag::overridden_here);

  return true;
}

static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) {
  // This can happen with circular inheritance.
  // FIXME: This shouldn't be possible once name lookup goes through the
  // request-evaluator.
  if (override == base)
    return true;

  ASTContext &ctx = override->getASTContext();
  auto &diags = ctx.Diags;

  // Check property and subscript overriding.
  if (auto *baseASD = dyn_cast<AbstractStorageDecl>(base)) {
    auto *overrideASD = cast<AbstractStorageDecl>(override);

    // Make sure that the overriding property doesn't have storage.
    if ((overrideASD->hasStorage() ||
         overrideASD->getAttrs().hasAttribute<LazyAttr>()) &&
        !(overrideASD->getParsedAccessor(AccessorKind::WillSet) ||
          overrideASD->getParsedAccessor(AccessorKind::DidSet))) {
      bool downgradeToWarning = false;
      if (!ctx.isSwiftVersionAtLeast(5) &&
          overrideASD->getAttrs().hasAttribute<LazyAttr>()) {
        // Swift 4.0 had a bug where lazy properties were considered
        // computed by the time of this check. Downgrade this diagnostic to
        // a warning.
        downgradeToWarning = true;
      }
      auto diagID = downgradeToWarning ?
          diag::override_with_stored_property_warn :
          diag::override_with_stored_property;
      diags.diagnose(overrideASD, diagID,
                     overrideASD->getBaseName().getIdentifier());
      diags.diagnose(baseASD, diag::property_override_here);
      if (!downgradeToWarning)
        return true;
    }

    // Make sure that an observing property isn't observing something
    // read-only.  Observing properties look at change, read-only properties
    // have nothing to observe!
    bool baseIsSettable = baseASD->isSettable(baseASD->getDeclContext());
    if (baseIsSettable) {
      baseIsSettable =
         baseASD->isSetterAccessibleFrom(overrideASD->getDeclContext());
    }
    if (overrideASD->getWriteImpl() == WriteImplKind::InheritedWithObservers
        && !baseIsSettable) {
      diags.diagnose(overrideASD, diag::observing_readonly_property,
                     overrideASD->getBaseName().getIdentifier());
      diags.diagnose(baseASD, diag::property_override_here);
      return true;
    }

    // Make sure we're not overriding a settable property with a non-settable
    // one.  The only reasonable semantics for this would be to inherit the
    // setter but override the getter, and that would be surprising at best.
    if (baseIsSettable && !overrideASD->isSettable(override->getDeclContext())) {
      diags.diagnose(overrideASD, diag::override_mutable_with_readonly_property,
                     overrideASD->getBaseName().getIdentifier());
      diags.diagnose(baseASD, diag::property_override_here);
      return true;
    }


    // Make sure a 'let' property is only overridden by 'let' properties.  A
    // let property provides more guarantees than the getter of a 'var'
    // property.
    if (auto VD = dyn_cast<VarDecl>(baseASD)) {
      if (VD->isLet()) {
        diags.diagnose(overrideASD, diag::override_let_property,
                    VD->getName());
        diags.diagnose(baseASD, diag::property_override_here);
        return true;
      }
    }
  }

  // Various properties are only checked for the storage declarations
  // and not for the individual accessors. Otherwise, we end up with
  // duplicated diagnostics.
  bool isAccessor = isa<AccessorDecl>(override);

  // Non-Objective-C declarations in extensions cannot override or
  // be overridden.
  if (!isAccessor &&
      (isa<ExtensionDecl>(base->getDeclContext()) ||
       isa<ExtensionDecl>(override->getDeclContext())) &&
      !base->isObjC()) {
    // Suppress this diagnostic for overrides of a non-open NSObject.hashValue
    // property; these are diagnosed elsewhere. An error message complaining
    // about extensions would be misleading in this case; the correct fix is to
    // override NSObject.hash instead.
    if (isNSObjectHashValue(base) && 
        !base->hasOpenAccess(override->getDeclContext()))
      return true;
    bool baseCanBeObjC = canBeRepresentedInObjC(base);
    diags.diagnose(override, diag::override_decl_extension, baseCanBeObjC,
                   !isa<ExtensionDecl>(base->getDeclContext()));
    if (baseCanBeObjC) {
      SourceLoc insertionLoc =
        override->getAttributeInsertionLoc(/*forModifier=*/false);
      diags.diagnose(base, diag::overridden_here_can_be_objc)
        .fixItInsert(insertionLoc, "@objc ");
    } else {
      diags.diagnose(base, diag::overridden_here);
    }

    return true;
  }

  // If the overriding declaration does not have the 'override' modifier on
  // it, complain.
  if (!override->getAttrs().hasAttribute<OverrideAttr>() &&
      overrideRequiresKeyword(base) != OverrideRequiresKeyword::Never &&
      !override->isImplicit() &&
      override->getDeclContext()->getParentSourceFile()) {
    auto theDiag =
      overrideRequiresKeyword(base) == OverrideRequiresKeyword::Always
        ? diag::missing_override
        : diag::missing_override_warn;

    auto diagLoc = override->getStartLoc();
    // If dynamic cast to VarDecl succeeds, use the location of its parent
    // pattern binding which will return the VarLoc.
    if (auto VD = dyn_cast<VarDecl>(override)) {
      diagLoc = VD->getParentPatternBinding()->getLoc();
    }

    diags.diagnose(override, theDiag).fixItInsert(diagLoc, "override ");
    diags.diagnose(base, diag::overridden_here);
  }

  // If the overridden method is declared in a Swift Class Declaration,
  // dispatch will use table dispatch. If the override is in an extension
  // warn, since it is not added to the class vtable.
  //
  // FIXME: Only warn if the extension is in another module, and if
  // it is in the same module, update the vtable.
  if (auto *baseDecl = dyn_cast<ClassDecl>(base->getDeclContext())) {
    if (!isAccessor &&
        baseDecl->hasKnownSwiftImplementation() &&
        !base->isObjCDynamic() &&
        isa<ExtensionDecl>(override->getDeclContext())) {
      diags.diagnose(override, diag::override_class_declaration_in_extension);
      diags.diagnose(base, diag::overridden_here);
    }
  }
  // If the overriding declaration is 'throws' but the base is not,
  // complain.
  if (auto overrideFn = dyn_cast<AbstractFunctionDecl>(override)) {
    if (overrideFn->hasThrows() &&
        !cast<AbstractFunctionDecl>(base)->hasThrows()) {
      diags.diagnose(override, diag::override_throws,
                  isa<ConstructorDecl>(override));
      diags.diagnose(base, diag::overridden_here);
    }

    if (!overrideFn->hasThrows() && base->isObjC() &&
        cast<AbstractFunctionDecl>(base)->hasThrows()) {
      diags.diagnose(override, diag::override_throws_objc,
                     isa<ConstructorDecl>(override));
      diags.diagnose(base, diag::overridden_here);
    }
  }

  // The overridden declaration cannot be 'final'.
  if (base->isFinal() && !isAccessor) {
    // FIXME: Customize message to the kind of thing.
    auto baseKind = base->getDescriptiveKind();
    switch (baseKind) {
    case DescriptiveDeclKind::StaticProperty:
    case DescriptiveDeclKind::StaticMethod:
    case DescriptiveDeclKind::StaticSubscript:
      override->diagnose(diag::override_static, baseKind);
      break;
    default:
      override->diagnose(diag::override_final,
                         override->getDescriptiveKind(), baseKind);
      break;
    }

    base->diagnose(diag::overridden_here);

    return true;
  }

  // FIXME: Possibly should extend to more availability checking.
  if (auto *attr = base->getAttrs().getUnavailable(ctx)) {
    diagnoseUnavailableOverride(override, base, attr);
  }

  if (!ctx.LangOpts.DisableAvailabilityChecking) {
    diagnoseOverrideForAvailability(override, base);
  }

  // Overrides of NSObject.hashValue are deprecated; one should override
  // NSObject.hash instead.
  // FIXME: Remove this when NSObject.hashValue becomes non-open in
  // swift-corelibs-foundation.
  if (isNSObjectHashValue(base) &&
      base->hasOpenAccess(override->getDeclContext())) {
    override->diagnose(diag::override_nsobject_hashvalue_warning)
      .fixItReplace(SourceRange(override->getNameLoc()), "hash");
  }

  /// Check attributes associated with the base; some may need to merged with
  /// or checked against attributes in the overriding declaration.
  AttributeOverrideChecker attrChecker(base, override);
  for (auto attr : base->getAttrs()) {
    attrChecker.visit(attr);
  }

  return false;
}

/// Minimize the set of overridden associated types, eliminating any
/// associated types that are overridden by other associated types.
static void minimizeOverriddenAssociatedTypes(
                           llvm::TinyPtrVector<ValueDecl *> &assocTypes) {
  // Mark associated types that are "worse" than some other associated type,
  // because they come from an inherited protocol.
  bool anyWorse = false;
  std::vector<bool> worseThanAny(assocTypes.size(), false);
  for (unsigned i : indices(assocTypes)) {
    auto assoc1 = cast<AssociatedTypeDecl>(assocTypes[i]);
    auto proto1 = assoc1->getProtocol();
    for (unsigned j : range(i + 1, assocTypes.size())) {
      auto assoc2 = cast<AssociatedTypeDecl>(assocTypes[j]);
      auto proto2 = assoc2->getProtocol();
      if (proto1->inheritsFrom(proto2)) {
        anyWorse = true;
        worseThanAny[j] = true;
      } else if (proto2->inheritsFrom(proto1)) {
        anyWorse = true;
        worseThanAny[i] = true;
        break;
      }
    }
  }

  // If we didn't find any associated types that were "worse", we're done.
  if (!anyWorse) return;

  // Copy in the associated types that aren't worse than any other associated
  // type.
  unsigned nextIndex = 0;
  MutableArrayRef<ValueDecl *> buffer = assocTypes;
  for (unsigned i : indices(buffer)) {
    if (worseThanAny[i]) continue;
    buffer[nextIndex++] = buffer[i];
  }

  assocTypes.erase(assocTypes.begin() + nextIndex, assocTypes.end());
}

/// Sort associated types just based on the protocol.
static int compareSimilarAssociatedTypes(ValueDecl *const *lhs,
                                         ValueDecl *const *rhs) {
  auto lhsProto = cast<AssociatedTypeDecl>(*lhs)->getProtocol();
  auto rhsProto = cast<AssociatedTypeDecl>(*rhs)->getProtocol();
  return TypeDecl::compare(lhsProto, rhsProto);
}

/// Compute the set of associated types that are overridden by the given
/// associated type.
static llvm::TinyPtrVector<ValueDecl *>
computeOverriddenAssociatedTypes(AssociatedTypeDecl *assocType) {
  // Find associated types with the given name in all of the inherited
  // protocols.
  llvm::TinyPtrVector<ValueDecl *> overriddenAssocTypes;
  auto proto = assocType->getProtocol();
  proto->walkInheritedProtocols([&](ProtocolDecl *inheritedProto) {
    if (proto == inheritedProto) return TypeWalker::Action::Continue;

    // Objective-C protocols
    if (inheritedProto->isObjC()) return TypeWalker::Action::Continue;

    // Look for associated types with the same name.
    bool foundAny = false;
    if (auto found = inheritedProto->getAssociatedType(assocType->getName())) {
      overriddenAssocTypes.push_back(found);
      foundAny = true;
    }

    return foundAny ? TypeWalker::Action::SkipChildren
                    : TypeWalker::Action::Continue;
  });

  // Minimize the set of inherited associated types, eliminating any that
  // themselves are overridden.
  minimizeOverriddenAssociatedTypes(overriddenAssocTypes);

  // Sort the set of inherited associated types.
  llvm::array_pod_sort(overriddenAssocTypes.begin(),
                       overriddenAssocTypes.end(),
                       compareSimilarAssociatedTypes);

  return overriddenAssocTypes;
}

llvm::Expected<llvm::TinyPtrVector<ValueDecl *>>
OverriddenDeclsRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
  // Value to return in error cases
  auto noResults = llvm::TinyPtrVector<ValueDecl *>();

  // If there is a @_nonoverride attribute, this does not override anything.
  if (decl->getAttrs().hasAttribute<NonOverrideAttr>())
    return noResults;

  // For an associated type, compute the (minimized) set of overridden
  // declarations.
  if (auto assocType = dyn_cast<AssociatedTypeDecl>(decl)) {
    return computeOverriddenAssociatedTypes(assocType);
  }

  // Only members of classes or protocols can override other declarations.
  if (!decl->getDeclContext()->getSelfClassDecl() &&
      !isa<ProtocolDecl>(decl->getDeclContext()))
    return noResults;

  // Types that aren't associated types cannot be overridden.
  if (isa<TypeDecl>(decl))
    return noResults;

  // Accessors determine their overrides based on their abstract storage
  // declarations.
  if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
    auto overridingASD = accessor->getStorage();

    // Check the various overridden storage declarations.
    SmallVector<OverrideMatch, 2> matches;
    for (auto overridden : overridingASD->getOverriddenDecls()) {
      auto baseASD = cast<AbstractStorageDecl>(overridden);
      auto kind = accessor->getAccessorKind();

      // If the base doesn't consider this an opaque accessor,
      // this isn't really an override.
      if (!baseASD->requiresOpaqueAccessor(kind))
        continue;

      // Find the base accessor; if there isn't one, we're done.
      auto baseAccessor = baseASD->getOpaqueAccessor(kind);
      if (!baseAccessor)
        continue;

      assert(!baseAccessor->hasForcedStaticDispatch() &&
             "opaque accessor with forced static dispatch?");

      switch (kind) {
      case AccessorKind::Get:
      case AccessorKind::Read:
        break;

      case AccessorKind::Modify:
      case AccessorKind::Set:
        // For setter accessors, we need the base's setter to be
        // accessible from the overriding context, or it's not an override.
        if (!baseASD->isSetterAccessibleFrom(overridingASD->getDeclContext()))
          continue;
        break;

#define OPAQUE_ACCESSOR(ID, KEYWORD)
#define ACCESSOR(ID) \
      case AccessorKind::ID:
#include "swift/AST/AccessorKinds.def"
        llvm_unreachable("non-opaque accessor was required as opaque by base");
      }

      // We are overriding the base accessor.
      matches.push_back({baseAccessor, /*IsExact=*/true});
    }

    if (matches.empty())
      return noResults;

    // Check the correctness of the overrides.
    OverrideMatcher matcher(accessor);
    return matcher.checkPotentialOverrides(
                                       matches,
                                       OverrideCheckingAttempt::PerfectMatch);
  }

  // Only initializers, declarations marked with the 'override' declaration
  // modifier, and members of protocols can override declarations.
  if (!isa<ConstructorDecl>(decl) &&
      !isa<ProtocolDecl>(decl->getDeclContext()) &&
      !decl->getAttrs().hasAttribute<OverrideAttr>())
    return noResults;

  // Try to match potential overridden declarations.
  OverrideMatcher matcher(decl);
  if (!matcher) {
    return noResults;
  }

  auto matches = matcher.match(OverrideCheckingAttempt::PerfectMatch);
  if (matches.empty()) {
    return noResults;
  }

  // If we have more than one potential match from a class, diagnose the
  // ambiguity and fail.
  if (matches.size() > 1 && decl->getDeclContext()->getSelfClassDecl()) {
    diagnoseGeneralOverrideFailure(decl, matches,
                                   OverrideCheckingAttempt::PerfectMatch);
    invalidateOverrideAttribute(decl);
    return noResults;
  }

  // Check the matches. If any are ill-formed, invalidate the override attribute
  // so we don't try again.
  return matcher.checkPotentialOverrides(matches,
                                         OverrideCheckingAttempt::PerfectMatch);
}

llvm::Expected<bool>
IsABICompatibleOverrideRequest::evaluate(Evaluator &evaluator,
                                         ValueDecl *decl) const {
  auto base = decl->getOverriddenDecl();
  if (!base)
    return false;

  auto baseInterfaceTy = base->getInterfaceType();
  auto derivedInterfaceTy = decl->getInterfaceType();

  auto selfInterfaceTy = decl->getDeclContext()->getDeclaredInterfaceType();

  auto overrideInterfaceTy = selfInterfaceTy->adjustSuperclassMemberDeclType(
      base, decl, baseInterfaceTy);

  return derivedInterfaceTy->matches(overrideInterfaceTy,
                                     TypeMatchFlags::AllowABICompatible);
}
