Repository navigation
Description
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
thomhurst commentedon Nov 3, 2026
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.
thomhurst commentedon Nov 4, 2026
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)forvoid 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.