Hi All,
While I wait for the feedback from the authors of P3835 below, let me share a different example that puzzles me. Imagine a three-file scenario.

// lib1.hpp
// -----
bool is_calibrated(shared_ptr<Tool> const& t)
  pre (t != nullptr);
// -----

// Lib2.hpp
// ----
void work(shared_ptr<Tool>& t)
  pre(is_calibrated(t));
// ----

// Main.cpp
// ----
work(t);
// ----

If I somehow manage to configure my build chain to runtime-check preconditions of the library lib2, does this mean that the assertion `t != nullptr` will be checked or not? The assertion as well as function is_calibrared is defined in a different library that I am not runtime-assertion-checking. Such a combination of preconditions seems plausible: the author of `work()` can assume that predicates in contract assertions can themselves have narrow contacts, and that preconditions of preconditions apply recursively. And this is true; but it is not clear how the selective runtime-checking enablement works in that case. 

I do not think it should be left to implementations. I think the Standard should guarantee that if an assertion predicate is evaluated using the `enforce` mode, the preconditions of functions called in that predicate are also evaluated in `enforce` mode. But I am not sure if this is implementable. This gets even more interesting with `observe` mode. 

Regards,
&rzej;

czw., 2 paź 2025 o 22:31 Andrzej Krzemienski <akrzemi1@gmail.com> napisał(a):


pon., 29 wrz 2025 o 22:14 John Spicer via SG21 <sg21@lists.isocpp.org> napisał(a):
I think that compile-time and link-time selection of semantics is a desirable feature.

But that misses the essential point of p3835r0 that the semantics need to apply to software “components” and not to translation units or to the entire program.

If you consider the example in the paper I referenced, it is essential that the check in l1.cpp fail.

There could be some other contract check in c1.cpp that is expected to be ignored.

The key issue is not, IMO, how you control a “checking mode” that applies to a TU or the program, the issue is how you apply various “checking modes” to different components (e.g., libraries).

There are a number of possible solutions to this problem, each of which have their own tradeoffs.

But the first step is the recognition that this is a problem that needs to be solved in order for contracts to be viable in the real world.

I would like to understand this expectation a bit more. Rather than talking about the details I would focus on the motivation. 

The scenario that I am familiar with is that when a program P uses a library L, it is likely that P will use L incorrectly, and additional measures need to be taken to test if P is using L correctly. This would mean that in the P2900 world we would want to runtime check the assertions *at the library boundary* but not necessarily *inside* the library. IOW, If I were the author of P, I would trust library L that it was thoroughly tested, and would not want to assertion-test its implementation. But I would like to test if I am *using* the library correctly. So I would like to enable every precondition in L's interface and some contract_asset statements close to library entry points that also function as preconditions. But only those. If libstdc++'s STL implementation offers control macros to enable STL-specific assertions, those assertions practically check if the user is using the STL correctly: not if STL has been correctly implemented.

But P3835 seems to be expressing a different need. So my question to the authors of P3835 is: is your motivating use case testing the library *usage* or really testing one library's implementation in a different way than another library's implementation? If it is the latter, that would be strange: you would have to mistrust the library L enough to want to keep checking its implementation, but at the same time trust it enough that the author put the right assertions in the right places with sufficient density.

Regards,
&rzej;