static ManagedValue emitSelfForMemberInit(SILGenFunction &SGF, SILLocation loc,
                                          VarDecl *selfDecl) {
  CanType selfFormalType = selfDecl->getType()->getCanonicalType();
  if (selfFormalType->hasReferenceSemantics())
    return SGF.emitRValueForDecl(loc, selfDecl, selfFormalType,
                                 AccessSemantics::DirectToStorage,
                                 SGFContext::AllowImmediatePlusZero)
      .getAsSingleValue(SGF, loc);
  else
    return SGF.emitAddressOfLocalVarDecl(loc, selfDecl, selfFormalType,
                                         SGFAccessKind::Write);
}
/// Emit a member initialization for the members described in the
/// given pattern from the given source value.
static void emitMemberInit(SILGenFunction &SGF, VarDecl *selfDecl,
                           Pattern *pattern, RValue &&src) {
  switch (pattern->getKind()) {
  case PatternKind::Paren:
    return emitMemberInit(SGF, selfDecl,
                          cast<ParenPattern>(pattern)->getSubPattern(),
                          std::move(src));

  case PatternKind::Tuple: {
    auto tuple = cast<TuplePattern>(pattern);
    auto fields = tuple->getElements();

    SmallVector<RValue, 4> elements;
    std::move(src).extractElements(elements);
    for (unsigned i = 0, n = fields.size(); i != n; ++i) {
      emitMemberInit(SGF, selfDecl, fields[i].getPattern(),
                     std::move(elements[i]));
    }
    break;
  }

  case PatternKind::Named: {
    auto named = cast<NamedPattern>(pattern);
    // Form the lvalue referencing this member.
    WritebackScope scope(SGF);
    SILLocation loc = pattern;
    ManagedValue self;
    CanType selfFormalType = selfDecl->getType()
        ->getInOutObjectType()->getCanonicalType();
    if (selfFormalType->hasReferenceSemantics())
      self = SGF.emitRValueForDecl(loc, selfDecl, selfDecl->getType(),
                                   AccessSemantics::DirectToStorage,
                                   SGFContext::AllowImmediatePlusZero)
        .getAsSingleValue(SGF, loc);
    else
      self = SGF.emitLValueForDecl(loc, selfDecl,
                                   src.getType()->getCanonicalType(),
                                   AccessKind::Write,
                                   AccessSemantics::DirectToStorage);

    LValue memberRef =
      SGF.emitPropertyLValue(loc, self, selfFormalType, named->getDecl(),
                             AccessKind::Write,
                             AccessSemantics::DirectToStorage);

    // Assign to it.
    SGF.emitAssignToLValue(loc, std::move(src), std::move(memberRef));
    return;
  }

  case PatternKind::Any:
    return;

  case PatternKind::Typed:
    return emitMemberInit(SGF, selfDecl,
                          cast<TypedPattern>(pattern)->getSubPattern(),
                          std::move(src));

  case PatternKind::Var:
    return emitMemberInit(SGF, selfDecl,
                          cast<VarPattern>(pattern)->getSubPattern(),
                          std::move(src));

#define PATTERN(Name, Parent)
#define REFUTABLE_PATTERN(Name, Parent) case PatternKind::Name:
#include "swift/AST/PatternNodes.def"
    llvm_unreachable("Refutable pattern in pattern binding");
  }
}