There's been a lot of debate about the inheritance of in contracts, in particular what's supposed to happen if a method in a base class has an in contract and its override doesn't.
http://d.puremagic.com/issues/show_bug.cgi?id=6856

The spec isn't explicit on whether the overridden method retains the base's in contract unchanged or loses its in contract altogether.

Some claim that the absence of an in contract is just syntactic sugar for an empty in contract, in which case the override loses the in contract (can be called with any arguments of the correct types). This is the view taken by DMD.

But others claim that you shouldn't have to specify an in contract in order to inherit the one you already have, and that if you want to remove it altogether then you should have to do it explicitly.

What's more, there's a hole in the current equivalence between no in contract and an empty in contract: in only the former case does the compiler reject an in contract on an override further down the hierarchy. This will want to be fixed if an explicit empty in contract becomes the only way to lift all argument restrictions when overriding a method.


Moreover, there are hijacking vulnerabilities.

http://dlang.org/hijack.html
addresses the danger that a derived class may define a method, and then a later version of the base class coincidentally defines a method with the same name but different semantics. Further problems in this area would ensue if the default behaviour were to pass through the base class's in contract unchanged. Though doing and dusting
http://d.puremagic.com/issues/show_bug.cgi?id=3836
would alleviate this.

Another scenario I've thought of is:
- library class defines a method with an in contract
- application class overrides this method, and has the same argument restrictions as the library class
- a later version of the library class widens the range of acceptable inputs
- however, the app's override is not prepared to deal with inputs that are newly allowed by the API

I don't know if there's a way to deal with this short of doing away with in contract inheritance altogether. Of course, the app programmer could protect against this by duplicating the contract checking in the body of the method, and doing so would even show whether the input to the function was actually outside the range allowed by the API or merely outside the range that the app class's version of the method can deal with. But it's better not to have to duplicate code like this.

But if we avoided this by getting rid of in contract inheritance, it might just lead more programmers to break the inheritance model by forbidding operations on objects of the derived class that are allowed on objects of the base class. I suppose this is a variant of
http://en.wikipedia.org/wiki/Circle-ellipse_problem
It would also get in the way of another proposal I'm inclined to agree with, that anything that calls a method on an object reference of the base class type should be required to adhere to the base class's API, of which the in contract is a part.
http://d.puremagic.com/issues/show_bug.cgi?id=6857
(see also the thread "define in contract according to the caller, not the callee." on this 'group)

Still, is there a good way of dealing with the scenario I've brought up here?


Another thing that's needed for a robust DbC system in D:
http://d.puremagic.com/issues/show_bug.cgi?id=6549

Stewart.

Reply via email to