C++ Logo


Advanced search

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

From: Timur Doumler <cpp_at_[hidden]>
Date: Sat, 7 Oct 2023 12:24:16 +0300
To clarify:

In C++, even if we go with the "function-like" P2961 syntax, we can't make contracts always look like function-like macros. Yes, the most basic contracts indeed look syntactically like function calls or function-like macros:

pre (x != 0)

Then we have postconditions that name the return value. This already doesn't look like a function call anymore because of the colon. Maybe this still qualifies as valid function-like macro syntax? I'm not sure:

post (ret: ret != 0)

And then we have a number of extensions which we already know we want to standardise for C++ after we get the initial, basic version through (which we call the "Contracts MVP"). All of these post-MVP extensions are *not* compatible with function-like macro syntax.

For example, we need the ability to annotate a contract with multiple labels simultaneously. The exact syntax is to be decided, but if we go for P2961 rather than P2935 then it could be something like

pre <audit, new> (x != 0)

or perhaps

pre (x != 0) [audit, new]

In any case, you cannot absorb these labels into a single keyword and make the whole thing functional-macro-like, unless you want a combinatorial explosion of keywords.

We will further have labels that take parameters, such as

pre <audit_level(3)> (x != 0)

There is no way to do this with a function-like macro syntax as far as I can see.

And then we want to introduce captures for contracts, which would work similar to lambda captures. They allow you to do things like "remembering" a value at the point when the function begins and then use that value in a postcondition that is evaluated when the function returns, for example

void increment_size()
  post [old_size = size()] (size() == old_size + 1);

There are more such planned extensions; if you're curious, please check out P2755 <https://wg21.link/p2755>.

Perhaps, for C you will never want to adopt any of these extensions, and that's fine. But I think it's important to mention that at least in C++, they will come. Having a syntax for contracts that is fully compatible with function-like macro syntax is therefore just as much a non-goal for us as having a syntax for contracts that is fully compatible with attribute syntax, or having a syntax for contracts that is compatible with any other existing feature. That's not what we're going for in C++. Contracts are a new language feature and like any new language feature they will have a new, not backwards-compatible syntax in C++, one way or another (whether we adopt P2935 or P2961). The only question here — why I started this thread — is which of these syntaxes would create fewer problems for C.

Hope that makes sense?

Please let me know if you have any further thoughts on this. Thanks!


> On 6 Oct 2023, at 21:40, Martin Uecker <ma.uecker_at_[hidden]> wrote:
> Am Freitag, dem 06.10.2023 um 14:14 -0400 schrieb Aaron Ballman:
>> On Fri, Oct 6, 2023 at 2:00 PM Martin Uecker <ma.uecker_at_[hidden]> wrote:
>>> Am Freitag, dem 06.10.2023 um 13:57 -0400 schrieb Aaron Ballman via Liaison:
>>>> On Fri, Oct 6, 2023 at 12:56 PM Timur Doumler <cpp_at_[hidden]> wrote:
>>>>> OK, thanks, I understand that argument now.
>>>>> I am not sure though if it makes much sense to design our syntax around that, given that we *already* know we can't (and don't want to) achieve this kind of seamless backwards-compatibility in C++, and by extension in any code shared between C and C++, so only codebases in pure C would benefit from such a possibility. And you won't get backwards-compatibility with older compilers, only with newer compilers in "old standard" mode, because every existing compiler I'm aware of rejects the colon between [[...]] as a syntax error today.
>>>>> However, my understanding is that with either of the syntax proposals, we would be able to achieve backwards-compability with older compilers via wrapping the whole feature in macros, in exactly the same way we do for other new features that add new syntax.
>>>>> I am really interested whether anyone here has a preference for one syntax and against the other for any other reason that does *not* have to do with ignorability?
>>>> I strongly prefer the syntax that looks like a function-like macro
>>>> over the syntax that looks like an attribute. I think it eases
>>>> portability, especially when compiling newer source code with an older
>>>> implementation. I don't think we should be making the user scan for
>>>> whether there's one colon or two colons to know what language feature
>>>> they're using. I think constructs like lambdas can already look quite
>>>> noisy with their balanced delimiters and this introduces another
>>>> instance of that. Also, it helps this confusion by making it more
>>>> visually distinct:
>>>> void func(int i) <Which comes first: type attributes or contracts?>;
>>>> While users still need to know which order to put things in because we
>>>> don't allow interleaving there, at least they're not trying to
>>>> remember how to order two things both using [[]] syntax.
>>> I think function-like macros were not proposed. But I would also
>>> prefer this.
>> Heh, sorry for being unclear, I didn't mean to imply it was actually a
>> function-like macro under the hood. I meant `pre(operand)` where the
>> syntax looks like a function call or function-like macro invocation.
> Yes, I was also not clear. I think it would be fine if it
> is fixed to always be like a function-like macro and
> not have the [] <> prefixed versions, and it it ideally
> had a longer name that we can make a true keyword later.
> Martin
>> ~Aaron
>>> Martin
>>>> ~Aaron
>>>>> Cheers,
>>>>> Timur
>>>>>> On 6 Oct 2023, at 19:35, Jens Maurer <jens.maurer_at_[hidden]> wrote:
>>>>>>> On 06/10/2023 18.32, Timur Doumler wrote:
>>>>>>>> On 6 Oct 2023, at 19:28, Jens Maurer <jens.maurer_at_[hidden]> wrote:
>>>>>>>>> If that is indeed the case, then the attribute-like syntax for Contracts would not be ignorable in C, either.
>>>>>>>> Right, but the argument is that implementations can add the small extension
>>>>>>>> to parse-ignore ":" in that spot right now, and then be future-proof for
>>>>>>>> ignoring future attribute-like contracts.
>>>>>>> Right. Yes, I can follow that argument. But that begs the question: what is so special or different about Contracts that you want this feature in particular to be backwards-compatibly-ignorable by older compilers, considering that we don't do that for any other new language feature where we add new syntax to the language?
>>>>>> The argument, as far as I understand, is that contracts in particular are well
>>>>>> suited to be retrofitted on existing code bases that need to be compatible
>>>>>> with older compilers / language versions.
>>>>>> For any other new language feature, you can just choose to ignore it for your
>>>>>> meant-to-be-compatible code base. But contracts are so valuable to find
>>>>>> bugs in existing software, so you want them everywhere ASAP.
>>>>>> (I'm just repeating an argument I think I heard. This is not my opinion.)
>>>>>> Jens
>>>> _______________________________________________
>>>> Liaison mailing list
>>>> Liaison_at_[hidden]
>>>> Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/liaison
>>>> Link to this post: http://lists.isocpp.org/liaison/2023/10/1274.php

Received on 2023-10-07 09:24:20