Contracts authors defend configurable checks across translation units
P3846 responds to objections about mixed contract semantics and compiler assumptions. It treats optional assertions and mandatory safety checks as different requirements.
The strongest response to a criticism can accept its example while disputing what the example proves. October's contracts defense does that with mixed evaluation semantics. It acknowledges that a library cannot always predict which checking policy applies to a shared inline definition. The authors argue that this follows from C++'s compilation model and belongs within a configurable assertion design.
P3846R0, dated October 6, is led by Timur Doumler and Joshua Berne with a broad group of contributors. It responds to recent papers and national-body comments, including P3835R0. Its purpose is to defend retaining contracts in C++26. The paper is an argument in ballot resolution, not a report that every objection has been withdrawn.
The key disagreement concerns what a contract assertion promises to the program that uses it. The defenders describe assertions as redundant to correct program execution, independently checkable, and configurable outside the source. Critics want stronger control when a component relies on a check. Those requirements overlap, but they do not define the same facility.
The response accepts the mixed-definition case
P3835 describes an inline function compiled under quick-enforce in a library and ignore in its client. A non-inlined call can ultimately use the client's emitted definition. P3846 agrees that users without full build control cannot reliably predict the chosen semantic in this situation.
Its response rejects the assumption that the inline function belongs uniquely to the library translation unit. The header definition participates in every translation unit that includes it. Different compilations can emit versions with different configured semantics, and an existing linker can select one of those definitions.
The authors argue that mixed configuration already exists for macro-based assertions. Their claim is that standard contracts improve the situation by bounding behavior to the incorporated semantics instead of making differing macro expansions a one-definition-rule violation. That comparison is central to the defense. It does not provide the stronger component-local guarantee requested by P3835.
I find the distinction useful even where I remain sympathetic to the criticism. A configurable diagnostic can be valuable without being an unconditional safety boundary. The difficulty is making sure the interface's apparent promise matches the guarantee that a separately built program can actually rely on.
Implementation strategies have different costs
P3846 describes several ways a toolchain can implement the flexible model. One compiles each translation unit with fixed semantics and uses existing linkers. Another delays the choice until link, load, or runtime through an assertion hook. A further approach carries semantic information into linking through toolchain extensions.
These strategies trade runtime cost against control over which behavior is chosen and compatibility with current tools. The paper favors the first as an initial default while allowing alternatives to develop within the same specification. That is a deliberate deployment argument for preserving implementation freedom.
The important practical limit remains visible. Under the fixed-per-translation-unit strategy, an assertion intended to be checked can be ignored when the program selects a definition compiled that way. The authors consider that acceptable for a redundant assertion. A user who needs non-ignorable validation has a different requirement to satisfy.
This also explains why a standard feature need not mandate one build flag. The specification defines allowed behavior, while implementations choose configuration interfaces and strategies. A portable understanding of the language still needs toolchain documentation to explain the behavior of a particular build.
An unchecked assertion is different from a miscompilation
P3846 separately addresses an optimization example where a compiler removes a caller-side check based on a callee's enforced assertion, but the final program selects a different callee definition. The paper classifies that transformation as a compiler bug, not a permitted consequence of mixed-mode contracts.
The distinction is between choosing a permitted evaluation semantic and making an assumption that the selected definition does not support. A compiler can inline a known body and optimize according to its behavior. If it leaves a call whose definition can be supplied elsewhere, it cannot simultaneously assume implementation choices unique to the discarded local body.
The paper illustrates the principle with an inline function whose result depends on unspecified argument evaluation order. Different compiled definitions can make different permitted choices. A caller that retains an external call must test the actual returned result where its behavior depends on that result. Assuming one local choice after allowing another definition to supply the call would be inconsistent.
That explanation matters because it prevents two separate concerns from being combined. The assertion can legitimately go unchecked under a selected ignore definition. The compiler cannot use a check from another version to justify removing necessary caller behavior. P3846 defends the first possibility while rejecting the second.
Adoption arguments do not erase the stronger use case
The authors argue that optional checks support incremental deployment and performance-sensitive libraries. They also defend standard syntax for preconditions and postconditions as an improvement for tools and readers over unrelated assertion macros. Those benefits concern expressing and detecting requirements across existing code.
Non-ignorable checks remain a recognized extension direction in the paper. The defense points to labels proposed for later work and to ordinary control flow for checks that must execute today. It does not claim that October's response has already added a label mechanism to the C++26 draft. The distinction also affects dependency management. P3846 argues that a standard assertion facility can replace numerous library-specific configuration mechanisms, while leaving binary distributors free to select their supported build configurations. That is an argument about reducing duplicated policy interfaces, not a promise that independently compiled dependencies all acquire identical checking behavior.
I prefer to assess this debate through the required guarantee. P3846 gives a detailed case for configurable assertions under the existing compilation model. P3835 asks how a library can bind a stronger policy to its shared definitions. Understanding the response requires retaining both facts, including the admitted limit on predicting a shared inline assertion's semantic in a mixed build.