示例#1
0
/// Emit a collection downcast expression.
///
/// \param conditional Whether to emit a conditional downcast; if
/// false, this will emit a forced downcast.
static RValue emitCollectionDowncastExpr(SILGenFunction &SGF,
                                         ManagedValue source,
                                         Type sourceType,
                                         SILLocation loc,
                                         Type destType,
                                         SGFContext C,
                                         bool conditional) {
  // Compute substitutions for the intrinsic call.
  auto fromCollection = cast<BoundGenericStructType>(
                          sourceType->getCanonicalType());
  auto toCollection = cast<BoundGenericStructType>(
                        destType->getCanonicalType());
  // Get the intrinsic function.
  auto &ctx = SGF.getASTContext();
  FuncDecl *fn = nullptr;
  if (fromCollection->getDecl() == ctx.getArrayDecl()) {
    fn = conditional ? SGF.SGM.getArrayConditionalCast(loc)
                     : SGF.SGM.getArrayForceCast(loc);
  } else if (fromCollection->getDecl() == ctx.getDictionaryDecl()) {
    fn = (conditional
           ? SGF.SGM.getDictionaryDownCastConditional(loc)
           : SGF.SGM.getDictionaryDownCast(loc));
  } else if (fromCollection->getDecl() == ctx.getSetDecl()) {
    fn = (conditional
           ? SGF.SGM.getSetDownCastConditional(loc)
           : SGF.SGM.getSetDownCast(loc));
  } else {
    llvm_unreachable("unsupported collection upcast kind");
  }

  // This will have been diagnosed by the accessors above.
  if (!fn) return SGF.emitUndefRValue(loc, destType);

  auto fnGenericParams = fn->getGenericSignature()->getGenericParams();
  auto fromSubsts = fromCollection->gatherAllSubstitutions(
      SGF.SGM.SwiftModule, nullptr);
  auto toSubsts = toCollection->gatherAllSubstitutions(
      SGF.SGM.SwiftModule, nullptr);
  assert(fnGenericParams.size() == fromSubsts.size() + toSubsts.size() &&
         "wrong number of generic collection parameters");
  (void) fnGenericParams;

  // Form type parameter substitutions.
  SmallVector<Substitution, 4> subs;
  subs.append(fromSubsts.begin(), fromSubsts.end());
  subs.append(toSubsts.begin(), toSubsts.end());

  return SGF.emitApplyOfLibraryIntrinsic(loc, fn, subs, {source}, C);
}