Defender methods and compatibility

Brian Goetz brian.goetz at oracle.com
Tue Nov 23 11:31:39 PST 2010


Here are our latest thoughts on compatibility promises for various operations 
on extension methods (adding a default to an existing method, adding a new 
method with a default, removing a default from a method, changing a default, etc.)

Our first instinct was to make an analogy with operations on classes.  Consider:

de-abs: Taking an existing abstract method and adding a body
re-abs: Converting a concrete method into an abstract one
add-meth: Adding a new concrete method
rem-meth: Removing a concrete method
mod-meth: Modify the body of a concrete method

Recall that a binary-compatible (BC) change does not prevent linkage with 
pre-existing binaries, while a source-compatible (SC) changes does not prevent 
compilation with pre-existing sources. For example, adding a method to an 
interface is BC (because no pre-existing binary calls the new method), but it 
is not SC (because a pre-existing class declaration that implements the 
interface will now fail to compile).

With BC and SC in mind, the existing rules are:

de-abs: BC, SC
re-abs: not BC, not SC
add-meth: BC, SC*
rem-meth: not BC, not SC
mod-meth: BC, SC

*This would fail to be SC only if it created an invalid overloading, e.g., 
adding a method whose signature is incompatible with a method in a subclass, 
such as adding a method "int foo()" when a subclass has a method "float foo()".

If we consider the operations on interfaces:

add-def: Add a default to an existing non-extension method
rem-def: Remove a default from an extension method
add-extn: Add a new method with a default
rem-extn: Remove a method with a default
mod-extn: Modify the default on an extension method

Ideally, these should be analogous to the existing operations:

add-def is-like de-abs (and therefore hopefully BC/SC)
rem-def is-like re-abs (no compatibility promise)
add-extn is-like add-meth (and therefore hopefully BC/SC)
rem-extn is-like rem-meth (no compatibility promise)
mod-extn is-like mod-meth (and therefore hopefully BC/SC)

These analogies only hold true to a point -- when the modifications create no 
invalid multiple inheritance (i.e., two unrelated interfaces provide the same 
name and signature but different defaults.)  This is the multiple-inheritance 
analogue of the asterisk next to SC for add-meth (creating an invalid 
overloading).  Whereas this is only an issue with add-meth in the existing 
cases, it also becomes an issue for add-def and mod-extn with extension methods.

Here's an example of a change that is not source-compatible:

interface A { extension void m() default X.a }
interface B { }
class C implements A, B { }

// Now change and recompile B only as
interface B { extension void m() default X.b }

The change to B is not source compatible because C can no longer be 
recompiled.  Also, it is not binary compatible because a pre-existing binary 
that calls C.m() is now ambiguous.  So while we hoped that add-extn would be 
BC and SC, it is neither.  (The same goes for add-def and mod-extn, since the 
example can be expressed in terms of adding/modifying defaults.)

However, we can arrange things so that the change to B _becomes_ binary 
compatible.  Observe that if a program can _ever_ be compiled, then it can 
_always_ be made to link.  If we record the initial "known good" configuration 
of A+B+C in C's class file, then binaries that link against A+B+C can be made 
to see no ambiguity even after the new B is introduced, rendering the change 
to B binary compatible.  Only an attempt to recompile C will give an error, 
due to the fundamental source incompatibility introduced by the new B.

The mechanism to record and use a "known good" configuration will be explained 
separately.  The key point is that the familiar guarantee of binary 
compatibility continues to be available, even with strange new multiple 
inheritances due to separate compilation of extension methods.

So we have the desired behavior:

add-def - BC, SC**
rem-def - no compatibility promise
add-extn - BC, SC**
rem-extn - no compatibility promise
mod-extn - BC, SC**

Where the SC** means "providing that the modification does not create the 
situation where a class multiply inherits methods with the same signature but 
different defaults."

While this restriction may be unsatisfying, this is really not all that 
different from the existing SC* behavior of add-meth.




More information about the lambda-dev mailing list