@@ -2822,12 +2822,78 @@ RValue RValueEmitter::visitDynamicSubscriptExpr(
28222822 E->getType ()->getCanonicalType (), C);
28232823}
28242824
2825+ namespace {
2826+ class CollectValueInitialization : public Initialization {
2827+ ManagedValue Value;
2828+
2829+ public:
2830+ ManagedValue getValue () const {
2831+ assert (Value);
2832+ return Value;
2833+ }
2834+
2835+ void copyOrInitValueInto (SILGenFunction &SGF, SILLocation loc,
2836+ ManagedValue value, bool isInit) override {
2837+ if (!isInit) value = value.copy (SGF, loc);
2838+ Value = value;
2839+ }
2840+ };
2841+ }
28252842
28262843RValue RValueEmitter::visitTupleElementExpr (TupleElementExpr *E,
28272844 SGFContext C) {
28282845 assert (!E->getType ()->is <LValueType>() &&
28292846 " RValueEmitter shouldn't be called on lvalues" );
2830-
2847+
2848+ auto tupleType = cast<TupleType>(E->getBase ()->getType ()->getCanonicalType ());
2849+ auto projectedEltInit = C.getEmitInto ();
2850+
2851+ std::optional<CollectValueInitialization> collection;
2852+
2853+ // If we have an initialization to emit into, or if we'd need to emit
2854+ // a tuple that contains pack expansions, make a tuple initialization
2855+ // of it plus some black holes.
2856+ if (projectedEltInit || tupleType->containsPackExpansionType ()) {
2857+ TupleInitialization tupleInit (tupleType);
2858+
2859+ auto projectedIndex = E->getFieldNumber ();
2860+ auto numElts = tupleType->getNumElements ();
2861+ assert (projectedIndex < numElts);
2862+
2863+ tupleInit.SubInitializations .reserve (numElts);
2864+ for (auto i : range (numElts)) {
2865+ // Create a black-hole initialization for everything except the
2866+ // projected index.
2867+ if (i != projectedIndex) {
2868+ tupleInit.SubInitializations .emplace_back (new BlackHoleInitialization ());
2869+
2870+ // If we have an initialization for the projected initialization,
2871+ // put it in the right place.
2872+ } else if (projectedEltInit) {
2873+ tupleInit.SubInitializations .emplace_back (projectedEltInit,
2874+ PointerIsNotOwned);
2875+
2876+ // Otherwise, create the collection initialization and put it in the
2877+ // right place.
2878+ } else {
2879+ collection.emplace ();
2880+ tupleInit.SubInitializations .emplace_back (&*collection,
2881+ PointerIsNotOwned);
2882+ }
2883+ }
2884+
2885+ // Emit the expression into the initialization.
2886+ SGF.emitExprInto (E->getBase (), &tupleInit);
2887+
2888+ // If we had an initialization to emit into, we've done so.
2889+ if (projectedEltInit) {
2890+ return RValue::forInContext ();
2891+ }
2892+
2893+ // Otherwise, pull out the owned value.
2894+ return RValue (SGF, E, collection->getValue ());
2895+ }
2896+
28312897 // If our client is ok with a +0 result, then we can compute our base as +0
28322898 // and return its element that way. It would not be ok to reuse the Context's
28332899 // address buffer though, since our base value will a different type than the
0 commit comments