[Feature]: ergonomic call-site for [AssertionExtension] classes that introduce their own generic parameter (original) (raw)

Problem Statement

Once the dual-generic emit bug (#5918) is fixed, an [AssertionExtension] class with its own generic parameter and a concrete (covariance-candidate) receiver compiles cleanly. The remaining friction is the call-site: the generated extension's signature is Matches<TActual, T>(this IAssertionSource<TActual> source, Func<T, bool> predicate, ...) where TActual : Exception, which means callers have to specify TActual explicitly when they only care about T:

Assert.That(ex).Matches<Exception, MyPayload>(p => p.IsValid);

Type inference can pick up T from the predicate argument, but it can't pick up TActual from the receiver expression alone, so the redundant Exception has to be written out at every call site.

Proposed Solution

This is a design call rather than a prescription, but the desired ergonomic end-state is: when the receiver type is concrete (the covariance-candidate branch the generator already detects), the call-site only needs to specify the class's own generic parameters. The receiver type isn't repeated.

There are a few plausible shapes for this (omit the covariant TActual and pin the receiver to IAssertionSource<TConcrete> directly; emit an additional inference-friendly overload alongside the covariant one; encode it through a constraint shape the inferencer can resolve from the receiver). Would prefer to wait on your steer about which shape fits the rest of the generator's design before opening a PR for this.

Alternatives Considered

Feature Category

Assertions

How important is this feature to you?

Nice to have - would improve my experience

Additional Context

This is downstream of the dual-generic-emit fix (#5918). The emit fix is structural. Without it the generated source doesn't compile at all. This issue is purely about call-site ergonomics once the compile-time bug is gone.

Contribution