/// Emit a concrete implementation of materializeForSet.
void SILGenFunction::emitMaterializeForSet(FuncDecl *decl) {
  assert(decl->getAccessorKind() == AccessorKind::IsMaterializeForSet);

  MagicFunctionName = SILGenModule::getMagicFunctionName(decl);

  MaterializeForSetEmitter emitter
    = MaterializeForSetEmitter::forConcreteImplementation(
        SGM, decl, getForwardingSubstitutions());
  emitter.emit(*this);
}
/// Emit an open-coded protocol-witness thunk for materializeForSet if
/// delegating to the standard implementation isn't good enough.
///
/// materializeForSet sometimes needs to be open-coded because of the
/// thin callback function, which is dependent but cannot be reabstracted.
///
/// - In a protocol extension, the callback doesn't know how to capture
///   or reconstruct the generic conformance information.
///
/// - The abstraction pattern of the variable from the witness may
///   differ from the abstraction pattern of the protocol, likely forcing
///   a completely different access pattern (e.g. to write back a
///   reabstracted value instead of modifying it in-place).
///
/// \return true if special code was emitted
bool SILGenFunction::
maybeEmitMaterializeForSetThunk(ProtocolConformance *conformance,
                                SILLinkage linkage,
                                FuncDecl *requirement,
                                FuncDecl *witness,
                                ArrayRef<Substitution> witnessSubs) {

  MaterializeForSetEmitter emitter
    = MaterializeForSetEmitter::forWitnessThunk(
        SGM, conformance, linkage, requirement, witness,
        witnessSubs);

  if (!emitter.shouldOpenCode())
    return false;

  emitter.emit(*this);
  return true;
}
/// Emit an open-coded protocol-witness thunk for materializeForSet if
/// delegating to the standard implementation isn't good enough.
///
/// materializeForSet sometimes needs to be open-coded because of the
/// thin callback function, which is dependent but cannot be reabstracted.
///
/// - In a protocol extension, the callback doesn't know how to capture
///   or reconstruct the generic conformance information.
///
/// - The abstraction pattern of the variable from the witness may
///   differ from the abstraction pattern of the protocol, likely forcing
///   a completely different access pattern (e.g. to write back a
///   reabstracted value instead of modifying it in-place).
///
/// \return true if special code was emitted
bool SILGenFunction::
maybeEmitMaterializeForSetThunk(ProtocolConformance *conformance,
                                SILLinkage linkage,
                                Type selfInterfaceType,
                                Type selfType,
                                GenericEnvironment *genericEnv,
                                FuncDecl *requirement,
                                FuncDecl *witness,
                                SubstitutionList witnessSubs) {

  MaterializeForSetEmitter emitter
    = MaterializeForSetEmitter::forWitnessThunk(
        SGM, conformance, linkage, selfInterfaceType, selfType,
        genericEnv, requirement, witness, witnessSubs);

  if (!emitter.shouldOpenCode())
    return false;

  emitter.emit(*this);
  return true;
}