Bug 145391 - [generics] Call generic method from within inter-type method: NoSuchMethodError
Summary: [generics] Call generic method from within inter-type method: NoSuchMethodError
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.5.0   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 1.6.2   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-06-05 13:37 EDT by Michael Herrmann CLA
Modified: 2008-08-20 16:49 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Herrmann CLA 2006-06-05 13:37:55 EDT
Compiling and running the following code:

public class GenericType<V extends Integer> {

	public GenericType(V value) {}

	public void foo() {}

	public void bar() {}

	protected V getValue() {
		return null;
	}

	public static void main(String[] args) {
		new GenericType<Integer>(null).foo();
	}

}

aspect SomeAspect {
	before(GenericType t): call(* GenericType.foo()) && target(t) {
		// Direct call to non-generic method works
		t.bar();
		// Indirect call to non-generic method works
		t.callNormalMethod();
		// Direct call to generic method works
		t.getValue();
		// Indirect call to generic method produces a NoSuchMethodError
		t.callGenericMethod();
	}

	private void GenericType.callNormalMethod() {
		bar();
	}

	private void GenericType.callGenericMethod() {
		getValue();
	}
}

produces the following error:

Exception in thread "main" java.lang.NoSuchMethodError: GenericType.ajc$protecte
dDispatch$GenericType$getValue()Ljava/lang/Integer;
        at SomeAspect.ajc$interMethod$SomeAspect$GenericType$callGenericMethod(G
enericType.java:34)
        at GenericType.ajc$interMethodDispatch2$SomeAspect$callGenericMethod(Gen
ericType.java:1)
        at SomeAspect.ajc$interMethodDispatch1$SomeAspect$GenericType$callGeneri
cMethod(GenericType.java)
        at SomeAspect.ajc$before$SomeAspect$1$f6d0c54(GenericType.java:26)
        at GenericType.main(GenericType.java:14)

in versions 1.5.0, 1.5.1a and the current development version. The bug also occurs if V is declared as <V extends java.util.EventListener>, but does not occur is V is declared as <V extends Object> (I haven't tried anything else).
Comment 1 Andrew Clement CLA 2006-06-06 04:11:27 EDT
thanks for the clear bug report and test program.

the erasure of the method invoked by the ITD is being lost during (de)serialization.  Leaving us with a 'V extends Object' return value which is incorrect.
Comment 2 Andrew Clement CLA 2006-06-06 06:37:52 EDT
this related case is also a problem:  (typevar as parameter rather than return type)

public class GenericType2<V extends Integer> {

        public GenericType2(V value) {}

        public void foo() {}

        protected void getValue(V aV) {
        }

        public static void main(String[] args) {
                new GenericType2<Integer>(null).foo();
        }

}

aspect SomeAspect {
        before(GenericType2 t): call(* GenericType2.foo()) && target(t) {
                t.callGenericMethod();
        }

        private void GenericType2.callGenericMethod() {
                getValue(new Integer(45));
        }
}
Comment 3 Andrew Clement CLA 2006-06-07 04:25:20 EDT
these two testcases are committed - commented out in Ajc152Tests
Comment 4 Andrew Clement CLA 2007-10-24 10:06:12 EDT
investigate for 1.5.4, but might fall back to 1.6.0 if it is a bit tricky to get solved!
Comment 5 Andrew Clement CLA 2008-08-20 16:49:18 EDT
I have fixed the first case of this:

        private void GenericType.callGenericMethod() {
                getValue();
        }

will now work.  Yet more code that wasn't generics aware needed changing.

Case 2 i am not fixing.  If you write this Java code:

public class GenericType2<V extends Integer> {
  public void getValue(V v) {}

  public void foo() {
    getValue(new Integer(45));
  }
}

Then it doesn't compile with javac:

"The method getValue(V) in the type GenericType2<V> is not applicable for the arguments (Integer)"

(which I perhaps found a little surprising giving that the parameter meets the specified bound).

AspectJ gives the same error if the getValue() call is moved out into the ITD