Thread overview
Re: in/out contracts on prototypes
May 16, 2018
Jonathan M Davis
May 16, 2018
Manu
May 16, 2018
Jonathan M Davis
May 16, 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

May 16, 2018
On Wed., 16 May 2018, 12:52 pm Jonathan M Davis via Digitalmars-d, < digitalmars-d@puremagic.com> wrote:

> 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
>

This is exactly the type of issue where the new dip system is really impotent, and a disadvantage compared to the prior process.

For something like this where it would be nice but it doesn't block anyone,
nobody will ever take the time to write a dip.
It should just be fixed by someone who knows how to do it. I'm sure it's
not even slightly controversial.

I miss Kenji!

>


May 16, 2018
On Wednesday, May 16, 2018 14:03:50 Manu via Digitalmars-d wrote:
> On Wed., 16 May 2018, 12:52 pm Jonathan M Davis via Digitalmars-d, <
>
> digitalmars-d@puremagic.com> wrote:
> > 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.
>
> This is exactly the type of issue where the new dip system is really impotent, and a disadvantage compared to the prior process.
>
> For something like this where it would be nice but it doesn't block
> anyone, nobody will ever take the time to write a dip.
> It should just be fixed by someone who knows how to do it. I'm sure it's
> not even slightly controversial.

I don't think that the current DIP process really impedes anything here. The core problem is that someone who knows enough to be able to actually design and implement the solution needs to step up and do it. I don't think that whether that includes writing a DIP in addition to implementing it is all that relevant. The core problem is that someone needs to step up and do it, and as with far too much around here, no one who is capable of doing so has done so. And since this _is_ the sort of issue that's unlikely to be a real pain point, it's not necessarily very likely that anyone is going to step up and do it, so almost inevitably, stuff like this gets done because it's a pain point for someone. The simple fact that most of us agree that something should be done is rarely sufficient motivation in and of itself.

> I miss Kenji!

Yeah. It would be nice if he were still around. Certainly, he'd be one of the folks with the expertise to figure this one out.

- Jonathan M Davis