contracts: add violation handler infrastructure and annotated optional#7129
contracts: add violation handler infrastructure and annotated optional#7129Sanchit2662 wants to merge 1 commit intoTheHPXProject:masterfrom
Conversation
Signed-off-by: Sanchit2662 <sanchit2662@gmail.com>
|
Can one of the admins verify this patch? |
|
@Sanchit2662 What's your plans with moving this forward? |
|
Hey @hkaiser , thanks for taking a look! Yeah so the plan is definitely not to keep this as a separate standalone thing. The idea is to integrate it properly with the existing assertion infrastructure in HPX. What I'm thinking is that The three modes map pretty naturally to what HPX already does. IGNORE is basically how release builds work today where For what to annotate first, I was thinking of following the same priority P3471 uses for the hardened STL. So hpx::optional first since it's a direct equivalent (operator*, operator->, value() all need has_value() to be true). Then HPX containers for out-of-bounds stuff, then On the macro side, the design I have in mind keeps a clean migration path. When a C++26 compiler with native contract support shows up, One thing I'm genuinely unsure about though: should the contract mode be its own CMake option like |
IIUC, you suggest adding an additional mode to the existing infrastructure that logs violations. That would be ok, I think.
As said, modifying
For pre-C++26 compilers this has to be a HPX CMake option. For conforming compilers this can be derived from the compiler options themselves. |
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| ErrorProne | 4 high 1 critical 12 medium |
🟢 Metrics 46 complexity · 0 duplication
Metric Results Complexity 46 Duplication 0
TIP This summary will be updated as you push new changes. Give us feedback
What this is
A standalone, buildable contracts infrastructure - violation handler with enforce/observe/ignore mode dispatch, the macro layer (
HPX_CONTRACT_ASSERT,HPX_PRE,HPX_POST), and a minimaloptional<T>annotated with P3471 preconditions. Lives inpoc/contracts/and builds independently of HPX's CMake so anyone can run it without a full HPX build.This is a proof-of-concept : not the real integration, just enough to show the approach is sound.
What I built
Three files that form the core of what the full project would need:
violation_handler.hpp- aviolation_infostruct that mirrors whatstd::contract_violationwill look like in C++26, plus a customizable handler (default: log to stderr + abort). This is the same pattern HPX already uses forassertion_handler.contract_macros.hpp-HPX_CONTRACT_ASSERT,HPX_PRE,HPX_POSTmacros that dispatch to the right behavior depending on a compile-time mode flag.annotated_optional.hpp- a minimaloptional<T>withHPX_CONTRACT_ASSERT(has_value())onoperator*,operator->, andvalue()- exactly the P3471 preconditions, and exactly what was done in the realoptional.hppon thefeat/contracts-optional-operator-starbranch.Plus a
contracts_poc.cppwith 20 tests that run across all three modes and aCMakeLists.txtthat builds all three at once.How it works
The key idea is compile-time mode selection:
-DHPX_CONTRACTS_MODE=0→ ENFORCE: check predicate, call handler, abort on violation-DHPX_CONTRACTS_MODE=1→ OBSERVE: check predicate, call handler, continue-DHPX_CONTRACTS_MODE=2→ IGNORE: predicate never evaluated (zero cost)These map directly to P2900's three semantics. In IGNORE mode
HPX_CONTRACT_ASSERT(expr)compiles to((void)0)- zero overhead.The violation handler is user-installable (same API as
hpx::assertion::set_assertion_handler), which makes it testable - instead of aborting, tests install a recording handler that captures violations and check them.Build it yourself
What this isn't
This is not the actual implementation. Specifically:
.cppunderlibs/core/contracts/src/withHPX_CORE_EXPORTlinkage.HPX_ASSERTat all. The real integration (viaHPX_CONTRACTS_WITH_ASSERTS_AS_CONTRACT_ASSERTS) is already in the existing contracts module.optional<T>here is a standalone toy. The actual annotation is already on thefeat/contracts-optional-operator-starbranch in the realoptional.hpp.Questions for reviewers
The violation handler is
noexceptthroughout (matching the existinghandle_assert). Is that right for observe mode too, or should we allow the handler to throw in observe mode to integrate with HPX's exception-based error propagation?For
HPX_PRE/HPX_POSTin fallback mode - I currently put them as body statements (top of function / before return). When native contracts land, they move to the declaration. Does HPX want a migration story for that, or is it acceptable that fallback-mode and native-modeHPX_PREare syntactically in different positions?Is the priority order right - containers first, then futures, then parallel algorithms? Or should futures come first since
future::get()on an invalid future is probably the most common real-world bug?