C++ Logo


Advanced search

Re: [wg14/wg21 liaison] P2961R1 syntax for Contracts: viable for C?

From: Martin Uecker <ma.uecker_at_[hidden]>
Date: Fri, 06 Oct 2023 16:53:58 +0200
Am Freitag, dem 06.10.2023 um 16:09 +0300 schrieb Timur Doumler:
> Hi Martin,
> > On 6 Oct 2023, at 08:31, Martin Uecker <ma.uecker_at_[hidden]> wrote:
> >
> > Am Freitag, dem 06.10.2023 um 02:02 +0300 schrieb Ville Voutilainen:
> > > On Thu, 5 Oct 2023 at 20:50, Martin Uecker via Liaison
> > > <liaison_at_[hidden]> wrote:
> > > > > WG21 does not want contract annotations to be ignorable in the same
> > > > > way as attributes (both in terms of allowing an implementation to not
> > > > > support contracts and in terms of not allowing syntactic errors in the
> > > > > arguments to the contract), so that would be a very poor fit.
> > > >
> > > > Ah, right, I forgot that this was a design goal.
> > > >
> > > > (The problem is that this will make it much harder for C projects
> > > > to usefully adopt it.)
> > >
> > > WG14 doesn't necessarily need to set that design goal for itself even
> > > if WG21 might. It's unclear to me whether
> > > that design goal is the right choice for the ecosystem of C.
> >
> > To be honest, I think it is a mistake also for C++. I believe
> > that even for C++ people will end up trying to introduce this into
> > existing code and then are forced to make it ignorable by wrapping it
> > into #ifdef or macros. The end result would neither be nice
> > nor ignorable.
> There is a reason for this design goal. Contracts in C++ cannot be token-ignorable, because that would mean that the entities inside the contract predicate are sometimes parsed and odr-used, but sometimes not parsed and odr-used, and in C++ we have SFINAE so we can branch on whether an entity is odr-used.

Ok, thanks! This makes sense.

But I am trying to anticipate what happens in the future: Won't people
then simply do:

#if ... compiler and version check ...

void foo(int x)
  pre ( x > 0)

This code is then "ignorable" and will be ignored by older compilers
and in that case nothing is even parsed or odr-used.

One can say, this is then the user fault, but what other choice do you
have in reality if you need to support different compilers and versions?

> And an explicit goal of Contracts – the main purpose of which is to detect bugs – is that you should never be able to branch on whether a contract is checked or ignored, because then you could have a bug that cannot be detected by a Contract check – the bug is there when Contracts are off, but as soon as you switch them on to find the bug, your program takes a different branch where the bug is not present, and the bug disappears. We want to make this impossible by design.

This makes sense, but I do not get the connection to "ignorable".
The #ifdef above would encourage compile-time checks
based on support for contracts.

> Therefore you won't be able to do with C++ Contracts what you can do with macro assert in <cassert> today: define NDEBUG and have all the assert macros token-ignored. We want to explicitly ban that case.

Yes, but are you not just forcing people to do exactly this by
creating a syntax they have to put into a preprocessor wrapper?

> You will be able to turn the actual runtime check off, so if you have `pre(expr)`, then `expr` won't be evaluated (for example in Release mode), but you won't be able to turn off the fact that `expr` is still parsed and odr-used.
> I'm not sure if the term "odr-use" makes any sense in C but I hope you still know what I mean. The gist is that Contracts in C++ are not, and never will be, token-ignorable.

And this is fine in theory but it will only work for
completely new projects that start fresh with C++26 with
a new compiler.

And maybe this is just OK for a new C++ features, but I think for
C where old code and existing projects as well as compatiblity
across compiler and language versions is really important.

So I think we need to plan for a transition period. And I do not see
how you can have a transition period for a feature you can not turn
off based on a compiler or language versions.

> So if you're telling me that in C, [[ ... ]] is token ignorable, then that means that we cannot use the [[ ... ]] syntax for Contracts, unless you're OK with Contracts behaving differently in C and C++ in the sense that they can be token-ignored in C but not in C++.
> Please let me know if any of the above isn't clear, I would really like to make sure that we're on the same page here.

Let's see... In any case, thank you for your explanations!


> Cheers,
> Timur

Received on 2023-10-06 14:54:01