/// 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); }