Hi everyone,
Thanks again for all your feedback on this thread, this is immensely helpful input.
So far, the discussion has exclusively focused on `pre` and `post`, which are part of a function declaration, but we also have a third type of contract, `assert` which is a statement or expression inside a function body.
The P2935 (attribute-like) syntax spells them as follows,
void f() {
int i = get_i();
[[ assert: i >= 0 ]]; // this is a contract assert
// ...
}
The P2961 syntax would really, really like to spell them as follows:
void f() {
int i = get_i();
assert (i >= 0); // this is a contract assert
// ...
}
But of course we can't use `assert` because that already has a meaning today (the `assert` macro from "assert.h") and that meaning cannot be made incompatible with contract asserts. In particular, macro assert is token-ignored if NDEBUG is defined, whereas contact asserts are never, and can never be, token-ignored – you can switch the contract semantic to "unchecked" so that the expression is not evaluated at runtime, but it still needs to be parsed – and therefore it still needs to be correct code, and so existing code like this can never work with Contracts:
#ifndef NDEBUG
DebugThingy dbg;
#endif
void f() {
assert(dbg.checkSomething()); // OK with macro, syntax error with contract if NDEBUG not defined
// ...
}
Long story short, we decided that if we want to adopt the P2961 syntax, we cannot use the keyword "assert" because we cannot replace the existing assert macro by Contracts due to the differences in semantics and the resulting code breakage. So we grudgingly realised that if we decide to go down the P2961 route, we need to pick a different keyword which is not "assert". Two candidate keywords are currently under discussion:
contract_assert
and
assertexpr
Does any of this raise any concerns with C? If we want a Contracts facility in C compatible with C++, we need to deal with assertions as well, not just pre and post. Does this change anyone's opinion on whether you'd prefer the C++ committee to adopt the P2935 (attribute-like) syntax or the P2961 syntax?
Cheers,
Timur
On 5 Oct 2023, at 18:09, Aaron Ballman <aaron@aaronballman.com> wrote:
On Thu, Oct 5, 2023 at 7:58 AM Timur Doumler via Liaison<liaison@lists.isocpp.org> wrote:
Hello SG22,
In SG21 (Contracts), we have been discussing the syntax for preconditions, postconditions, and assertions which will be part of the new Contracts facility we're designing for C++26. We currently have two syntax proposals on the table – we have not yet decided which one we prefer.
One is the attribute-like syntax which you might have already seen (see P2935R3). With this syntax, a function declaration with a precondition and a postcondition looks like this:
int f(int i)
[[ pre: i >= 0 ]]
[[ post r: r > i ]];
The other is a newer proposal that seeks to eliminate the various issues with attribute-like syntax we discovered (see P2961R1, which I am co-authoring together with Jens Maurer, in Cc). The P2961R1 syntax looks like this:
void f(int i)
pre (i >= 0)
post (r: r > i);
At the last SG21 telecon, the question has been raised whether the P2961R1 syntax would be compatible with C, in case C wishes to standardise a Contracts facility consistent with the C++ one. As the main paper author of P2961R1, I was directed to ask WG14 about their opinion and report back to SG21.
However, I have been informed by Ville (in Cc) that WG14 is currently doing a ballot, that the WG14 Convener is adamant about having as little as possible technical discussion during a ballot, and that discussing a future proposal on the WG14 reflector would therefore be inappropriate at this time.
So, if you don't mind, I'm going to try my luck with SG22 instead. Do any of you folks have any desire to standardise Contracts for C, to have a syntax for this that looks like the C++ one, and do you have any technical concerns about the syntax proposed in P2961R1?
Any and all feedback would be greatly appreciated.
Thank you for reaching out!I am personally *very* motivated to see Contracts get into C; I thinkthe functionality is incredibly important for a whole host of reasonsthat I probably don't need to convince you of. :-D I really appreciateall efforts to come up with syntax & semantics that can work for bothC and C++ because I would love to get to a day where the OS headersand C standard library headers can provide contracts that the STL cantake advantage of as well. Getting as much of the source code stack tosupport contracts as possible seems like a good goal to strive for.The syntax that looks like `[[ pre: expr ]]` is a problem in Ccurrently. [[ always introduces an attribute specifier list currently,and we have an allowance for implementations to eat balanced tokensbetween the double square brackets. While it may be possible to changethis rule, it should be noted that the rule was introduced at therequest of several implementers of C and the decision was recentlyreaffirmed by the committee during NB comment resolution for C23, so Iwould expect that to be contentious. IMO, even in C++ only, claimingthat it's not an attribute because of the presence of a single colonis not compelling rationale to me -- users already understand thatanything between [[]] is an attribute and trying to change that to be"could be an attribute or it could be something entirely differentfrom attributes" is going to be confusing and cause problems inpractice.The syntax that looks like `pre (i >= 0)` is slightly problematic in Cin that it's using an unreserved identifier. However, I think that'spretty easy to work around by introducing it as `_Pre` in C andproviding something like a `<stdcontracts.h>` with a macro so you canget the `pre` spelling in header code shared between C and C++. Then,10+ years later, we can deprecate the ugly reserved keyword in C useand start using the prettier keyword. (We did this in C23 withnumerous earlier-C keywords like `_Bool`, `_Alignas`, `_Thread_local`,etc.) C doesn't really have the notion of conditional keywords, so Idon't think that will be an option for us (especially because we'dstill have to worry about macros named `pre`:https://sourcegraph.com/search?q=context:global+%28%23define+pre%29%5B+%5Ct%5D%2B&patternType=regexp&case=yes&sm=1&groupBy=repoand https://sourcegraph.com/search?q=context:global+%28%23define+post%29%5B+%5Ct%5D%2B&patternType=regexp&case=yes&sm=1&groupBy=reposhow there are such uses in the wild).Because contracts are not intended to be an optional feature animplementation can support at its discretion, I greatly prefer thesyntactic direction from P2961R1 over the syntax from P2935R3. Even inC++, I think it's a superior way to surface the functionality becauseit doesn't attempt to redefine existing syntax for new,similar-but-not-actually-the-same kinds of functionality.~Aaron
Thanks,
Timur
_______________________________________________
Liaison mailing list
Liaison@lists.isocpp.org
Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/liaison
Searchable archives: http://lists.isocpp.org/liaison/2023/10/index.php