Skip to content

Typed tuple rows with multiple trailing values skip argument type validation #7463

Open

Description

@thomhurst

Summary

The test-data analyzer skips type validation when a typed tuple row supplies multiple loose values for a trailing array or params collection on a generic test method. An invalid final value can therefore compile without TUnit0001, leaving the mismatch to execution. The closed-signature validation should check every supplied element.

Reproduction

On .NET 10, use a source derived from TypedDataSourceAttribute<(int[], int, string, int)> on [Test] void Run<T>(T[] values, T value, params IEnumerable<string> rest). Return a row (new[] { 1 }, 2, "a", 3) using the normal typed source override. Run TestDataAnalyzer over the declaration: it returns no diagnostic, although the last integer cannot be collected into IEnumerable<string>.

Expected and actual

Expected: infer T = int from the leading values and report TUnit0001 for the final integer. Actual: typed-row inference returns null when tuple arity exceeds the parameter count, and the analyzer's open generic path skips validation.

The generator and reflection inferrers both contain this arity restriction. At main d9e9e66, see source-generator inference. This also prevents declared-type inference for valid expanded tuples; check runtime fallback behavior in both modes when fixing it.

Environment

.NET SDK 10.0.403, net10.0, current Roslyn analyzer host. Found while extending regression coverage for #7460; its generator-base source regression does not use this tuple inference path. Please support expanded trailing tuple values consistently in typed-row inference and analyzer validation.

Acceptance criteria

  • Infer generic method arguments consistently in source-generated and reflection discovery when a typed tuple supplies multiple loose values for a supported trailing array or params collection. Preserve rejection of excess values when the signature cannot collect them.
  • After closing the generic signature, validate every supplied trailing element and report TUnit0001 for the invalid final integer in the reproduction. Accept the corresponding all-string row.
  • Add analyzer regressions for valid and invalid expanded rows, inference parity coverage for both metadata-collection modes, and targeted execution coverage for valid rows in both modes. Review affected generator snapshots.
  • Preserve existing packed-array/collection and omitted-trailing-argument behavior. Check runtime fallback behavior so inference changes do not change valid-row execution unexpectedly.

Activity

  1. thomhurst commented on Nov 3, 2026

    @thomhurst
    OwnerAuthor

    Audited against origin/main d9e9e66: both TypedDataSourceInference.InferMethodTypeArgumentsFromRowType and ReflectionTestDataCollector.InferTypesFromTypedRow reject tuple rows longer than the data-parameter list before binding trailing values. Open PR #7460 (head 54ede11) retains that upper-arity check, so it does not resolve this issue. Added explicit acceptance criteria for inference parity, complete trailing-element validation, and valid-row execution regressions. No prerequisite or parking condition is needed; this remains available for implementation.

  2. added
    bugSomething isn't working
    P3Low: cleanup, minor enhancement, or rare edge case
    on Nov 3, 2026
  3. thomhurst commented on Nov 4, 2026

    @thomhurst
    OwnerAuthor

    Nonblocking CodeRabbit finding on #7571 adds an execution requirement to the existing “preserve rejection of excess values when the signature cannot collect them” criterion: #7571 (comment).

    A member source returning (int,int,int) for void Run(int first,int second) now preserves all three columns through UnwrapTupleWithTypes. Generated invocation rejects args.Length=3; reflection's CreateReflectionTestInvoker copies only parameters.Length and silently ignores the extra column. Verified the invoker paths on df2cf32; current main also lacks a reflection arity guard. Add a non-collecting excess-row execution regression in both modes and reject excess values before reflection invocation, while retaining valid params/collecting behavior. This is distinct from analyzer validation but exercises the same row-arity contract already covered by this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low: cleanup, minor enhancement, or rare edge casebugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions