in/out contracts on prototypes

Jonathan M Davis newsgroup.d at jmdavisprog.com
Wed May 16 19:51:55 UTC 2018


On Wednesday, May 16, 2018 12:16:11 Manu via Digitalmars-d wrote:
> So, in/out contracts are cool. They can be used to assert valid value
> ranges for arguments and return values.
> This is useful for proving correctness, and also, this limiting of
> value ranges is information that the optimiser can take and use in
> various optimisations.
>
> I often call to extern C/C++ code, or even to D code built in a static
> lib with a .di as interface.
> Sadly, in/out contracts can not be used and offer no advantage in
> these cases, because calls are  made via function prototypes.
>
> I'm wondering if it should also be possible to apply in/out contracts
> to function prototypes?
> They are usually evaluated in the entry/exit blocks when compiling
> functions, but when applied to prototypes, they would rather need to
> be evaluated immediately before/after the function call in the calling
> code.
>
> Some advantages of this are:
>   - Attributing C/C++ functions with contracts to prove that they're
> called correctly, where calling from C code would otherwise just rely
> on documentation to inform correct arguments.
>   - The optimiser is able to gain value from known valid value ranges,
> even when inlining is not possible (ie, opaque binary interface/libs).
>
> This is kinda neat; we are able to offer a superior experience wrt
> perf and correctness, even when calling C api's! (assuming the author
> of the C binding takes the time to translate the documented argument
> validity to contracts, which feels worth the effort!)

Really, ideally, contracts would be treated as part of the signature and
would be compiled in or not based on the caller and not the callee - e.g.
you shouldn't have to use a debug build of Phobos to get the assertions in
its in and out contracts when you call any of its non-templated functions.
Those assertions are testing the caller, not the function that they're
associated with. As such, they really should be compiled in on the caller
side regardless of any performance considerations. As it is, outside of
classes, contracts don't really buy you anything over simply putting
assertions in the function body.

Unfortunately, I have no idea how easy it would be to move the contracts to
the caller side, and there's the question of how that works with separate
compilation (since presumably at that point, the contracts would be treated
as part of the signature and need to be with the signature, which is not the
case at all right now). But if we could make a change like that, it would
actually make contracts worth something IMHO, whereas right now, I think
that they're mostly pointless, because you can get the same effect with
assertions in the function itself.

This issue pops up every so often, and I expect that it will continue to do
so until we solve it or determine that it's not reasonably feasible, but
someone with the appropriate expertise about the implementation issues is
going to need to write a DIP about it, or all we're likely to do is to talk
about how nice it would be if it happened.

- Jonathan M Davis



More information about the Digitalmars-d mailing list