Date: Sun, 8 Oct 2023 19:22:47 +0300
Hi Ville and Martin,
We have the same debate within SG21 as well – some people argue that contracts should be seen as ignorable in the way you describe, other people argue they shouldn't be. I don't think there is really a right or wrong here. The way you see Contracts will depend on how you intend to use Contracts or what you think they should be used for, and the opinion on that varies substantially depending on whom you ask (and that's exactly what makes this feature so especially challenging to design!)
For example, if your intent is to unit-test precondition failures ("negative testing") – and there are people for whom this is important – then the view that "Contracts are ignorable in a correct program" where "correct program" means "program without Contract violations" is not helpful at all because you're actually relying on well-defined behaviour for the case where you contracts *are* violated and you certainly can't have Contracts be ignored if you want those tests to pass. But at the same time, other people don't want to do such things, and/or they say that you shouldn't do them or shouldn't depend on such behaviour.
Ultimately, our responsibility is to the users of the language, so IMHO we should pick whatever solution provides the most value for the most users.
In any case, even if we don't agree on everything 100%, I think we have identified some important tradeoffs and insights in this design space that haven't been discussed before, so I'm very grateful for having learned something here, and I'll make sure to add a summary of this discussion to the next revision of P2961. Thanks you so much for providing your point of view and explaining it so patiently!
Cheers,
Timur
> On 8 Oct 2023, at 17:13, Ville Voutilainen <ville.voutilainen_at_[hidden]> wrote:
>
> On Sun, 8 Oct 2023 at 16:41, Martin Uecker <ma.uecker_at_[hidden]> wrote:
>>> To me, this compromise sounds doable, consistent with what we've done before for other features shared between C and C++, and still better than using [[ ... ]] which apparently in C has the
>>> notion of "this is token-ignorable". At least for newer compilers that know about Contracts, token-ignoring Contracts is not something that I would want to allow or encourage. Attributes in
>>> C are all either for enabling/disabling warnings or for giving optimisation hints to the backend. Contracts are not like that at all. They are a core language feature and there is nothing
>>> "optional" about them – in the sense that an implementation shouldn't be allowed to just not implement them and still be conforming.
>>>
>>> Anyway, I hope this makes sense, but if I'm missing something please let me know!
>>
>> I still like to comment on this last point and why I am
>> not convinced by it.
>>
>> First, whether a new implementation is allowed to ignore
>> them or not, is a matter of standardization and not of
>> syntax: If the standard says it can be ignored it can
>> be ignored and it says it cannot ignored, then it cannot
>> be ignored by a conforming implementation.
>>
>> Second, attributes are ideally suited and would solve all
>> the technical issues related to backwards compatibility
>> we discussed here in a nice way. The would also have
>> no risk, as we can always invent new syntax later.
>> In contrast, introducing new syntax now has a huge risk
>> and opportunity cost.
>>
>> Finally, I think from a perspective of semantics, attributes
>> are also an excellent fit: Contracts are annotations that
>> - when removed from a correct program - should not change its
>> semantics. For me, this makes them seem more similar to
>> other annotations (as expressed by attributes) than to other
>> language constracts. For me, the use of attributes for all
>> such annotations would make a lot of sense. This would be
>> easy to explain and teach and work with.
>
>
> For what it's worth, the remarks about contract ignorability don't
> convince me either. I can live with it just fine
> if C++ compilers are not allowed to ignore contract annotations, but I
> don't see a theoretical or a practical
> need to impose the same requirement on C compilers. We have four C++
> compilers to worry about,
> and all of them seem capable of strictly implementing the same rules
> in this area, that they won't ignore
> contract annotations and will diagnose syntax errors in them.
>
> There's many more C compilers, and some of them are.. ..for the lack
> of a better word, smaller-scale.
> Some of them might be geared for use cases and audiences where
> implementing contracts is a significant
> burden without much added value. So allowing such implementations to
> ignore contract annotations
> would make their implementers' lives easier.
>
> And, again, for manyeth time: the sky will not fall if someone
> develops a library that I really want to use,
> but compiles it only ever with a C compiler that ignores contract
> annotations. Once I compile it with an implementation
> that syntax-checks contract annotations, I can report back bugs, if any.
>
> That scenario is rather unlikely, and it's quite likely that code that
> I want to use with contract annotation syntax
> checks on will already have been compiled with a compiler that doesn't
> ignore contract annotations.
>
> In other words, insisting that C compilers shouldn't be allowed to
> ignore contract annotations because C++ compilers aren't
> has
> A) seemingly remotely plausible downsides for contract users
> B) and therefore remotely plausible upsides for contract users
> C) some highly plausible downsides for implementers of simplistic C compilers
> D) and likely no upsides for those implementers
>
> The combination of that is that I don't see the point of insisting on
> it. The only people who will notice this in practice
> are the compiler implementers who have a choice between suffering a
> burden of implementing something they see
> no use for, and being non-conforming. The users mentioned in A/B will
> not see this problem in practice, or in the
> rare case where they do, fixing it should be fairly simple and quick
> and is 100% compatible with a C compiler
> that ignores contract annotations.
>
> And, after all, a 100% conforming C++ implementation could say "yes, I
> implement C++ contracts, but the only semantic
> available is 'ignore', so I'll never perform a run-time check of a
> contract nor will I invoke a violation handler". All in all,
> it doesn't add much that such an implementation will syntax-check a
> contract annotation, when using such an implementation
> doesn't otherwise result in the contract annotations having any
> effect, other than language-lawyering ones such as ODR-using
> the entities named in the annotations.
We have the same debate within SG21 as well – some people argue that contracts should be seen as ignorable in the way you describe, other people argue they shouldn't be. I don't think there is really a right or wrong here. The way you see Contracts will depend on how you intend to use Contracts or what you think they should be used for, and the opinion on that varies substantially depending on whom you ask (and that's exactly what makes this feature so especially challenging to design!)
For example, if your intent is to unit-test precondition failures ("negative testing") – and there are people for whom this is important – then the view that "Contracts are ignorable in a correct program" where "correct program" means "program without Contract violations" is not helpful at all because you're actually relying on well-defined behaviour for the case where you contracts *are* violated and you certainly can't have Contracts be ignored if you want those tests to pass. But at the same time, other people don't want to do such things, and/or they say that you shouldn't do them or shouldn't depend on such behaviour.
Ultimately, our responsibility is to the users of the language, so IMHO we should pick whatever solution provides the most value for the most users.
In any case, even if we don't agree on everything 100%, I think we have identified some important tradeoffs and insights in this design space that haven't been discussed before, so I'm very grateful for having learned something here, and I'll make sure to add a summary of this discussion to the next revision of P2961. Thanks you so much for providing your point of view and explaining it so patiently!
Cheers,
Timur
> On 8 Oct 2023, at 17:13, Ville Voutilainen <ville.voutilainen_at_[hidden]> wrote:
>
> On Sun, 8 Oct 2023 at 16:41, Martin Uecker <ma.uecker_at_[hidden]> wrote:
>>> To me, this compromise sounds doable, consistent with what we've done before for other features shared between C and C++, and still better than using [[ ... ]] which apparently in C has the
>>> notion of "this is token-ignorable". At least for newer compilers that know about Contracts, token-ignoring Contracts is not something that I would want to allow or encourage. Attributes in
>>> C are all either for enabling/disabling warnings or for giving optimisation hints to the backend. Contracts are not like that at all. They are a core language feature and there is nothing
>>> "optional" about them – in the sense that an implementation shouldn't be allowed to just not implement them and still be conforming.
>>>
>>> Anyway, I hope this makes sense, but if I'm missing something please let me know!
>>
>> I still like to comment on this last point and why I am
>> not convinced by it.
>>
>> First, whether a new implementation is allowed to ignore
>> them or not, is a matter of standardization and not of
>> syntax: If the standard says it can be ignored it can
>> be ignored and it says it cannot ignored, then it cannot
>> be ignored by a conforming implementation.
>>
>> Second, attributes are ideally suited and would solve all
>> the technical issues related to backwards compatibility
>> we discussed here in a nice way. The would also have
>> no risk, as we can always invent new syntax later.
>> In contrast, introducing new syntax now has a huge risk
>> and opportunity cost.
>>
>> Finally, I think from a perspective of semantics, attributes
>> are also an excellent fit: Contracts are annotations that
>> - when removed from a correct program - should not change its
>> semantics. For me, this makes them seem more similar to
>> other annotations (as expressed by attributes) than to other
>> language constracts. For me, the use of attributes for all
>> such annotations would make a lot of sense. This would be
>> easy to explain and teach and work with.
>
>
> For what it's worth, the remarks about contract ignorability don't
> convince me either. I can live with it just fine
> if C++ compilers are not allowed to ignore contract annotations, but I
> don't see a theoretical or a practical
> need to impose the same requirement on C compilers. We have four C++
> compilers to worry about,
> and all of them seem capable of strictly implementing the same rules
> in this area, that they won't ignore
> contract annotations and will diagnose syntax errors in them.
>
> There's many more C compilers, and some of them are.. ..for the lack
> of a better word, smaller-scale.
> Some of them might be geared for use cases and audiences where
> implementing contracts is a significant
> burden without much added value. So allowing such implementations to
> ignore contract annotations
> would make their implementers' lives easier.
>
> And, again, for manyeth time: the sky will not fall if someone
> develops a library that I really want to use,
> but compiles it only ever with a C compiler that ignores contract
> annotations. Once I compile it with an implementation
> that syntax-checks contract annotations, I can report back bugs, if any.
>
> That scenario is rather unlikely, and it's quite likely that code that
> I want to use with contract annotation syntax
> checks on will already have been compiled with a compiler that doesn't
> ignore contract annotations.
>
> In other words, insisting that C compilers shouldn't be allowed to
> ignore contract annotations because C++ compilers aren't
> has
> A) seemingly remotely plausible downsides for contract users
> B) and therefore remotely plausible upsides for contract users
> C) some highly plausible downsides for implementers of simplistic C compilers
> D) and likely no upsides for those implementers
>
> The combination of that is that I don't see the point of insisting on
> it. The only people who will notice this in practice
> are the compiler implementers who have a choice between suffering a
> burden of implementing something they see
> no use for, and being non-conforming. The users mentioned in A/B will
> not see this problem in practice, or in the
> rare case where they do, fixing it should be fairly simple and quick
> and is 100% compatible with a C compiler
> that ignores contract annotations.
>
> And, after all, a 100% conforming C++ implementation could say "yes, I
> implement C++ contracts, but the only semantic
> available is 'ignore', so I'll never perform a run-time check of a
> contract nor will I invoke a violation handler". All in all,
> it doesn't add much that such an implementation will syntax-check a
> contract annotation, when using such an implementation
> doesn't otherwise result in the contract annotations having any
> effect, other than language-lawyering ones such as ODR-using
> the entities named in the annotations.
Received on 2023-10-08 16:22:51