Repository navigation
Source generator: params T[] on a generic test method fails to compile (CS0246, CS1503) #7099
Copy link
Copy link
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
Summary
A generic test method whose last parameter is params T[] (or a plain trailing T[]) does not compile in source-generation mode once the method is closed through [GenerateGenericTest], or through type inference from another argument. The generated code reports CS0246 and CS1503, so the whole test project fails to build. This came up while working on #7094.
Repro
public class ParamsGenericTests
{
[Test]
[GenerateGenericTest(typeof(int))]
[Arguments(1, 2, 3)]
public void Explicit_Many<T>(params T[] values) { }
}The same happens for these shapes:
- zero arguments (
[Arguments]), one argument, and many arguments - reference types (
[GenerateGenericTest(typeof(string))],[Arguments("a", "b", "c")]) - a leading non-generic parameter (
Test<T>(string label, params T[] values)) - an array passed as the only argument (
[Arguments(new[] { 4, 5 })]) - a plain trailing array (
Test<T>(T[] values)) - a class type parameter (
[GenerateGenericTest(typeof(int))] class Foo<T> { [Test, Arguments(1, 2)] void Test(params T[] values) }) - inference from a leading argument (
[Arguments(1, 2, 3)] Test<T>(T first, params T[] rest))
Errors
MyTests_ParamsGenericTests_Explicit_Many__T__.g.cs(24,121): error CS0246: The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)
MyTests_ParamsGenericTests_Explicit_Many__T__.g.cs(34,84): error CS0246: The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)
MyTests_ParamsGenericTests_Explicit_Many__T__.g.cs(34,41): error CS1503: Argument 1: cannot convert from 'T[]' to 'int'
The generated code that triggers them:
// parameter metadata (line 24)
global::TUnit.Core.ParameterMetadataFactory.Create(typeof(object), "values", new global::TUnit.Core.ConcreteType(typeof(T[])), false)
// invoker for the closed Explicit_Many<int> (line 34)
instance.Explicit_Many<int>(global::TUnit.Core.Helpers.CastHelper.Cast<T[]>(args[0]));Root cause
There are three gaps in TUnit.Core.SourceGenerator:
CodeGenerationHelpers.GenerateTypeInfohandles type parameters (T) and constructed generics (List<T>), but not arrays of a type parameter.T[]falls through toConcreteType(typeof(T[])), andTis not in scope in the generated class.SubstituteTypeParameters, which the concrete-instantiation invoker uses, does not recurse intoIArrayTypeSymbol.T[]staysT[]instead of becomingint[].EmitConcreteInvokeBody(the invoker for[GenerateGenericTest]and inferred instantiations) casts each argument to its declared parameter type by position. It never applies the trailing-array binding that non-generic methods get throughTupleArgumentHelper.GenerateArgumentAccessWithParams(packing the remaining row values,Array.Empty<T>()for zero, andToTrailingArrayfor a single value). So even with (2) fixed,[Arguments(1, 2, 3)]would pass onlyargs[0].
Reflection mode
On current main, with EnableTUnitSourceGeneration=false and --reflection:
- Every
[GenerateGenericTest]shape above passes, including the class-type-parameter case. - Inferred instantiations fail at test build time:
[Arguments(1, 2, 3)] Test<T>(T first, params T[] rest)reportsGenericTypeResolutionException: Type mismatch: Cannot use argument of type 'Int32' for parameter of type 'T[]'.TestGenericTypeResolver.ResolveMethodGenericArgumentsmaps each row value positionally against the declared parameter types, so the trailing values meetT[]. [Arguments(1, 2, 3)] Test<T>(params T[] values), with no other parameter to infer from, fails the same way in reflection mode. In source-gen mode it generates no test at all, with no diagnostic, becauseInferTypesFromArgumentsAttributeonly infers from parameters whose type is a bare type parameter.
The two inference gaps are separate from this compile error and are left for a follow-up.
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
fix: address review findings for generic params T[] binding
thomhurst commentedon Oct 17, 2026
PR #7101 (fe482c9) also fixes inference from a leading argument in reflection mode, so
Test<T>(T first, params T[] rest)now works in both modes. Both modes also inferTfrom a lone array value. Still open: inferringTonly from loose params values, as in[Arguments(1, 2, 3)] Test<T>(params T[] values). Reflection mode needs a change to the invoker inReflectionTestDataCollector.cs, which defaults an unmappedTtoobject. Source-gen still emits no test for this case.fix(sourcegen): bind params T[] on generic test methods
fix: address review findings for generic params T[] binding
fix(sourcegen): bind params T[] on generic test methods
fix: address review findings for generic params T[] binding
fix(sourcegen): bind params T[] on generic test methods
fix: address review findings for generic params T[] binding
fix(sourcegen): bind params T[] on generic test methods (#7101)