Skip to content

dev_cast is a set of SPELLINGS, not the property: four review rounds each found a new one, so the structural answer is an AST-level check #828

Description

@localai-bot

scripts/check-device-leakage.py's dev_cast bucket wants to enforce a
property:

an integer becomes a vt::DeviceType outside the platform seam.

It is a regular expression over comment-stripped text, so it cannot enforce that
property. It enforces a set of spellings. The difference is not academic —
it is measured, four times over, on this one bucket:

round what slipped evidence
ship (#660) dev_cast added, "anchored on the TARGET TYPE, not on the operand and not on one cast keyword"
review 1 (vt::DeviceType)1 — a literal operand, the purest form of the defect. The mutant written to rule this out used an identifier operand, so it could not see the gap it existed to close PR #671, head 094ac9e4
review 2 a reference target, east const, a dereferenced operand, a second star, std::bit_castnine compile-verified spellings that all write the target type at the conversion site, which the docstring claimed was the anchor PR #671, head 074ef1420
review 3 a C-style reference target, the DECLARATION form's cv-qualifiers (a fourth place a cv-qualifier can sit, where the mutant asserted "all three"), bit_cast's two-argument form, a cv-qualifier inside the pointer run, a character-literal operand, __builtin_bit_cast PR #671, head 79ebbce42

Every one of those was closed at zero hits on the 760-file scanned tree, so
none of them was a coverage/false-positive trade. There was simply always
another spelling. Three of the four rounds found the same shape — the checker's
own message asserting coverage the pattern did not have — and AGENTS.md makes
that message the authority on what the gate enforces, so an over-claiming message
is a defect in the gate rather than a wording nit.

The pattern is now honest about this: it enumerates what it matches, states each
blind spot with a reason true of that entry alone, and says in as many words that
what it enforces is a set of spellings rather than the property. That is the
right interim. It is not the answer.

What the answer looks like

An AST-level check, over the same scan roots, where the question is a query
rather than a guess:

  • a CXXStaticCastExpr / CStyleCastExpr / CXXFunctionalCastExpr /
    CXXReinterpretCastExpr / ImplicitCastExpr, or a bit_cast call, or a
    VarDecl with a list-initialiser,
  • whose destination type canonicalises to vt::DeviceType (which resolves
    aliases, macros and template parameters for free — three of the standing blind
    spots),
  • whose source type is integral (which the text checker cannot type-check at
    all, and is why every cast to DeviceType currently counts and buys its
    exemption through DSR-ALLOW),
  • excluding the platform seam's own registry inverse.

clang-query can express that today; a clang-tidy check or a small
LibTooling binary can gate it. The cost is a compilation database for the
scanned roots, which the CMake build already emits
(CMAKE_EXPORT_COMPILE_COMMANDS), and a clang dependency in the lane that runs
it — which is why this is a row of its own and not a fix inside PR #671.

Acceptance

  • The AST check reproduces every one of M20-M46's spellings as RED, on the same
    synthetic-tree method, without enumerating them: it must go red on a
    spelling that was never written down, and the test proves that by planting one
    invented at test time.
  • The blind spots it does have are stated in its own message, per entry, the way
    the regex's are.
  • The regex bucket either retires or becomes the fast pre-filter, with the AST
    check as the authority. Decide that in the spec, with the CI cost measured.

Provenance

Found while closing review round 3 of PR #671 (row LTX25-DEVICE-SEAM-SIBLING,
campaign #644). Blocks nothing; it is the standing debt the four rounds are the
argument for.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions