Bug 137479 - Problems checking override/hiding rules for LTW of decp
Summary: Problems checking override/hiding rules for LTW of decp
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 1.5.2   Edit
Assignee: Andrew Clement CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-04-19 07:45 EDT by Andrew Clement CLA
Modified: 2006-04-19 11:48 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Clement CLA 2006-04-19 07:45:08 EDT
Errors like this are possible:

info weaving 'com.ibm.ws.classloader.CompoundClassLoader'
info weaver operating in reweavajc -1able mode.  Need to verify any required types exist.
error at com\ibm\ws\classloader\CompoundClassLoader.java::0 The return type is incompatible with java.lang.ClassLoader.access$000()

Where access$000 is static...
Comment 1 Andrew Clement CLA 2006-04-19 07:47:06 EDT
I investigated what was actually going on and although they are both static, static methods have to obey some rules.

From the Java Spec, 8.4.6.2: If a class declares a static method then the declaration of that method is said to hide any and all methods with the same signature in the superclasses.
From 8.4.6.3: If a method declaration overrides or hides the declaration of another method, then a compile-time error occurs if they have different return values or if one has a return type and the other is void.

So, this will fail to compile 

====8<========= A.java ========
import java.util.*;

class A {
  static List foo() { return null; }
}

class B extends A {
  static String foo() { return null; }
}
====8<========= A.java ========

javac A.java
A.java:8: foo() in B cannot override foo() in A; attempting to use incompatible return type
found   : java.lang.String
required: java.util.List

The problem in this failing scenario is that these are synthetic accessor methods and you kind of have 'no control' over what gets created, so let's compile this program:

====8<========= A.java ========
import java.util.*;

class A {
  private static List o;

  static class Inner {
    List foo() { return o; }
  }
}

class B extends A {
  private static String o;

  static class Inner {
    String foo() { return o; }
  }
}
====8<========= A.java ========
Both A and B need a synthetic accessor method created so that 'o' can be reached from the inner type.  If we javap the output, we see:

>javap A
class A extends java.lang.Object{
    A();
    static java.util.List access$000();
}


>javap B
class B extends A{
    B();
    static java.lang.String access$000();
}

You can see the access$000() breaks the rules above but that is OK in this case because the accessors are used locally inside the type - so my fix is to ignore return type compatibility when the methods are synthetic.
Comment 2 Andrew Clement CLA 2006-04-19 07:59:09 EDT
fix committed, waiting on build.
Comment 3 Andrew Clement CLA 2006-04-19 11:48:26 EDT
build available.