Skip to content

CMTK0003 misses unawaited assertions dropped together through Task.WhenAll #157

Closed

Description

@CaffeinatedCoder

Found while fixing #152 (its variant sweep covers one dropped call per statement, not a collection of them).

Problem

A statement that drops a Task.WhenAll of assertions of CodoMetis.TypeKit.Testing, unawaited, compiles with no CMTK0003, so a failing assertion's task goes unobserved and the test passes:

public static void Run(Task<Option<int>> option, Task<Result<Fault>> command)
{
    Task.WhenAll(option.ShouldBeNone(), command.ShouldBeSuccess());   // no diagnostic
}

Measured on fix/cmtk0003-wrapped-assertions (#152's fix) with the real analyzer and Testing assemblies, by an analyzer test expecting no diagnostic, which passed.

The rule's other form already reports the same shape: Task.WhenAll(orders.CancelAsync(a), orders.CancelAsync(b)); dropped is a "collection of Results" (CMTK0003), because WhenAll returns Task<Result[]>. Over assertions that return a plain Task, WhenAll returns a plain Task, which carries nothing the rule reads.

Expected

A dropped Task.WhenAll (and WhenAny?) whose arguments the statement made as pending assertions is reported, as a collection of results is; awaited, held or _ = stays silent. Add the shape to Variants/DroppedTaskShapes.

Release

Under decision 118 this reach can ship in 2.3.0 only before the tag; after it, it waits for 3.0.0. Decide whether 2.3.0 takes it.

Activity

  1. added this to the 2.3.0 milestone on Oct 29, 2026
  2. added
    bugSomething isn't working
    silentCompiles or answers and does less than it appears to
    severity/lowCosmetic, message or documentation-level difference
    package/analyzersAffects CodoMetis.TypeKit.Analyzers
    package/testingAffects CodoMetis.TypeKit.Testing
    on Oct 29, 2026
  3. CaffeinatedCoder commented on Oct 29, 2026

    @CaffeinatedCoder
    OwnerAuthor

    Fixed in #164 (into release/2.3.0). CMTK0003 reports an assertion handed to Task.WhenAll, Task.Run or Task.WhenEach whose task is dropped, and one given to Task.WhenAny in any use, since WhenAny finishes with the first task and never faults. It counts arguments, arrays, collection expressions, Select, query syntax, ToList, method groups (pending.Select(OptionAssertions.ShouldBeNone)) and an async lambda that awaits one with no catch between.

    Task.WaitAny is covered too: it returns an index and leaves every failure unobserved, so each assertion it was given is reported, with the assertion named. Task.WaitAll throws an AggregateException when one fails, so it observes them and stays silent. A WhenAny of assertions converted to a plain Task or waited for, and a loop that never reads the assertions its header made, are reported. Held tasks, an assertion discarded where it is made and one given to a call that returns no task stay silent. All of it is held by DroppedTaskVariantTests (830 cases).

  4. CaffeinatedCoder commented on Oct 29, 2026

    @CaffeinatedCoder
    OwnerAuthor

    Fixed in #164, merged into release/2.3.0 (9878a6c).

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

    area/option-resultOption, Result and their extensionsbugSomething isn't workingpackage/analyzersAffects CodoMetis.TypeKit.Analyzerspackage/testingAffects CodoMetis.TypeKit.Testingseverity/lowCosmetic, message or documentation-level differencesilentCompiles or answers and does less than it appears to

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions