Skip to content

Nested tuple designation is not reconstructed when the inner tuple has 8 or more elements #3962

Description

@siegfriedpammer

Follow-up to #3950, which reconstructs nested tuple designations. An inner tuple of eight or more elements is not reconstructed, because its last element is reached through the Rest field rather than an Item_N field of the temporary itself.

Repro

static (T1, T2) GetTuple<T1, T2>() => default;

public static void RestChainedInner()
{
    var (x, (a, b, c, d, e, f, g, h)) = GetTuple<int, (int, int, int, int, int, int, int, int)>();
    Console.WriteLine(x);
    Console.WriteLine(a);
    // ... all eight inner elements read
    Console.WriteLine(h);
}

Actual

(int, (int, int, int, int, int, int, int, int)) tuple = GetTuple<int, (int, int, int, int, int, int, int, int)>();
(int, int, int, int, int, int, int, int) item = tuple.Item2;
int item2 = tuple.Item1;
int item3 = item.Item1;
// ...
int item10 = item.Rest.Item1;

Expected

var (x, (a, b, c, d, e, f, g, h)) = GetTuple<int, (int, int, int, int, int, int, int, int)>();

Seven or fewer inner elements reconstruct correctly, so this is specific to the Rest chaining of long tuples.

Notes for whoever picks this up

AllUsesAreTupleElementReads in DeconstructionTransform is the guard that rejects it, and it is the obvious suspect since it requires every use of the temporary to be ldobj(ldflda Item_N(...)) while a Rest-chained read is ldobj(ldflda Item1(ldflda Rest(...))). Extending it to step over Rest accesses is not sufficient on its own: with that change the match still bails at the same guard, so the use shape differs from what that reading suggests and the cause needs to be established before fixing.

The index arithmetic is already in place: TupleTransform.MatchTupleFieldAccess walks the Rest chain and folds it back into a flat position (position += TupleType.RestPosition - 1), and TupleType counts cardinality flattened.

Only sugar is lost; the output above is correct and recompiles.


Written by an AI agent (Claude) on Siegfried's behalf.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions