Cross compilation and default methods

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Apr 4 09:39:32 PDT 2013


I think I've already made clear that

(i) "the current status quo is:" (as in _not set in stone_)
(ii) "I believe this is an area where there's room for improvement" (as 
in _not set in stone_)

But you asked as to why the compiler behaved in a certain odd way, and 
that's your answer :-)

Now, all this won't be covered in any JLSs or JVMs - so this stuff it's 
not, strictly speaking, (well, up to a certain point) subkect to EG 
discussions. But of course we should get our story straight before 
shipping. That said, talking about these issues at this point in time, 
with the libraries, VM and language being still under active (and heavy) 
development, would seem a bit premature - like talking calmly in the 
living room when you know there's water in your basement ;-).

I would suggest to postpone this discussion after feature freeze. Once 
all the language features will have been stabilized, it will become 
clearer as to what the right strategy is in order to support cross 
compilation.

Maurizio

On 04/04/13 17:27, Stephan Herrmann wrote:
> From the perspective of a compiler developer your answers
> are perfectly suitable. IFF you confirm that this behavior is
> going to stay, we'll look into making Eclipse behave similarly.
>
> Once we get bug reports about this, however, we'll need another
> way of explaining, I'm afraid.
>
> > It might be a problem with that particular hierarchy; the following
> > works ok:
>
> That's the kind of answer I'm not planning to give to a user :)
>
> cheers,
> Stephan
>
> On 04/04/2013 06:10 PM, Maurizio Cimadamore wrote:
>> On 04/04/13 16:43, Stephan Herrmann wrote:
>>> Hi Maurizio,
>>>
>>> On 04/03/2013 10:43 AM, Maurizio Cimadamore wrote:
>>>> the current status quo is:
>>>>
>>>> 1) javac reads default methods, regardless of the source/target 
>>>> versions
>>>> used to compile
>>>> 2) a class is allowed to implement an interface and _not_ providing
>>>> implementations for the defaults, regardless of source/target
>>>> 3) default method resolution only kicks in when source = 8 (mainly for
>>>> perfomance/compatibility risks)
>>>> 4) well-formedness checks on defaults (i.e. clashes) are only 
>>>> enabled if
>>>> source = 8
>>>
>>> Thanks.
>>> Unfortunately, I don't see how this explains the following observation:
>>>
>>> compile this at -source 1.8:
>>>
>>>     interface I0 {
>>>       void foo();
>>>     }
>>>     public interface I extends I0 {
>>>       default void foo() { }
>>>       default void bar() { }
>>>     }
>>>
>>> then compile this at -source 1.7:
>>>
>>>     public class C implements I {
>>>       void test() {
>>>         foo();
>>>         bar();
>>>         I i = this;
>>>         i.foo();
>>>         i.bar();
>>>       }
>>>     }
>>>
>>> I get 3 errors:
>>
>> It might be a problem with that particular hierarchy; the following
>> works ok:
>>
>> //compiled with JDK 8
>> interface I {
>> default void m() {}
>> }
>>
>> //compiled with JDK 7
>> class E implements I { }
>>
>>>
>>> C.java:1: error: C is not abstract and does not override abstract
>>> method foo() in I0
>>> public class C implements I {
>>>        ^
>>> C.java:3: error: cannot find symbol
>>>     foo();
>>>     ^
>>>   symbol:   method foo()
>>>   location: class C
>>> C.java:4: error: cannot find symbol
>>>     bar();
>>>     ^
>>>   symbol:   method bar()
>>>   location: class C
>>>
>>> Sorry, if I'm being dense.
>>> I can see that I.foo() is not recognized as implementing I0.foo(), OK.
>>> That situation should probably just be avoided by library designers
>>> to avoid confusion.
>>>
>>> But why can those methods be invoked via 'i' but not via implicit
>>> 'this'? Is this an implementation detail leaking out into observable
>>> behavior? How can this be explained to users?
>> This is a result of the JDK 7 invariant on class well-formedness. If a
>> class is well-formed, a class should contain all required concrete
>> methods implementing corresponding abstract methods in implemented
>> interfaces. This means that javac doesn't even bother looking into
>> interfaces when resolving a method call where the receiver is a concrete
>> class.
>>
>> Maurizio
>>>
>>>
>>>> I believe this is an area where there's room for improvement; things
>>>> like (3) seems to be counterintuitive given that the compiler knows
>>>> about default methods. What has put me off to go ahead and support
>>>> default method resolution with source < 8 is the fact that the new
>>>> resolution algorithm needs to look at more supertypes than the old one
>>>> (i.e. it needs to look at all supertinterface before being able to 
>>>> give
>>>> up). This leads to subtle problems where you need more dependencies on
>>>> your classpath in order to be able to compile a class, as a seemingly
>>>> unrelated interface that was not needed before will suddenly be
>>>> inspected by javac.
>>>
>>> I can see. I don't think users will actually expect full fledged
>>> analysis of default methods in 1.7 mode. Not being blamed about
>>> unimplemented default methods is already good. There has to be a line
>>> beyond which compilation in 1.7 against 1.8 class files tells the
>>> user: sorry, I can't figure this out, please align compiler settings
>>> and versions of class libraries. My main question is: where exactly
>>> will you draw this line? I'd love to see javac and Eclipse drawing
>>> the same line, so can we make this explicit?
>>> From there, each compiler team can figure out how to explain the
>>> situation to the user.
>>>
>>> cheers,
>>> Stephan
>>>
>>>
>>
>



More information about the lambda-spec-observers mailing list