C++ Logo

sg15

Advanced search

Re: [isocpp-sg15] [isocpp-sg21] [isocpp-ext] A small request re the "new UB" concern, please

From: Joshua Berne <berne_at_[hidden]>
Date: Thu, 23 Oct 2025 18:30:13 -0400
On Thu, Oct 23, 2025 at 6:10 PM Ville Voutilainen via SG21 <
sg21_at_[hidden]> wrote:

> On Fri, 24 Oct 2025 at 01:05, Oliver Hunt via Ext <ext_at_[hidden]>
> wrote:
> > Is the issue that in observe mode in this case that these contract
> assertions turn into something like (pseudo code)
> >
> > if (p != nullptr) report();
> > if (!p->foo()) report();
> >
> > And the compiler is permitted to assume that `p->foo()` means that `p`
> is nonnull and back propagate that assumption forward or backwards through
> time?
> >
> > I had thought that the observable checkpoints were intended to act as a
> fence that prevented such optimization?
>
> The issue isn't such an optimization, but that the second check has
> UB. It won't propagate backwards, but it's still UB.
>

Yes, there is no concern with time travel optimizations, there are concerns
that people might observe all contract assertions and then be surprised by
their program's behavior after having been notified of the first violation.

Observe gives one and only one promise: The first time a contract
violation is detected, your violation handler will be invoked.

After that, your program is *definitely* in a buggy state, by definition
--- you identified this buggy state by writing your contract assertion in
the first place. Observe might, potentially, if you write contract
assertions whose predicates have preconditions on the assumption that
earlier contract assertions must absolutely have been enforced, lead you to
violating the preconditions of those later contract assertions and thus
turning your contract on with observe "introduces UB".

Oh no. How scary. Pardon my sarcasm.

Notice how observe told you your program had a bug, and then your incorrect
program behavior after that notification changed into different incorrect
program behavior. That is life with programs with bugs. If you don't like
it, don't write programs with bugs, or don't deploy observe. Eventually,
I believe, you'll find the need for observe becomes essential as your
software evolves.

There's no need to write observe-safe code --- the above code isn't even
enforce-safe, because we all know that `p` may be a non-null but still
dangling pointer and then --- oh no --- the second contract assertion has
UB when evaluated. If you do want such things then just make every
expression have as wide a contract as possible (even though you'll never
get most of them to be completely wide).

Received on 2025-10-23 22:30:29