Background
Because C# forbids partial type-argument specification, AssertionExtensionGenerator emits two extension overloads for assertion classes that have their own generic parameters on a covariant receiver (see the block comment at TUnit.Assertions.SourceGenerator/Generators/AssertionExtensionGenerator.cs:167-198, issue #5922):
- a covariant overload
<TActual, T...> for polymorphic receivers, and
- a pinned-receiver overload
<T...> for inference-friendly call sites.
Whether the pinned overload is needed is decided by the OwnGenericsAreInferable() heuristic in TUnit.Assertions.SourceGenerator/Generators/CovarianceHelper.cs (~lines 97-180). The heuristic is deliberately conservative — e.g. any type parameter appearing only inside a delegate/lambda or Expression<> parameter is treated as non-inferable — so it sometimes emits a pinned overload that no call site can ever prefer.
Each dead overload bloats the public API surface, IntelliSense completion lists, and overload-resolution candidate sets (longer error messages on misuse).
Task
- Add test coverage that characterizes which (covariant, pinned) pairs the generator currently emits across the real assertion classes.
- Refine the inferability analysis: model C# type-inference rules more precisely for the common shapes (value parameters, delegate parameters whose type args appear elsewhere, params arrays, nested generics).
- Drop the pinned overload where the covariant overload is provably always inferable.
- Re-verify snapshots and the public API approval tests; confirm no call site in
TUnit.TestProject / assertions test suites regresses to requiring explicit type arguments.
Notes
- Bias must remain toward correctness: a wrongly-dropped pinned overload is a user-facing compile break, a wrongly-kept one is only noise. Only drop where provable.
Part of a generics-DX review of the assertions library.
Background
Because C# forbids partial type-argument specification,
AssertionExtensionGeneratoremits two extension overloads for assertion classes that have their own generic parameters on a covariant receiver (see the block comment atTUnit.Assertions.SourceGenerator/Generators/AssertionExtensionGenerator.cs:167-198, issue #5922):<TActual, T...>for polymorphic receivers, and<T...>for inference-friendly call sites.Whether the pinned overload is needed is decided by the
OwnGenericsAreInferable()heuristic inTUnit.Assertions.SourceGenerator/Generators/CovarianceHelper.cs(~lines 97-180). The heuristic is deliberately conservative — e.g. any type parameter appearing only inside a delegate/lambda orExpression<>parameter is treated as non-inferable — so it sometimes emits a pinned overload that no call site can ever prefer.Each dead overload bloats the public API surface, IntelliSense completion lists, and overload-resolution candidate sets (longer error messages on misuse).
Task
TUnit.TestProject/ assertions test suites regresses to requiring explicit type arguments.Notes
Part of a generics-DX review of the assertions library.