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.
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
Restfield rather than anItem_Nfield of the temporary itself.Repro
Actual
Expected
Seven or fewer inner elements reconstruct correctly, so this is specific to the
Restchaining of long tuples.Notes for whoever picks this up
AllUsesAreTupleElementReadsinDeconstructionTransformis the guard that rejects it, and it is the obvious suspect since it requires every use of the temporary to beldobj(ldflda Item_N(...))while aRest-chained read isldobj(ldflda Item1(ldflda Rest(...))). Extending it to step overRestaccesses 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.MatchTupleFieldAccesswalks theRestchain and folds it back into a flat position (position += TupleType.RestPosition - 1), andTupleTypecounts cardinality flattened.Only sugar is lost; the output above is correct and recompiles.
Written by an AI agent (Claude) on Siegfried's behalf.