[Development] Disavowing the Lakos Rule for Q_ASSERT

Marc Mutz marc.mutz at qt.io
Thu Aug 29 15:43:58 CEST 2024


I'm ok with 1-3, I'm not ok with 4.

The state of the art is what the std prescribes, not what a stdlib 
implementation does. stdlibs are magic; they can theoretically remove 
the noexcept for new code and keep it for old. Or they can let contract
violations pass magically. We can't, at least not with a lot of manual
labour (QT_REMOVED_SINCE/QT6_NEW_OVERLOAD).

If we get (1), I think we'll very quickly also get a build mode in which 
these throw.

And I'm also questioning the alternatives to throwing from assertions 
(or Q_PRE, if you want). You can fork, yes. Very complicated, and 
probably slow as hell (I still remember Qt 5 QSharedPointer negative 
tests were even slow on Linux). We can't call a QtTest-handler, because 
that handler cannot return without an exception, because the code 
following the assertion typically assumes that the assertion holds and 
runs into Language UB (non-recoverable) as a consequence if it didn't.

Finally, one thing that Lakos wrote in his paper 
(https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2861r0.pdf) 
was that it should be up to *the owner of main()* to determine how 
precondition violations are handled. Neither std nor Qt should decide 
for the user here.

I think this is very pertinent to the current software security 
legislation being proposed on both sides and Qt should not shut the door 
in front of users that would like to run checked build modes in production.

Therefore: no noexcept on narrow-contract functions is still paramount, 
IMNSHO.

Again, a hunch is not enough to sway me here. A meaningful increase in 
runtime speed would need to be demonstrated, and even then, we would 
need to weigh that feature against the desire for certain customers (one 
being ourselves, for negative testing) to use a checked build mode in 
production.

Thanks,
Marc


On 28.08.24 17:49, Thiago Macieira wrote:
> On Wednesday 28 August 2024 03:23:52 GMT-7 Volker Hilsheimer via Development
> wrote:
>> TL;DR: Given that the tradeoff is between two marginally and somewhat
>> speculative benefits, it seems to me that a pragmatic (as opposed to
>> dogmatic) application of the Lakos rule in the cases where Q_ASSERT is used
>> to verify preconditions is sensible for us. Which in our governance model
>> translates to maintainer privilege. In other words: if Thiago believes that
>> making something noexcept is correct because a try/catch on the call site
>> would be the completely wrong tool to deal with the mistake that the
>> Q_ASSERT guards against, then that’s acceptable (and doesn’t mean that it
>> cannot be discussed passionately in code review).
> 
> Here's the summary if what I am proposing:
> 
> 1. Introduce new macros to document pre- and post-conditions, to be used
> mostly in inline code.
> 
> Eventually, those pre- and post-conditions can be changed into contracts, when
> the language has them and we can use them in our sources without lots of ugly
> #if. Depending on the syntax for them (which I didn't bother to look up), that
> may not be until 2032 for the majority of contracts.
> 
> 2. Leave Q_ASSERT for checking on internal conditions, which the user has no
> reasonable way of corrupting, short of messy bugs elsewhere.
> 
> I mean, even this function has a precondition of "you haven't overwritten
> global memory somehow":
> 	Q_DECL_IMPORT extern int value;
> 	int f() { return value; }
> 
> 3. Internal consistency checks do not imply narrow contract. Therefore,
> Q_ASSERTs do not imply noexcept(false)
> 
> 4. [This is the contentious one, if we accept #1] Functions with precondition
> checks and narrow contracts can still be noexcept
> 
> In this, I am proposing we follow the state-of-the-art, namely the Standard
> Libraries, where they have marked noexcept functions with certain
> preconditions like std::vector::operator[] and std::basic_string_view char+len
> constructor.
> 
> IF and when they deploy a solution to allow turning those checks into checked
> preconditions that may throw, we copy their solution and apply the same.
> 
> 
-- 
Marc Mutz <marc.mutz at qt.io> (he/his)
Principal Software Engineer

The Qt Company
Erich-Thilo-Str. 10 12489
Berlin, Germany
www.qt.io

Geschäftsführer: Mika Pälsi, Juha Varelius, Jouni Lintunen
Sitz der Gesellschaft: Berlin,
Registergericht: Amtsgericht Charlottenburg,
HRB 144331 B



More information about the Development mailing list