On 26.08.24 22:12, Thiago Macieira wrote: > On Monday 26 August 2024 12:55:04 GMT-7 Marc Mutz via Development wrote: >> I don't see a proposal for an alternative rule in the above. Please >> provide a) a new rule and b) rationale for it. Bonus points for being >> implementable in a static checker like Clazy or Axivion. > > "Q_ASSERT don't affect noexceptness" > > Or > > "noexcept(false) if you call other, noexcept(false) functions from your code", > which includes all the pthread cancellation points in glibc. Since qt_assert > is noexcept, Q_ASSERT is not included. This is very easy to implement with a > static checker. > > We could be more complex, with "Q_ASSERT that check preconditions imply > noexcept(false) but Q_ASSERT that verify the state of the internal invariant > against corruption don't". This would not be easy to implement with a static > checker.
If we make the distinction between Q_ASSERT-as-precondition-check and Q_ASSERT-as-internal-invariant/state-check (with a new macro name/names), then I can agree to that. Note, however, that the example that sparked this discussion (View::slice(int, int)) remains noexcept(false) under this rule, too. Ditto op==(It, It). I have tried to adjust https://wiki.qt.io/Things_To_Look_Out_For_In_Reviews#noexcept accordingly. For offline reader convenience, it currently reads: > Only functions that cannot fail to meet their post-conditions can be > noexcept. Failure to meet post-conditions can stem from a variety of reasons, > including a) having preconditions that are not met, b) calling a Posix > Cancellation Point or another noexcept(false) function (which may prematurely > end the function), or c) allocating memory or other resources (file handles, > mutexes). Rationale: This is the Lakos Rule (latest version: > https://wg21.link/p2861). We should track what the standard does and not > invent rules of our own. Specifically for preconditions, there are vague > plans to make them testable from QtTest by making Q_ASSERT() throw an > exception instead of calling abort() on failure; any noexcept function > in-between will cause this to not work. Specifically for (b), some Posix > systems implement thread cancellation by throwing an exception-like object to > unwind the stack (e.g. glibc-based ones). Such exceptions must not be > swallowed by user code (incl. Qt code) lest thread cancellations ends in > std::terminate(). > Exception: Like the std smart pointers, our smart pointers > operator*() may also be noexcept, but then they must not contain a > Q_ASSERT(). Rationale: When in Rome^WC++, do as the Romans do^W^Wstd does. > Distinguish Q_ASSERT()s that check for precondition violations (= > user is responsible) and those that check internal state/invariants in our > code (= we are responsible). The former requires the function containing them > to be noexcept(false), the latter doesn't. Rationale: The Lakos Rule is about > contract violations, not about internal consistency checks. If internal > consistency is found to be in disarray, recovery is likely impossible. If a > call contract is violated, OTOH, that may be very much recoverable, because > it's detected before "something bad" may happen. We'll hopefully get separate > macros for the two, but for now, be aware of the two different use cases of > assertions. > Thanks, Marc -- Marc Mutz <marc.m...@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 -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development