@@ -478,9 +478,76 @@ bool SILPackType::containsPackExpansionType() const {
478478 return false ;
479479}
480480
481+ CanPackType
482+ CanTupleType::getInducedPackTypeImpl (CanTupleType tuple) {
483+ return getInducedPackTypeImpl (tuple, 0 , tuple->getNumElements ());
484+ }
485+
481486CanPackType
482487CanTupleType::getInducedPackTypeImpl (CanTupleType tuple, unsigned start, unsigned count) {
483488 assert (start + count <= tuple->getNumElements () && " range out of range" );
484489 auto &ctx = tuple->getASTContext ();
485490 return CanPackType::get (ctx, tuple.getElementTypes ().slice (start, count));
486491}
492+
493+ static CanType getApproximateFormalElementType (const ASTContext &ctx,
494+ CanType loweredEltType) {
495+ CanType formalEltType = TupleType::getEmpty (ctx);
496+ if (auto expansion = dyn_cast<PackExpansionType>(loweredEltType))
497+ formalEltType = CanPackExpansionType::get (formalEltType,
498+ expansion.getCountType ());
499+ return formalEltType;
500+ }
501+
502+ template <class Collection >
503+ static CanPackType getApproximateFormalPackType (const ASTContext &ctx,
504+ Collection loweredEltTypes) {
505+ // Build an array of formal element types, but be lazy about it:
506+ // use the original array unless we see an element type that doesn't
507+ // work as a legal format type.
508+ Optional<SmallVector<CanType, 4 >> formalEltTypes;
509+ for (auto i : indices (loweredEltTypes)) {
510+ auto loweredEltType = loweredEltTypes[i];
511+ bool isLegal = loweredEltType->isLegalFormalType ();
512+
513+ // If the type isn't legal as a formal type, substitute the empty
514+ // tuple type (or an invariant expansion of it over the count type).
515+ CanType formalEltType = loweredEltType;
516+ if (!isLegal) {
517+ formalEltType = getApproximateFormalElementType (ctx, loweredEltType);
518+ }
519+
520+ // If we're already building an array, unconditionally append to it.
521+ // Otherwise, if the type isn't legal, build the array up to this
522+ // point and then append. Otherwise, we're still being lazy.
523+ if (formalEltTypes) {
524+ formalEltTypes->push_back (formalEltType);
525+ } else if (!isLegal) {
526+ formalEltTypes.emplace ();
527+ formalEltTypes->reserve (loweredEltTypes.size ());
528+ formalEltTypes->append (loweredEltTypes.begin (),
529+ loweredEltTypes.begin () + i);
530+ formalEltTypes->push_back (formalEltType);
531+ }
532+
533+ assert (isLegal || formalEltTypes.hasValue ());
534+ }
535+
536+ // Use the array we built if we made one (if we ever saw a non-legal
537+ // element type).
538+ if (formalEltTypes) {
539+ return CanPackType::get (ctx, *formalEltTypes);
540+ } else {
541+ return CanPackType::get (ctx, loweredEltTypes);
542+ }
543+ }
544+
545+ CanPackType SILPackType::getApproximateFormalPackType () const {
546+ return ::getApproximateFormalPackType (getASTContext (), getElementTypes ());
547+ }
548+
549+ CanPackType
550+ CanTupleType::getInducedApproximateFormalPackTypeImpl (CanTupleType tuple) {
551+ return ::getApproximateFormalPackType (tuple->getASTContext (),
552+ tuple.getElementTypes ());
553+ }
0 commit comments