DIP 1009--Improve Contract Usability--Preliminary Review Round 1

Moritz Maxeiner via Digitalmars-d digitalmars-d at puremagic.com
Wed Jun 21 04:53:35 PDT 2017


On Wednesday, 21 June 2017 at 09:10:33 UTC, MysticZach wrote:
> On Wednesday, 21 June 2017 at 05:19:26 UTC, H. S. Teoh wrote:
>> On Wed, Jun 21, 2017 at 01:06:40AM +0000, MysticZach via 
>> Digitalmars-d wrote:
>>> On Tuesday, 20 June 2017 at 21:04:16 UTC, Steven 
>>> Schveighoffer wrote:
>>> > This is much much better. The verbosity of contracts isn't 
>>> > really the brace, it's the asserts.
>>> 
>>> I think it's both, and I think the brace is the only thing 
>>> that can be improved upon. How could you justify insisting 
>>> that everyone use the built-in asserts for their contracts?
>> [...]
>>
>> Umm... I think we're not quite on the same page here.  What 
>> *else* are people supposed to use inside their contracts 
>> besides the built-in assert??
>
> Many people have expressed discontent with existing asserts. In 
> fact, they were just changed yesterday to address one of these 
> concerns:
>
> https://github.com/dlang/dmd/pull/6901

Just my two cents, again: DbC prohibits broken contracts, i.e. 
any violation is a bug. From my point of view, a broken contract 
in the simple syntax as proposed by H.S.Teoh, should by default
- in debug mode: Give you debug information (stack trace, etc.) 
then terminate
- in release mode: Print file and line number and then terminate
No cleanup by default.

People I've observed voicing issues with assert have happened to 
fall into one of these three categories:

- People who agree with the terminate approach, but want custom 
cleanup

I remain skeptical about the sanity of calling arbitrary code 
with the knowledge of a previously triggered bug (in release 
mode), but that can be easily addressed by allowing to register a 
hook that gets called on contract violations; the process will 
still terminate after the hook is finished, though.

- People whose use cases (allegedly) allows recovery of bugs

I would consider these as niche cases that are already covered by 
the preexisting verbose syntax: `in { if (!cond) throw 
Exception(); }`. I would simply not include support for that in 
the easy-to-read variant.

- People who use assert (or other Errors) for user input 
validation

That's not what they are for.

To sum it up, I would like semantics similar to this (simplified) 
code for this syntax:

---
void delegate() nothrow onContractViolation;

template validateContract(T) if (isInputContract!T || 
isOutputContract!T)
{
     version (ValidateContracts) void violated(ref T contract)
     {
         import core.stdc.stdlib : _Exit;

         debug printDebugInfo(contract);
         else  printFileAndLIne(contract);

         if (onContractViolation !is null) onContractViolation();

         _Exit(1); // without scope guard since 
onContractViolation is `nothrow`
     }

     static if (isInputContract!T) {
         void validateContract(T contract)
         {
             version (ValidateContracts) if (!contract) 
violated(contract);
         }
     } else {
         void validateContract(T contract, T.ResultType result)
         {
             version (ValidateContracts) if (!contract(result)) 
violated(contract);
         }
     }
}
---


More information about the Digitalmars-d mailing list