Thoughts about in contract inheritance

Timon Gehr timon.gehr at
Wed Feb 29 06:44:07 PST 2012

On 02/29/2012 03:06 PM, Stewart Gordon wrote:
> 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.
> The spec isn't explicit on whether the overridden method retains the
> base's in contract unchanged or loses its in contract altogether.

The front page of the web site is quite explicit about this:

// Interfaces and classes
interface Printable {
     void print(uint level)
     in { assert(level > 0); } // contract is part of the interface

// Interface implementation
class Widget : Printable {
     void print(uint level) { ... } // <-- assumed to inherit contract

// Single inheritance of state
class ExtendedWidget : Widget {
     override void print(uint level)
     in { /* weakening precondition is okay */ } body { // <-- see here!
          ... level may be 0 here ...

Anyway, probably it is not stated explicitly in the relevant parts of 
the spec because it is assumed that the reader is familiar with similar 
features in other languages.

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

This is the bug in 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.
> 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.

Not at all. If anything, it would alleviate the issue. Likely, assertion 
failures would be introduced that show that there is a consistency 
problem in the application.

> Though doing and dusting
> 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
> ...

This is not a contract-related problem. It is a breaking API change, 
whether or not the library class defines language level contracts.

> But if we avoided this by getting rid of in contract inheritance,

If we want to avoid this we'd have to get rid of inheritance altogether, 
not just contract inheritance. A contract always has a corresponding 

> 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
> 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.
> (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?

Library writers shouldn't silently change functionality and/or redefine 
interfaces. The new stuff should be introduced under a different name 
and the old name should be deprecated. (As an inferior alternative, the 
library user could just read the change log and notice that there is now 
a problem.)

Anyway, this second scenario has a similar severity under the current 
contract inheritance behavior in DMD 2.058 and the right inheritance 
behavior in a future version of DMD.

> Another thing that's needed for a robust DbC system in D:
> Stewart.

More information about the Digitalmars-d mailing list