//===--- 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 {
  auto storageDC = storage->getDeclContext();
  bool result = (!storage->isStatic() && storageDC->isTypeContext() &&
                 storageDC->hasValueSemantics());

  // '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>(storageDC))
    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.
  auto storageDC = storage->getDeclContext();
  bool result = (!storage->isStatic() && storageDC->isTypeContext() &&
                 storageDC->hasValueSemantics());

  // 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|
                                                ParameterList::WithoutTypes);

  // 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) {
  (void)accessor->getInterfaceType();
  
  // 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->isStatic())
    getter->setStatic();

  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 isStatic = storage->isStatic();
  bool isMutating = storage->isSetterMutating();

  GenericParamList *genericParams = createAccessorGenericParams(storage);

  // Add a "(value : T, indices...)" argument list.
  auto *param = new (ctx) ParamDecl(ParamDecl::Specifier::Default,
                                    SourceLoc(), SourceLoc(),
                                    Identifier(), loc,
                                    ctx.getIdentifier("value"),
                                    storage->getDeclContext());
  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);

  if (isStatic)
    setter->setStatic();

  // 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 isStatic = storage->isStatic();
  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 (isStatic)
    accessor->setStatic();

  // 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)) {
    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(var->getTypeLoc().getLoc(), " { 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(var->getTypeLoc().getLoc(), " { 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;
}
