Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 416349

Summary: [compiler][1.7] Name clash not reported by ecj but fails with javac 1.7
Product: [Eclipse Project] JDT Reporter: Marcin Wisnicki <mwisnicki>
Component: CoreAssignee: JDT-Core-Inbox <jdt-core-inbox>
Status: CLOSED WONTFIX QA Contact:
Severity: normal    
Priority: P3 CC: stephan.herrmann
Version: 4.3   
Target Milestone: ---   
Hardware: PC   
OS: All   
Whiteboard: stalebug

Description Marcin Wisnicki CLA 2013-09-02 07:49:26 EDT
javac: 1.7.0_25

<code>
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

public class Nameclash implements Function<Class<?>, List<Method>>, Predicate<Method> {

	@Override
	public boolean apply(Method input) {
		return true;
	}

	@Override
	public List<Method> apply(Class<?> input) {
		return Arrays.asList(input.getMethods());
	}
}

interface Function<F, T> {
	T apply(F input);
}

interface Predicate<T> {
	boolean apply(T input);
}
</code>

javac complains that:

<pre>
Nameclash.java:10: error: name clash: apply(Method) in Nameclash overrides a method whose erasure is the same as another method, yet
 neither overrides the other
        public boolean apply(Method input) {
                       ^
  first method:  apply(F) in Function
  second method: apply(T#2) in Predicate
  where F,T#1,T#2 are type-variables:
    F extends Object declared in interface Function
    T#1 extends Object declared in interface Function
    T#2 extends Object declared in interface Predicate
Nameclash.java:15: error: name clash: apply(Class<?>) in Nameclash overrides a method whose erasure is the same as another method, y
et neither overrides the other
        public List<Method> apply(Class<?> input) {
                            ^
  first method:  apply(T#1) in Predicate
  second method: apply(F) in Function
  where T#1,F,T#2 are type-variables:
    T#1 extends Object declared in interface Predicate
    F extends Object declared in interface Function
    T#2 extends Object declared in interface Function
2 errors
</pre>

Erased methods actually differ by return type (boolean vs List) so I don't know who to blame but behaviour should be consistent.
Comment 1 Marcin Wisnicki CLA 2013-09-02 07:50:59 EDT
The actual erased return types are of course boolean and Object.
Comment 2 Stephan Herrmann CLA 2013-09-02 16:20:49 EDT
trying different version of javac and ecj, only javac >= 1.7 report this error.

It would be good to know the Oracle bug by which javac has change in this regard.

OTOH, the following test main (compiled with javac 1.6- or ecj) runs just fine:

    public static void main(String[] args) {
      Nameclash n = new Nameclash();
      for (Method m: n.apply(Nameclash.class)) {
        System.out.println(m);
      }
      if (n.apply(Nameclash.class.getMethods()[0])) {
        System.out.println("yes");
      }

      Function<Class<?>, List<Method>> f = n;      
      for (Method m: f.apply(Nameclash.class)) {
        System.out.println(m);
      }

      Predicate<Method> p = n;
      if (p.apply(Nameclash.class.getMethods()[0])) {
        System.out.println("yes");
      }
    }

So at first glance I see no reason to reject the program.
Maybe this was an unintended change in javac??

Only when looking into the compiled bytecode I see two conflicting bridge methods:

  public volatile synthetic Object apply(Object arg1)
  public volatile synthetic boolean apply(Object arg1)

In source code, return types are not used for overload resolution, yet the JVM
seems to be able to pick the right bridge method.

(in reply to comment 0):
> I don't know who to blame but behaviour should be consistent

So far I don't know either. First of all I'd like the behavior to be consistent
with the JLS => more investigation needed.
Comment 3 Marcin Wisnicki CLA 2013-09-22 18:24:37 EDT
Bug: https://bugs.openjdk.java.net/browse/JDK-6182950
Commit: http://hg.openjdk.java.net/jdk7/tl/langtools/rev/5caa6c45936a

I'm not sure their analysis applies in this case, since the clash occurs between synthetic bridge methods which are not accessible from within Nameclash class (JLS8.4.8.3).
Comment 4 Stephan Herrmann CLA 2013-09-23 20:36:28 EDT
(In reply to Marcin Wisnicki from comment #3)
> Bug: https://bugs.openjdk.java.net/browse/JDK-6182950
> Commit: http://hg.openjdk.java.net/jdk7/tl/langtools/rev/5caa6c45936a
> 
> I'm not sure their analysis applies in this case, since the clash occurs
> between synthetic bridge methods which are not accessible from within
> Nameclash class (JLS8.4.8.3).

Thanks for digging this out.
Unfortunately, our case here is more complex. We don't know yet if the change regarding our example was an (accidental?) side-effect of the bug you cited or if yet another bug fix in javac is involved.
Comment 5 Eclipse Genie CLA 2020-04-07 14:36:14 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug.

If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.