//===--- CodeSynthesis.cpp - Type Checking for Declarations ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 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 declarations.
//
//===----------------------------------------------------------------------===//

#include "CodeSynthesis.h"

#include "DerivedConformance/DerivedConformance.h"
#include "TypeCheckDecl.h"
#include "TypeCheckDistributed.h"
#include "TypeCheckObjC.h"
#include "TypeCheckType.h"
#include "TypeChecker.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/AvailabilityInference.h"
#include "swift/AST/ConformanceLookup.h"
#include "swift/AST/DistributedDecl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Assertions.h"
#include "swift/Basic/Defer.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Sema/ConstraintSystem.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
using namespace swift;

const bool IsImplicit = true;

Expr *swift::buildSelfReference(VarDecl *selfDecl,
                                SelfAccessorKind selfAccessorKind,
                                bool isLValue, Type convertTy) {
  auto &ctx = selfDecl->getASTContext();
  auto selfTy = selfDecl->getTypeInContext();

  switch (selfAccessorKind) {
  case SelfAccessorKind::Peer:
    assert(!convertTy || convertTy->isEqual(selfTy));
    return new (ctx) DeclRefExpr(selfDecl, DeclNameLoc(), IsImplicit,
                                 AccessSemantics::Ordinary,
                                 isLValue ? LValueType::get(selfTy) : selfTy);

  case SelfAccessorKind::Super: {
    assert(!isLValue);

    // Get the superclass type of self, looking through a metatype if needed.
    auto isMetatype = false;
    if (auto *metaTy = selfTy->getAs<MetatypeType>()) {
      isMetatype = true;
      selfTy = metaTy->getInstanceType();
    }
    selfTy = selfTy->getSuperclass();
    if (!selfTy) {
      // Error recovery path. We end up here if getSuperclassDecl() succeeds
      // but getSuperclass() fails (because, for instance, a generic parameter
      // of a generic nominal type cannot be resolved).
      selfTy = ErrorType::get(ctx);
    }
    if (isMetatype)
      selfTy = MetatypeType::get(selfTy);

    auto *superRef =
        new (ctx) SuperRefExpr(selfDecl, SourceLoc(), IsImplicit, selfTy);

    // If no conversion type was specified, or we're already at that type, we're
    // done.
    if (!convertTy || convertTy->isEqual(selfTy) || selfTy->is<ErrorType>())
      return superRef;

    // Insert the appropriate expr to handle the upcast.
    if (isMetatype) {
      assert(convertTy->castTo<MetatypeType>()
                 ->getInstanceType()
                 ->isExactSuperclassOf(selfTy->getMetatypeInstanceType()));
      return new (ctx) MetatypeConversionExpr(superRef, convertTy);
    } else {
      assert(convertTy->isExactSuperclassOf(selfTy));
      return new (ctx) DerivedToBaseExpr(superRef, convertTy);
    }
  }
  }
  llvm_unreachable("bad self access kind");
}

Argument swift::buildSelfArgument(VarDecl *selfDecl,
                                  SelfAccessorKind selfAccessorKind,
                                  bool isMutable) {
  auto &ctx = selfDecl->getASTContext();
  auto *selfRef = buildSelfReference(selfDecl, selfAccessorKind, isMutable);
  return isMutable ? Argument::implicitInOut(ctx, selfRef)
                   : Argument::unlabeled(selfRef);
}

/// Build an argument list that forwards references to the specified parameter
/// list.
ArgumentList *swift::buildForwardingArgumentList(ArrayRef<ParamDecl *> params,
                                                 ASTContext &ctx) {
  SmallVector<Argument, 4> args;
  for (auto *param : params) {
    auto type = param->getTypeInContext();

    Expr *ref = new (ctx) DeclRefExpr(param, DeclNameLoc(), /*implicit*/ true);
    ref->setType(param->isInOut() ? LValueType::get(type) : type);

    if (param->isInOut()) {
      ref = new (ctx) InOutExpr(SourceLoc(), ref, type, /*isImplicit=*/true);
    } else if (param->isVariadic()) {
      assert(ref->getType()->isEqual(type));
      ref = VarargExpansionExpr::createParamExpansion(ctx, ref);
    }
    args.emplace_back(SourceLoc(), param->getArgumentName(), ref);
  }
  return ArgumentList::createImplicit(ctx, args);
}

static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var,
                                         ASTContext &ctx) {
  // First and foremost, if this is a constant don't bother.
  if (var->isLet())
    return;

  // If there's no parent pattern there's not enough structure to even perform
  // this analysis. Just bail.
  if (!var->getParentPattern())
    return;

  // We can only provide default values for patterns binding a single variable.
  // i.e. var (a, b) = getSomeTuple() is not allowed.
  if (!var->getParentPattern()->getSingleVar())
    return;

  // Whether we have explicit initialization.
  bool isExplicitlyInitialized = false;
  if (auto pbd = var->getParentPatternBinding()) {
    const auto i = pbd->getPatternEntryIndexForVarDecl(var);
    isExplicitlyInitialized = pbd->isExplicitlyInitialized(i);
  }

  // Whether we can default-initialize this property.
  auto binding = var->getParentPatternBinding();
  bool isDefaultInitializable =
      var->getAttrs().hasAttribute<LazyAttr>() ||
      (binding && binding->isDefaultInitializable());

  // If this is neither explicitly initialized nor
  // default-initializable, don't add anything.
  if (!isExplicitlyInitialized && !isDefaultInitializable)
    return;

  // We can add a default value now.

  // If the variable has a type T? and no initial value, return a nil literal
  // default arg. All lazy variables return a nil literal as well. *Note* that
  // the type will always be a sugared T? because we don't default init an
  // explicit Optional<T>.
  bool isNilInitialized =
    var->getAttrs().hasAttribute<LazyAttr>() ||
    (!isExplicitlyInitialized && isDefaultInitializable &&
     var->getValueInterfaceType()->isOptional() &&
     (var->getAttachedPropertyWrappers().empty() ||
      var->isPropertyMemberwiseInitializedWithWrappedType()));
  if (isNilInitialized) {
    arg->setDefaultArgumentKind(DefaultArgumentKind::NilLiteral);
    return;
  }

  // If there's a backing storage property, the memberwise initializer
  // will be in terms of that.
  VarDecl *backingStorageVar = var->getPropertyWrapperBackingProperty();

  // Set the default value to the variable. When we emit this in silgen
  // we're going to call the variable's initializer expression.
  arg->setStoredProperty(backingStorageVar ? backingStorageVar : var);
  arg->setDefaultArgumentKind(DefaultArgumentKind::StoredProperty);
}

/// Describes the kind of implicit constructor that will be
/// generated.
enum class ImplicitConstructorKind {
  /// The default constructor, which default-initializes each
  /// of the instance variables.
  Default,
  /// The default constructor of a distributed actor.
  /// Similarly to a Default one it initializes each of the instance variables,
  /// however it also implicitly gains an DistributedActorSystem parameter.
  DefaultDistributedActor,
  /// The memberwise constructor, which initializes each of
  /// the instance variables from a parameter of the same type and
  /// name.
  Memberwise,
};

static ParamDecl *createMemberwiseInitParameter(DeclContext *DC,
                                                SourceLoc paramLoc,
                                                VarDecl *var) {
  auto &ctx = var->getASTContext();
  auto varInterfaceType = var->getValueInterfaceType();
  bool isAutoClosure = false;

  if (var->getAttrs().hasAttribute<LazyAttr>()) {
    // If var is a lazy property, its value is provided for the underlying
    // storage.  We thus take an optional of the property's type.  We only
    // need to do this because the implicit initializer is added before all
    // the properties are type checked.  Perhaps init() synth should be
    // moved later.
    varInterfaceType = OptionalType::get(varInterfaceType);
  } else if (Type backingPropertyType =
                 var->getPropertyWrapperBackingPropertyType()) {
    // For a property that has a wrapper, writing the initializer
    // with an '=' implies that the memberwise initializer should also
    // accept a value of the original property type. Otherwise, the
    // memberwise initializer will be in terms of the backing storage
    // type.
    if (var->isPropertyMemberwiseInitializedWithWrappedType()) {
      if (auto initTy = var->getPropertyWrapperInitValueInterfaceType()) {
        varInterfaceType = initTy;

        auto initInfo = var->getPropertyWrapperInitializerInfo();
        isAutoClosure = initInfo.getWrappedValuePlaceholder()->isAutoClosure();
      }
    } else {
      varInterfaceType = backingPropertyType;
    }
  }

  Type resultBuilderType = var->getResultBuilderType();
  if (resultBuilderType) {
    // If the variable's type is structurally a function type, use that
    // type. Otherwise, form a non-escaping function type for the function
    // parameter.
    bool isStructuralFunctionType =
        varInterfaceType->lookThroughAllOptionalTypes()->is<AnyFunctionType>();
    if (!isStructuralFunctionType) {
      auto extInfo = ASTExtInfoBuilder().withNoEscape().build();
      varInterfaceType = FunctionType::get({}, varInterfaceType, extInfo);
    }
  }

  // Create the parameter.
  ParamDecl *arg =
      ParamDecl::createImplicit(ctx, /*specifierLoc=*/SourceLoc(), paramLoc,
                                var->getName(), paramLoc, var->getName(),
                                varInterfaceType, DC, ParamSpecifier::Default);
  arg->setAutoClosure(isAutoClosure);

  // Don't allow the parameter to accept temporary pointer conversions.
  arg->setNonEphemeralIfPossible();

  // Attach a result builder attribute if needed.
  if (resultBuilderType) {
    auto typeExpr = TypeExpr::createImplicit(resultBuilderType, ctx);
    auto attr = CustomAttr::create(ctx, SourceLoc(), typeExpr, /*owner*/ arg,
                                   /*implicit=*/true);
    arg->addAttribute(attr);
  }

  maybeAddMemberwiseDefaultArg(arg, var, ctx);

  return arg;
}

/// Create an implicit struct or class constructor.
///
/// \param decl The struct or class for which a constructor will be created.
/// \param ICK The kind of implicit constructor to create.
///
/// \returns The newly-created constructor, which has already been type-checked
/// (but has not been added to the containing struct or class).
static ConstructorDecl *
createImplicitConstructor(NominalTypeDecl *decl, ImplicitConstructorKind ICK,
                          std::optional<MemberwiseInitKind> memberwiseKind,
                          ASTContext &ctx) {
  ASSERT(ICK != ImplicitConstructorKind::Memberwise || memberwiseKind);
  assert(!decl->hasClangNode());

  SourceLoc Loc = decl->getLoc();
  auto accessLevel = AccessLevel::Internal;

  // Determine the parameter type of the implicit constructor.
  SmallVector<ParamDecl*, 8> params;
  SmallVector<DefaultArgumentInitializer *, 8> defaultInits;
  if (ICK == ImplicitConstructorKind::Memberwise) {
    assert(isa<StructDecl>(decl) && "Only struct have memberwise constructor");

    for (auto var : decl->getMemberwiseInitProperties(memberwiseKind.value())) {
      accessLevel = std::min(accessLevel, var->getFormalAccess());
      params.push_back(createMemberwiseInitParameter(decl, Loc, var));
    }
  } else if (ICK == ImplicitConstructorKind::DefaultDistributedActor) {
    auto classDecl = dyn_cast<ClassDecl>(decl);
    assert(classDecl && decl->isDistributedActor() &&
           "Only 'distributed actor' type can gain implicit distributed actor init");

    /// Add 'system' parameter to default init of distributed actors.
    if (swift::ensureDistributedModuleLoaded(decl)) {
      // copy access level of distributed actor init from the nominal decl
      accessLevel = decl->getEffectiveAccess();
      auto systemTy = getDistributedActorSystemType(classDecl);

      // Create the parameter. API name is actorSystem, local name is system
      ParamDecl *arg =
          ParamDecl::createImplicit(ctx, /*specifierLoc=*/SourceLoc(), Loc,
                                    ctx.Id_actorSystem, Loc, ctx.Id_system,
                                    systemTy, decl, ParamSpecifier::Default);

      params.push_back(arg);
    }
  }

  auto paramList = ParameterList::create(ctx, params);
  
  // Create the constructor.
  DeclName name(ctx, DeclBaseName::createConstructor(), paramList);
  auto *ctor = new (ctx) ConstructorDecl(
      name, Loc,
      /*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
      /*Async=*/false, /*AsyncLoc=*/SourceLoc(),
      /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
      /*ThrownType=*/TypeLoc(), paramList, /*GenericParams=*/nullptr, decl);

  // Mark implicit.
  ctor->setImplicit();
  ctor->setSynthesized();
  ctor->setAccess(accessLevel);

  if (ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues) &&
      !decl->isActor()) {
    // If any of the type's actor-isolated properties:
    //   1. Have non-Sendable type, or
    //   2. Have an isolated initial value
    // then the initializer must also be actor-isolated. If all
    // isolated properties have Sendable type and a nonisolated
    // default value, then the initializer can be nonisolated.
    //
    // These rules only apply for global actor isolation, because actor
    // initializers apply Sendable checking to arguments at the call-site,
    // and actor initializers do not run on the actor, so initial values
    // cannot be actor-instance-isolated.
    ActorIsolation existingIsolation = getActorIsolation(decl);
    VarDecl *previousVar = nullptr;
    bool hasError = false;

    // FIXME: Calling `getAllMembers` here causes issues for conformance
    // synthesis to RawRepresentable and friends. Instead, iterate over
    // both the stored properties and the init accessor properties, as
    // those can participate in implicit initializers.

    auto stored = decl->getStoredProperties();
    auto initAccessor = decl->getInitAccessorProperties();

    auto shouldAddNonisolated = [&](ArrayRef<VarDecl *> properties) {
      if (hasError)
        return false;

      bool addNonisolated = true;
      for (auto *var : properties) {
        auto *pbd = var->getParentPatternBinding();
        if (!pbd)
          continue;

        auto i = pbd->getPatternEntryIndexForVarDecl(var);
        if (pbd->isInitializerSubsumed(i))
          continue;

        ActorIsolation initIsolation;
        if (var->hasInitAccessor()) {
          // Init accessors share the actor isolation of the property;
          // the accessor body can call anything in that isolation domain,
          // and we don't attempt to infer when the isolation isn't
          // necessary.
          initIsolation = getActorIsolation(var);
        } else {
          initIsolation = var->getInitializerIsolation();
        }

        auto type = var->getInterfaceType();

        // If a property has a property wrapper, the memberwise initializer
        // could use a wrapped type instead of a backing storage type depending
        // on a property wrapper capabilities. Sendable check has to be
        // performed on the type that would be used by the initializer.
        if (ICK == ImplicitConstructorKind::Memberwise) {
          if (auto *property = var->getOriginalVarForBackingStorage()) {
            if (property->isPropertyMemberwiseInitializedWithWrappedType())
              type = property->getPropertyWrapperInitValueInterfaceType();
          }
        }

        type = decl->mapTypeIntoEnvironment(type);

        auto isolation = getActorIsolation(var);
        if (isolation.isGlobalActor()) {
          if (!type->isSendableType() ||
              initIsolation.isGlobalActor()) {
            // If different isolated stored properties require different
            // global actors, it is impossible to initialize this type.
            if (existingIsolation != isolation) {
              ctx.Diags
                  .diagnose(decl->getLoc(),
                            diag::conflicting_stored_property_isolation,
                            ICK == ImplicitConstructorKind::Memberwise,
                            decl->getDeclaredType(), existingIsolation,
                            isolation)
                  .warnUntilLanguageMode(LanguageMode::v6);
              if (previousVar) {
                previousVar->diagnose(diag::property_requires_actor,
                                      previousVar, existingIsolation);
              }
              var->diagnose(diag::property_requires_actor, var, isolation);
              hasError = true;
              return false;
            }

            existingIsolation = isolation;
            previousVar = var;
            addNonisolated = false;
          }
        }
      }

      return addNonisolated;
    };

    if (shouldAddNonisolated(stored) &&
        shouldAddNonisolated(initAccessor)) {
      addNonIsolatedToSynthesized(decl, ctor);
    }
  }

  if (ICK == ImplicitConstructorKind::Memberwise) {
    ctor->setIsMemberwiseInitializer(memberwiseKind.value());

    if (!ctx.LangOpts.hasFeature(Feature::IsolatedDefaultValues)) {
      addNonIsolatedToSynthesized(decl, ctor);
    }
  }

  // If we are defining a default initializer for a class that has a superclass,
  // it overrides the default initializer of its superclass. Add an implicit
  // 'override' attribute.
  if (auto classDecl = dyn_cast<ClassDecl>(decl)) {
    if (classDecl->getSuperclass())
      ctor->addAttribute(new (ctx) OverrideAttr(/*IsImplicit=*/true));
  }

  return ctor;
}

/// Create a stub body that emits a fatal error message.
static std::pair<BraceStmt *, bool>
synthesizeStubBody(AbstractFunctionDecl *fn, void *) {
  auto *ctor = cast<ConstructorDecl>(fn);
  auto &ctx = ctor->getASTContext();

  auto unimplementedInitDecl = ctx.getUnimplementedInitializer();
  auto classDecl = ctor->getDeclContext()->getSelfClassDecl();
  if (!unimplementedInitDecl) {
    ctx.Diags.diagnose(classDecl->getLoc(),
                       diag::missing_unimplemented_init_runtime);
    return { nullptr, true };
  }

  auto *staticStringDecl = ctx.getStaticStringDecl();
  auto staticStringType = staticStringDecl->getDeclaredInterfaceType();
  auto staticStringInit = ctx.getStringBuiltinInitDecl(staticStringDecl);

  auto *uintDecl = ctx.getUIntDecl();
  auto uintType = uintDecl->getDeclaredInterfaceType();
  auto uintInit = ctx.getIntBuiltinInitDecl(uintDecl);

  // Create a call to Swift._unimplementedInitializer
  auto loc = classDecl->getLoc();
  Expr *ref = new (ctx) DeclRefExpr(unimplementedInitDecl,
                                   DeclNameLoc(loc),
                                   /*Implicit=*/true);
  ref->setType(unimplementedInitDecl->getInterfaceType()
                                    ->removeArgumentLabels(1));

  llvm::SmallString<64> buffer;
  StringRef fullClassName = ctx.AllocateCopy(
                              (classDecl->getModuleContext()->getName().str() +
                               "." +
                               classDecl->getName().str()).toStringRef(buffer));

  auto *className = new (ctx) StringLiteralExpr(fullClassName, loc,
                                                /*Implicit=*/true);
  className->setBuiltinInitializer(staticStringInit);
  assert(isa<ConstructorDecl>(className->getBuiltinInitializer().getDecl()));
  className->setType(staticStringType);

  auto *initName = new (ctx) MagicIdentifierLiteralExpr(
    MagicIdentifierLiteralExpr::Function, loc, /*Implicit=*/true);
  initName->setType(staticStringType);
  initName->setBuiltinInitializer(staticStringInit);

  auto *file = new (ctx) MagicIdentifierLiteralExpr(
    MagicIdentifierLiteralExpr::FileID, loc, /*Implicit=*/true);
  file->setType(staticStringType);
  file->setBuiltinInitializer(staticStringInit);

  auto *line = new (ctx) MagicIdentifierLiteralExpr(
    MagicIdentifierLiteralExpr::Line, loc, /*Implicit=*/true);
  line->setType(uintType);
  line->setBuiltinInitializer(uintInit);

  auto *column = new (ctx) MagicIdentifierLiteralExpr(
    MagicIdentifierLiteralExpr::Column, loc, /*Implicit=*/true);
  column->setType(uintType);
  column->setBuiltinInitializer(uintInit);

  auto *argList = ArgumentList::forImplicitUnlabeled(
      ctx, {className, initName, file, line, column});
  auto *call = CallExpr::createImplicit(ctx, ref, argList);
  call->setType(ctx.getNeverType());
  call->setThrows(nullptr);

  SmallVector<ASTNode, 2> stmts;
  stmts.push_back(call);
  stmts.push_back(ReturnStmt::createImplicit(ctx, /*Result=*/nullptr));
  return { BraceStmt::create(ctx, SourceLoc(), stmts, SourceLoc(),
                             /*implicit=*/true),
           /*isTypeChecked=*/true };
}

/// Clone the base class initializer's generic parameter list, but change the
/// depth of the generic parameters to be one greater than the depth of the
/// subclass.
static GenericParamList *
createDesignatedInitOverrideGenericParams(ASTContext &ctx,
                                          ClassDecl *classDecl,
                                          ConstructorDecl *superclassCtor) {
  auto *genericParams = superclassCtor->getGenericParams();

  // If genericParams is non-null, the base class initializer has its own
  // generic parameters. Otherwise, it is non-generic with a contextual
  // 'where' clause.
  if (genericParams == nullptr)
    return nullptr;

  unsigned depth = classDecl->getGenericSignature().getNextDepth();

  SmallVector<GenericTypeParamDecl *, 4> newParams;
  for (auto *param : genericParams->getParams()) {
    auto *newParam = GenericTypeParamDecl::createImplicit(
        classDecl, param->getName(), depth, param->getIndex(),
        param->getParamKind());
    newParams.push_back(newParam);
  }

  return GenericParamList::create(ctx, SourceLoc(),
                                  newParams, SourceLoc(),
                                  ArrayRef<RequirementRepr>(), SourceLoc());
}

/// True if the type has an opaque clang implementation, meaning it is imported
/// and doesn't have an \c \@objcImplementation extension.
static bool hasClangImplementation(const NominalTypeDecl *decl) {
  return decl->hasClangNode() && !decl->getObjCImplementationDecl();
}

/// True if \p member is in the main body of \p ty, where the "main body" is
/// either the type itself (the usual case) or its \c \@objcImplementation
/// extension (if one is present).
static bool isInMainBody(ValueDecl *member, NominalTypeDecl *ty) {
  return member->getDeclContext() ==
              ty->getImplementationContext()->getAsGenericContext();
}

static void
configureInheritedDesignatedInitAttributes(ClassDecl *classDecl,
                                           ConstructorDecl *ctor,
                                           ConstructorDecl *superclassCtor,
                                           ASTContext &ctx) {
  assert(isInMainBody(ctor, classDecl));

  AccessLevel access = classDecl->getFormalAccess();
  access = std::max(access, AccessLevel::Internal);
  access = std::min(access, superclassCtor->getFormalAccess());

  ctor->setAccess(access);

  AccessScope superclassInliningAccessScope =
      superclassCtor->getFormalAccessScope(/*useDC*/nullptr,
                                           /*usableFromInlineAsPublic=*/true);

  if (superclassInliningAccessScope.isPublic()) {
    if (superclassCtor->getAttrs().hasAttribute<InlinableAttr>()) {
      // Inherit the @inlinable attribute.
      auto *clonedAttr = new (ctx) InlinableAttr(/*implicit=*/true);
      ctor->addAttribute(clonedAttr);
    } else if (superclassCtor->getAttrs().hasAttribute<InlineAttr>() &&
               superclassCtor->getAttrs().getAttribute<InlineAttr>()->getKind()
               == InlineKind::Always) {
      // Inherit the @inline(always) attribute.
      auto *clonedAttr = new (ctx) InlineAttr(SourceLoc(), SourceRange(),
                                              InlineKind::Always,
                                              /*implicit=*/true);
      ctor->addAttribute(clonedAttr);
    } else if (access == AccessLevel::Internal && !superclassCtor->isDynamic()){
      // Inherit the @usableFromInline attribute.
      auto *clonedAttr = new (ctx) UsableFromInlineAttr(/*implicit=*/true);
      ctor->addAttribute(clonedAttr);
    }
  }

  // Inherit the @discardableResult attribute.
  if (superclassCtor->getAttrs().hasAttribute<DiscardableResultAttr>()) {
    auto *clonedAttr = new (ctx) DiscardableResultAttr(/*implicit=*/true);
    ctor->addAttribute(clonedAttr);
  }

  // Inherit the rethrows attribute.
  if (superclassCtor->getAttrs().hasAttribute<RethrowsAttr>()) {
    auto *clonedAttr = new (ctx) RethrowsAttr(/*implicit=*/true);
    ctor->addAttribute(clonedAttr);
  }

  // If the superclass has its own availability, make sure the synthesized
  // constructor is only as available as its superclass's constructor.
  if (superclassCtor->getAttrs().hasAttribute<AvailableAttr>()) {
    SmallVector<const Decl *, 2> asAvailableAs;

    // We don't have to look at enclosing contexts of the superclass constructor,
    // because designated initializers must always be defined in the superclass
    // body, and we already enforce that a superclass is at least as available as
    // a subclass.
    asAvailableAs.push_back(superclassCtor);
    if (auto *parentDecl = classDecl->getInnermostDeclWithAvailability()) {
      asAvailableAs.push_back(parentDecl);
    }
    AvailabilityInference::applyInferredAvailableAttrs(ctor, asAvailableAs);
  }

  // Wire up the overrides.
  ctor->setOverriddenDecl(superclassCtor);

  if (superclassCtor->isRequired())
    ctor->addAttribute(new (ctx) RequiredAttr(/*IsImplicit=*/false));
  else
    ctor->addAttribute(new (ctx) OverrideAttr(/*IsImplicit=*/false));

  // If the superclass constructor is @objc but the subclass constructor is
  // not representable in Objective-C, add @nonobjc implicitly.
  std::optional<ForeignAsyncConvention> asyncConvention;
  std::optional<ForeignErrorConvention> errorConvention;
  if (superclassCtor->isObjC() &&
      !isRepresentableInLanguage(ctor, ObjCReason::MemberOfObjCSubclass,
                                 asyncConvention, errorConvention))
    ctor->addAttribute(new (ctx) NonObjCAttr(/*isImplicit=*/true));
}

static std::pair<BraceStmt *, bool>
synthesizeDesignatedInitOverride(AbstractFunctionDecl *fn, void *context) {
  auto *ctor = cast<ConstructorDecl>(fn);
  auto &ctx = ctor->getASTContext();

  auto *superclassCtor = (ConstructorDecl *) context;

  // Reference to super.init.
  auto *selfDecl = ctor->getImplicitSelfDecl();
  auto superArg = buildSelfArgument(selfDecl, SelfAccessorKind::Super,
                                    /*isMutable*/ false);

  SubstitutionMap subs;
  if (auto *genericEnv = fn->getGenericEnvironment())
    subs = genericEnv->getForwardingSubstitutionMap();
  subs = SubstitutionMap::getOverrideSubstitutions(superclassCtor, fn)
      .subst(subs);
  ConcreteDeclRef ctorRef(superclassCtor, subs);

  auto type = superclassCtor->getInitializerInterfaceType();
  if (auto *genericFnType = type->getAs<GenericFunctionType>())
    type = genericFnType->substGenericArgs(subs);
  auto *ctorRefExpr =
      new (ctx) OtherConstructorDeclRefExpr(ctorRef, DeclNameLoc(),
                                            IsImplicit, type);

  if (auto *funcTy = type->getAs<FunctionType>())
    type = funcTy->getResult();
  auto *superclassCtorRefExpr =
      DotSyntaxCallExpr::create(ctx, ctorRefExpr, SourceLoc(), superArg, type);
  superclassCtorRefExpr->setThrows(nullptr);

  auto *bodyParams = ctor->getParameters();
  auto *ctorArgs = buildForwardingArgumentList(bodyParams->getArray(), ctx);
  auto *superclassCallExpr =
      CallExpr::createImplicit(ctx, superclassCtorRefExpr, ctorArgs);

  if (auto *funcTy = type->getAs<FunctionType>())
    type = funcTy->getResult();
  superclassCallExpr->setType(type);
  if (auto thrownInterfaceType = ctor->getEffectiveThrownErrorType()) {
    Type superThrownType = ctor->mapTypeIntoEnvironment(*thrownInterfaceType);
    superclassCallExpr->setThrows(
        ThrownErrorDestination::forMatchingContextType(superThrownType));
  } else {
    superclassCallExpr->setThrows(nullptr);
  }

  Expr *expr = superclassCallExpr;

  if (superclassCtor->hasAsync()) {
    expr = new (ctx) AwaitExpr(SourceLoc(), expr, type, /*implicit=*/true);
  }
  if (superclassCtor->hasThrows()) {
    expr = new (ctx) TryExpr(SourceLoc(), expr, type, /*implicit=*/true);
  }

  auto *rebindSelfExpr =
    new (ctx) RebindSelfInConstructorExpr(expr, selfDecl);

  SmallVector<ASTNode, 2> stmts;
  stmts.push_back(rebindSelfExpr);
  stmts.push_back(ReturnStmt::createImplicit(ctx, /*Result=*/nullptr));
  return { BraceStmt::create(ctx, SourceLoc(), stmts, SourceLoc(),
                            /*implicit=*/true),
           /*isTypeChecked=*/true };
}

/// The kind of designated initializer to synthesize.
enum class DesignatedInitKind {
  /// A stub initializer, which is not visible to name lookup and
  /// merely aborts at runtime.
  Stub,

  /// An initializer that simply chains to the corresponding
  /// superclass initializer.
  Chaining
};

/// Create a new initializer that overrides the given designated
/// initializer.
///
/// \param classDecl The subclass in which the new initializer will
/// be declared.
///
/// \param superclassCtor The superclass initializer for which this
/// routine will create an override.
///
/// \param kind The kind of initializer to synthesize.
///
/// \returns the newly-created initializer that overrides \p
/// superclassCtor.
static ConstructorDecl *
createDesignatedInitOverride(ClassDecl *classDecl,
                             ConstructorDecl *superclassCtor,
                             DesignatedInitKind kind,
                             ASTContext &ctx) {
  // Lookup will sometimes give us initializers that are from the ancestors of
  // our immediate superclass.  So, from the superclass constructor, we look
  // one level up to the enclosing type context which will either be a class
  // or an extension.  We can use the type declared in that context to check
  // if it's our immediate superclass and give up if we didn't.
  //
  // FIXME: Remove this when lookup of initializers becomes restricted to our
  // immediate superclass.
  auto *superclassDecl = superclassCtor->getDeclContext()->getSelfClassDecl();
  if (classDecl->getSuperclassDecl() != superclassDecl)
    return nullptr;

  auto *genericParams = createDesignatedInitOverrideGenericParams(
      ctx, classDecl, superclassCtor);

  auto superclassCtorSig = superclassCtor->getGenericSignature();

  // Compute a generic signature for the initializer, and a substitution map
  // from the superclass initializer signature to the initializer generic
  // signature.
  auto subMap = SubstitutionMap::getOverrideSubstitutions(
      superclassDecl, classDecl, superclassCtorSig, genericParams);
  auto genericSig = ctx.getOverrideGenericSignature(
      superclassDecl, classDecl, superclassCtorSig, genericParams);

  assert(!subMap.getRecursiveProperties().hasArchetype());

  if (superclassCtorSig) {
    auto *genericEnv = genericSig.getGenericEnvironment();

    // If the base class initializer has a 'where' clause, it might impose
    // requirements on the base class's own generic parameters that are not
    // satisfied by the derived class. In this case, we don't want to inherit
    // this initializer; there's no way to call it on the derived class.
    auto checkResult = checkRequirements(
        superclassCtorSig.getRequirements(),
        [&](Type type) -> Type {
          auto substType = type.subst(subMap);
          return GenericEnvironment::mapTypeIntoEnvironment(genericEnv, substType);
        });
    if (checkResult != CheckRequirementsResult::Success)
      return nullptr;
  }

  // Create the initializer parameter list by cloning the superclass initializer
  // parameter list and applying the substitution map.
  OptionSet<ParameterList::CloneFlags> options
    = (ParameterList::Implicit |
       ParameterList::Inherited |
       ParameterList::NamedArguments);
  auto *superclassParams = superclassCtor->getParameters();
  auto *bodyParams = superclassParams->clone(ctx, options);

  // If the superclass is generic, we need to map the superclass constructor's
  // parameter types into the generic context of our class.
  //
  // We might have to apply substitutions, if for example we have a declaration
  // like 'class A : B<Int>'.
  for (unsigned idx : range(superclassParams->size())) {
    auto *superclassParam = superclassParams->get(idx);
    auto *bodyParam = bodyParams->get(idx);

    auto paramTy = superclassParam->getInterfaceType();
    auto substTy = paramTy.subst(subMap);

    bodyParam->setInterfaceType(substTy);
  }

  Type thrownType;
  if (auto superThrownType = superclassCtor->getThrownInterfaceType()) {
    thrownType = superThrownType.subst(subMap);
  }

  // Create the initializer declaration, inheriting the name,
  // failability, and throws from the superclass initializer.
  auto implCtx = classDecl->getImplementationContext();
  auto ctor = new (ctx) ConstructorDecl(
      superclassCtor->getName(), implCtx->getBraces().Start,
      superclassCtor->isFailable(),
      /*FailabilityLoc=*/SourceLoc(),
      /*Async=*/superclassCtor->hasAsync(),
      /*AsyncLoc=*/SourceLoc(),
      /*Throws=*/superclassCtor->hasThrows(),
      /*ThrowsLoc=*/SourceLoc(), TypeLoc::withoutLoc(thrownType), bodyParams,
      genericParams, implCtx->getAsGenericContext());

  ctor->setImplicit();

  // Set the interface type of the initializer.
  ctor->setGenericSignature(genericSig);

  ctor->setImplicitlyUnwrappedOptional(
    superclassCtor->isImplicitlyUnwrappedOptional());

  configureInheritedDesignatedInitAttributes(classDecl, ctor,
                                             superclassCtor, ctx);

  if (kind == DesignatedInitKind::Stub) {
    // Make this a stub implementation.
    ctor->setBodySynthesizer(synthesizeStubBody);

    // Note that this is a stub implementation.
    ctor->setStubImplementation(true);

    return ctor;
  }

  // Form the body of a chaining designated initializer.
  assert(kind == DesignatedInitKind::Chaining);
  ctor->setBodySynthesizer(synthesizeDesignatedInitOverride, superclassCtor);

  return ctor;
}

/// Diagnose a missing required initializer.
static void diagnoseMissingRequiredInitializer(
              ClassDecl *classDecl,
              ConstructorDecl *superInitializer,
              bool downgradeToWarning,
              ASTContext &ctx) {
  // Find the location at which we should insert the new initializer.
  SourceLoc insertionLoc;
  SourceLoc indentationLoc;
  for (auto member : classDecl->getMembers()) {
    // If we don't have an indentation location yet, grab one from this
    // member.
    if (indentationLoc.isInvalid()) {
      indentationLoc = member->getLoc();
    }

    // We only want to look at explicit constructors.
    auto ctor = dyn_cast<ConstructorDecl>(member);
    if (!ctor)
      continue;

    if (ctor->isImplicit())
      continue;

    insertionLoc = ctor->getEndLoc();
    indentationLoc = ctor->getLoc();
  }

  // If no initializers were listed, start at the opening '{' for the class.
  if (insertionLoc.isInvalid()) {
    insertionLoc = classDecl->getBraces().Start;
  }
  if (indentationLoc.isInvalid()) {
    indentationLoc = classDecl->getBraces().End;
  }

  // Adjust the insertion location to point at the end of this line (i.e.,
  // the start of the next line).
  insertionLoc = Lexer::getLocForEndOfLine(ctx.SourceMgr,
                                           insertionLoc);

  // Find the indentation used on the indentation line.
  StringRef extraIndentation;
  StringRef indentation = Lexer::getIndentationForLine(
      ctx.SourceMgr, indentationLoc, &extraIndentation);

  // Pretty-print the superclass initializer into a string.
  // FIXME: Form a new initializer by performing the appropriate
  // substitutions of subclass types into the superclass types, so that
  // we get the right generic parameters.
  std::string initializerText;
  {
    PrintOptions options;
    options.PrintImplicitAttrs = false;

    // Render the text.
    llvm::raw_string_ostream out(initializerText);
    {
      ExtraIndentStreamPrinter printer(out, indentation);
      printer.printNewline();

      // If there is no explicit 'required', print one.
      bool hasExplicitRequiredAttr = false;
      if (auto requiredAttr
            = superInitializer->getAttrs().getAttribute<RequiredAttr>())
          hasExplicitRequiredAttr = !requiredAttr->isImplicit();

      if (!hasExplicitRequiredAttr)
        printer << "required ";

      superInitializer->print(printer, options);
    }

    // Add a dummy body.
    out << " {\n";
    out << indentation << extraIndentation << "fatalError(\"";
    superInitializer->getName().printPretty(out);
    out << " has not been implemented\")\n";
    out << indentation << "}\n";
  }

  // Complain.
  ctx.Diags
      .diagnose(insertionLoc, diag::required_initializer_missing,
                superInitializer->getName(),
                superInitializer->getDeclContext()->getDeclaredInterfaceType())
      .warnUntilLanguageModeIf(downgradeToWarning, LanguageMode::v6)
      .fixItInsert(insertionLoc, initializerText);

  ctx.Diags.diagnose(findNonImplicitRequiredInit(superInitializer),
                     diag::required_initializer_here);
}

/// FIXME: This is temporary until we come up with a way to overcome circularity
/// issues.
///
/// This method is intended to be used only in places that expect
/// lazy and property wrapper backing storage synthesis has happened
/// or can tolerate absence of such properties.
///
/// \param typeDecl The nominal type to enumerate current properties and their
/// auxiliary vars for.
///
/// \param callback The callback to be called for each property and auxiliary
/// var associated with the given type. The callback should return `true` to
/// indicate that enumeration should continue and `false` otherwise.
///
/// \returns true which indicates "failure" if callback returns `false`
/// at least once.
static bool enumerateCurrentPropertiesAndAuxiliaryVars(
    NominalTypeDecl *typeDecl, llvm::function_ref<bool(VarDecl *)> callback) {
  bool hadErrors = false;

  std::function<void(Decl *)> visitMember;
  visitMember = [&](Decl *member) {
    if (hadErrors)
      return;

    if (auto *var = dyn_cast<VarDecl>(member)) {
      if (!callback(var)) {
        hadErrors = true;
        return;
      }
    }
    member->visitAuxiliaryDecls(visitMember);
  };

  for (auto *member :
       typeDecl->getImplementationContext()->getCurrentMembers()) {
    visitMember(member);
    if (hadErrors)
      return true;
  }

  return false;
}

bool AreAllStoredPropertiesDefaultInitableRequest::evaluate(
    Evaluator &evaluator, NominalTypeDecl *decl) const {
  assert(!hasClangImplementation(decl));

  std::multimap<VarDecl *, VarDecl *> initializedViaInitAccessor;
  decl->collectPropertiesInitializableByInitAccessors(
      initializedViaInitAccessor);

  llvm::SmallPtrSet<PatternBindingDecl *, 4> checked;
  return !enumerateCurrentPropertiesAndAuxiliaryVars(
      decl, [&](VarDecl *property) {
        auto *pbd = property->getParentPatternBinding();
        if (!pbd || !checked.insert(pbd).second)
          return true;

        // If a stored property lacks an initial value and if there is no way to
        // synthesize an initial value (e.g. for an optional) then we suppress
        // generation of the default initializer.

        // Static variables are irrelevant.
        if (pbd->isStatic())
          return true;

        for (auto idx : range(pbd->getNumPatternEntries())) {
          bool HasStorage = false;
          bool CheckDefaultInitializer = true;
          pbd->getPattern(idx)->forEachVariable([&HasStorage,
                                                 &CheckDefaultInitializer,
                                                 &initializedViaInitAccessor](
                                                    VarDecl *VD) {
            // If one of the bound variables is @NSManaged, go ahead no matter
            // what.
            if (VD->getAttrs().hasAttribute<NSManagedAttr>())
              CheckDefaultInitializer = false;

            // If this property is covered by one or more init accessor(s)
            // check whether at least one of them is initializable.
            auto initAccessorProperties =
                llvm::make_range(initializedViaInitAccessor.equal_range(VD));
            if (llvm::any_of(initAccessorProperties, [&](const auto &entry) {
                  auto *property = entry.second->getParentPatternBinding();
                  return property->isInitialized(0) ||
                         property->isDefaultInitializable();
                }))
              return;

            if (VD->hasStorageOrWrapsStorage())
              HasStorage = true;

            // Treat an init accessor property that doesn't initialize other
            // properties  as stored for initialization purposes.
            if (auto *initAccessor = VD->getAccessor(AccessorKind::Init)) {
              HasStorage |= initAccessor->getInitializedProperties().empty();
            }
          });

          if (!HasStorage)
            return true;

          if (pbd->isInitialized(idx))
            return true;

          // If we cannot default initialize the property, we cannot
          // synthesize a default initializer for the class.
          if (CheckDefaultInitializer && !pbd->isDefaultInitializable()) {
            return false;
          }
        }
        return true;
      });
}

static bool areAllStoredPropertiesDefaultInitializable(Evaluator &eval,
                                                       NominalTypeDecl *decl) {
  if (hasClangImplementation(decl))
    return true;

  return evaluateOrDefault(
      eval, AreAllStoredPropertiesDefaultInitableRequest{decl}, false);
}

bool
HasUserDefinedDesignatedInitRequest::evaluate(Evaluator &evaluator,
                                              NominalTypeDecl *decl) const {
  assert(!hasClangImplementation(decl));

  auto results = decl->lookupDirect(DeclBaseName::createConstructor());
  for (auto *member : results) {
    if (!isInMainBody(member, decl))
      continue;

    auto *ctor = cast<ConstructorDecl>(member);
    if (ctor->isDesignatedInit() && !ctor->isSynthesized())
      return true;
  }

  return false;
}

static bool hasUserDefinedDesignatedInit(Evaluator &eval,
                                         NominalTypeDecl *decl) {
  // Imported decls don't have a designated initializer defined by the user.
  if (hasClangImplementation(decl))
    return false;

  return evaluateOrDefault(eval, HasUserDefinedDesignatedInitRequest{decl},
                           false);
}

static bool canInheritDesignatedInits(Evaluator &eval, ClassDecl *decl) {
  // We can only inherit designated initializers if the user hasn't defined
  // a designated init of their own, and all the stored properties have initial
  // values.
  return !hasUserDefinedDesignatedInit(eval, decl) &&
         areAllStoredPropertiesDefaultInitializable(eval, decl);
}

static ValueDecl *findImplementedObjCDecl(ValueDecl *VD) {
  // If VD has an ObjC name...
  if (auto vdSelector = VD->getObjCRuntimeName()) {
    // and it's in an extension...
    if (auto implED = dyn_cast<ExtensionDecl>(VD->getDeclContext())) {
      // and that extension is the @objcImplementation of a class's main body...
      if (auto interfaceCD =
              dyn_cast_or_null<ClassDecl>(implED->getImplementedObjCDecl())) {
        // Find the initializer in the class's main body that matches VD.
        for (auto interfaceVD : interfaceCD->getAllMembers()) {
          if (auto interfaceCtor = dyn_cast<ConstructorDecl>(interfaceVD)) {
            if (vdSelector == interfaceCtor->getObjCRuntimeName()) {
              return interfaceCtor;
            }
          }
        }
      }
    }
  }

  return VD;
}

static void collectNonOveriddenSuperclassInits(
    ClassDecl *subclass, SmallVectorImpl<ConstructorDecl *> &results) {
  auto *superclassDecl = subclass->getSuperclassDecl();
  assert(superclassDecl);

  // Record all of the initializers the subclass has overridden, excluding stub
  // overrides, which we don't want to consider as viable delegates for
  // convenience inits.
  llvm::SmallPtrSet<ConstructorDecl *, 4> overriddenInits;

  auto ctors = subclass->lookupDirect(DeclBaseName::createConstructor());
  for (auto *member : ctors) {
    if (!isInMainBody(member, subclass))
      continue;

    auto *ctor = cast<ConstructorDecl>(member);
    if (!ctor->hasStubImplementation())
      if (auto overridden = ctor->getOverriddenDecl())
        overriddenInits.insert(overridden);
  }

  superclassDecl->synthesizeSemanticMembersIfNeeded(
    DeclBaseName::createConstructor());

  NLOptions subOptions = {NLFlags::QualifiedDefault,
                          NLFlags::IgnoreAccessControl,
                          NLFlags::IgnoreMissingImports};
  SmallVector<ValueDecl *, 4> lookupResults;
  subclass->lookupQualified(
      superclassDecl, DeclNameRef::createConstructor(),
      subclass->getStartLoc(),
      subOptions, lookupResults);

  for (auto decl : lookupResults) {
    // HACK: If an @objcImplementation extension declares an initializer, its
    // interface usually also has a declaration. We need the interface decl for
    // access control computations, but the name lookup returns the
    // implementation decl because it's in the Swift module. Go find the
    // matching interface decl.
    // (Note that this is necessary for both newly-declared inits and overrides,
    // even implicit ones.)
    decl = findImplementedObjCDecl(decl);

    auto superclassCtor = cast<ConstructorDecl>(decl);

    // Skip invalid superclass initializers.
    if (superclassCtor->isInvalid())
      continue;

    // Skip unavailable superclass initializers.
    if (superclassCtor->isUnavailable())
      continue;

    if (!overriddenInits.count(superclassCtor))
      results.push_back(superclassCtor);
  }
}

/// For a class with a superclass, automatically define overrides
/// for all of the superclass's designated initializers.
static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) {
  // Bail out if we're validating one of our constructors already;
  // we'll revisit the issue later.
  auto results = decl->lookupDirect(DeclBaseName::createConstructor());
  for (auto *member : results) {
    if (isa<ExtensionDecl>(member->getDeclContext()))
      continue;

    if (member->isRecursiveValidation())
      return;
  }

  // We can only inherit initializers if we have a superclass.
  if (!decl->getSuperclassDecl() || !decl->getSuperclass())
    return;

  // Check whether the user has defined a designated initializer for this class,
  // and whether all of its stored properties have initial values.
  auto &ctx = decl->getASTContext();
  bool foundDesignatedInit = hasUserDefinedDesignatedInit(ctx.evaluator, decl);
  bool defaultInitable =
      areAllStoredPropertiesDefaultInitializable(ctx.evaluator, decl);

  // In cases where we can't define any overrides, we used to suppress
  // diagnostics about missing required initializers. Now we emit diagnostics,
  // but downgrade them to warnings prior to Swift 6.
  bool downgradeRequiredInitsToWarning =
      !defaultInitable && !foundDesignatedInit;

  SmallVector<ConstructorDecl *, 4> nonOverriddenSuperclassCtors;
  collectNonOveriddenSuperclassInits(decl, nonOverriddenSuperclassCtors);

  bool inheritDesignatedInits = canInheritDesignatedInits(ctx.evaluator, decl);
  for (auto *superclassCtor : nonOverriddenSuperclassCtors) {
    // We only care about required or designated initializers.
    if (!superclassCtor->isDesignatedInit()) {
      if (superclassCtor->isRequired()) {
        assert(superclassCtor->isInheritable() &&
               "factory initializers cannot be 'required'");
        if (!decl->inheritsSuperclassInitializers()) {
          diagnoseMissingRequiredInitializer(
              decl, superclassCtor, downgradeRequiredInitsToWarning, ctx);
        }
      }
      continue;
    }

    // If the superclass initializer is not accessible from the derived
    // class, don't synthesize an override, since we cannot reference the
    // superclass initializer's method descriptor at all.
    //
    // FIXME: This should be checked earlier as part of calculating
    // canInheritInitializers.
    if (!superclassCtor->isAccessibleFrom(decl))
      continue;

    // Diagnose a missing override of a required initializer.
    if (superclassCtor->isRequired() && !inheritDesignatedInits) {
      diagnoseMissingRequiredInitializer(
          decl, superclassCtor, downgradeRequiredInitsToWarning, ctx);
      continue;
    }

    // A designated or required initializer has not been overridden.

    // We can't define any overrides if we have any uninitialized
    // stored properties.
    if (!defaultInitable && !foundDesignatedInit)
      continue;

    bool alreadyDeclared = false;

    auto results = decl->lookupDirect(DeclBaseName::createConstructor());
    for (auto *member : results) {
      if (!isInMainBody(member, decl))
        continue;

      auto *ctor = cast<ConstructorDecl>(member);

      // Skip any invalid constructors.
      if (ctor->isInvalid())
        continue;

      auto type = swift::getMemberTypeForComparison(ctor, nullptr);
      if (isOverrideBasedOnType(ctor, type, superclassCtor)) {
        alreadyDeclared = true;
        break;
      }
    }

    // If we have already introduced an initializer with this parameter type,
    // don't add one now.
    if (alreadyDeclared)
      continue;

    // If we're inheriting initializers, create an override delegating
    // to 'super.init'. Otherwise, create a stub which traps at runtime.
    auto kind = inheritDesignatedInits ? DesignatedInitKind::Chaining
                                       : DesignatedInitKind::Stub;

    if (auto ctor = createDesignatedInitOverride(
                      decl, superclassCtor, kind, ctx)) {
      auto *implCtx = decl->getImplementationContext();

      // In an '@objc @implementation' class a stub initializer is still
      // reachable from Objective-C (e.g. '[Class new]') and traps at runtime if
      // it's invoked, so warn the author to implement it. (Non-required
      // designated inits; required ones are handled by
      // diagnoseMissingRequiredInitializer above.)
      if (kind == DesignatedInitKind::Stub &&
          implCtx->getDecl()->isObjCImplementation())
        ctx.Diags.diagnose(implCtx->getDecl(),
                           diag::objc_implementation_missing_inherited_init,
                           superclassCtor);

      implCtx->addMember(ctor);
    }
  }
}

bool
InheritsSuperclassInitializersRequest::evaluate(Evaluator &eval,
                                                ClassDecl *decl) const {
  // Check if we parsed the @_inheritsConvenienceInitializers attribute.
  if (decl->getAttrs().hasAttribute<InheritsConvenienceInitializersAttr>())
    return true;

  auto superclassDecl = decl->getSuperclassDecl();
  assert(superclassDecl);

  // If the superclass has known-missing designated initializers, inheriting
  // is unsafe.
  if ((superclassDecl->hasClangNode() ||
       superclassDecl->getModuleContext() != decl->getParentModule()) &&
      superclassDecl->hasMissingDesignatedInitializers())
    return false;

  // If we're allowed to inherit designated initializers, then we can inherit
  // convenience inits too.
  if (canInheritDesignatedInits(eval, decl))
    return true;

  // Otherwise we need to check whether the user has overridden all of the
  // superclass' designed inits.
  SmallVector<ConstructorDecl *, 4> nonOverriddenSuperclassCtors;
  collectNonOveriddenSuperclassInits(decl, nonOverriddenSuperclassCtors);

  auto allDesignatedInitsOverridden =
      llvm::none_of(nonOverriddenSuperclassCtors, [](ConstructorDecl *ctor) {
        return ctor->isDesignatedInit();
      });
  return allDesignatedInitsOverridden;
}

static bool shouldAttemptInitializerSynthesis(const NominalTypeDecl *decl) {
  // Don't synthesize initializers for imported decls.
  if (hasClangImplementation(decl))
    return false;

  // Don't add implicit constructors in module interfaces.
  if (decl->getDeclContext()->isInSwiftinterface())
    return false;

  // Don't attempt if we know the decl is invalid.
  if (decl->isInvalid())
    return false;

  return true;
}

void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
  // If we already added implicit initializers, we're done.
  if (decl->addedImplicitInitializers())
    return;

  decl->setAddedImplicitInitializers();

  if (!shouldAttemptInitializerSynthesis(decl))
    return;

  if (auto *classDecl = dyn_cast<ClassDecl>(decl)) {
    addImplicitInheritedConstructorsToClass(classDecl);
  }

  // Force the memberwise and default initializers if the type has them.
  // FIXME: We need to be more lazy about synthesizing constructors.
  (void)decl->getMemberwiseInitializer(MemberwiseInitKind::Regular);
  (void)decl->getMemberwiseInitializer(MemberwiseInitKind::Compatibility);
  (void)decl->getDefaultInitializer();
}

evaluator::SideEffect
ResolveImplicitMemberRequest::evaluate(Evaluator &evaluator,
                                       NominalTypeDecl *target,
                                       ImplicitMemberAction action) const {
  ASSERT(!isa<ProtocolDecl>(target));

  // FIXME: This entire request is a layering violation made of smaller,
  // finickier layering violations. See rdar://56844567

  // Checks whether the target conforms to the given protocol. If the
  // conformance is incomplete, force the conformance.
  //
  // Returns whether the target conforms to the protocol.
  auto evaluateTargetConformanceTo = [&](ProtocolDecl *protocol) {
    if (!protocol)
      return false;

    auto targetType = target->getDeclaredInterfaceType();
    auto ref = lookupConformance(targetType, protocol);
    if (ref.isInvalid()) {
      return false;
    }

    if (auto *conformance = dyn_cast<NormalProtocolConformance>(
            ref.getConcrete()->getRootConformance())) {
      // Complete evaluate the conformance.
      evaluateOrDefault(evaluator,
                        ResolveTypeWitnessesRequest{conformance},
                        evaluator::SideEffect());

      // FIXME: This should be more fine-grained to avoid having to check
      // for a cycle here.
      if (!evaluator.hasActiveRequest(ResolveValueWitnessesRequest{conformance})) {
        conformance->resolveValueWitnesses();
      }
    }

    return true;
  };

  auto &Context = target->getASTContext();
  switch (action) {
  case ImplicitMemberAction::ResolveImplicitInit:
    TypeChecker::addImplicitConstructors(target);
    break;
  case ImplicitMemberAction::ResolveCodingKeys: {
    // CodingKeys is a special type which may be synthesized as part of
    // Encodable/Decodable conformance. If the target conforms to either
    // protocol and would derive conformance to either, the type may be
    // synthesized.
    // If the target conforms to either and the conformance has not yet been
    // evaluated, then we should do that here.
    //
    // Try to synthesize Decodable first. If that fails, try to synthesize
    // Encodable. If either succeeds and CodingKeys should have been
    // synthesized, it will be synthesized.
    auto *decodableProto = Context.getProtocol(KnownProtocolKind::Decodable);
    auto *encodableProto = Context.getProtocol(KnownProtocolKind::Encodable);
    if (!evaluateTargetConformanceTo(decodableProto)) {
      (void)evaluateTargetConformanceTo(encodableProto);
    }
  }
    break;
  case ImplicitMemberAction::ResolveEncodable: {
    // encode(to:) may be synthesized as part of derived conformance to the
    // Encodable protocol.
    // If the target should conform to the Encodable protocol, check the
    // conformance here to attempt synthesis.
    auto *encodableProto = Context.getProtocol(KnownProtocolKind::Encodable);
    (void)evaluateTargetConformanceTo(encodableProto);
  }
    break;
  case ImplicitMemberAction::ResolveDecodable: {
    // init(from:) may be synthesized as part of derived conformance to the
    // Decodable protocol.
    // If the target should conform to the Decodable protocol, check the
    // conformance here to attempt synthesis.
    TypeChecker::addImplicitConstructors(target);
    auto *decodableProto = Context.getProtocol(KnownProtocolKind::Decodable);
    (void)evaluateTargetConformanceTo(decodableProto);
    break;
  }
  }
  return std::make_tuple<>();
}

bool HasMemberwiseInitRequest::evaluate(Evaluator &evaluator, StructDecl *decl,
                                        MemberwiseInitKind initKind) const {
  if (!shouldAttemptInitializerSynthesis(decl))
    return false;

  // If the user has already defined a designated initializer, then don't
  // synthesize a memberwise init.
  if (hasUserDefinedDesignatedInit(evaluator, decl))
    return false;

  auto &ctx = decl->getASTContext();
  if (initKind == MemberwiseInitKind::Compatibility) {
    // In the next language mode we should stop creating the compatibility
    // initializer if 'DeprecateCompatMemberwiseInit' is enabled.
    if (ctx.LangOpts.hasFeature(Feature::DeprecateCompatMemberwiseInit) &&
        ctx.isLanguageModeAtLeast(LanguageMode::future)) {
      return false;
    }

    // If there are no extra properties present for the compatibility
    // initializer we don't need to synthesize it. The compatibility initializer
    // is guaranteed to be a superset of the regular initializer so we can just
    // compare sizes.
    using Kind = MemberwiseInitKind;
    auto regularProps = decl->getMemberwiseInitProperties(Kind::Regular);
    auto compatProps = decl->getMemberwiseInitProperties(Kind::Compatibility);
    ASSERT(regularProps.size() <= compatProps.size() && "Must be superset");
    if (regularProps.size() == compatProps.size())
      return false;
  }

  std::multimap<VarDecl *, VarDecl *> initializedViaAccessor;
  decl->collectPropertiesInitializableByInitAccessors(initializedViaAccessor);

  llvm::SmallPtrSet<VarDecl *, 4> initializedProperties;
  llvm::SmallVector<std::pair<VarDecl *, Identifier>> invalidOrderings;

  llvm::SmallVector<std::pair<VarDecl *, AvailabilityRestriction>>
      availabilityRestrictions;

  // Synthesized memberwise intializers are available at the intersection of the
  // availability of the struct containing the initializer and the deployment
  // target (since they have at most 'internal' accessibility and therefore
  // cannot be invoked by module clients).
  auto structAvailability = AvailabilityContext::forDeclSignature(decl);
  structAvailability.constrainWithContext(
      AvailabilityContext::forDeploymentTarget(ctx), ctx);

  if (enumerateCurrentPropertiesAndAuxiliaryVars(decl, [&](VarDecl *var) {
        if (var->isStatic())
          return true;

        if (var->getOriginalWrappedProperty())
          return true;

        if (!var->isMemberwiseInitialized(initKind, /*preferDeclared=*/true))
          return true;

        if (auto *initAccessor = var->getAccessor(AccessorKind::Init)) {
          // Check whether the property has stronger availability restrictions
          // than the initializer.
          if (!var->hasStorage()) {
            if (auto restriction =
                    structAvailability.unsatisfiedRestrictionForDecl(var)) {
              availabilityRestrictions.push_back({var, *restriction});
              return true;
            }
          }

          // Make sure that all properties accessed by init accessor
          // are previously initialized.
          for (auto *property : initAccessor->getAccessedProperties()) {
            if (!initializedProperties.count(property))
              invalidOrderings.push_back({var, property->getName()});
          }

          // Record all of the properties initialized by calling init accessor.
          auto properties = initAccessor->getInitializedProperties();
          initializedProperties.insert(var);
          initializedProperties.insert(properties.begin(), properties.end());
          return true;
        }

        switch (initializedViaAccessor.count(var)) {
        // Not covered by an init accessor.
        case 0:
          initializedProperties.insert(var);
          return true;

        // Covered by a single init accessor, we'll handle that
        // once we get to the property with init accessor.
        case 1:
          return true;

        // Covered by more than one init accessor which means that we
        // cannot synthesize memberwise initializer due to intersecting
        // initializations.
        default:
          return false;
        }
      }))
    return false;

  if (!invalidOrderings.empty()) {
    ctx.Diags.diagnose(decl, diag::cannot_synthesize_memberwise_init, decl);

    for (const auto &invalid : invalidOrderings) {
      auto *accessor = invalid.first->getAccessor(AccessorKind::Init);
      ctx.Diags.diagnose(accessor->getLoc(),
                         diag::out_of_order_access_in_init_accessor,
                         invalid.first->getName(), invalid.second);
    }

    return false;
  }

  if (!availabilityRestrictions.empty()) {
    ctx.Diags.diagnose(decl, diag::cannot_synthesize_memberwise_init, decl);

    for (const auto &[var, restriction] : availabilityRestrictions) {
      ctx.Diags.diagnose(
          var->getLoc(),
          diag::unavailable_init_accessor_prevent_memberwise_init_synthesis,
          restriction.isUnavailable(), var);
    }

    return false;
  }

  return !initializedProperties.empty();
}

ConstructorDecl *
SynthesizeMemberwiseInitRequest::evaluate(Evaluator &evaluator,
                                          NominalTypeDecl *decl,
                                          MemberwiseInitKind initKind) const {
  ASSERT(decl->hasMemberwiseInitializer(initKind));

  // Create the implicit memberwise constructor.
  auto &ctx = decl->getASTContext();
  auto ctor = createImplicitConstructor(
      decl, ImplicitConstructorKind::Memberwise, initKind, ctx);

  // The diagnostic for the compatibility memberwise initializer assumes it's
  // fileprivate at most, make sure that's true.
  ASSERT(initKind != MemberwiseInitKind::Compatibility ||
         ctor->getFormalAccess() <= AccessLevel::FilePrivate);

  decl->addMember(ctor);
  return ctor;
}

ConstructorDecl *
ResolveEffectiveMemberwiseInitRequest::evaluate(Evaluator &evaluator,
                                                NominalTypeDecl *decl) const {
  // For now, use the compatibility memberwise initializer that includes all
  // private properties.
  // FIXME: Can we switch to the regular?
  auto &ctx = decl->getASTContext();
  auto initKind = MemberwiseInitKind::Compatibility;

  // Compute the access level for the memberwise initializer. The minimum of:
  // - Public, by default. This enables public nominal types to have public
  //   memberwise initializers.
  //   - The `public` default is important for synthesized member types, e.g.
  //     `TangentVector` structs synthesized during `Differentiable` derived
  //     conformances. Manually extending these types to define a public
  //     memberwise initializer causes a redeclaration error.
  // - The minimum access level of memberwise-initialized properties in the
  //   nominal type declaration.
  // FIXME: This doesn't correctly handle init accessors.
  auto accessLevel = AccessLevel::Public;
  for (auto *member : decl->getMembers()) {
    auto *var = dyn_cast<VarDecl>(member);
    if (!var)
      continue;
    if (!var->isMemberwiseInitialized(initKind, /*preferDeclared=*/true))
      continue;

    accessLevel = std::min(accessLevel, var->getFormalAccess());
  }

  // If a memberwise initializer exists, set its access level and return it.
  // First try the compatibility initializer, then the regular if it contains
  // all the necessary properties.
  {
    auto *initDecl = [&]() -> ConstructorDecl * {
      using Kind = MemberwiseInitKind;

      // Always use the compat init if present.
      if (auto *init = decl->getMemberwiseInitializer(Kind::Compatibility))
        return init;

      // If there is no compatibility init, check to see if the regular init
      // has all the necessary properties.
      auto regularProps = decl->getMemberwiseInitProperties(Kind::Regular);
      auto compatProps = decl->getMemberwiseInitProperties(Kind::Compatibility);
      if (regularProps.size() != compatProps.size())
        return nullptr;

      return decl->getMemberwiseInitializer(Kind::Regular);
    }();
    if (initDecl) {
      initDecl->overwriteAccess(accessLevel);
      return initDecl;
    }
  }

  auto isEffectiveMemberwiseInitializer = [&](ConstructorDecl *initDecl) {
    // Check for `nullptr`.
    if (!initDecl)
      return false;
    // Get all stored properties, excluding `let` properties with initial
    // values.
    SmallVector<VarDecl *, 8> storedProperties;
    for (auto *vd : decl->getStoredProperties()) {
      if (vd->isLet() && vd->hasInitialValue())
        continue;
      storedProperties.push_back(vd);
    }
    auto initDeclType =
        initDecl->getMethodInterfaceType()->getAs<AnyFunctionType>();
    // Return false if initializer does not have a valid interface type.
    if (!initDeclType)
      return false;
    // Return false if stored property count does not have parameter count.
    if (storedProperties.size() != initDeclType->getNumParams())
      return false;
    // Return true if all stored property types/names match initializer
    // parameter types/labels.
    return llvm::all_of(
        llvm::zip(storedProperties, initDeclType->getParams()),
        [&](std::tuple<VarDecl *, AnyFunctionType::Param> pair) {
          auto *storedProp = std::get<0>(pair);
          auto param = std::get<1>(pair);
          return storedProp->getInterfaceType()->isEqual(
                     param.getPlainType()) &&
                 storedProp->getName() == param.getLabel();
        });
  };

  // Otherwise, look for a user-defined effective memberwise initializer.
  ConstructorDecl *memberwiseInitDecl = nullptr;
  auto initDecls = decl->lookupDirect(DeclBaseName::createConstructor());
  for (auto *decl : initDecls) {
    auto *initDecl = dyn_cast<ConstructorDecl>(decl);
    if (!isEffectiveMemberwiseInitializer(initDecl))
      continue;
    assert(!memberwiseInitDecl && "Memberwise initializer already found");
    memberwiseInitDecl = initDecl;
  }

  // Otherwise, create a memberwise initializer, set its access level, and
  // return it.
  if (!memberwiseInitDecl) {
    memberwiseInitDecl = createImplicitConstructor(
        decl, ImplicitConstructorKind::Memberwise, initKind, ctx);
    memberwiseInitDecl->overwriteAccess(accessLevel);
    decl->addMember(memberwiseInitDecl);
  }
  return memberwiseInitDecl;
}

bool
HasDefaultInitRequest::evaluate(Evaluator &evaluator,
                                NominalTypeDecl *decl) const {
  assert(isa<StructDecl>(decl) || isa<ClassDecl>(decl));

  if (!shouldAttemptInitializerSynthesis(decl))
    return false;

  if (auto *sd = dyn_cast<StructDecl>(decl)) {
    assert(!sd->hasUnreferenceableStorage() &&
           "User-defined structs cannot have unreferenceable storage");
    (void)sd;
  }

  // Don't synthesize a default for a subclass, it will attempt to inherit its
  // initializers from its superclass.
  if (auto *cd = dyn_cast<ClassDecl>(decl))
    if (cd->getSuperclassDecl())
      return false;

  // If the user has already defined a designated initializer, then don't
  // synthesize a default init.
  if (hasUserDefinedDesignatedInit(evaluator, decl))
    return false;

  // Regardless of whether all of the properties are initialized or
  // not distributed actors always get a special "default" init based
  // on `id` and `actorSystem` synthesized properties.
  if (decl->isDistributedActor())
    return true;

  // We can only synthesize a default init if all the stored properties have an
  // initial value.
  return areAllStoredPropertiesDefaultInitializable(evaluator, decl);
}

/// Synthesizer callback for a function body consisting of "return".
static std::pair<BraceStmt *, bool>
synthesizeSingleReturnFunctionBody(AbstractFunctionDecl *afd, void *) {
  ASTContext &ctx = afd->getASTContext();
  SmallVector<ASTNode, 1> stmts;
  stmts.push_back(
      ReturnStmt::createImplicit(ctx, afd->getLoc(), /*result*/ nullptr));
  return { BraceStmt::create(ctx, afd->getLoc(), stmts, afd->getLoc(), true),
           /*isTypeChecked=*/true };
}

ConstructorDecl *
SynthesizeDefaultInitRequest::evaluate(Evaluator &evaluator,
                                       NominalTypeDecl *decl) const {
  auto &ctx = decl->getASTContext();

  // Create the default constructor.
  auto ctorKind = decl->isDistributedActor() ?
      ImplicitConstructorKind::DefaultDistributedActor :
      ImplicitConstructorKind::Default;
  if (auto ctor = createImplicitConstructor(
          decl, ctorKind, /*memberwiseKind*/ std::nullopt, ctx)) {
    // Add the constructor.
    decl->addMember(ctor);

    // Lazily synthesize an empty body for the default constructor.
    ctor->setBodySynthesizer(synthesizeSingleReturnFunctionBody);
    return ctor;
  }

  // no default init was synthesized
  return nullptr;
}

ValueDecl *swift::getProtocolRequirement(ProtocolDecl *protocol,
                                         Identifier name) {
  auto lookup = protocol->lookupDirect(name);
  // Erase declarations that are not protocol requirements.
  // This is important for removing default implementations of the same name.
  llvm::erase_if(lookup, [](ValueDecl *v) {
    return !isa<ProtocolDecl>(v->getDeclContext()) ||
           !v->isProtocolRequirement();
  });
  assert(lookup.size() == 1 && "Ambiguous protocol requirement");
  return lookup.front();
}

bool swift::hasLetStoredPropertyWithInitialValue(NominalTypeDecl *nominal) {
  return llvm::any_of(nominal->getStoredProperties(), [&](VarDecl *v) {
    return v->isLet() && v->hasInitialValue();
  });
}

/// Determine whether a synthesized requirement for the given conformance
/// should be explicitly marked as 'nonisolated'.
static bool synthesizedRequirementIsNonIsolated(
    const NormalProtocolConformance *conformance) {
  // @preconcurrency suppresses this.
  if (conformance->isPreconcurrency())
    return false;

  // Explicit global actor isolation suppresses this.
  if (conformance->hasExplicitGlobalActorIsolation())
    return false;

  // Explicit nonisolated forces this.
  if (conformance->getOptions()
          .contains(ProtocolConformanceFlags::Nonisolated))
    return true;

  // When we are inferring conformance isolation, only add nonisolated if
  // either
  //   (1) the protocol inherits from SendableMetatype, or
  //   (2) the conforming type is nonisolated.
  ASTContext &ctx = conformance->getDeclContext()->getASTContext();
  if (!ctx.LangOpts.hasFeature(Feature::InferIsolatedConformances))
    return true;

  // Check inheritance from SendableMetatype, which implies that the conformance
  // will be nonisolated.
  auto sendableMetatypeProto =
      ctx.getProtocol(KnownProtocolKind::SendableMetatype);
  if (sendableMetatypeProto &&
      conformance->getProtocol()->inheritsFrom(sendableMetatypeProto))
    return true;

  auto nominalType = conformance->getType()->getAnyNominal();
  if (!nominalType)
    return true;

  return !getActorIsolation(nominalType).isMainActor();
}

bool swift::addNonIsolatedToSynthesized(DerivedConformance &derived,
                                        ValueDecl *value) {
  if (auto *conformance = derived.Conformance) {
    if (!synthesizedRequirementIsNonIsolated(conformance))
      return false;
  }

  return addNonIsolatedToSynthesized(derived.Nominal, value);
}

bool swift::addNonIsolatedToSynthesized(NominalTypeDecl *nominal,
                                        ValueDecl *value) {
  if (!getActorIsolation(nominal).isActorIsolated())
    return false;

  ASTContext &ctx = nominal->getASTContext();
  value->addAttribute(NonisolatedAttr::createImplicit(ctx));
  return true;
}

void swift::applyInferredSPIAccessControlAttr(Decl *decl,
                                              const Decl *inferredFromDecl,
                                              ASTContext &ctx) {
  auto spiGroups = inferredFromDecl->getSPIGroups();
  if (spiGroups.empty())
    return;

  auto spiAttr =
      SPIAccessControlAttr::create(ctx, SourceLoc(), SourceRange(), spiGroups);
  decl->addAttribute(spiAttr);
}
