Skip to content

feat(format): cpp-type-preservation-v1 7-gate PARTIAL discharge#1393

Open
noahgift wants to merge 1 commit intomainfrom
feat/cpp-001-007-partial-discharge
Open

feat(format): cpp-type-preservation-v1 7-gate PARTIAL discharge#1393
noahgift wants to merge 1 commit intomainfrom
feat/cpp-001-007-partial-discharge

Conversation

@noahgift
Copy link
Copy Markdown
Contributor

@noahgift noahgift commented May 2, 2026

Summary

  • Binds FALSIFY-CPP-001..007 from cpp-type-preservation-v1 at PARTIAL_ALGORITHM_LEVEL via 7 verdict functions for the Decy C++→Rust transpiler.
  • 30 unit tests including 5-bucket field-count sweep + 4-bucket implicit-this sweep + vacuous-Pass guard for unused features.
  • Algorithm-level coverage advances by 7 gates; runtime ship % unchanged.

Gates bound

Gate ID Rule
CPP-001 Class with N fields → struct with N pub fields
CPP-002 Constructor → pub fn new(...) -> Self
CPP-003 Destructor → impl Drop for X
CPP-004 namespace Xpub mod X (with pub visibility)
CPP-005 operator+impl std::ops::Add
CPP-006 Inheritance → composition + impl Deref
CPP-007 Implicit this->xself.x (count-preserving)

Five Whys

See commit message — captures count-preserving rationale for CPP-007, vacuous-Pass for unused-feature gates, and why pub visibility is modeled separately for CPP-004.

Test plan

  • cargo test -p aprender-core --lib cpp_001_007 — 30 passed
  • PMAT pre-commit gates green
  • CI green

🤖 Generated with Claude Code

Binds FALSIFY-CPP-001..007 from cpp-type-preservation-v1 at
PARTIAL_ALGORITHM_LEVEL via 7 verdict functions for the Decy
C++→Rust transpiler's type-preservation invariants.

- CPP-001: class with N fields → struct with N pub fields
- CPP-002: constructor → `pub fn new(...) -> Self`
- CPP-003: destructor → `impl Drop for X`
- CPP-004: namespace → `pub mod X` with matching name
- CPP-005: operator+ → `impl std::ops::Add for X`
- CPP-006: inheritance → composition + `impl Deref`
- CPP-007: implicit this.field → self.field (count-preserving)

## Five Whys

1. Why does cpp-type-preservation-v1 list 7 falsification IDs without
   algorithm-level discharge? PMAT lints flagged FALSIFY-CPP-001..007
   as unbound at PARTIAL_ALGORITHM_LEVEL.
2. Why does that block ship? Coverage % cannot move while peripheral
   Decy C++ transpiler type-preservation gates are unbound.
3. Why count-preserving for CPP-007 (not bit-exact)? The contract
   asks "implicit `this->x` becomes `self.x`" — the algorithm-level
   decision rule is "every implicit-this in C++ produced exactly one
   self.field in Rust." Count equality catches the regression class
   "CXXThisExpr handling dropped some accesses" without requiring
   us to model the full AST.
4. Why vacuous Pass for unused-feature gates (CPP-002/003/005/006)?
   When the C++ source has no constructor / destructor / operator+ /
   inheritance, the gate's antecedent is false and the implication
   is vacuously true. Returning Fail would penalize plain
   field-only structs — not the regression class the gate exists to
   catch.
5. Why model `pub` visibility separately for CPP-004? Per the
   contract: `namespace math { ... }` → `pub mod math { ... }`.
   The `pub` visibility is critical — a private `mod math` would
   silently drop all the namespace's contents from any cross-crate
   re-import, even though name + content match. Modeling visibility
   separately catches that regression class.

Adds 30 unit tests including a 5-bucket field-count sweep and
a 4-bucket implicit-this sweep. Realistic-healthy walks the
canonical Decy transpilation; pre-fix walks 7 simultaneous
regressions; vacuous-Pass test guards the unused-feature edge cases.

No runtime % shift; algorithm-level coverage advances by 7 gates.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant