Date: Wed, 19 Aug 2026 00:25:56 +0200
Hi Jonathan,
On Tue, Aug 18, 2026 at 11:30 PM Jonathan Grant <jgrantonline_at_[hidden]>
wrote:
> > compile_assert, if I understand it correctly, is identical to contracts
> in P2900 when set up to have a C++ library that does not implement its
> violation handler function. Your program will link if and only if it could
> be proven during compilation. That already works like that - in fact, I at
> first didn't notice I had forgotten to switch over to my experimental
> libc++ until it failed to link after adding a few contracts. The first few
> in the places they were called were always true and didn't emit a symbol to
> link to in the first place.
> >
>
> compile_assert() is eloquent, just a few lines of code, it uses the
> compiler's internal knowledge and exposes it to the programmer,
> compile_assert isn't present in any compiled code. The sample works in GCC
> since version 4.5.3 (2011). The Linux Kernel has had similar for over a
> decade. So my proposal would standardize existing use.
>
> Matt Borland's SafeNumbers uses compile_assert for Compile Time
> Pre-Condition checks
> https://develop.safe-numbers.cpp.al/compile_time_checks.html
>
> I've read P2900 C++ Contracts and it's very different. P2900 is a very
> large specification and at runtime.
>
> It's a functional safety concern to have runtime behaviour in callbacks,
> and ignore. observe - continuing means the issue is missed, enforce - very
> difficult to recover from such a callback - far better to identify such
> bugs at compile-time. quick-enforce, is just std::terminate()?
>
> On top of the simple statement form of compile_assert() it's possible to
> implement more advanced Rust style ownership models, optionality etc. P2900
> does look very large for what could can be achieved at compile-time in a
> few lines. Compile-time Contracts I put in one of the testsuite files was 3
> lines of code on top of compile_assert().
>
> Maybe with your knowledge and experience of P2900 C++ Contracts you'd like
> to see the compile_assert example of contracts? It's here on godbolt, see
> it find the bugs at compile time on lines 78 and 79.
>
> https://godbolt.org/z/9P731ozzz
https://godbolt.org/z/PTMbMY1MW is the same in P2900, on the stock GCC 16.1
that you also used. I made a custom violation handler that calls a
nonexistent function called "failed to prove" if the compiler fails to
prove them. It behaves the same as your example, and similarly relies on
the optimizer to accomplish this. P2900 has different ways to be usable,
and this is one of them. It's not one that I think most people will want to
use, because of fragility, but it definitely works. This is also the
approach I described in the previous message, see above. The contract
violation handler is defined inline to make the compiler not output a copy
if it's not used; otherwise it functions as described.
For a targeted embedded target this is probably usable. For any general use
it is not.
> > With regards to proving things at compile time, the current definition
> of contracts is enough for simple assertions. Anything that is too
> complicated (lamdbas, usually) or that passes through an opaque interface
> that the compiler cannot see into, cannot be optimized. In particular, a
> sequence f(g(x)) where both g(x) has a postcondition r:p(rv) and f(r) has a
> precondition p(r), cannot forward the result of a postcondition on g(x) to
> f, as there is no way to explain that evaluating p with the same argument
> twice will do the same thing twice. For repeated checks on a precondition
> we have taken that allowance into the standard, but for this specific
> situation we'd need something like [[reproducible]] or [[unsequenced]] as
> in C.
> >
>
> Do you mean though abstract base classes with virtual functions?
>
> compile_assert works through APIs, but I have not tried opaque interfaces.
> It might work.
>
No, this is for general function contracts. Compilers cannot in general
look into functions unless they are available to the compiler to use
(without runtime substitutability, see also gcc bugs) or are sufficiently
clear from their declaration (ie, reproducible, unsequenced, return-type
constrained or some such).
> > Beyond that, I know that multiple different groups of people are looking
> into what specifically we can do with contracts as specified, and what we'd
> need to change or add. So far the results seem to be that it works well
> enough, but that with minor tweaks we can make it more powerful. A
> hypothetical [[mustprove]] attribute could exist in a compiler, requesting
> it to fail the build if it cannot prove a functions' calls' pre-contracts,
> and its postcontract, based on its own pre-contracts and its calls'
> postcontracts. Basically, asking the compiler to do the Hoare propagation
> and seeing if it connects, at a semantic level that would need to be done
> early on in a compiler. Given such information, depending on build modes, a
> compiler can just remove all checks in that function, as there's no way
> they don't hold. Will never be able to do all code - but if it can do 95%
> of the code, I'll happily review or rewrite the remaining 5%. Think of it
> like a borrow checker for the guarantees
> > that brings, except functional safety (and whatever memory safety was
> expressed in contracts).
> >
>
> I implemented an Ownership class borrow checker with a few lines of code
> using compile_assert(), at compile-time.
>
> Sir Tony Hoare gave a good presentation, may I ask if you have seen this
> one?
> The 1980 ACM Turing Award Lecture
> The Emperor's Old Clothes
>
> Tony Hoare wrote about PL/1 and ADA, how they got bigger, more
> complicated. Tony Hoare spoke about simplification of programming
> languages, taking a subset when referring to ALGOL, ADA and other projects
> from his career.
>
I'm very much on board with restricting C++ in ways that allow the inner
core to get out and be a future language - see also P3716 (subsetting),
P4314 (on activating a profile) and at least 10 other papers in the past
three years all targeted at having a future C++ that contains less features
you're going to find, and more constructs that allow you to write code
safely. The old adage - make it easy to use and hard to misuse - is the one
where we have to provide the tools so that our users can implement it. They
need ways to check that what people pass in is actually correct, that the
intermediate results make sense, that the return values comply with what
the function promises, that users don't use overly-powerful constructs or
outdated strategies like reinterpret_cast and strncpy in any new code, so
that we will end up with a new environment where functions are always
called in contract, where outmoded and outdated constructs are not usable
in new code, and where we can move towards compile-time proving as much as
possible. In a way, profiles *is* compile-time proving that a given
guarantee holds, not actually too dissimilar in spirit from compile-time
proving contracts, just with a wider scope.
>
> I'll share a quote:
>
> "I conclude that there are two ways of constructing a software design: One
> way is to make it so simple that there are obviously no deficiencies and
> the other way is to make it so complicated that there are no obvious
> deficiencies."
>
It is one of my favorites. So much software, especially today, is being
built by adding much more code that eventually it'll kinda run, but nobody
has any idea what goes where. I prefer his second option; make software
that cleanly separates responsibilities such that it's obviously correct.
> But let's first see what happens with the C++26 DIS. If you want to form
> an opinion on how well it works, try it out - godbolt, local install - and
> form your own opinion. And if you'd like it to have more features maybe
> consider not voting against for that reason. That's not going to get you
> more features - it's only going to cause more turbulence and delay.
> >
>
> Tony Hoare was keen on subsets, simple features, I feel similar, my
> preference I rather it was far smaller and at compile-time, without any
> runtime behaviour. A contract is a compile-time proof obligation, it should
> not have runtime behaviour. Tony Hoare suggested to resist features whose
> complexity exceeds our ability to understand their consequences. ie my
> objection is not against Hoare Logic Contracts in C++; it's an objection to
> making the technological mechanics of expressing Contracts a runtime model.
>
> May I ask your viewpoint - would you consider if the design of C++
> Contracts were simpler, compile-time only, without any runtime
> behaviour/callbacks would that be more useful for programmers?
>
If it only did compile-time checks, it would be unsuitable for 95%+ of
them. For the remaining 5% it'd be better, if only by virtue of being
simpler.
P2900 allows it to be proven at compile time (just under as-if rule), see
above. It allows it to spill to runtime. It has defined mechanisms to
change from "enforce" to some other semantic, and the predefined ones that
we know people use now and will want to use, even if you should never want
to use them.
On Tue, Aug 18, 2026 at 11:30 PM Jonathan Grant <jgrantonline_at_[hidden]>
wrote:
> > compile_assert, if I understand it correctly, is identical to contracts
> in P2900 when set up to have a C++ library that does not implement its
> violation handler function. Your program will link if and only if it could
> be proven during compilation. That already works like that - in fact, I at
> first didn't notice I had forgotten to switch over to my experimental
> libc++ until it failed to link after adding a few contracts. The first few
> in the places they were called were always true and didn't emit a symbol to
> link to in the first place.
> >
>
> compile_assert() is eloquent, just a few lines of code, it uses the
> compiler's internal knowledge and exposes it to the programmer,
> compile_assert isn't present in any compiled code. The sample works in GCC
> since version 4.5.3 (2011). The Linux Kernel has had similar for over a
> decade. So my proposal would standardize existing use.
>
> Matt Borland's SafeNumbers uses compile_assert for Compile Time
> Pre-Condition checks
> https://develop.safe-numbers.cpp.al/compile_time_checks.html
>
> I've read P2900 C++ Contracts and it's very different. P2900 is a very
> large specification and at runtime.
>
> It's a functional safety concern to have runtime behaviour in callbacks,
> and ignore. observe - continuing means the issue is missed, enforce - very
> difficult to recover from such a callback - far better to identify such
> bugs at compile-time. quick-enforce, is just std::terminate()?
>
> On top of the simple statement form of compile_assert() it's possible to
> implement more advanced Rust style ownership models, optionality etc. P2900
> does look very large for what could can be achieved at compile-time in a
> few lines. Compile-time Contracts I put in one of the testsuite files was 3
> lines of code on top of compile_assert().
>
> Maybe with your knowledge and experience of P2900 C++ Contracts you'd like
> to see the compile_assert example of contracts? It's here on godbolt, see
> it find the bugs at compile time on lines 78 and 79.
>
> https://godbolt.org/z/9P731ozzz
https://godbolt.org/z/PTMbMY1MW is the same in P2900, on the stock GCC 16.1
that you also used. I made a custom violation handler that calls a
nonexistent function called "failed to prove" if the compiler fails to
prove them. It behaves the same as your example, and similarly relies on
the optimizer to accomplish this. P2900 has different ways to be usable,
and this is one of them. It's not one that I think most people will want to
use, because of fragility, but it definitely works. This is also the
approach I described in the previous message, see above. The contract
violation handler is defined inline to make the compiler not output a copy
if it's not used; otherwise it functions as described.
For a targeted embedded target this is probably usable. For any general use
it is not.
> > With regards to proving things at compile time, the current definition
> of contracts is enough for simple assertions. Anything that is too
> complicated (lamdbas, usually) or that passes through an opaque interface
> that the compiler cannot see into, cannot be optimized. In particular, a
> sequence f(g(x)) where both g(x) has a postcondition r:p(rv) and f(r) has a
> precondition p(r), cannot forward the result of a postcondition on g(x) to
> f, as there is no way to explain that evaluating p with the same argument
> twice will do the same thing twice. For repeated checks on a precondition
> we have taken that allowance into the standard, but for this specific
> situation we'd need something like [[reproducible]] or [[unsequenced]] as
> in C.
> >
>
> Do you mean though abstract base classes with virtual functions?
>
> compile_assert works through APIs, but I have not tried opaque interfaces.
> It might work.
>
No, this is for general function contracts. Compilers cannot in general
look into functions unless they are available to the compiler to use
(without runtime substitutability, see also gcc bugs) or are sufficiently
clear from their declaration (ie, reproducible, unsequenced, return-type
constrained or some such).
> > Beyond that, I know that multiple different groups of people are looking
> into what specifically we can do with contracts as specified, and what we'd
> need to change or add. So far the results seem to be that it works well
> enough, but that with minor tweaks we can make it more powerful. A
> hypothetical [[mustprove]] attribute could exist in a compiler, requesting
> it to fail the build if it cannot prove a functions' calls' pre-contracts,
> and its postcontract, based on its own pre-contracts and its calls'
> postcontracts. Basically, asking the compiler to do the Hoare propagation
> and seeing if it connects, at a semantic level that would need to be done
> early on in a compiler. Given such information, depending on build modes, a
> compiler can just remove all checks in that function, as there's no way
> they don't hold. Will never be able to do all code - but if it can do 95%
> of the code, I'll happily review or rewrite the remaining 5%. Think of it
> like a borrow checker for the guarantees
> > that brings, except functional safety (and whatever memory safety was
> expressed in contracts).
> >
>
> I implemented an Ownership class borrow checker with a few lines of code
> using compile_assert(), at compile-time.
>
> Sir Tony Hoare gave a good presentation, may I ask if you have seen this
> one?
> The 1980 ACM Turing Award Lecture
> The Emperor's Old Clothes
>
> Tony Hoare wrote about PL/1 and ADA, how they got bigger, more
> complicated. Tony Hoare spoke about simplification of programming
> languages, taking a subset when referring to ALGOL, ADA and other projects
> from his career.
>
I'm very much on board with restricting C++ in ways that allow the inner
core to get out and be a future language - see also P3716 (subsetting),
P4314 (on activating a profile) and at least 10 other papers in the past
three years all targeted at having a future C++ that contains less features
you're going to find, and more constructs that allow you to write code
safely. The old adage - make it easy to use and hard to misuse - is the one
where we have to provide the tools so that our users can implement it. They
need ways to check that what people pass in is actually correct, that the
intermediate results make sense, that the return values comply with what
the function promises, that users don't use overly-powerful constructs or
outdated strategies like reinterpret_cast and strncpy in any new code, so
that we will end up with a new environment where functions are always
called in contract, where outmoded and outdated constructs are not usable
in new code, and where we can move towards compile-time proving as much as
possible. In a way, profiles *is* compile-time proving that a given
guarantee holds, not actually too dissimilar in spirit from compile-time
proving contracts, just with a wider scope.
>
> I'll share a quote:
>
> "I conclude that there are two ways of constructing a software design: One
> way is to make it so simple that there are obviously no deficiencies and
> the other way is to make it so complicated that there are no obvious
> deficiencies."
>
It is one of my favorites. So much software, especially today, is being
built by adding much more code that eventually it'll kinda run, but nobody
has any idea what goes where. I prefer his second option; make software
that cleanly separates responsibilities such that it's obviously correct.
> But let's first see what happens with the C++26 DIS. If you want to form
> an opinion on how well it works, try it out - godbolt, local install - and
> form your own opinion. And if you'd like it to have more features maybe
> consider not voting against for that reason. That's not going to get you
> more features - it's only going to cause more turbulence and delay.
> >
>
> Tony Hoare was keen on subsets, simple features, I feel similar, my
> preference I rather it was far smaller and at compile-time, without any
> runtime behaviour. A contract is a compile-time proof obligation, it should
> not have runtime behaviour. Tony Hoare suggested to resist features whose
> complexity exceeds our ability to understand their consequences. ie my
> objection is not against Hoare Logic Contracts in C++; it's an objection to
> making the technological mechanics of expressing Contracts a runtime model.
>
> May I ask your viewpoint - would you consider if the design of C++
> Contracts were simpler, compile-time only, without any runtime
> behaviour/callbacks would that be more useful for programmers?
>
If it only did compile-time checks, it would be unsuitable for 95%+ of
them. For the remaining 5% it'd be better, if only by virtue of being
simpler.
P2900 allows it to be proven at compile time (just under as-if rule), see
above. It allows it to spill to runtime. It has defined mechanisms to
change from "enforce" to some other semantic, and the predefined ones that
we know people use now and will want to use, even if you should never want
to use them.
--- With regards to a comment Ville made, apparently there has been a Windows-available build of GCC for a while now; I could find four flavors of a GCC build that runs contracts, and a number of people that use Windows that found that they were already using a contracts-supporting compiler. So that has existed, even for Windows users that want Windows-executable outputting compilers, for a few months. I didn't respond earlier because I haven't used it in years and have no idea on what state the platform is in. Best regards, Peter Bindels
Received on 2026-08-18 22:26:13
