//===--- TypeCheckStorage.cpp - Checking Properties and Subscripts -------===//
//
// 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 properties, subscripts as well
// as their accessors.
//
//===----------------------------------------------------------------------===//

#include "CodeSynthesis.h"
#include "TypeChecker.h"
#include "TypeCheckDecl.h"
#include "TypeCheckType.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/AST/DiagnosticsSema.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/PropertyWrappers.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/AST/Types.h"
using namespace swift;

/// Set each bound variable in the pattern to have an error type.
void swift::setBoundVarsTypeError(Pattern *pattern, ASTContext &ctx) {
  pattern->forEachVariable([&](VarDecl *var) {
    // Don't change the type of a variable that we've been able to
    // compute a type for.
    if (var->hasType() && !var->getType()->hasError())
      return;

    var->markInvalid();
  });
}

/// Build a default initializer for the given type.
Expr *TypeChecker::buildDefaultInitializer(Type type) {
  // Default-initialize optional types and weak values to 'nil'.
  if (type->getReferenceStorageReferent()->getOptionalObjectType())
    return new (Context) NilLiteralExpr(SourceLoc(), /*Implicit=*/true);

  // Build tuple literals for tuple types.
  if (auto tupleType = type->getAs<TupleType>()) {
    SmallVector<Expr *, 2> inits;
    for (const auto &elt : tupleType->getElements()) {
      if (elt.isVararg())
        return nullptr;

      auto eltInit = buildDefaultInitializer(elt.getType());
      if (!eltInit)
        return nullptr;

      inits.push_back(eltInit);
    }

    return TupleExpr::createImplicit(Context, inits, { });
  }

  // We don't default-initialize anything else.
  return nullptr;
}

/// Does the context allow pattern bindings that don't bind any variables?
static bool contextAllowsPatternBindingWithoutVariables(DeclContext *dc) {
  
  // Property decls in type context must bind variables.
  if (dc->isTypeContext())
    return false;
  
  // Global variable decls must bind variables, except in scripts.
  if (dc->isModuleScopeContext()) {
    if (dc->getParentSourceFile()
        && dc->getParentSourceFile()->isScriptMode())
      return true;
    
    return false;
  }
  
  return true;
}

static bool hasStoredProperties(NominalTypeDecl *decl) {
  return (isa<StructDecl>(decl) ||
          (isa<ClassDecl>(decl) && !decl->hasClangNode()));
}

static void computeLoweredStoredProperties(NominalTypeDecl *decl) {
  // Just walk over the members of the type, forcing backing storage
  // for lazy properties and property wrappers to be synthesized.
  for (auto *member : decl->getMembers()) {
    auto *var = dyn_cast<VarDecl>(member);
    if (!var || var->isStatic())
      continue;

    if (var->getAttrs().hasAttribute<LazyAttr>())
      (void) var->getLazyStorageProperty();

    if (var->hasAttachedPropertyWrapper())
      (void) var->getPropertyWrapperBackingProperty();
  }
}

llvm::Expected<ArrayRef<VarDecl *>>
StoredPropertiesRequest::evaluate(Evaluator &evaluator,
                                  NominalTypeDecl *decl) const {
  if (!hasStoredProperties(decl))
    return ArrayRef<VarDecl *>();

  SmallVector<VarDecl *, 4> results;

  // Unless we're in a source file we don't have to do anything
  // special to lower lazy properties and property wrappers.
  if (isa<SourceFile>(decl->getModuleScopeContext()))
    computeLoweredStoredProperties(decl);

  for (auto *member : decl->getMembers()) {
    if (auto *var = dyn_cast<VarDecl>(member))
      if (!var->isStatic() && var->hasStorage())
        results.push_back(var);
  }

  return decl->getASTContext().AllocateCopy(results);
}

llvm::Expected<ArrayRef<Decl *>>
StoredPropertiesAndMissingMembersRequest::evaluate(Evaluator &evaluator,
                                                   NominalTypeDecl *decl) const {
  if (!hasStoredProperties(decl))
    return ArrayRef<Decl *>();

  SmallVector<Decl *, 4> results;

  // Unless we're in a source file we don't have to do anything
  // special to lower lazy properties and property wrappers.
  if (isa<SourceFile>(decl->getModuleScopeContext()))
    computeLoweredStoredProperties(decl);

  for (auto *member : decl->getMembers()) {
    if (auto *var = dyn_cast<VarDecl>(member))
      if (!var->isStatic() && var->hasStorage())
        results.push_back(var);

    if (auto missing = dyn_cast<MissingMemberDecl>(member))
      if (missing->getNumberOfFieldOffsetVectorEntries() > 0)
        results.push_back(missing);
  }

  return decl->getASTContext().AllocateCopy(results);
}

/// Validate the \c entryNumber'th entry in \c binding.
static void validatePatternBindingEntry(TypeChecker &tc,
                                        PatternBindingDecl *binding,
                                        unsigned entryNumber) {
  // If the pattern already has a type, we're done.
  if (binding->getPattern(entryNumber)->hasType())
    return;

  // Resolve the pattern.
  auto *pattern = tc.resolvePattern(binding->getPattern(entryNumber),
                                    binding->getDeclContext(),
                                    /*isStmtCondition*/true);
  if (!pattern) {
    binding->setInvalid();
    binding->getPattern(entryNumber)->setType(ErrorType::get(tc.Context));
    return;
  }

  binding->setPattern(entryNumber, pattern,
                      binding->getPatternList()[entryNumber].getInitContext());

  // Validate 'static'/'class' on properties in nominal type decls.
  auto StaticSpelling = binding->getStaticSpelling();
  if (StaticSpelling != StaticSpellingKind::None &&
      isa<ExtensionDecl>(binding->getDeclContext())) {
    if (auto *NTD = binding->getDeclContext()->getSelfNominalTypeDecl()) {
      if (!isa<ClassDecl>(NTD)) {
        if (StaticSpelling == StaticSpellingKind::KeywordClass) {
          tc.diagnose(binding, diag::class_var_not_in_class, false)
            .fixItReplace(binding->getStaticLoc(), "static");
          tc.diagnose(NTD, diag::extended_type_declared_here);
        }
      }
    }
  }

  // Check the pattern. We treat type-checking a PatternBindingDecl like
  // type-checking an expression because that's how the initial binding is
  // checked, and they have the same effect on the file's dependencies.
  //
  // In particular, it's /not/ correct to check the PBD's DeclContext because
  // top-level variables in a script file are accessible from other files,
  // even though the PBD is inside a TopLevelCodeDecl.
  TypeResolutionOptions options(TypeResolverContext::PatternBindingDecl);

  if (binding->isInitialized(entryNumber)) {
    // If we have an initializer, we can also have unknown types.
    options |= TypeResolutionFlags::AllowUnspecifiedTypes;
    options |= TypeResolutionFlags::AllowUnboundGenerics;
  }

  if (tc.typeCheckPattern(pattern, binding->getDeclContext(), options)) {
    setBoundVarsTypeError(pattern, tc.Context);
    binding->setInvalid();
    pattern->setType(ErrorType::get(tc.Context));
    return;
  }

  // If the pattern didn't get a type or if it contains an unbound generic type,
  // we'll need to check the initializer.
  if (!pattern->hasType() || pattern->getType()->hasUnboundGenericType()) {
    if (tc.typeCheckPatternBinding(binding, entryNumber))
      return;
    
    // A pattern binding at top level is not allowed to pick up another decl's
    // opaque result type as its type by type inference.
    if (!binding->getDeclContext()->isLocalContext()
        && binding->getInit(entryNumber)->getType()->hasOpaqueArchetype()) {
      // TODO: Check whether the type is the pattern binding's own opaque type.
      tc.diagnose(binding, diag::inferred_opaque_type,
                  binding->getInit(entryNumber)->getType());
    }
  }

  // If the pattern binding appears in a type or library file context, then
  // it must bind at least one variable.
  if (!contextAllowsPatternBindingWithoutVariables(binding->getDeclContext())) {
    llvm::SmallVector<VarDecl*, 2> vars;
    binding->getPattern(entryNumber)->collectVariables(vars);
    if (vars.empty()) {
      // Selector for error message.
      enum : unsigned {
        Property,
        GlobalVariable,
      };
      tc.diagnose(binding->getPattern(entryNumber)->getLoc(),
                  diag::pattern_binds_no_variables,
                  binding->getDeclContext()->isTypeContext()
                                                   ? Property : GlobalVariable);
    }
  }
}

/// Validate the entries in the given pattern binding declaration.
void swift::validatePatternBindingEntries(TypeChecker &tc,
                                          PatternBindingDecl *binding) {
  if (binding->hasValidationStarted())
    return;

  DeclValidationRAII IBV(binding);

  for (unsigned i = 0, e = binding->getNumPatternEntries(); i != e; ++i)
    validatePatternBindingEntry(tc, binding, i);
}

llvm::Expected<bool>
IsGetterMutatingRequest::evaluate(Evaluator &evaluator,
                                  AbstractStorageDecl *storage) const {
  bool result = (!storage->isStatic() &&
                 doesContextHaveValueSemantics(storage->getDeclContext()));

  // 'lazy' overrides the normal accessor-based rules and heavily
  // restricts what accessors can be used.  The getter is considered
  // mutating if this is instance storage on a value type.
  if (storage->getAttrs().hasAttribute<LazyAttr>()) {
    return result;
  }

  // If we have an attached property wrapper, the getter's mutating-ness
  // depends on the composition of the wrappers.
  if (auto var = dyn_cast<VarDecl>(storage)) {
    if (auto mut = var->getPropertyWrapperMutability()) {
      return mut->Getter == PropertyWrapperMutability::Mutating
        && result;
    }
  }

  auto checkMutability = [&](AccessorKind kind) -> bool {
    auto *accessor = storage->getParsedAccessor(kind);
    if (!accessor)
      return false;

    return accessor->isMutating();
  };

  // Protocol requirements are always written as '{ get }' or '{ get set }';
  // the @_borrowed attribute determines if getReadImpl() becomes Get or Read.
  if (isa<ProtocolDecl>(storage->getDeclContext()))
    return checkMutability(AccessorKind::Get);

  switch (storage->getReadImpl()) {
  case ReadImplKind::Stored:
  case ReadImplKind::Inherited:
    return false;

  case ReadImplKind::Get:
    return checkMutability(AccessorKind::Get);

  case ReadImplKind::Address:
    return checkMutability(AccessorKind::Address);

  case ReadImplKind::Read:
    return checkMutability(AccessorKind::Read);
  }

  llvm_unreachable("bad impl kind");
}

llvm::Expected<bool>
IsSetterMutatingRequest::evaluate(Evaluator &evaluator,
                                  AbstractStorageDecl *storage) const {
  // By default, the setter is mutating if we have an instance member of a
  // value type, but this can be overridden below.
  bool result = (!storage->isStatic() &&
                 doesContextHaveValueSemantics(storage->getDeclContext()));

  // If we have an attached property wrapper, the setter is mutating
  // or not based on the composition of the wrappers.
  if (auto var = dyn_cast<VarDecl>(storage)) {
    if (auto mut = var->getPropertyWrapperMutability()) {
      return mut->Setter == PropertyWrapperMutability::Mutating
        && result;
    }
  }

  auto impl = storage->getImplInfo();
  switch (impl.getWriteImpl()) {
  case WriteImplKind::Immutable:
  case WriteImplKind::Stored:
    // Instance member setters are mutating; static property setters and
    // top-level setters are not.
    // It's important that we use this logic for "immutable" storage
    // in order to handle initialization of let-properties.
    return result;

  case WriteImplKind::StoredWithObservers:
  case WriteImplKind::InheritedWithObservers:
  case WriteImplKind::Set: {
    auto *setter = storage->getParsedAccessor(AccessorKind::Set);

    if (setter)
      result = setter->isMutating();


    // As a special extra check, if the user also gave us a modify
    // coroutine, check that it has the same mutatingness as the setter.
    // TODO: arguably this should require the spelling to match even when
    // it's the implied value.
    auto modifyAccessor = storage->getParsedAccessor(AccessorKind::Modify);

    if (impl.getReadWriteImpl() == ReadWriteImplKind::Modify &&
        modifyAccessor != nullptr) {
      auto modifyResult = modifyAccessor->isMutating();
      if ((result || storage->isGetterMutating()) != modifyResult) {
        modifyAccessor->diagnose(
            diag::modify_mutatingness_differs_from_setter,
            modifyResult ? SelfAccessKind::Mutating
                         : SelfAccessKind::NonMutating,
            modifyResult ? SelfAccessKind::NonMutating
                         : SelfAccessKind::Mutating);
        if (setter)
          setter->diagnose(diag::previous_accessor, "setter", 0);
        modifyAccessor->setInvalid();
      }
    }

    return result;
  }

  case WriteImplKind::MutableAddress:
    return storage->getParsedAccessor(AccessorKind::MutableAddress)
      ->isMutating();

  case WriteImplKind::Modify:
    return storage->getParsedAccessor(AccessorKind::Modify)
      ->isMutating();
  }
  llvm_unreachable("bad storage kind");
}

llvm::Expected<OpaqueReadOwnership>
OpaqueReadOwnershipRequest::evaluate(Evaluator &evaluator,
                                     AbstractStorageDecl *storage) const {
  return (storage->getAttrs().hasAttribute<BorrowedAttr>()
          ? OpaqueReadOwnership::Borrowed
          : OpaqueReadOwnership::Owned);
}

/// Insert the specified decl into the DeclContext's member list.  If the hint
/// decl is specified, the new decl is inserted next to the hint.
static void addMemberToContextIfNeeded(Decl *D, DeclContext *DC,
                                       Decl *Hint = nullptr) {
  if (auto *ntd = dyn_cast<NominalTypeDecl>(DC)) {
    ntd->addMember(D, Hint);
  } else if (auto *ed = dyn_cast<ExtensionDecl>(DC)) {
    ed->addMember(D, Hint);
  } else {
    assert((DC->isLocalContext() || isa<FileUnit>(DC)) &&
           "Unknown declcontext");
  }
}

/// Build a parameter list which can forward the formal index parameters of a
/// declaration.
///
/// \param prefix optional arguments to be prefixed onto the index
///   forwarding pattern.
static ParameterList *
buildIndexForwardingParamList(AbstractStorageDecl *storage,
                              ArrayRef<ParamDecl*> prefix,
                              ASTContext &context) {
  auto subscript = dyn_cast<SubscriptDecl>(storage);

  // Fast path: if this isn't a subscript, just use whatever we have.
  if (!subscript)
    return ParameterList::create(context, prefix);

  // Clone the parameter list over for a new decl, so we get new ParamDecls.
  auto indices = subscript->getIndices()->clone(context,
                                                ParameterList::Implicit);

  // Give all of the parameters meaningless names so that we can forward
  // them properly.  If it's declared anonymously, SILGen will think
  // it's unused.
  // TODO: use some special DeclBaseName for this?
  for (auto param : indices->getArray()) {
    if (!param->hasName())
      param->setName(context.getIdentifier("anonymous"));
    assert(param->hasName());
  }

  if (prefix.empty())
    return indices;
  
  
  // Otherwise, we need to build up a new parameter list.
  SmallVector<ParamDecl*, 4> elements;

  // Start with the fields we were given, if there are any.
  elements.append(prefix.begin(), prefix.end());
  elements.append(indices->begin(), indices->end());
  return ParameterList::create(context, elements);
}

/// Create the generic parameters needed for the given accessor, if any.
static GenericParamList *createAccessorGenericParams(
                                              AbstractStorageDecl *storage) {
  // Accessors of generic subscripts get a copy of the subscript's
  // generic parameter list, because they're not nested inside the
  // subscript.
  if (auto *subscript = dyn_cast<SubscriptDecl>(storage)) {
    if (auto genericParams = subscript->getGenericParams())
      return genericParams->clone(subscript->getDeclContext());
  }

  return nullptr;
}

static bool doesAccessorHaveBody(AccessorDecl *accessor) {
  // Protocol requirements don't have bodies.
  //
  // FIXME: Revisit this if we ever get 'real' default implementations.
  if (isa<ProtocolDecl>(accessor->getDeclContext()))
    return false;

  auto *storage = accessor->getStorage();

  // NSManaged getters and setters don't have bodies.
  if (storage->getAttrs().hasAttribute<NSManagedAttr>())
    if (accessor->isGetterOrSetter())
      return false;

  return true;
}


/// Build a reference to the subscript index variables for this subscript
/// accessor.
static Expr *buildSubscriptIndexReference(ASTContext &ctx,
                                          AccessorDecl *accessor) {
  // Pull out the body parameters, which we should have cloned
  // previously to be forwardable.  Drop the initial buffer/value
  // parameter in accessors that have one.
  auto params = accessor->getParameters()->getArray();
  auto accessorKind = accessor->getAccessorKind();

  // Ignore the value parameter of a setter.
  if (accessorKind == AccessorKind::Set) {
    params = params.slice(1);
  }

  // Okay, everything else should be forwarded, build the expression.
  return buildArgumentForwardingExpr(params, ctx);
}

namespace {
  enum class TargetImpl {
    /// We're doing an ordinary storage reference.
    Ordinary,
    /// We're referencing the physical storage created for the storage.
    Storage,
    /// We're referencing this specific implementation of the storage, not
    /// an override of it.
    Implementation,
    /// We're referencing the superclass's implementation of the storage.
    Super,
    /// We're referencing the backing property for a property with a wrapper
    /// through the 'value' property.
    Wrapper,
    /// We're referencing the backing property for a property with a wrapper
    /// through the 'projectedValue' property.
    WrapperStorage,
  };
} // end anonymous namespace

namespace  {
  /// Describes the information needed to perform property wrapper access via
  /// the enclosing self.
  struct EnclosingSelfPropertyWrapperAccess {
    /// The (genreric) subscript that will be used to perform the access.
    SubscriptDecl *subscript;

    /// The property being accessed.
    VarDecl *accessedProperty;
  };
}

/// Determine whether the given property should be accessed via the enclosing-self access pattern.
static Optional<EnclosingSelfPropertyWrapperAccess>
getEnclosingSelfPropertyWrapperAccess(VarDecl *property, bool forProjected) {
  // The enclosing-self pattern only applies to instance properties of
  // classes.
  if (!property->isInstanceMember())
    return None;
  auto classDecl = property->getDeclContext()->getSelfClassDecl();
  if (!classDecl)
    return None;

  // The pattern currently only works with the outermost property wrapper.
  Type outermostWrapperType = property->getPropertyWrapperBackingPropertyType();
  if (!outermostWrapperType)
    return None;
  NominalTypeDecl *wrapperTypeDecl = outermostWrapperType->getAnyNominal();
  if (!wrapperTypeDecl)
    return None;

  // Look for a generic subscript that fits the general form we need.
  auto wrapperInfo = wrapperTypeDecl->getPropertyWrapperTypeInfo();
  auto subscript =
      forProjected ? wrapperInfo.enclosingInstanceProjectedSubscript
                   : wrapperInfo.enclosingInstanceWrappedSubscript;
  if (!subscript)
    return None;

  EnclosingSelfPropertyWrapperAccess result;
  result.subscript = subscript;

  if (forProjected) {
    result.accessedProperty =
        property->getPropertyWrapperBackingPropertyInfo().storageWrapperVar;
  } else {
    result.accessedProperty = property;
  }
  return result;
}

/// Build an l-value for the storage of a declaration.
static Expr *buildStorageReference(AccessorDecl *accessor,
                                   AbstractStorageDecl *storage,
                                   TargetImpl target,
                                   bool isLValue,
                                   ASTContext &ctx) {
  // Local function to "finish" the expression, creating a member reference
  // to the given sequence of underlying variables.
  Optional<EnclosingSelfPropertyWrapperAccess> enclosingSelfAccess;
  llvm::TinyPtrVector<VarDecl *> underlyingVars;
  auto finish = [&](Expr *result) -> Expr * {
    for (auto underlyingVar : underlyingVars) {
      auto subs = result->getType()
          ->getWithoutSpecifierType()
          ->getContextSubstitutionMap(
            accessor->getParentModule(),
            underlyingVar->getDeclContext());

      ConcreteDeclRef memberRef(underlyingVar, subs);
      auto *memberRefExpr = new (ctx) MemberRefExpr(
          result, SourceLoc(), memberRef, DeclNameLoc(), /*Implicit=*/true);
      auto type = underlyingVar->getValueInterfaceType().subst(subs);
      if (isLValue)
        type = LValueType::get(type);
      memberRefExpr->setType(type);
      
      result = memberRefExpr;
    }
    
    return result;
  };

  VarDecl *selfDecl = accessor->getImplicitSelfDecl();

  AccessSemantics semantics;
  SelfAccessorKind selfAccessKind;
  Type selfTypeForAccess = (selfDecl ? selfDecl->getType() : Type());

  auto *genericEnv = accessor->getGenericEnvironment();
  SubstitutionMap subs;
  if (genericEnv)
    subs = genericEnv->getForwardingSubstitutionMap();

  switch (target) {
  case TargetImpl::Ordinary:
    semantics = AccessSemantics::Ordinary;
    selfAccessKind = SelfAccessorKind::Peer;
    break;

  case TargetImpl::Storage:
    semantics = AccessSemantics::DirectToStorage;
    selfAccessKind = SelfAccessorKind::Peer;
    break;

  case TargetImpl::Implementation:
    semantics = AccessSemantics::DirectToImplementation;
    selfAccessKind = SelfAccessorKind::Peer;
    break;

  case TargetImpl::Super:
    // If this really is an override, use a super-access.
    if (auto override = storage->getOverriddenDecl()) {
      semantics = AccessSemantics::Ordinary;
      selfAccessKind = SelfAccessorKind::Super;

      auto *baseClass = override->getDeclContext()->getSelfClassDecl();
      selfTypeForAccess = selfTypeForAccess->getSuperclassForDecl(baseClass);
      subs =
        selfTypeForAccess->getContextSubstitutionMap(
          accessor->getParentModule(),
          baseClass);

      storage = override;

    // Otherwise do a self-reference, which is dynamically bogus but
    // should be statically valid.  This should only happen in invalid cases.    
    } else {
      semantics = AccessSemantics::Ordinary;
      selfAccessKind = SelfAccessorKind::Peer;
    }
    break;

  case TargetImpl::Wrapper: {
    auto var = cast<VarDecl>(accessor->getStorage());
    auto *backing = var->getPropertyWrapperBackingProperty();

    // Error recovery.
    if (!backing) {
      auto type = storage->getValueInterfaceType();
      if (isLValue)
        type = LValueType::get(type);
      return new (ctx) ErrorExpr(SourceRange(), type);
    }

    storage = backing;

    // If the outermost property wrapper uses the enclosing self pattern,
    // record that.
    unsigned lastWrapperIdx = var->getAttachedPropertyWrappers().size();
    unsigned firstWrapperIdx = 0;
    enclosingSelfAccess =
        getEnclosingSelfPropertyWrapperAccess(var, /*forProjected=*/false);
    if (enclosingSelfAccess)
      firstWrapperIdx = 1;

    // Perform accesses to the wrappedValues along the composition chain.
    for (unsigned i : range(firstWrapperIdx, lastWrapperIdx)) {
      auto wrapperInfo = var->getAttachedPropertyWrapperTypeInfo(i);
      underlyingVars.push_back(wrapperInfo.valueVar);
    }
    semantics = AccessSemantics::DirectToStorage;
    selfAccessKind = SelfAccessorKind::Peer;
    break;
  }

  case TargetImpl::WrapperStorage: {
    auto var =
        cast<VarDecl>(accessor->getStorage())->getOriginalWrappedProperty();
    auto *backing = var->getPropertyWrapperBackingProperty();

    // Error recovery.
    if (!backing) {
      auto type = storage->getValueInterfaceType();
      if (isLValue)
        type = LValueType::get(type);
      return new (ctx) ErrorExpr(SourceRange(), type);
    }

    storage = backing;

    enclosingSelfAccess =
        getEnclosingSelfPropertyWrapperAccess(var, /*forProjected=*/true);
    if (!enclosingSelfAccess) {
      underlyingVars.push_back(
        var->getAttachedPropertyWrapperTypeInfo(0).projectedValueVar);
    }
    semantics = AccessSemantics::DirectToStorage;
    selfAccessKind = SelfAccessorKind::Peer;
    break;
  }
  }

  if (!selfDecl) {
    assert(target != TargetImpl::Super);
    auto *storageDRE = new (ctx) DeclRefExpr(storage, DeclNameLoc(),
                                             /*IsImplicit=*/true, semantics);
    auto type = storage->getValueInterfaceType().subst(subs);
    if (isLValue)
      type = LValueType::get(type);
    storageDRE->setType(type);

    return finish(storageDRE);
  }

  bool isMemberLValue = isLValue;

  // If we're acessing a property wrapper, determine if the
  // intermediate access requires an lvalue.
  if (underlyingVars.size() > 0) {
    isMemberLValue = underlyingVars[0]->isGetterMutating();
    if (isLValue)
      isMemberLValue |= underlyingVars[0]->isSetterMutating();
  }

  bool isSelfLValue = storage->isGetterMutating();
  if (isMemberLValue)
    isSelfLValue |= storage->isSetterMutating();

  Expr *selfDRE =
    buildSelfReference(selfDecl, selfAccessKind, isSelfLValue,
                       ctx);
  if (isSelfLValue)
    selfTypeForAccess = LValueType::get(selfTypeForAccess);

  if (!selfDRE->getType()->isEqual(selfTypeForAccess)) {
    assert(selfAccessKind == SelfAccessorKind::Super);
    selfDRE = new (ctx) DerivedToBaseExpr(selfDRE, selfTypeForAccess);
  }

  Expr *lookupExpr;
  ConcreteDeclRef memberRef(storage, subs);
  auto type = storage->getValueInterfaceType().subst(subs);
  if (isMemberLValue)
    type = LValueType::get(type);

  // When we are performing access via a property wrapper's static subscript
  // that accepts the enclosing self along with key paths, form that subscript
  // operation now.
  if (enclosingSelfAccess) {
    Type storageType = storage->getValueInterfaceType().subst(subs);
    // Metatype instance for the wrapper type itself.
    TypeExpr *wrapperMetatype = TypeExpr::createImplicit(storageType, ctx);

    // Key path referring to the property being accessed.
    Expr *propertyKeyPath = new (ctx) KeyPathDotExpr(SourceLoc());
    propertyKeyPath = new (ctx) UnresolvedDotExpr(
        propertyKeyPath, SourceLoc(),
        enclosingSelfAccess->accessedProperty->getFullName(), DeclNameLoc(),
        /*Implicit=*/true);
    propertyKeyPath = new (ctx) KeyPathExpr(
        SourceLoc(), nullptr, propertyKeyPath);

    // Key path referring to the backing storage property.
    Expr *storageKeyPath = new (ctx) KeyPathDotExpr(SourceLoc());
    storageKeyPath = new (ctx) UnresolvedDotExpr(
        storageKeyPath, SourceLoc(), storage->getFullName(), DeclNameLoc(),
        /*Implicit=*/true);
    storageKeyPath = new (ctx) KeyPathExpr(
        SourceLoc(), nullptr, storageKeyPath);
    Expr *args[3] = {
      selfDRE,
      propertyKeyPath,
      storageKeyPath
    };

    SubscriptDecl *subscriptDecl = enclosingSelfAccess->subscript;
    auto &tc = static_cast<TypeChecker&>(*ctx.getLazyResolver());
    lookupExpr = SubscriptExpr::create(
        ctx, wrapperMetatype, SourceLoc(), args,
        subscriptDecl->getFullName().getArgumentNames(), { }, SourceLoc(),
        nullptr, subscriptDecl, /*Implicit=*/true);
    tc.typeCheckExpression(lookupExpr, accessor);

    // Make sure we produce an lvalue only when desired.
    if (isMemberLValue != lookupExpr->getType()->is<LValueType>()) {
      if (isMemberLValue) {
        // Strip off an extraneous load.
        if (auto load = dyn_cast<LoadExpr>(lookupExpr))
          lookupExpr = load->getSubExpr();
      } else {
        lookupExpr = new (ctx) LoadExpr(
            lookupExpr, lookupExpr->getType()->getRValueType());
      }
    }
  } else if (auto subscript = dyn_cast<SubscriptDecl>(storage)) {
    Expr *indices = buildSubscriptIndexReference(ctx, accessor);
    lookupExpr = SubscriptExpr::create(ctx, selfDRE, indices, memberRef,
                                       /*IsImplicit=*/true, semantics);

    if (selfAccessKind == SelfAccessorKind::Super)
      cast<LookupExpr>(lookupExpr)->setIsSuper(true);

    lookupExpr->setType(type);

  } else {
    lookupExpr = new (ctx) MemberRefExpr(selfDRE, SourceLoc(), memberRef,
                                         DeclNameLoc(), /*IsImplicit=*/true,
                                         semantics);

    if (selfAccessKind == SelfAccessorKind::Super)
      cast<LookupExpr>(lookupExpr)->setIsSuper(true);

    lookupExpr->setType(type);
  }

  return finish(lookupExpr);
}

/// Load the value of VD.  If VD is an @override of another value, we call the
/// superclass getter.  Otherwise, we do a direct load of the value.
static Expr *
createPropertyLoadOrCallSuperclassGetter(AccessorDecl *accessor,
                                         AbstractStorageDecl *storage,
                                         TargetImpl target,
                                         ASTContext &ctx) {
  return buildStorageReference(accessor, storage, target, /*isLValue=*/false,
                               ctx);
}

static Optional<ProtocolConformanceRef>
checkConformanceToNSCopying(ASTContext &ctx, VarDecl *var, Type type) {
  auto dc = var->getDeclContext();
  auto proto = ctx.getNSCopyingDecl();

  if (proto) {
    auto result = TypeChecker::conformsToProtocol(type, proto, dc, None);
    if (result)
      return result;
  }

  ctx.Diags.diagnose(var->getLoc(), diag::nscopying_doesnt_conform);
  return None;
}

static std::pair<Type, bool> getUnderlyingTypeOfVariable(VarDecl *var) {
  Type type = var->getType()->getReferenceStorageReferent();

  if (Type objectType = type->getOptionalObjectType()) {
    return {objectType, true};
  } else {
    return {type, false};
  }
}

Optional<ProtocolConformanceRef>
TypeChecker::checkConformanceToNSCopying(VarDecl *var) {
  Type type = getUnderlyingTypeOfVariable(var).first;
  return ::checkConformanceToNSCopying(Context, var, type);
}

/// Synthesize the code to store 'Val' to 'VD', given that VD has an @NSCopying
/// attribute on it.  We know that VD is a stored property in a class, so we
/// just need to generate something like "self.property = val.copy(zone: nil)"
/// here.  This does some type checking to validate that the call will succeed.
static Expr *synthesizeCopyWithZoneCall(Expr *Val, VarDecl *VD,
                                        ASTContext &Ctx) {
  // We support @NSCopying on class types (which conform to NSCopying),
  // protocols which conform, and option types thereof.
  auto underlyingTypeAndIsOptional = getUnderlyingTypeOfVariable(VD);
  auto underlyingType = underlyingTypeAndIsOptional.first;
  auto isOptional = underlyingTypeAndIsOptional.second;

  // The element type must conform to NSCopying.  If not, emit an error and just
  // recovery by synthesizing without the copy call.
  auto conformance = checkConformanceToNSCopying(Ctx, VD, underlyingType);
  if (!conformance)
    return Val;

  //- (id)copyWithZone:(NSZone *)zone;
  DeclName copyWithZoneName(Ctx, Ctx.getIdentifier("copy"), { Ctx.Id_with });
  FuncDecl *copyMethod = nullptr;
  for (auto member : conformance->getRequirement()->getMembers()) {
    if (auto func = dyn_cast<FuncDecl>(member)) {
      if (func->getFullName() == copyWithZoneName) {
        copyMethod = func;
        break;
      }
    }
  }
  assert(copyMethod != nullptr);

  // If we have an optional type, we have to "?" the incoming value to only
  // evaluate the subexpression if the incoming value is non-null.
  if (isOptional) {
    Val = new (Ctx) BindOptionalExpr(Val, SourceLoc(), 0);
    Val->setType(underlyingType);
  }

  SubstitutionMap subs =
    SubstitutionMap::get(copyMethod->getGenericSignature(),
                         {underlyingType},
                         ArrayRef<ProtocolConformanceRef>(*conformance));
  ConcreteDeclRef copyMethodRef(copyMethod, subs);
  auto copyMethodType = copyMethod->getInterfaceType()
                           ->castTo<GenericFunctionType>()
                           ->substGenericArgs(subs);
  auto DRE = new (Ctx) DeclRefExpr(copyMethodRef, DeclNameLoc(),
                                   /*IsImplicit=*/true);
  DRE->setType(copyMethodType);

  // Drop the self type
  copyMethodType = copyMethodType->getResult()->castTo<FunctionType>();

  auto DSCE = new (Ctx) DotSyntaxCallExpr(DRE, SourceLoc(), Val);
  DSCE->setImplicit();
  DSCE->setType(copyMethodType);
  DSCE->setThrows(false);

  Expr *Nil = new (Ctx) NilLiteralExpr(SourceLoc(), /*implicit*/true);
  Nil->setType(copyMethodType->getParams()[0].getParameterType());

  auto *Call = CallExpr::createImplicit(Ctx, DSCE, { Nil }, { Ctx.Id_with });
  Call->setType(copyMethodType->getResult());
  Call->setThrows(false);

  TypeLoc ResultTy;
  ResultTy.setType(VD->getType());

  // If we're working with non-optional types, we're forcing the cast.
  if (!isOptional) {
    auto *Cast =
      new (Ctx) ForcedCheckedCastExpr(Call, SourceLoc(), SourceLoc(),
                                      TypeLoc::withoutLoc(underlyingType));
    Cast->setCastKind(CheckedCastKind::ValueCast);
    Cast->setType(underlyingType);
    Cast->setImplicit();

    return Cast;
  }

  // We're working with optional types, so perform a conditional checked
  // downcast.
  auto *Cast =
    new (Ctx) ConditionalCheckedCastExpr(Call, SourceLoc(), SourceLoc(),
                                         TypeLoc::withoutLoc(underlyingType));
  Cast->setCastKind(CheckedCastKind::ValueCast);
  Cast->setType(OptionalType::get(underlyingType));
  Cast->setImplicit();

  // Use OptionalEvaluationExpr to evaluate the "?".
  auto *Result = new (Ctx) OptionalEvaluationExpr(Cast);
  Result->setType(OptionalType::get(underlyingType));

  return Result;
}

/// In a synthesized accessor body, store 'value' to the appropriate element.
///
/// If the property is an override, we call the superclass setter.
/// Otherwise, we do a direct store of the value.
static
void createPropertyStoreOrCallSuperclassSetter(AccessorDecl *accessor,
                                               Expr *value,
                                               AbstractStorageDecl *storage,
                                               TargetImpl target,
                                               SmallVectorImpl<ASTNode> &body,
                                               ASTContext &ctx) {
  // If the storage is an @NSCopying property, then we store the
  // result of a copyWithZone call on the value, not the value itself.
  if (auto property = dyn_cast<VarDecl>(storage)) {
    if (property->getAttrs().hasAttribute<NSCopyingAttr>())
      value = synthesizeCopyWithZoneCall(value, property, ctx);
  }

  // Error recovery.
  if (value->getType()->hasError())
    return;

  Expr *dest = buildStorageReference(accessor, storage, target,
                                     /*isLValue=*/true, ctx);

  // A lazy property setter will store a value of type T into underlying storage
  // of type T?.
  auto destType = dest->getType()->getWithoutSpecifierType();

  // Error recovery.
  if (destType->hasError())
    return;

  if (!destType->isEqual(value->getType())) {
    assert(destType->getOptionalObjectType()->isEqual(value->getType()));
    value = new (ctx) InjectIntoOptionalExpr(value, destType);
  }

  auto *assign = new (ctx) AssignExpr(dest, SourceLoc(), value,
                                      /*IsImplicit=*/true);
  assign->setType(ctx.TheEmptyTupleType);

  body.push_back(assign);
}

LLVM_ATTRIBUTE_UNUSED
static bool isSynthesizedComputedProperty(AbstractStorageDecl *storage) {
  return (storage->getAttrs().hasAttribute<LazyAttr>() ||
          storage->getAttrs().hasAttribute<NSManagedAttr>() ||
          (isa<VarDecl>(storage) &&
           cast<VarDecl>(storage)->hasAttachedPropertyWrapper()));
}

/// Synthesize the body of a trivial getter.  For a non-member vardecl or one
/// which is not an override of a base class property, it performs a direct
/// storage load.  For an override of a base member property, it chains up to
/// super.
static std::pair<BraceStmt *, bool>
synthesizeTrivialGetterBody(AccessorDecl *getter, TargetImpl target,
                            ASTContext &ctx) {
  auto storage = getter->getStorage();
  assert(!isSynthesizedComputedProperty(storage) ||
         target == TargetImpl::Wrapper ||
         target == TargetImpl::WrapperStorage);

  SourceLoc loc = storage->getLoc();

  Expr *result =
    createPropertyLoadOrCallSuperclassGetter(getter, storage, target, ctx);
  ASTNode returnStmt = new (ctx) ReturnStmt(SourceLoc(), result,
                                            /*IsImplicit=*/true);

  return { BraceStmt::create(ctx, loc, returnStmt, loc, true),
           /*isTypeChecked=*/true };
}

/// Synthesize the body of a getter which just directly accesses the
/// underlying storage.
static std::pair<BraceStmt *, bool>
synthesizeTrivialGetterBody(AccessorDecl *getter, ASTContext &ctx) {
  assert(getter->getStorage()->hasStorage());
  return synthesizeTrivialGetterBody(getter, TargetImpl::Storage, ctx);
}

/// Synthesize the body of a getter which just delegates to its superclass
/// implementation.
static std::pair<BraceStmt *, bool>
synthesizeInheritedGetterBody(AccessorDecl *getter, ASTContext &ctx) {
  // This should call the superclass getter.
  return synthesizeTrivialGetterBody(getter, TargetImpl::Super, ctx);
}

/// Synthesize the body of a getter which just delegates to an addressor.
static std::pair<BraceStmt *, bool>
synthesizeAddressedGetterBody(AccessorDecl *getter, ASTContext &ctx) {
  assert(getter->getStorage()->getParsedAccessor(AccessorKind::Address));

  // This should call the addressor.
  return synthesizeTrivialGetterBody(getter, TargetImpl::Implementation, ctx);
}

/// Synthesize the body of a getter which just delegates to a read
/// coroutine accessor.
static std::pair<BraceStmt *, bool>
synthesizeReadCoroutineGetterBody(AccessorDecl *getter, ASTContext &ctx) {
  assert(getter->getStorage()->getParsedAccessor(AccessorKind::Read));

  // This should call the read coroutine.
  return synthesizeTrivialGetterBody(getter, TargetImpl::Implementation, ctx);
}

namespace {
  /// This ASTWalker explores an expression tree looking for expressions (which
  /// are DeclContext's) and changes their parent DeclContext to NewDC.
  class RecontextualizeClosures : public ASTWalker {
    DeclContext *NewDC;
  public:
    RecontextualizeClosures(DeclContext *NewDC) : NewDC(NewDC) {}

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      // If we find a closure, update its declcontext and do *not* walk into it.
      if (auto CE = dyn_cast<AbstractClosureExpr>(E)) {
        CE->setParent(NewDC);
        return { false, E };
      }
      
      if (auto CLE = dyn_cast<CaptureListExpr>(E)) {
        // Make sure to recontextualize any decls in the capture list as well.
        for (auto &CLE : CLE->getCaptureList()) {
          CLE.Var->setDeclContext(NewDC);
          CLE.Init->setDeclContext(NewDC);
        }
      }
      
      // Unlike a closure, a TapExpr is not a DeclContext, so we need to
      // recontextualize its variable and then anything else in its body.
      // FIXME: Might be better to change walkToDeclPre() and walkToStmtPre()
      // below, but I don't know what other effects that might have.
      if (auto TE = dyn_cast<TapExpr>(E)) {
        TE->getVar()->setDeclContext(NewDC);
        for (auto node : TE->getBody()->getElements())
          node.walk(RecontextualizeClosures(NewDC));
      }

      return { true, E };
    }

    /// We don't want to recurse into declarations or statements.
    bool walkToDeclPre(Decl *) override { return false; }
    std::pair<bool, Stmt*> walkToStmtPre(Stmt *S) override { return {false,S}; }
  };
} // end anonymous namespace

/// Synthesize the getter for a lazy property with the specified storage
/// vardecl.
static std::pair<BraceStmt *, bool>
synthesizeLazyGetterBody(AccessorDecl *Get, VarDecl *VD, VarDecl *Storage,
                         ASTContext &Ctx) {
  // FIXME: Remove TypeChecker dependencies below.
  auto &TC = *(TypeChecker *) Ctx.getLazyResolver();

  // The getter checks the optional, storing the initial value in if nil.  The
  // specific pattern we generate is:
  //   get {
  //     if let tmp1 = storage {
  //       return tmp1
  //     }
  //     let tmp2 : Ty = <<initializer expression>>
  //     storage = tmp2
  //     return tmp2
  //   }
  SmallVector<ASTNode, 6> Body;

  // Load the existing storage and store it into the 'tmp1' temporary.
  auto *Tmp1VD = new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Introducer::Let,
                                   /*IsCaptureList*/false, SourceLoc(),
                                   Ctx.getIdentifier("tmp1"), Get);
  Tmp1VD->setInterfaceType(VD->getValueInterfaceType());
  Tmp1VD->setHasNonPatternBindingInit();
  Tmp1VD->setImplicit();

  auto *Named = new (Ctx) NamedPattern(Tmp1VD, /*implicit*/true);
  Named->setType(Tmp1VD->getType());
  auto *Let = new (Ctx) VarPattern(SourceLoc(), /*let*/true, Named,
                                   /*implict*/true);
  Let->setType(Named->getType());
  auto *Some = new (Ctx) OptionalSomePattern(Let, SourceLoc(),
                                             /*implicit*/true);
  Some->setElementDecl(Ctx.getOptionalSomeDecl());
  Some->setType(OptionalType::get(Let->getType()));

  auto *StoredValueExpr =
    createPropertyLoadOrCallSuperclassGetter(Get, Storage,
                                             TargetImpl::Storage, Ctx);
  SmallVector<StmtConditionElement, 1> Cond;
  Cond.emplace_back(SourceLoc(), Some, StoredValueExpr);

  // Build the early return inside the if.
  auto *Tmp1DRE = new (Ctx) DeclRefExpr(Tmp1VD, DeclNameLoc(), /*Implicit*/true,
                                        AccessSemantics::Ordinary);
  Tmp1DRE->setType(Tmp1VD->getType());
  auto *Return = new (Ctx) ReturnStmt(SourceLoc(), Tmp1DRE,
                                      /*implicit*/true);


  // Build the "if" around the early return.
  Body.push_back(new (Ctx) IfStmt(LabeledStmtInfo(),
                                  SourceLoc(), Ctx.AllocateCopy(Cond), Return,
                                  /*elseloc*/SourceLoc(), /*else*/nullptr,
                                  /*implicit*/ true));


  auto *Tmp2VD = new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Introducer::Let,
                                   /*IsCaptureList*/false, SourceLoc(),
                                   Ctx.getIdentifier("tmp2"),
                                   Get);
  Tmp2VD->setInterfaceType(VD->getValueInterfaceType());
  Tmp2VD->setImplicit();


  // Take the initializer from the PatternBindingDecl for VD.
  // TODO: This doesn't work with complicated patterns like:
  //   lazy var (a,b) = foo()
  auto PBD = VD->getParentPatternBinding();
  unsigned entryIndex = PBD->getPatternEntryIndexForVarDecl(VD);

  Expr *InitValue;
  if (PBD->getPatternList()[entryIndex].getInit()) {
    PBD->setInitializerSubsumed(entryIndex);

    if (!PBD->isInitializerChecked(entryIndex))
      TC.typeCheckPatternBinding(PBD, entryIndex);

    InitValue = PBD->getPatternList()[entryIndex].getInit();
  } else {
    InitValue = new (Ctx) ErrorExpr(SourceRange(), Tmp2VD->getType());
  }

  // Recontextualize any closure declcontexts nested in the initializer to
  // realize that they are in the getter function.
  Get->getImplicitSelfDecl()->setDeclContext(Get);

  InitValue->walk(RecontextualizeClosures(Get));

  // Wrap the initializer in a LazyInitializerExpr to avoid walking it twice.
  auto initType = InitValue->getType();
  InitValue = new (Ctx) LazyInitializerExpr(InitValue);
  InitValue->setType(initType);

  Pattern *Tmp2PBDPattern = new (Ctx) NamedPattern(Tmp2VD, /*implicit*/true);
  Tmp2PBDPattern =
    TypedPattern::createImplicit(Ctx, Tmp2PBDPattern, Tmp2VD->getType());

  auto *Tmp2PBD = PatternBindingDecl::createImplicit(
      Ctx, StaticSpellingKind::None, Tmp2PBDPattern, InitValue, Get,
      /*VarLoc*/ InitValue->getStartLoc());
  Body.push_back(Tmp2PBD);
  Body.push_back(Tmp2VD);

  // Assign tmp2 into storage.
  auto Tmp2DRE = new (Ctx) DeclRefExpr(Tmp2VD, DeclNameLoc(), /*Implicit*/true,
                                       AccessSemantics::DirectToStorage);
  Tmp2DRE->setType(Tmp2VD->getType());
  createPropertyStoreOrCallSuperclassSetter(Get, Tmp2DRE, Storage,
                                            TargetImpl::Storage, Body, Ctx);

  // Return tmp2.
  Tmp2DRE = new (Ctx) DeclRefExpr(Tmp2VD, DeclNameLoc(), /*Implicit*/true,
                                  AccessSemantics::DirectToStorage);
  Tmp2DRE->setType(Tmp2VD->getType());

  Body.push_back(new (Ctx) ReturnStmt(SourceLoc(), Tmp2DRE, /*implicit*/true));

  return { BraceStmt::create(Ctx, VD->getLoc(), Body, VD->getLoc(),
                             /*implicit*/true),
           /*isTypeChecked=*/true };
}

/// Synthesize the body of a getter for a property wrapper, which
/// delegates to the wrapper's "value" property.
static std::pair<BraceStmt *, bool>
synthesizePropertyWrapperGetterBody(AccessorDecl *getter, ASTContext &ctx) {
  return synthesizeTrivialGetterBody(getter, TargetImpl::Wrapper, ctx);
}

static std::pair<BraceStmt *, bool>
synthesizeInvalidAccessor(AccessorDecl *accessor, ASTContext &ctx) {
  auto loc = accessor->getLoc();
  return { BraceStmt::create(ctx, loc, ArrayRef<ASTNode>(), loc, true), true };
}

static std::pair<BraceStmt *, bool>
synthesizeGetterBody(AccessorDecl *getter, ASTContext &ctx) {
  auto storage = getter->getStorage();

  // Synthesize the getter for a lazy property or property wrapper.
  if (auto var = dyn_cast<VarDecl>(storage)) {
    if (var->getAttrs().hasAttribute<LazyAttr>()) {
      auto *storage = var->getLazyStorageProperty();
      return synthesizeLazyGetterBody(getter, var, storage, ctx);
    }

    if (var->hasAttachedPropertyWrapper()) {
      return synthesizePropertyWrapperGetterBody(getter, ctx);
    }

    if (var->getOriginalWrappedProperty(
            PropertyWrapperSynthesizedPropertyKind::StorageWrapper)) {
      return synthesizeTrivialGetterBody(getter, TargetImpl::WrapperStorage,
                                         ctx);
    }
  }

  if (getter->hasForcedStaticDispatch()) {
    return synthesizeTrivialGetterBody(getter, TargetImpl::Ordinary, ctx);
  }

  switch (getter->getStorage()->getReadImpl()) {
  case ReadImplKind::Stored:
    return synthesizeTrivialGetterBody(getter, ctx);

  case ReadImplKind::Get:
    return synthesizeInvalidAccessor(getter, ctx);

  case ReadImplKind::Inherited:
    return synthesizeInheritedGetterBody(getter, ctx);

  case ReadImplKind::Address:
    return synthesizeAddressedGetterBody(getter, ctx);

  case ReadImplKind::Read:
    return synthesizeReadCoroutineGetterBody(getter, ctx);
  }
  llvm_unreachable("bad ReadImplKind");
}

/// Synthesize the body of a setter which just stores to the given storage
/// declaration (which doesn't have to be the storage for the setter).
static std::pair<BraceStmt *, bool>
synthesizeTrivialSetterBodyWithStorage(AccessorDecl *setter,
                                       TargetImpl target,
                                       AbstractStorageDecl *storageToUse,
                                       ASTContext &ctx) {
  SourceLoc loc = setter->getStorage()->getLoc();

  VarDecl *valueParamDecl = setter->getParameters()->get(0);

  auto *valueDRE =
    new (ctx) DeclRefExpr(valueParamDecl, DeclNameLoc(), /*IsImplicit=*/true);
  valueDRE->setType(valueParamDecl->getType());

  SmallVector<ASTNode, 1> setterBody;

  createPropertyStoreOrCallSuperclassSetter(setter, valueDRE, storageToUse,
                                            target, setterBody, ctx);
  return { BraceStmt::create(ctx, loc, setterBody, loc, true),
           /*isTypeChecked=*/true };
}

static std::pair<BraceStmt *, bool>
synthesizeTrivialSetterBody(AccessorDecl *setter, ASTContext &ctx) {
  auto storage = setter->getStorage();
  assert(!isSynthesizedComputedProperty(storage));

  return synthesizeTrivialSetterBodyWithStorage(setter, TargetImpl::Storage,
                                                storage, ctx);
}

/// Synthesize the body of a setter for a property wrapper, which
/// delegates to the wrapper's "value" property.
static std::pair<BraceStmt *, bool>
synthesizePropertyWrapperSetterBody(AccessorDecl *setter, ASTContext &ctx) {
  return synthesizeTrivialSetterBodyWithStorage(setter, TargetImpl::Wrapper,
                                                setter->getStorage(), ctx);
}

/// Synthesize the body of a setter which just delegates to a mutable
/// addressor.
static std::pair<BraceStmt *, bool>
synthesizeMutableAddressSetterBody(AccessorDecl *setter, ASTContext &ctx) {
  // This should call the mutable addressor.
  return synthesizeTrivialSetterBodyWithStorage(setter,
                                                TargetImpl::Implementation,
                                                setter->getStorage(), ctx);
}

/// Synthesize the body of a setter which just delegates to a modify
/// coroutine accessor.
static std::pair<BraceStmt *, bool>
synthesizeModifyCoroutineSetterBody(AccessorDecl *setter, ASTContext &ctx) {
  // This should call the modify coroutine.
  return synthesizeTrivialSetterBodyWithStorage(setter,
                                                TargetImpl::Implementation,
                                                setter->getStorage(), ctx);
}

static Expr *maybeWrapInOutExpr(Expr *expr, ASTContext &ctx) {
  if (auto lvalueType = expr->getType()->getAs<LValueType>()) {
    auto type = lvalueType->getObjectType();
    return new (ctx) InOutExpr(SourceLoc(), expr, type, true);
  }

  return expr;
}

/// Given a VarDecl with a willSet: and/or didSet: specifier, synthesize the
/// setter which calls them.
static std::pair<BraceStmt *, bool>
synthesizeObservedSetterBody(AccessorDecl *Set, TargetImpl target,
                             ASTContext &Ctx) {
  auto VD = cast<VarDecl>(Set->getStorage());

  SourceLoc Loc = VD->getLoc();

  // Start by finding the decls for 'self' and 'value'.
  auto *SelfDecl = Set->getImplicitSelfDecl();
  VarDecl *ValueDecl = Set->getParameters()->get(0);

  bool IsSelfLValue = VD->isSetterMutating();

  SubstitutionMap subs;
  if (auto *genericEnv = Set->getGenericEnvironment())
    subs = genericEnv->getForwardingSubstitutionMap();

  // The setter loads the oldValue, invokes willSet with the incoming value,
  // does a direct store, then invokes didSet with the oldValue.
  SmallVector<ASTNode, 6> SetterBody;

  auto callObserver = [&](AccessorDecl *observer, VarDecl *arg) {
    ConcreteDeclRef ref(observer, subs);
    auto type = observer->getInterfaceType().subst(subs);
    Expr *Callee = new (Ctx) DeclRefExpr(ref, DeclNameLoc(), /*imp*/true);
    Callee->setType(type);
    auto *ValueDRE = new (Ctx) DeclRefExpr(arg, DeclNameLoc(), /*imp*/true);
    ValueDRE->setType(arg->getType());

    if (SelfDecl) {
      auto *SelfDRE = buildSelfReference(SelfDecl, SelfAccessorKind::Peer,
                                         IsSelfLValue, Ctx);
      SelfDRE = maybeWrapInOutExpr(SelfDRE, Ctx);
      auto *DSCE = new (Ctx) DotSyntaxCallExpr(Callee, SourceLoc(), SelfDRE);

      if (auto funcType = type->getAs<FunctionType>())
        type = funcType->getResult();
      DSCE->setType(type);
      DSCE->setThrows(false);
      Callee = DSCE;
    }

    auto *Call = CallExpr::createImplicit(Ctx, Callee, { ValueDRE },
                                          { Identifier() });
    if (auto funcType = type->getAs<FunctionType>())
      type = funcType->getResult();
    Call->setType(type);
    Call->setThrows(false);

    SetterBody.push_back(Call);
  };

  // If there is a didSet, it will take the old value.  Load it into a temporary
  // 'let' so we have it for later.
  // TODO: check the body of didSet to only do this load (which may call the
  // superclass getter) if didSet takes an argument.
  VarDecl *OldValue = nullptr;
  if (VD->getParsedAccessor(AccessorKind::DidSet)) {
    Expr *OldValueExpr
      = buildStorageReference(Set, VD, target, /*isLValue=*/true, Ctx);
    OldValueExpr = new (Ctx) LoadExpr(OldValueExpr, VD->getType());

    OldValue = new (Ctx) VarDecl(/*IsStatic*/false, VarDecl::Introducer::Let,
                                 /*IsCaptureList*/false, SourceLoc(),
                                 Ctx.getIdentifier("tmp"), Set);
    OldValue->setImplicit();
    OldValue->setInterfaceType(VD->getValueInterfaceType());
    auto *tmpPattern = new (Ctx) NamedPattern(OldValue, /*implicit*/ true);
    auto *tmpPBD = PatternBindingDecl::createImplicit(
        Ctx, StaticSpellingKind::None, tmpPattern, OldValueExpr, Set);
    SetterBody.push_back(tmpPBD);
    SetterBody.push_back(OldValue);
  }

  if (auto willSet = VD->getParsedAccessor(AccessorKind::WillSet))
    callObserver(willSet, ValueDecl);
  
  // Create an assignment into the storage or call to superclass setter.
  auto *ValueDRE = new (Ctx) DeclRefExpr(ValueDecl, DeclNameLoc(), true);
  ValueDRE->setType(ValueDecl->getType());
  createPropertyStoreOrCallSuperclassSetter(Set, ValueDRE, VD, target,
                                            SetterBody, Ctx);

  if (auto didSet = VD->getParsedAccessor(AccessorKind::DidSet))
    callObserver(didSet, OldValue);

  return { BraceStmt::create(Ctx, Loc, SetterBody, Loc, true),
           /*isTypeChecked=*/true };
}

static std::pair<BraceStmt *, bool>
synthesizeStoredWithObserversSetterBody(AccessorDecl *setter, ASTContext &ctx) {
  return synthesizeObservedSetterBody(setter, TargetImpl::Storage, ctx);
}

static std::pair<BraceStmt *, bool>
synthesizeInheritedWithObserversSetterBody(AccessorDecl *setter,
                                           ASTContext &ctx) {
  return synthesizeObservedSetterBody(setter, TargetImpl::Super, ctx);
}

static std::pair<BraceStmt *, bool>
synthesizeSetterBody(AccessorDecl *setter, ASTContext &ctx) {
  auto storage = setter->getStorage();

  // Synthesize the setter for a lazy property or property wrapper.
  if (auto var = dyn_cast<VarDecl>(storage)) {
    if (var->getAttrs().hasAttribute<LazyAttr>()) {
      // Lazy property setters write to the underlying storage.
      auto *storage = var->getLazyStorageProperty();
      return synthesizeTrivialSetterBodyWithStorage(setter, TargetImpl::Storage,
                                                    storage, ctx);
    }

    if (var->hasAttachedPropertyWrapper()) {
      if (var->getParsedAccessor(AccessorKind::WillSet) ||
          var->getParsedAccessor(AccessorKind::DidSet)) {
        return synthesizeObservedSetterBody(setter, TargetImpl::Wrapper, ctx);
      }

      return synthesizePropertyWrapperSetterBody(setter, ctx);
    }

    // Synthesize a getter for the storage wrapper property of a property
    // with an attached wrapper.
    if (auto original = var->getOriginalWrappedProperty(
            PropertyWrapperSynthesizedPropertyKind::StorageWrapper)) {
      auto backingVar = original->getPropertyWrapperBackingProperty();
      return synthesizeTrivialSetterBodyWithStorage(setter,
                                                    TargetImpl::WrapperStorage,
                                                    backingVar, ctx);
    }
  }

  switch (storage->getWriteImpl()) {
  case WriteImplKind::Immutable:
    llvm_unreachable("synthesizing setter from immutable storage");

  case WriteImplKind::Stored:
    return synthesizeTrivialSetterBody(setter, ctx);

  case WriteImplKind::StoredWithObservers:
    return synthesizeStoredWithObserversSetterBody(setter, ctx);

  case WriteImplKind::InheritedWithObservers:
    return synthesizeInheritedWithObserversSetterBody(setter, ctx);

  case WriteImplKind::Set:
    return synthesizeInvalidAccessor(setter, ctx);

  case WriteImplKind::MutableAddress:
    return synthesizeMutableAddressSetterBody(setter, ctx);

  case WriteImplKind::Modify:
    return synthesizeModifyCoroutineSetterBody(setter, ctx);
  }
  llvm_unreachable("bad ReadImplKind");
}

static std::pair<BraceStmt *, bool>
synthesizeCoroutineAccessorBody(AccessorDecl *accessor, ASTContext &ctx) {
  assert(accessor->isCoroutine());

  auto storage = accessor->getStorage();
  auto target = (accessor->hasForcedStaticDispatch()
                   ? TargetImpl::Ordinary
                   : TargetImpl::Implementation);

  SourceLoc loc = storage->getLoc();
  SmallVector<ASTNode, 1> body;

  bool isLValue = accessor->getAccessorKind() == AccessorKind::Modify;

  // Build a reference to the storage.
  Expr *ref = buildStorageReference(accessor, storage, target, isLValue, ctx);

  // Wrap it with an `&` marker if this is a modify.
  ref = maybeWrapInOutExpr(ref, ctx);

  // Yield it.
  YieldStmt *yield = YieldStmt::create(ctx, loc, loc, ref, loc, true);
  body.push_back(yield);

  return { BraceStmt::create(ctx, loc, body, loc, true),
           /*isTypeChecked=*/true };
}

/// Synthesize the body of a read coroutine.
static std::pair<BraceStmt *, bool>
synthesizeReadCoroutineBody(AccessorDecl *read, ASTContext &ctx) {
  assert(read->getStorage()->getReadImpl() != ReadImplKind::Read);
  return synthesizeCoroutineAccessorBody(read, ctx);
}

/// Synthesize the body of a modify coroutine.
static std::pair<BraceStmt *, bool>
synthesizeModifyCoroutineBody(AccessorDecl *modify, ASTContext &ctx) {
#ifndef NDEBUG
  auto impl = modify->getStorage()->getReadWriteImpl();
  assert(impl != ReadWriteImplKind::Modify &&
         impl != ReadWriteImplKind::Immutable);
#endif
  return synthesizeCoroutineAccessorBody(modify, ctx);
}

static std::pair<BraceStmt *, bool>
synthesizeAccessorBody(AbstractFunctionDecl *fn, void *) {
  auto *accessor = cast<AccessorDecl>(fn);
  auto &ctx = accessor->getASTContext();

  if (ctx.Stats)
    ctx.Stats->getFrontendCounters().NumAccessorBodiesSynthesized++;

  switch (accessor->getAccessorKind()) {
  case AccessorKind::Get:
    return synthesizeGetterBody(accessor, ctx);

  case AccessorKind::Set:
    return synthesizeSetterBody(accessor, ctx);

  case AccessorKind::Read:
    return synthesizeReadCoroutineBody(accessor, ctx);

  case AccessorKind::Modify:
    return synthesizeModifyCoroutineBody(accessor, ctx);

  case AccessorKind::WillSet:
  case AccessorKind::DidSet:
  case AccessorKind::Address:
  case AccessorKind::MutableAddress:
    break;
  }
  llvm_unreachable("bad synthesized function kind");
}

static void finishImplicitAccessor(AccessorDecl *accessor,
                                   ASTContext &ctx) {
  accessor->setImplicit();

  if (ctx.Stats)
    ctx.Stats->getFrontendCounters().NumAccessorsSynthesized++;

  if (doesAccessorHaveBody(accessor))
    accessor->setBodySynthesizer(&synthesizeAccessorBody);
}

static AccessorDecl *createGetterPrototype(AbstractStorageDecl *storage,
                                           ASTContext &ctx) {
  SourceLoc loc = storage->getLoc();

  ParamDecl *selfDecl = nullptr;
  if (storage->getDeclContext()->isTypeContext()) {
    if (storage->getAttrs().hasAttribute<LazyAttr>()) {
      // For lazy properties, steal the 'self' from the initializer context.
      auto *varDecl = cast<VarDecl>(storage);
      auto *bindingDecl = varDecl->getParentPatternBinding();
      auto *bindingInit = cast<PatternBindingInitializer>(
        bindingDecl->getPatternEntryForVarDecl(varDecl).getInitContext());

      selfDecl = bindingInit->getImplicitSelfDecl();
    }
  }

  GenericParamList *genericParams = createAccessorGenericParams(storage);

  // Add an index-forwarding clause.
  auto *getterParams = buildIndexForwardingParamList(storage, {}, ctx);

  SourceLoc staticLoc;
  if (storage->isStatic())
    staticLoc = storage->getLoc();

  auto getter = AccessorDecl::create(
      ctx, loc, /*AccessorKeywordLoc*/ loc,
      AccessorKind::Get, storage,
      staticLoc, StaticSpellingKind::None,
      /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
      genericParams,
      getterParams,
      TypeLoc(),
      storage->getDeclContext());

  // If we're stealing the 'self' from a lazy initializer, set it now.
  // Note that we don't re-parent the 'self' declaration to be part of
  // the getter until we synthesize the body of the getter later.
  if (selfDecl)
    *getter->getImplicitSelfDeclStorage() = selfDecl;

  if (storage->isGetterMutating())
    getter->setSelfAccessKind(SelfAccessKind::Mutating);
  else
    getter->setSelfAccessKind(SelfAccessKind::NonMutating);

  if (!storage->requiresOpaqueAccessor(AccessorKind::Get))
    getter->setForcedStaticDispatch(true);

  finishImplicitAccessor(getter, ctx);

  return getter;
}

static AccessorDecl *createSetterPrototype(AbstractStorageDecl *storage,
                                           ASTContext &ctx,
                                           AccessorDecl *getter = nullptr) {
  assert(storage->supportsMutation());

  SourceLoc loc = storage->getLoc();

  bool isMutating = storage->isSetterMutating();

  GenericParamList *genericParams = createAccessorGenericParams(storage);

  // Add a "(value : T, indices...)" argument list.
  auto *param = new (ctx) ParamDecl(SourceLoc(), SourceLoc(),
                                    Identifier(), loc,
                                    ctx.getIdentifier("value"),
                                    storage->getDeclContext());
  param->setSpecifier(ParamSpecifier::Default);
  param->setImplicit();

  auto *params = buildIndexForwardingParamList(storage, param, ctx);

  auto setter = AccessorDecl::create(
      ctx, loc, /*AccessorKeywordLoc*/ SourceLoc(),
      AccessorKind::Set, storage,
      /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
      /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
      genericParams, params,
      TypeLoc(),
      storage->getDeclContext());

  if (isMutating)
    setter->setSelfAccessKind(SelfAccessKind::Mutating);
  else
    setter->setSelfAccessKind(SelfAccessKind::NonMutating);

  // All mutable storage requires a setter.
  assert(storage->requiresOpaqueAccessor(AccessorKind::Set));

  finishImplicitAccessor(setter, ctx);

  return setter;
}

static AccessorDecl *
createCoroutineAccessorPrototype(AbstractStorageDecl *storage,
                                 AccessorKind kind,
                                ASTContext &ctx) {
  assert(kind == AccessorKind::Read || kind == AccessorKind::Modify);

  SourceLoc loc = storage->getLoc();

  bool isMutating = storage->isGetterMutating();
  if (kind == AccessorKind::Modify)
    isMutating |= storage->isSetterMutating();

  auto dc = storage->getDeclContext();

  // The forwarding index parameters.
  auto *params = buildIndexForwardingParamList(storage, {}, ctx);

  // Coroutine accessors always return ().
  Type retTy = TupleType::getEmpty(ctx);

  GenericParamList *genericParams = createAccessorGenericParams(storage);

  auto *accessor = AccessorDecl::create(
      ctx, loc, /*AccessorKeywordLoc=*/SourceLoc(),
      kind, storage,
      /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
      /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
      genericParams, params, TypeLoc::withoutLoc(retTy), dc);
  
  if (isMutating)
    accessor->setSelfAccessKind(SelfAccessKind::Mutating);
  else
    accessor->setSelfAccessKind(SelfAccessKind::NonMutating);

  // If the storage does not provide this accessor as an opaque accessor,
  // we can't add a dynamically-dispatched method entry for the accessor,
  // so force it to be statically dispatched. ("final" would be inappropriate
  // because the property can still be overridden.)
  if (!storage->requiresOpaqueAccessor(kind))
    accessor->setForcedStaticDispatch(true);

  // Make sure the coroutine is available enough to access
  // the storage (and its getters/setters if it has them).
  SmallVector<const Decl *, 2> asAvailableAs;
  asAvailableAs.push_back(storage);
  if (FuncDecl *getter = storage->getParsedAccessor(AccessorKind::Get)) {
    asAvailableAs.push_back(getter);
  }
  if (kind == AccessorKind::Modify) {
    if (FuncDecl *setter = storage->getParsedAccessor(AccessorKind::Set)) {
      asAvailableAs.push_back(setter);
    }
  }

  AvailabilityInference::applyInferredAvailableAttrs(accessor,
                                                     asAvailableAs, ctx);

  finishImplicitAccessor(accessor, ctx);

  return accessor;
}

static AccessorDecl *
createReadCoroutinePrototype(AbstractStorageDecl *storage,
                             ASTContext &ctx) {
  return createCoroutineAccessorPrototype(storage, AccessorKind::Read, ctx);
}

static AccessorDecl *
createModifyCoroutinePrototype(AbstractStorageDecl *storage,
                               ASTContext &ctx) {
  return createCoroutineAccessorPrototype(storage, AccessorKind::Modify, ctx);
}

llvm::Expected<AccessorDecl *>
SynthesizeAccessorRequest::evaluate(Evaluator &evaluator,
                                    AbstractStorageDecl *storage,
                                    AccessorKind kind) const {
  auto &ctx = storage->getASTContext();

  switch (kind) {
  case AccessorKind::Get:
    return createGetterPrototype(storage, ctx);

  case AccessorKind::Set:
    return createSetterPrototype(storage, ctx);

  case AccessorKind::Read:
    return createReadCoroutinePrototype(storage, ctx);

  case AccessorKind::Modify:
    return createModifyCoroutinePrototype(storage, ctx);

#define OPAQUE_ACCESSOR(ID, KEYWORD)
#define ACCESSOR(ID) \
  case AccessorKind::ID:
#include "swift/AST/AccessorKinds.def"
    llvm_unreachable("not an opaque accessor");
  }
  llvm_unreachable("Unhandled AccessorKind in switch");
}

llvm::Expected<bool>
RequiresOpaqueAccessorsRequest::evaluate(Evaluator &evaluator,
                                         VarDecl *var) const {
  // Nameless vars from interface files should not have any accessors.
  // TODO: Replace this check with a broader check that all storage decls
  //       from interface files have all their accessors up front.
  if (var->getBaseName().empty())
    return false;

  // Computed properties always require opaque accessors.
  if (!var->getImplInfo().isSimpleStored())
    return true;

  // The backing storage for a lazy property does require opaque accessors.
  if (var->isLazyStorageProperty())
    return false;

  auto *dc = var->getDeclContext();

  // Local stored variables don't require opaque accessors.
  if (dc->isLocalContext()) {
    return false;

  } else if (dc->isModuleScopeContext()) {
    // Fixed-layout global variables don't require opaque accessors.
    if (!var->isResilient() && !var->isNativeDynamic())
      return false;

  // Stored properties imported from Clang don't require opaque accessors.
  } else if (auto *structDecl = dyn_cast<StructDecl>(dc)) {
    if (structDecl->hasClangNode())
      return false;
  }

  // Stored properties in SIL mode don't get accessors.
  // But we might need to create opaque accessors for them.
  if (auto sourceFile = dc->getParentSourceFile()) {
    if (sourceFile->Kind == SourceFileKind::SIL) {
      if (!var->getParsedAccessor(AccessorKind::Get))
        return false;
    }
  }

  // Everything else requires opaque accessors.
  return true;
}

llvm::Expected<bool>
RequiresOpaqueModifyCoroutineRequest::evaluate(Evaluator &evaluator,
                                               AbstractStorageDecl *storage) const {
  // Only for mutable storage.
  if (!storage->supportsMutation())
    return false;

  auto *dc = storage->getDeclContext();

  // Local properties don't have an opaque modify coroutine.
  if (dc->isLocalContext())
    return false;

  // Fixed-layout global properties don't have an opaque modify coroutine.
  if (dc->isModuleScopeContext() && !storage->isResilient())
    return false;

  // Imported storage declarations don't have an opaque modify coroutine.
  if (storage->hasClangNode())
    return false;

  // Dynamic storage does not have an opaque modify coroutine.
  if (dc->getSelfClassDecl())
    if (storage->isObjCDynamic())
      return false;

  // Requirements of ObjC protocols don't have an opaque modify coroutine.
  if (auto protoDecl = dyn_cast<ProtocolDecl>(dc))
    if (protoDecl->isObjC())
      return false;

  return true;
}

/// Mark the accessor as transparent if we can.
///
/// If the storage is inside a fixed-layout nominal type, we can mark the
/// accessor as transparent, since in this case we just want it for abstraction
/// purposes (i.e., to make access to the variable uniform and to be able to
/// put the getter in a vtable).
///
/// If the storage is for a global stored property or a stored property of a
/// resilient type, we are synthesizing accessors to present a resilient
/// interface to the storage and they should not be transparent.
llvm::Expected<bool>
IsAccessorTransparentRequest::evaluate(Evaluator &evaluator,
                                       AccessorDecl *accessor) const {
  auto *storage = accessor->getStorage();
  if (storage->isTransparent())
    return true;

  if (accessor->getAttrs().hasAttribute<TransparentAttr>())
    return true;

  if (!accessor->isImplicit())
    return false;

  if (!doesAccessorHaveBody(accessor))
    return false;

  auto *DC = accessor->getDeclContext();
  auto *nominalDecl = DC->getSelfNominalTypeDecl();

  // Global variable accessors are not @_transparent.
  if (!nominalDecl)
    return false;

  // Accessors for resilient properties are not @_transparent.
  if (storage->isResilient())
    return false;

  // Accessors for classes with @objc ancestry are not @_transparent,
  // since they use a field offset variable which is not exported.
  if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
    if (classDecl->checkAncestry(AncestryFlags::ObjC))
      return false;

  // Accessors synthesized on-demand are never transaprent.
  if (accessor->hasForcedStaticDispatch())
    return false;

  if (accessor->getAccessorKind() == AccessorKind::Get ||
      accessor->getAccessorKind() == AccessorKind::Set) {
    // Getters and setters for lazy properties are not @_transparent.
    if (storage->getAttrs().hasAttribute<LazyAttr>())
      return false;

    // Getters/setters for a property with a wrapper are not @_transparent if
    // the backing variable has more-restrictive access than the original
    // property. The same goes for its storage wrapper.
    if (auto var = dyn_cast<VarDecl>(storage)) {
      if (auto backingVar = var->getPropertyWrapperBackingProperty()) {
        if (backingVar->getFormalAccess() < var->getFormalAccess())
          return false;
      }

      if (auto original = var->getOriginalWrappedProperty(
              PropertyWrapperSynthesizedPropertyKind::StorageWrapper)) {
        auto backingVar = original->getPropertyWrapperBackingProperty();
        if (backingVar->getFormalAccess() < var->getFormalAccess())
          return false;
      }
    }
  }

  switch (accessor->getAccessorKind()) {
  case AccessorKind::Get:
    break;

  case AccessorKind::Set:

    switch (storage->getWriteImpl()) {
    case WriteImplKind::Set:
      // Setters for property wrapper are OK, unless there are observers.
      // FIXME: This should be folded into the WriteImplKind below.
      if (auto var = dyn_cast<VarDecl>(storage)) {
        if (var->hasAttachedPropertyWrapper()) {
          if (var->getParsedAccessor(AccessorKind::DidSet) ||
              var->getParsedAccessor(AccessorKind::WillSet))
            return false;

          break;
        } else if (var->getOriginalWrappedProperty(
                     PropertyWrapperSynthesizedPropertyKind::StorageWrapper)) {
          break;
        }
      }

      // Anything else should not have a synthesized setter.
      LLVM_FALLTHROUGH;
    case WriteImplKind::Immutable:
      llvm_unreachable("should not be synthesizing accessor in this case");

    case WriteImplKind::StoredWithObservers:
    case WriteImplKind::InheritedWithObservers:
      // Setters for observed properties are not @_transparent (because the
      // observers are private) and cannot be referenced from a transparent
      // method).
      return false;

    case WriteImplKind::Stored:
    case WriteImplKind::MutableAddress:
    case WriteImplKind::Modify:
      break;
    }
    break;

  case AccessorKind::Read:
  case AccessorKind::Modify:
    break;

  case AccessorKind::WillSet:
  case AccessorKind::DidSet:
  case AccessorKind::Address:
  case AccessorKind::MutableAddress:
    llvm_unreachable("bad synthesized function kind");
  }

  return true;
}

llvm::Expected<VarDecl *>
LazyStoragePropertyRequest::evaluate(Evaluator &evaluator,
                                     VarDecl *VD) const {
  assert(isa<SourceFile>(VD->getDeclContext()->getModuleScopeContext()));
  assert(VD->getAttrs().hasAttribute<LazyAttr>());
  auto &Context = VD->getASTContext();

  // Create the storage property as an optional of VD's type.
  SmallString<64> NameBuf;
  NameBuf += "$__lazy_storage_$_";
  NameBuf += VD->getName().str();
  auto StorageName = Context.getIdentifier(NameBuf);
  auto StorageInterfaceTy = OptionalType::get(VD->getInterfaceType());
  auto StorageTy = OptionalType::get(VD->getType());

  auto *Storage = new (Context) VarDecl(/*IsStatic*/false, VarDecl::Introducer::Var,
                                        /*IsCaptureList*/false, VD->getLoc(),
                                        StorageName,
                                        VD->getDeclContext());
  Storage->setInterfaceType(StorageInterfaceTy);
  Storage->setLazyStorageProperty(true);
  Storage->setUserAccessible(false);

  // The storage is implicit and private.
  Storage->setImplicit();
  Storage->overwriteAccess(AccessLevel::Private);
  Storage->overwriteSetterAccess(AccessLevel::Private);

  addMemberToContextIfNeeded(Storage, VD->getDeclContext(), VD);

  // Create the pattern binding decl for the storage decl.  This will get
  // default initialized to nil.
  Pattern *PBDPattern = new (Context) NamedPattern(Storage, /*implicit*/true);
  PBDPattern->setType(StorageTy);
  PBDPattern = TypedPattern::createImplicit(Context, PBDPattern, StorageTy);
  auto *InitExpr = new (Context) NilLiteralExpr(SourceLoc(), /*Implicit=*/true);
  InitExpr->setType(Storage->getType());

  auto *PBD = PatternBindingDecl::createImplicit(
      Context, StaticSpellingKind::None, PBDPattern, InitExpr,
      VD->getDeclContext(), /*VarLoc*/ VD->getLoc());
  PBD->setInitializerChecked(0);

  addMemberToContextIfNeeded(PBD, VD->getDeclContext(), Storage);

  return Storage;
}

/// Synthesize a computed property `$foo` for a property with an attached
/// wrapper that has a `projectedValue` property.
static VarDecl *synthesizePropertyWrapperStorageWrapperProperty(
    ASTContext &ctx, VarDecl *var, Type wrapperType,
    VarDecl *wrapperVar) {
  // If the original property has a @_projectedValueProperty attribute, use
  // that to find the storage wrapper property.
  if (auto attr = var->getAttrs().getAttribute<ProjectedValuePropertyAttr>()){
    SmallVector<ValueDecl *, 2> declsFound;
    auto projectionName = attr->ProjectionPropertyName;
    auto dc = var->getDeclContext();
    if (dc->isTypeContext()) {
      dc->lookupQualified(dc->getSelfNominalTypeDecl(), projectionName,
                          NL_QualifiedDefault, declsFound);
    } else if (dc->isModuleScopeContext()) {
      dc->lookupQualified(dc->getParentModule(), projectionName,
                          NL_QualifiedDefault, declsFound);
    } else {
      llvm_unreachable("Property wrappers don't work in local contexts");
    }

    if (declsFound.size() == 1 && isa<VarDecl>(declsFound.front())) {
      auto property = cast<VarDecl>(declsFound.front());
      property->setOriginalWrappedProperty(var);
      return property;
    }

    ctx.Diags.diagnose(attr->getLocation(),
                       diag::property_wrapper_projection_value_missing,
                       projectionName);
    attr->setInvalid();
  }

  // Compute the name of the storage type.
  SmallString<64> nameBuf;
  nameBuf = "$";
  nameBuf += var->getName().str();
  Identifier name = ctx.getIdentifier(nameBuf);

  // Determine the type of the property.
  Type propertyType = wrapperType->getTypeOfMember(
      var->getModuleContext(), wrapperVar,
      wrapperVar->getValueInterfaceType());

  // Form the property.
  auto dc = var->getDeclContext();
  VarDecl *property = new (ctx) VarDecl(/*IsStatic=*/var->isStatic(),
                                        VarDecl::Introducer::Var,
                                        /*IsCaptureList=*/false,
                                        var->getLoc(),
                                        name, dc);
  property->setInterfaceType(propertyType);
  property->setImplicit();
  property->setOriginalWrappedProperty(var);
  addMemberToContextIfNeeded(property, dc, var);

  // Create the pattern binding declaration for the property.
  Pattern *pbdPattern = new (ctx) NamedPattern(property, /*implicit=*/true);
  pbdPattern->setType(propertyType);
  pbdPattern = TypedPattern::createImplicit(ctx, pbdPattern, propertyType);
  auto pbd = PatternBindingDecl::createImplicit(
      ctx, property->getCorrectStaticSpelling(), pbdPattern,
      /*init*/nullptr, dc, SourceLoc());
  addMemberToContextIfNeeded(pbd, dc, var);
  pbd->setStatic(var->isStatic());

  // Determine the access level for the property.
  property->overwriteAccess(var->getFormalAccess());

  // Determine setter access.
  property->overwriteSetterAccess(var->getSetterFormalAccess());

  // Add the accessors we need.
  bool hasSetter = wrapperVar->isSettable(nullptr) &&
      wrapperVar->isSetterAccessibleFrom(var->getInnermostDeclContext());
  if (hasSetter)
    property->setImplInfo(StorageImplInfo::getMutableComputed());
  else
    property->setImplInfo(StorageImplInfo::getImmutableComputed());

  var->getAttrs().add(
      new (ctx) ProjectedValuePropertyAttr(name, SourceLoc(), SourceRange(),
                                            /*Implicit=*/true));
  return property;
}

static void typeCheckSynthesizedWrapperInitializer(
    PatternBindingDecl *pbd, VarDecl *backingVar, PatternBindingDecl *parentPBD,
    Expr *&initializer) {
  // Figure out the context in which the initializer was written.
  DeclContext *originalDC = parentPBD->getDeclContext();
  if (!originalDC->isLocalContext()) {
    auto initContext =
        cast_or_null<PatternBindingInitializer>(parentPBD->getInitContext(0));
    if (initContext)
      originalDC = initContext;
  }

  // Type-check the initialization.
  ASTContext &ctx = pbd->getASTContext();
  auto &tc = *static_cast<TypeChecker *>(ctx.getLazyResolver());
  tc.typeCheckExpression(initializer, originalDC);
  if (auto initializerContext =
          dyn_cast_or_null<Initializer>(
            pbd->getPatternEntryForVarDecl(backingVar).getInitContext())) {
    tc.contextualizeInitializer(initializerContext, initializer);
  }
  tc.checkPropertyWrapperErrorHandling(pbd, initializer);
}

static PropertyWrapperMutability::Value
getGetterMutatingness(VarDecl *var) {
  return var->isGetterMutating()
    ? PropertyWrapperMutability::Mutating
    : PropertyWrapperMutability::Nonmutating;
}

static PropertyWrapperMutability::Value
getSetterMutatingness(VarDecl *var, DeclContext *dc) {
  if (!var->isSettable(nullptr) ||
      !var->isSetterAccessibleFrom(dc))
    return PropertyWrapperMutability::DoesntExist;
  
  return var->isSetterMutating()
    ? PropertyWrapperMutability::Mutating
    : PropertyWrapperMutability::Nonmutating;
}

llvm::Expected<Optional<PropertyWrapperMutability>>
PropertyWrapperMutabilityRequest::evaluate(Evaluator &,
                                           VarDecl *var) const {
  VarDecl *originalVar = var;
  unsigned numWrappers = originalVar->getAttachedPropertyWrappers().size();
  bool isProjectedValue = false;
  if (numWrappers < 1) {
    originalVar = var->getOriginalWrappedProperty(
        PropertyWrapperSynthesizedPropertyKind::StorageWrapper);
    if (!originalVar)
      return None;

    numWrappers = originalVar->getAttachedPropertyWrappers().size();
    isProjectedValue = true;
  }

  if (var->getParsedAccessor(AccessorKind::Get))
    return None;
  if (var->getParsedAccessor(AccessorKind::Set))
    return None;

  // Figure out which member we're looking through.
  auto varMember = isProjectedValue
    ? &PropertyWrapperTypeInfo::projectedValueVar
    : &PropertyWrapperTypeInfo::valueVar;

  // Start with the traits from the outermost wrapper.
  auto firstWrapper = originalVar->getAttachedPropertyWrapperTypeInfo(0);
  if (firstWrapper.*varMember == nullptr)
    return None;
  
  PropertyWrapperMutability result;
  
  result.Getter = getGetterMutatingness(firstWrapper.*varMember);
  result.Setter = getSetterMutatingness(firstWrapper.*varMember,
                                        var->getInnermostDeclContext());
  
  // Compose the traits of the following wrappers.
  for (unsigned i = 1; i < numWrappers && !isProjectedValue; ++i) {
    assert(var == originalVar);
    auto wrapper = var->getAttachedPropertyWrapperTypeInfo(i);
    if (!wrapper.valueVar)
      return None;
    
    PropertyWrapperMutability nextResult;
    nextResult.Getter =
                    result.composeWith(getGetterMutatingness(wrapper.valueVar));
    // A property must have a getter, so we can't compose a wrapper that
    // exposes a mutating getter wrapped inside a get-only wrapper.
    if (nextResult.Getter == PropertyWrapperMutability::DoesntExist) {
      auto &ctx = var->getASTContext();
      ctx.Diags.diagnose(var->getAttachedPropertyWrappers()[i]->getLocation(),
               diag::property_wrapper_mutating_get_composed_to_get_only,
               var->getAttachedPropertyWrappers()[i]->getTypeLoc(),
               var->getAttachedPropertyWrappers()[i-1]->getTypeLoc());

      return None;
    }
    nextResult.Setter =
              result.composeWith(getSetterMutatingness(wrapper.valueVar,
                                               var->getInnermostDeclContext()));
    result = nextResult;
  }
  assert(result.Getter != PropertyWrapperMutability::DoesntExist
         && "getter must exist");
  return result;
}

llvm::Expected<PropertyWrapperBackingPropertyInfo>
PropertyWrapperBackingPropertyInfoRequest::evaluate(Evaluator &evaluator,
                                                    VarDecl *var) const {
  // Determine the type of the backing property.
  auto wrapperType = var->getPropertyWrapperBackingPropertyType();
  if (!wrapperType || wrapperType->hasError())
    return PropertyWrapperBackingPropertyInfo();

  auto wrapperInfo = var->getAttachedPropertyWrapperTypeInfo(0);
  if (!wrapperInfo)
    return PropertyWrapperBackingPropertyInfo();

  // Compute the name of the storage type.
  ASTContext &ctx = var->getASTContext();
  SmallString<64> nameBuf;
  nameBuf = "_";
  nameBuf += var->getName().str();
  Identifier name = ctx.getIdentifier(nameBuf);

  // Determine the type of the storage.
  auto dc = var->getDeclContext();
  Type storageInterfaceType = wrapperType;
  Type storageType = dc->mapTypeIntoContext(storageInterfaceType);

  // Make sure that the property type matches the value of the
  // wrapper type.
  if (!storageInterfaceType->hasError()) {
    Type expectedPropertyType =
        computeWrappedValueType(var, storageInterfaceType);
    Type propertyType = var->getValueInterfaceType();
    assert(propertyType);
    if (!expectedPropertyType->hasError() &&
        !propertyType->hasError() &&
        !propertyType->isEqual(expectedPropertyType)) {
      var->diagnose(diag::property_wrapper_incompatible_property,
                    propertyType, wrapperType);
      if (auto nominalWrapper = wrapperType->getAnyNominal()) {
        nominalWrapper->diagnose(diag::property_wrapper_declared_here,
                                 nominalWrapper->getFullName());
      }
    }
  }

  // Create the backing storage property and note it in the cache.
  VarDecl *backingVar = new (ctx) VarDecl(/*IsStatic=*/var->isStatic(),
                                          VarDecl::Introducer::Var,
                                          /*IsCaptureList=*/false,
                                          var->getLoc(),
                                          name, dc);
  backingVar->setInterfaceType(storageInterfaceType);
  backingVar->setImplicit();
  backingVar->setOriginalWrappedProperty(var);

  // The backing storage is 'private'.
  backingVar->overwriteAccess(AccessLevel::Private);
  backingVar->overwriteSetterAccess(AccessLevel::Private);

  addMemberToContextIfNeeded(backingVar, dc, var);

  // Create the pattern binding declaration for the backing property.
  Pattern *pbdPattern = new (ctx) NamedPattern(backingVar, /*implicit=*/true);
  pbdPattern->setType(storageType);
  pbdPattern = TypedPattern::createImplicit(ctx, pbdPattern, storageType);
  auto pbd = PatternBindingDecl::createImplicit(
      ctx, var->getCorrectStaticSpelling(), pbdPattern,
      /*init*/ nullptr, dc, SourceLoc());
  addMemberToContextIfNeeded(pbd, dc, var);
  pbd->setStatic(var->isStatic());

  // Take the initializer from the original property.
  auto parentPBD = var->getParentPatternBinding();
  unsigned patternNumber = parentPBD->getPatternEntryIndexForVarDecl(var);
  
  // Force the default initializer to come into existence, if there is one,
  // and the wrapper doesn't provide its own.
  if (!parentPBD->isInitialized(patternNumber)
      && parentPBD->isDefaultInitializable(patternNumber)
      && !wrapperInfo.defaultInit) {
    auto &tc = *static_cast<TypeChecker *>(ctx.getLazyResolver());
    auto ty = parentPBD->getPattern(patternNumber)->getType();
    if (auto defaultInit = tc.buildDefaultInitializer(ty))
      parentPBD->setInit(patternNumber, defaultInit);
  }
  
  if (parentPBD->isInitialized(patternNumber) &&
      !parentPBD->isInitializerChecked(patternNumber)) {
    auto &tc = *static_cast<TypeChecker *>(ctx.getLazyResolver());
    tc.typeCheckPatternBinding(parentPBD, patternNumber);
  }

  Expr *originalInitialValue = nullptr;
  if (Expr *init = parentPBD->getInit(patternNumber)) {
    pbd->setInit(0, init);
    pbd->setInitializerChecked(0);
    originalInitialValue = findOriginalPropertyWrapperInitialValue(var, init);
  } else if (!parentPBD->isInitialized(patternNumber) &&
             wrapperInfo.defaultInit) {
    // FIXME: Record this expression somewhere so that DI can perform the
    // initialization itself.
    auto typeExpr = TypeExpr::createImplicit(storageType, ctx);
    Expr *initializer = CallExpr::createImplicit(ctx, typeExpr, {}, { });
    typeCheckSynthesizedWrapperInitializer(pbd, backingVar, parentPBD,
                                           initializer);
    pbd->setInit(0, initializer);
    pbd->setInitializerChecked(0);
  }

  // If there is a projection property (projectedValue) in the wrapper,
  // synthesize a computed property for '$foo'.
  VarDecl *storageVar = nullptr;
  if (wrapperInfo.projectedValueVar) {
    storageVar = synthesizePropertyWrapperStorageWrapperProperty(
        ctx, var, storageInterfaceType, wrapperInfo.projectedValueVar);
  }
  
  // Get the property wrapper information.
  if (!var->allAttachedPropertyWrappersHaveInitialValueInit() &&
      !originalInitialValue) {
    return PropertyWrapperBackingPropertyInfo(
        backingVar, storageVar, nullptr, nullptr, nullptr);
  }

  // Form the initialization of the backing property from a value of the
  // original property's type.
  OpaqueValueExpr *origValue =
      new (ctx) OpaqueValueExpr(var->getSourceRange(), var->getType(),
                                /*isPlaceholder=*/true);
  Expr *initializer = buildPropertyWrapperInitialValueCall(
      var, storageType, origValue,
      /*ignoreAttributeArgs=*/!originalInitialValue);
  typeCheckSynthesizedWrapperInitializer(
      pbd, backingVar, parentPBD, initializer);
  
  return PropertyWrapperBackingPropertyInfo(
      backingVar, storageVar, originalInitialValue, initializer, origValue);
}

/// Given a storage declaration in a protocol, set it up with the right
/// StorageImpl and add the right set of opaque accessors.
static void finishProtocolStorageImplInfo(AbstractStorageDecl *storage,
                                          StorageImplInfo &info) {
  if (auto *var = dyn_cast<VarDecl>(storage)) {
    SourceLoc typeLoc;
    if (auto *repr = var->getTypeRepr())
      typeLoc = repr->getLoc();
    
    if (info.hasStorage()) {
      // Protocols cannot have stored properties.
      if (var->isLet()) {
        var->diagnose(diag::protocol_property_must_be_computed_var)
            .fixItReplace(var->getParentPatternBinding()->getLoc(), "var")
            .fixItInsertAfter(typeLoc, " { get }");
      } else {
        auto diag = var->diagnose(diag::protocol_property_must_be_computed);
        auto braces = var->getBracesRange();

        if (braces.isValid())
          diag.fixItReplace(braces, "{ get <#set#> }");
        else
          diag.fixItInsertAfter(typeLoc, " { get <#set#> }");
      }
    }
  }

  auto protocol = cast<ProtocolDecl>(storage->getDeclContext());
  if (protocol->isObjC()) {
    info = StorageImplInfo::getComputed(info.supportsMutation());
  } else {
    info = StorageImplInfo::getOpaque(info.supportsMutation(),
                                      storage->getOpaqueReadOwnership());
  }
}

/// This emits a diagnostic with a fixit to remove the attribute.
template<typename ...ArgTypes>
void diagnoseAndRemoveAttr(Decl *D, DeclAttribute *attr,
                           ArgTypes &&...Args) {
  auto &ctx = D->getASTContext();
  ctx.Diags.diagnose(attr->getLocation(), std::forward<ArgTypes>(Args)...)
    .fixItRemove(attr->getRangeWithAt());
}

static void finishLazyVariableImplInfo(VarDecl *var,
                                       StorageImplInfo &info) {
  auto *attr = var->getAttrs().getAttribute<LazyAttr>();

  // It cannot currently be used on let's since we don't have a mutability model
  // that supports it.
  if (var->isLet())
    diagnoseAndRemoveAttr(var, attr, diag::lazy_not_on_let);

  // lazy must have an initializer.
  if (!var->getParentInitializer())
    diagnoseAndRemoveAttr(var, attr, diag::lazy_requires_initializer);

  bool invalid = false;

  if (isa<ProtocolDecl>(var->getDeclContext())) {
    diagnoseAndRemoveAttr(var, attr, diag::lazy_not_in_protocol);
    invalid = true;
  }

  // Lazy properties must be written as stored properties in the source.
  if (!info.isSimpleStored()) {
    diagnoseAndRemoveAttr(var, attr,
                          info.hasStorage()
                          ? diag::lazy_not_observable
                          : diag::lazy_not_on_computed);
    invalid = true;
  }

  // The pattern binding must only bind a single variable.
  if (!var->getParentPatternBinding()->getSingleVar())
    diagnoseAndRemoveAttr(var, attr, diag::lazy_requires_single_var);

  if (!invalid)
    info = StorageImplInfo::getMutableComputed();
}

static void finishPropertyWrapperImplInfo(VarDecl *var,
                                          StorageImplInfo &info) {
  auto parentSF = var->getDeclContext()->getParentSourceFile();
  if (!parentSF)
    return;

  // Properties with wrappers must not declare a getter or setter.
  if (!info.hasStorage() && parentSF->Kind != SourceFileKind::Interface) {
    auto &ctx = parentSF->getASTContext();
    for (auto attr : var->getAttrs().getAttributes<CustomAttr>())
      ctx.Diags.diagnose(attr->getLocation(), diag::property_wrapper_computed);

    return;
  }

  bool wrapperSetterIsUsable = false;
  if (var->getParsedAccessor(AccessorKind::Set)) {
    wrapperSetterIsUsable = true;
  } else if (parentSF && parentSF->Kind != SourceFileKind::Interface
             && !var->isLet()) {
    if (auto comp = var->getPropertyWrapperMutability()) {
      wrapperSetterIsUsable =
        comp->Setter != PropertyWrapperMutability::DoesntExist;
    } else {
      wrapperSetterIsUsable = true;
    }
  }

  if (wrapperSetterIsUsable)
    info = StorageImplInfo::getMutableComputed();
  else
    info = StorageImplInfo::getImmutableComputed();
}

static void finishNSManagedImplInfo(VarDecl *var,
                                    StorageImplInfo &info) {
  auto *attr = var->getAttrs().getAttribute<NSManagedAttr>();

  if (var->isLet())
    diagnoseAndRemoveAttr(var, attr, diag::attr_NSManaged_let_property);

  auto diagnoseNotStored = [&](unsigned kind) {
    diagnoseAndRemoveAttr(var, attr, diag::attr_NSManaged_not_stored, kind);
  };

  // @NSManaged properties must be written as stored.
  if (info.isSimpleStored()) {
    // @NSManaged properties end up being computed; complain if there is
    // an initializer.
    if (var->getParentInitializer()) {
      auto &Diags = var->getASTContext().Diags;
      Diags.diagnose(attr->getLocation(), diag::attr_NSManaged_initial_value)
           .highlight(var->getParentInitializer()->getSourceRange());
    }

    // Otherwise, ok.
    info = StorageImplInfo::getMutableComputed();

  } else if (info.getReadImpl() == ReadImplKind::Address ||
             info.getWriteImpl() == WriteImplKind::MutableAddress) {
    diagnoseNotStored(/*addressed*/ 2);
  } else if (info.getWriteImpl() == WriteImplKind::StoredWithObservers ||
             info.getWriteImpl() == WriteImplKind::InheritedWithObservers) {
    diagnoseNotStored(/*observing*/ 1);
  } else {
    diagnoseNotStored(/*computed*/ 0);
  }
}

static void finishStorageImplInfo(AbstractStorageDecl *storage,
                                  StorageImplInfo &info) {
  auto dc = storage->getDeclContext();

  if (auto var = dyn_cast<VarDecl>(storage)) {
    if (!info.hasStorage()) {
      if (auto *init = var->getParentInitializer()) {
        auto &Diags = var->getASTContext().Diags;
        Diags.diagnose(init->getLoc(), diag::getset_init)
             .highlight(init->getSourceRange());
      }
    }

    if (var->getAttrs().hasAttribute<LazyAttr>()) {
      finishLazyVariableImplInfo(var, info);
    } else if (var->getAttrs().hasAttribute<NSManagedAttr>()) {
      finishNSManagedImplInfo(var, info);
    } else if (var->hasAttachedPropertyWrapper()) {
      finishPropertyWrapperImplInfo(var, info);
    }
  }

  if (isa<ProtocolDecl>(dc))
    finishProtocolStorageImplInfo(storage, info);

  // If we have a stored property in an unsupported context, diagnose
  // and change it to computed to avoid confusing SILGen.

  // Note: Stored properties in protocols are diagnosed in
  // finishProtocolStorageImplInfo().

  if (info.hasStorage() && !storage->isStatic()) {
    if (isa<EnumDecl>(dc)) {
      storage->diagnose(diag::enum_stored_property);
      info = StorageImplInfo::getMutableComputed();
    } else if (isa<ExtensionDecl>(dc) &&
              !storage->getAttrs().getAttribute<DynamicReplacementAttr>()) {
      storage->diagnose(diag::extension_stored_property);

      info = (info.supportsMutation()
              ? StorageImplInfo::getMutableComputed()
              : StorageImplInfo::getImmutableComputed());
    }
  }
}

/// Gets the storage info of the provided storage decl if it has the
/// @_hasStorage attribute and it's not in SIL mode.
///
/// In this case, we say the decl is:
///
/// Read:
///   - Stored, always
/// Write:
///   - Stored, if the decl is a 'var'.
///   - StoredWithObservers, if the decl has a setter
///     - This indicates that the original decl had a 'didSet' and/or 'willSet'
///   - InheritedWithObservers, if the decl has a setter and is an overridde.
///   - Immutable, if the decl is a 'let' or it does not have a setter.
/// ReadWrite:
///   - Stored, if the decl has no accessors listed.
///   - Immutable, if the decl is a 'let' or it does not have a setter.
///   - MaterializeToTemporary, if the decl has a setter.
static StorageImplInfo classifyWithHasStorageAttr(VarDecl *var) {
  WriteImplKind writeImpl;
  ReadWriteImplKind readWriteImpl;

  if (var->getParsedAccessor(AccessorKind::Get) &&
      var->getParsedAccessor(AccessorKind::Set)) {
    // If we see `@_hasStorage var x: T { get set }`, then our property has
    // willSet/didSet observers.
    writeImpl = var->getAttrs().hasAttribute<OverrideAttr>() ?
      WriteImplKind::InheritedWithObservers :
      WriteImplKind::StoredWithObservers;
    readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
  } else if (var->isLet()) {
    writeImpl = WriteImplKind::Immutable;
    readWriteImpl = ReadWriteImplKind::Immutable;
  } else {
    // Default to stored writes.
    writeImpl = WriteImplKind::Stored;
    readWriteImpl = ReadWriteImplKind::Stored;
  }

  // Always force Stored reads if @_hasStorage is present.
  return StorageImplInfo(ReadImplKind::Stored, writeImpl, readWriteImpl);
}

llvm::Expected<StorageImplInfo>
StorageImplInfoRequest::evaluate(Evaluator &evaluator,
                                 AbstractStorageDecl *storage) const {
  if (auto *param = dyn_cast<ParamDecl>(storage)) {
    return StorageImplInfo::getSimpleStored(
      param->isInOut()
      ? StorageIsMutable
      : StorageIsNotMutable);
  }

  if (auto *var = dyn_cast<VarDecl>(storage)) {
    // Allow the @_hasStorage attribute to override all the accessors we parsed
    // when making the final classification.
    if (var->getAttrs().hasAttribute<HasStorageAttr>()) {
      // The SIL rules for @_hasStorage are slightly different from the non-SIL
      // rules. In SIL mode, @_hasStorage marks that the type is simply stored,
      // and the only thing that determines mutability is the existence of the
      // setter.
      //
      // FIXME: SIL should not be special cased here. The behavior should be
      //        consistent between SIL and non-SIL.
      //        The strategy here should be to keep track of all opaque accessors
      //        along with enough information to access the storage trivially
      //        if allowed. This could be a representational change to
      //        StorageImplInfo such that it keeps a bitset of listed accessors
      //        and dynamically determines the access strategy from that.
      auto *SF = storage->getDeclContext()->getParentSourceFile();
      if (SF && SF->Kind == SourceFileKind::SIL)
        return StorageImplInfo::getSimpleStored(
          var->getParsedAccessor(AccessorKind::Set)
          ? StorageIsMutable
          : StorageIsNotMutable);

      return classifyWithHasStorageAttr(var);
    }
  }

  bool hasWillSet = storage->getParsedAccessor(AccessorKind::WillSet);
  bool hasDidSet = storage->getParsedAccessor(AccessorKind::DidSet);
  bool hasSetter = storage->getParsedAccessor(AccessorKind::Set);
  bool hasModify = storage->getParsedAccessor(AccessorKind::Modify);
  bool hasMutableAddress = storage->getParsedAccessor(AccessorKind::MutableAddress);

  // 'get', 'read', and a non-mutable addressor are all exclusive.
  ReadImplKind readImpl;
  if (storage->getParsedAccessor(AccessorKind::Get)) {
    readImpl = ReadImplKind::Get;
  } else if (storage->getParsedAccessor(AccessorKind::Read)) {
    readImpl = ReadImplKind::Read;
  } else if (storage->getParsedAccessor(AccessorKind::Address)) {
    readImpl = ReadImplKind::Address;

  // If there's a writing accessor of any sort, there must also be a
  // reading accessor.
  } else if (hasSetter || hasModify || hasMutableAddress) {
    readImpl = ReadImplKind::Get;

  // Subscripts always have to have some sort of accessor; they can't be
  // purely stored.
  } else if (isa<SubscriptDecl>(storage)) {
    readImpl = ReadImplKind::Get;

  // Check if we have observers.
  } else if (hasWillSet || hasDidSet) {
    if (storage->getAttrs().hasAttribute<OverrideAttr>()) {
      readImpl = ReadImplKind::Inherited;
    } else {
      readImpl = ReadImplKind::Stored;
    }

  // Otherwise, it's stored.
  } else {
    readImpl = ReadImplKind::Stored;
  }

  // Prefer using 'set' and 'modify' over a mutable addressor.
  WriteImplKind writeImpl;
  ReadWriteImplKind readWriteImpl;
  if (hasSetter) {
    writeImpl = WriteImplKind::Set;
    if (hasModify) {
      readWriteImpl = ReadWriteImplKind::Modify;
    } else {
      readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
    }
  } else if (hasModify) {
    writeImpl = WriteImplKind::Modify;
    readWriteImpl = ReadWriteImplKind::Modify;
  } else if (hasMutableAddress) {
    writeImpl = WriteImplKind::MutableAddress;
    readWriteImpl = ReadWriteImplKind::MutableAddress;

  // Check if we have observers.
  } else if (readImpl == ReadImplKind::Inherited) {
    writeImpl = WriteImplKind::InheritedWithObservers;
    readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;

  // Otherwise, it's stored.
  } else if (readImpl == ReadImplKind::Stored &&
             !cast<VarDecl>(storage)->isLet()) {
    if (hasWillSet || hasDidSet) {
      writeImpl = WriteImplKind::StoredWithObservers;
      readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
    } else {
      writeImpl = WriteImplKind::Stored;
      readWriteImpl = ReadWriteImplKind::Stored;
    }

  // Otherwise, it's immutable.
  } else {
    writeImpl = WriteImplKind::Immutable;
    readWriteImpl = ReadWriteImplKind::Immutable;
  }

  StorageImplInfo info(readImpl, writeImpl, readWriteImpl);
  finishStorageImplInfo(storage, info);

  return info;
}
