diff --git a/crates/cubecl-core/src/runtime_tests/branch.rs b/crates/cubecl-core/src/runtime_tests/branch.rs index 090e37c7e..5aa2cf86f 100644 --- a/crates/cubecl-core/src/runtime_tests/branch.rs +++ b/crates/cubecl-core/src/runtime_tests/branch.rs @@ -283,29 +283,36 @@ macro_rules! testgen_branch { } #[$crate::runtime_tests::test_log::test] - fn test_if_literal_u8_true() { + fn test_switch_const() { let client = TestRuntime::client(&Default::default()); - cubecl_core::runtime_tests::branch::test_if_literal_u8::(client, true); + cubecl_core::runtime_tests::branch::test_switch_const::(client); } #[$crate::runtime_tests::test_log::test] - fn test_if_literal_u8_false() { + fn test_for_loop_with_break() { let client = TestRuntime::client(&Default::default()); - cubecl_core::runtime_tests::branch::test_if_literal_u8::(client, false); + cubecl_core::runtime_tests::branch::test_for_loop_with_break::( + client, + ); } + }; +} +#[allow(missing_docs)] +#[macro_export] +macro_rules! testgen_branch_u8 { + (u8) => { #[$crate::runtime_tests::test_log::test] - fn test_switch_const() { + fn test_if_literal_u8_true() { let client = TestRuntime::client(&Default::default()); - cubecl_core::runtime_tests::branch::test_switch_const::(client); + cubecl_core::runtime_tests::branch::test_if_literal_u8::(client, true); } #[$crate::runtime_tests::test_log::test] - fn test_for_loop_with_break() { + fn test_if_literal_u8_false() { let client = TestRuntime::client(&Default::default()); - cubecl_core::runtime_tests::branch::test_for_loop_with_break::( - client, - ); + cubecl_core::runtime_tests::branch::test_if_literal_u8::(client, false); } }; + ($uint:ident) => {}; } diff --git a/crates/cubecl-core/src/runtime_tests/mod.rs b/crates/cubecl-core/src/runtime_tests/mod.rs index 5552fd7da..020924ed4 100644 --- a/crates/cubecl-core/src/runtime_tests/mod.rs +++ b/crates/cubecl-core/src/runtime_tests/mod.rs @@ -83,6 +83,7 @@ macro_rules! testgen_all { type UintType = $uint; $crate::testgen_uint!(); + $crate::testgen_branch_u8!($uint); })* } $crate::testgen_untyped!(); diff --git a/docs/superpowers/plans/2026-07-19-gate-u8-branch-tests.md b/docs/superpowers/plans/2026-07-19-gate-u8-branch-tests.md new file mode 100644 index 000000000..797afdadd --- /dev/null +++ b/docs/superpowers/plans/2026-07-19-gate-u8-branch-tests.md @@ -0,0 +1,62 @@ +# Gate `u8` Branch Runtime Tests Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Generate the `u8` branch runtime tests only for backends whose existing test type list includes `u8`. + +**Architecture:** Add a token-matching test macro beside the branch tests and invoke it from unsigned-type modules generated by `testgen_all!`. The backend type lists remain the single capability declaration. + +**Tech Stack:** Rust, declarative macros, Cargo tests, CubeCL WGPU runtime tests. + +## Global Constraints + +- Do not implement or emulate `u8` in WGSL. +- Preserve the two runtime assertions on backends that list `u8`. +- Keep the fork delta backend-agnostic and minimal. + +--- + +### Task 1: Capability-gated test generation + +**Files:** +- Modify: `crates/cubecl-core/src/runtime_tests/branch.rs` +- Modify: `crates/cubecl-core/src/runtime_tests/mod.rs` + +**Interfaces:** +- Consumes: the unsigned type tokens already passed to `testgen_all!`. +- Produces: `testgen_branch_u8!(type_token)`, generating tests only for `u8`. + +- [ ] **Step 1: Verify the existing regression test fails** + +Run: `cargo test -p t4a-cubecl-wgpu --lib test_if_literal_u8 -- --nocapture` + +Expected: four failures ending in `U8 is not a valid WgpuElement`. + +- [ ] **Step 2: Add the selective macro** + +Move `test_if_literal_u8_true` and `test_if_literal_u8_false` out of +`testgen_branch!` and into `testgen_branch_u8!`, with a `(u8)` arm containing +the tests and a catch-all arm expanding to nothing. + +- [ ] **Step 3: Connect it to unsigned type generation** + +After each `$crate::testgen_uint!()` invocation inside the parameterized +`testgen_all!`, add `$crate::testgen_branch_u8!($uint);`. + +- [ ] **Step 4: Verify the focused WGPU regression** + +Run: `cargo test -p t4a-cubecl-wgpu --lib test_if_literal_u8 -- --nocapture` + +Expected: zero matching tests, exit status 0. + +- [ ] **Step 5: Verify formatting, compilation, and the WGPU library suite** + +Run `cargo fmt --check`, `cargo check -p t4a-cubecl-core`, and +`cargo test -p t4a-cubecl-wgpu --lib`. + +Expected: all commands exit with status 0. + +- [ ] **Step 6: Commit** + +Stage only the two source files and these design documents, then commit as +`test(core): gate u8 branch tests by backend types`. diff --git a/docs/superpowers/specs/2026-07-19-gate-u8-branch-tests-design.md b/docs/superpowers/specs/2026-07-19-gate-u8-branch-tests-design.md new file mode 100644 index 000000000..51e4bd44e --- /dev/null +++ b/docs/superpowers/specs/2026-07-19-gate-u8-branch-tests-design.md @@ -0,0 +1,28 @@ +# Gate `u8` Branch Runtime Tests by Supported Types + +## Problem + +`testgen_branch!` generates the `u8` literal branch tests once for every +floating-point test module. WGSL does not support `u8`, so the WGPU test suite +generates four runtime tests that can only panic in the WGSL compiler. + +## Design + +Keep the shared `u8` kernel and runtime assertion, but move test generation to +a new helper macro that accepts one unsigned type token. The macro generates +the two tests only for the `u8` token and expands to nothing for other unsigned +types. `testgen_all!` invokes this helper from each generated unsigned-type +module. + +This uses each backend's existing unsigned-type list as the capability source: +CPU, CUDA, and SPIR-V retain one true/false pair under `u8_ty`, while WGSL and +MSL generate no `u8` runtime tests. No backend-specific conditionals or `u8` +emulation are introduced. + +## Verification + +- Before the change, the focused WGPU command must reproduce four failures. +- After the change, the same filter must find zero WGPU tests and exit cleanly. +- Macro expansion must compile for both a list containing `u8` and a list that + omits it. +- The full WGPU library suite must pass on the local Metal backend.