// Allow casting a tuple by value when all elements in toType correspond to an // element of the same size or larger in fromType in the same order. static bool canUnsafeCastTuple(SILType fromType, CanTupleType fromTupleTy, SILType toType, SILModule &M) { unsigned numFromElts = fromTupleTy->getNumElements(); // Can the first element of fromTupleTy be cast by value into toType? if (numFromElts != 0 && SILType::canUnsafeCastValue( fromType.getTupleElementType(0), toType, M)) { return true; } // Otherwise, flatten one level of tuple elements on each side. CanTupleType toTupleTy = dyn_cast<TupleType>(toType.getSwiftRValueType()); if (!toTupleTy) return false; unsigned numToElts = toTupleTy->getNumElements(); if (numFromElts < numToElts) return false; for (unsigned i = 0; i != numToElts; ++i) { if (!SILType::canUnsafeCastValue(fromType.getTupleElementType(i), toType.getTupleElementType(i), M)) { return false; } } return true; }
bool AbstractionPattern::matchesTuple(CanTupleType substType) { switch (getKind()) { case Kind::Invalid: llvm_unreachable("querying invalid abstraction pattern!"); case Kind::PartialCurriedObjCMethodType: case Kind::CurriedObjCMethodType: case Kind::PartialCurriedCFunctionAsMethodType: case Kind::CurriedCFunctionAsMethodType: case Kind::CFunctionAsMethodType: case Kind::ObjCMethodType: return false; case Kind::Opaque: return true; case Kind::Tuple: return getNumTupleElements_Stored() == substType->getNumElements(); case Kind::ClangType: case Kind::Type: case Kind::Discard: if (isTypeParameter()) return true; auto tuple = dyn_cast<TupleType>(getType()); return (tuple && tuple->getNumElements() == substType->getNumElements()); } llvm_unreachable("bad kind"); }
/// Return the range of indexes for the given tuple type element. static std::pair<unsigned,unsigned> getElementRange(CanTupleType tupleType, unsigned eltIndex) { assert(eltIndex < tupleType->getNumElements()); unsigned begin = 0; for (unsigned i = 0; i < eltIndex; ++i) { begin += getRValueSize(tupleType.getElementType(i)); } unsigned end = begin + getRValueSize(tupleType.getElementType(eltIndex)); return { begin, end }; }
clang::CanQualType GenClangType::visitTupleType(CanTupleType type) { unsigned e = type->getNumElements(); if (e == 0) return getClangASTContext().VoidTy; CanType eltTy = type.getElementType(0); for (unsigned i = 1; i < e; i++) { assert(eltTy == type.getElementType(i) && "Only tuples where all element types are equal " "map to fixed-size arrays"); } auto clangEltTy = Converter.convert(IGM, eltTy); if (!clangEltTy) return clang::CanQualType(); APInt size(32, e); auto &ctx = getClangASTContext(); return ctx.getCanonicalType( ctx.getConstantArrayType(clangEltTy, size, clang::ArrayType::Normal, 0)); llvm_unreachable("Unexpected tuple type in Clang type generation!"); }