Miranda methods and Methods added by Code Generators
Andrew Dinn
adinn at redhat.com
Mon Aug 9 01:50:53 PDT 2010
Hi Maurizio,
On 08/07/2010 06:39 PM, maurizio cimadamore wrote:
> the compiler internally uses the IPROXY flag to mark Miranda methods:
>
> 146 /** Flag is set for compiler-generated abstract methods that implement
>
> 147 * an interface method (Miranda methods).
>
> 148 */
>
> 149 public static final int IPROXY = 1<<21;
>
>
> The code you are looking at discards SYNTHETIC methods because this
> method is meant to return an user-defined implementation of a given
> method symbol in a given class - and a SYNTEHTIC method is, by
> definition, not a user-defined method. This check turns out particularly
> useful when the class contains one or more bridge methods (the method
> that javac has to emit to preserve overriding in the face of type-erasure).
>
> In other words, javac is not complaining because it thinks that
> getAdvisor() is a Miranda method - it just complains because it sees a
> class not overriding all methods from its superinterfaces.
Yes, I noted that javac adds the IPROXY method attribute to any Miranda
methods it generates during the compile. But in this case I am referring
to a Miranda method generated during a previous compile then written to
the bytecode file for the class. Are you sugesting that Miranda methods
do not get written to the abstract class's bytecode file? As far as I
coudl tell they are written out as ABSTRACT SYNTHETIC methods but
without the IPROXY attribute (this attribute is private to javac).
Anyway, your comment merely provides an account of why the check is made
but this does not really address its validity. You are absolutely right
that in the circumstances I highlighted the purpose of the check is to
see whether the class has overridden all methods inherited from its
superinterfaces. Well, in this case the answer is that the class is
valid and the check is wrong. The situation is as follows. We have a
POJO class parent
abstract class Parent {
public abstract Foo getFoo();
. . .
}
AOP transforms this class as follows
abstract class Parent implements Advised {
// synthetic method added by AOP
public Advisor getAdvisor() {
. . .
}
public abstract Foo getFoo();
. . .
}
interface Advised {
public Advisor getAdvisor()
}
The bytecode file for this class contains an implementation of
getAdvisor() but it is tagged with the SYNTHETIC attribute.
Now we define a class Child as follows
class Child extends Parent {
public Foo getFoo() {
. . .
}
Now javac is asked to compile Child and the AOP transformed bytecode for
Parent is placed in the class path. javac complains that Child does not
implement getAdvisor(). Well, it does not need to because the
transformed code for Parent implements it. The immediate reason why the
parent implementation of getAdvisor() is discounted is because the
generated code for getAdvisor() is SYNTHETIC and the check I highlighted
ignores SYNTHETIC methods.
Now you may be right that this is nothing to do with Miranda methods. I
cannot really look into the minds of whoever originally designed the
code in order to argue a case. But javac is plainly wrong in stating
that Child does not have an implementation for getAdvisor(). This method
is defined by Parent and has perfectly valid, executable code. So, Child
ought to inherit this implementation.
In fact when Parent is not an abstract class the SYNTHETIC code is
inherited and executed without any problem. It is only in the case where
the parent is abstract that this issue arises (I'll just note that this
is because the check is only made when there may be Miranda methods to
look for). So, irrespective of motive can you explain to me why it is
correct to disregard this SYNTHETIC implementation?
regards,
Andrew Dinn
-----------
More information about the compiler-dev
mailing list