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_cast — nine 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.
scripts/check-device-leakage.py'sdev_castbucket wants to enforce aproperty:
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:
dev_castadded, "anchored on the TARGET TYPE, not on the operand and not on one cast keyword"(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 close094ac9e4const, a dereferenced operand, a second star,std::bit_cast— nine compile-verified spellings that all write the target type at the conversion site, which the docstring claimed was the anchor074ef1420bit_cast's two-argument form, a cv-qualifier inside the pointer run, a character-literal operand,__builtin_bit_cast79ebbce42Every 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:
CXXStaticCastExpr/CStyleCastExpr/CXXFunctionalCastExpr/CXXReinterpretCastExpr/ImplicitCastExpr, or abit_castcall, or aVarDeclwith a list-initialiser,vt::DeviceType(which resolvesaliases, macros and template parameters for free — three of the standing blind
spots),
all, and is why every cast to
DeviceTypecurrently counts and buys itsexemption through
DSR-ALLOW),clang-querycan express that today; aclang-tidycheck or a smallLibToolingbinary can gate it. The cost is a compilation database for thescanned roots, which the CMake build already emits
(
CMAKE_EXPORT_COMPILE_COMMANDS), and a clang dependency in the lane that runsit — which is why this is a row of its own and not a fix inside PR #671.
Acceptance
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 regex's are.
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.