Bug 293615 - error message since v3.6.0M2: name clash by overriding generic methods
Summary: error message since v3.6.0M2: name clash by overriding generic methods
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.6   Edit
Hardware: PC Linux
: P3 major (vote)
Target Milestone: 3.6 M4   Edit
Assignee: Srikanth Sankaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-10-28 15:55 EDT by andre.giessler CLA
Modified: 2010-07-02 10:55 EDT (History)
6 users (show)

See Also:


Attachments
Potential patch (8.02 KB, patch)
2009-11-09 06:18 EST, Srikanth Sankaran CLA
no flags Details | Diff
proposed patch + tests (7.87 KB, patch)
2009-11-11 00:22 EST, Srikanth Sankaran CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description andre.giessler CLA 2009-10-28 15:55:35 EDT
User-Agent:       Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090910 Ubuntu/9.04 (jaunty) Shiretoko/3.5.3
Build Identifier: I20090917-0100

Error message:
Name clash: The method put(K, V) of type OverrideBug<K,V> has the same erasure as put(K, V) of type Map<K,V> but does not override it

produced by compiling the following class:

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class OverrideBug<K, V> implements Map<K, List<V>> {

  @Override
  public void clear() {
    // TODO Auto-generated method stub

  }

  @Override
  public boolean containsKey(final Object arg0) {
    // TODO Auto-generated method stub
    return false;
  }

  @Override
  public boolean containsValue(final Object arg0) {
    // TODO Auto-generated method stub
    return false;
  }

  @Override
  public Set<java.util.Map.Entry<K, List<V>>> entrySet() {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public List<V> get(final Object arg0) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public boolean isEmpty() {
    // TODO Auto-generated method stub
    return false;
  }

  @Override
  public Set<K> keySet() {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public List<V> put(final K arg0, final List<V> arg1) {
    // TODO Auto-generated method stub
    return null;
  }

  public List<V> put(final K arg0, final V arg1) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public void putAll(final Map<? extends K, ? extends List<V>> arg0) {
    // TODO Auto-generated method stub

  }

  @Override
  public List<V> remove(final Object arg0) {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public int size() {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public Collection<List<V>> values() {
    // TODO Auto-generated method stub
    return null;
  }

}


earlier eclipse version 3.5.1 SR1 works fine with this example

Reproducible: Always

Steps to Reproduce:
1. create a new class
2. implement generic interface
3.
Comment 1 Srikanth Sankaran CLA 2009-10-29 03:39:52 EDT
See https://bugs.eclipse.org/bugs/show_bug.cgi?id=289247
and https://bugs.eclipse.org/bugs/show_bug.cgi?id=273862

(the latter is mistitled "Return type should be used to decide method duplicates " and is missing a NOT)

So, the observed name clash error is a direct result of the conscious
and considered decision to ignore the return types when deciding whether
two methods are duplicates.

See : http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6182950
supposedly implemented in b55 release of javac.

There are still two mysteries here: 

1. jdk-7-ea-bin-b65-windows-i586-16_jul_2009\jdk7\bin\javac compiles
this program silently. So what happened between b55 and b65 ?
(What is the behavior by the latest given b65 is dated ?)

2. How come the UI generated two put methods while Map has only one ?
I am unable to get the M3 eclipse to reproduce this problem.

So it would appear that there is no compiler problem here, at best a
case that needs to checked out by JDT/UI.
Comment 2 Srikanth Sankaran CLA 2009-10-29 03:59:39 EDT
Hello Andre, 

When I use Eclipse Version: 3.6.0 Build id: I20090917-0100 to
create a class OMap<K,V> that implements Map<K,<List<V>> and
use the quick fix to generate the unimplemented methods,
I don't end up with two versions of put().

Could you enumerate the exact steps you followed to end up with
the two put methods ? I am trying to rule out defects in the JDT/UI
component that is responsible for generating these stub methods.

I also check with more recent 20091025-2000 build and couldn't see
the problem there either.

(i.e only one put method is generated, if the second is manually added
I do see the name clash message)

Thanks!
Comment 3 andre.giessler CLA 2009-10-29 15:04:03 EDT
Hello srikanth,

sure, the steps to reproduce the error message are:
1. create a new class by right clicking in the package explorer in a java project, select "new" -> "class", leave all standard options and name the class OverrideBug
2. replace the automatically created code by

public class OverrideBug<K, V> implements Map<K, List<V>> {

and apply all quick fixes:
- import java.util.Map 
- import java.util.List
- add unimplemented methods
-> no error messages at that point

3. manually create the method
  public List<V> put(final K arg0, final V arg1) {
    return null;
  }
-> the mentioned error message appears


It seems to me that the signature 
public List<V> put(final K arg0, final V arg1)
can't be distinguished from
public List<V> put(final K key, final List<V> value)

although the class is syntactically correct. javac 1.6.0_16 from sun-java6-jdk compiles it without complaining.
Comment 4 Srikanth Sankaran CLA 2009-10-29 23:31:56 EDT
(In reply to comment #3)

> 3. manually create the method
>   public List<V> put(final K arg0, final V arg1) {
>     return null;
>   }
> -> the mentioned error message appears

Hi Andre,

    Thanks for the detailed steps. That clears any questions about
a JDT/UI defect lurking there. There is none. (I was worried about
the "Auto generated" comment in both the put methods)

> It seems to me that the signature 
> public List<V> put(final K arg0, final V arg1)
> can't be distinguished from
> public List<V> put(final K key, final List<V> value)
> although the class is syntactically correct. javac 1.6.0_16 from sun-java6-jdk
> compiles it without complaining.

This case should also be covered by http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6182950, not sure why javac7 b65 would accept it - perhaps the bug fix to 6182950 was inadequate. 

I am inclined to close this as NOT_ECLIPSE. Kent, can you weigh in on this ?
Can I also request you to test this case with javac7 b55 and javac7 latest ?
(My access to numbat is down).
Comment 5 Kent Johnson CLA 2009-10-30 10:03:57 EDT
Andre,

I believe Srikanth is on the right track since the case below (when the return types are equal) fails in eclipse and javac 6 & 7 with the same name clash error.

We'll double check with Sun, but I suspect this is a bug they will fix shortly.

import java.util.*;

class OverrideBug<K2, V2> implements Map<K2, List<V2>> {
  @Override public void clear() {}
  @Override public boolean containsKey(Object key) { return false; }
  @Override public boolean containsValue(Object value) { return false; }
  @Override public Set<java.util.Map.Entry<K2, List<V2>>> entrySet() {return null;}
  @Override public List<V2> get(Object key) { return null; }
  @Override public boolean isEmpty() { return false; }
  @Override public Set<K2> keySet() { return null; }
  @Override public List<V2> put(K2 key, List<V2> value) { return null; }
  @Override public void putAll(Map<? extends K2, ? extends List<V2>> m) {}
  @Override public List<V2> remove(Object key) { return null; }
  @Override public int size() { return 0; }
  @Override public Collection<List<V2>> values() { return null; }

  public V2 put(K2 k, V2 v) {
    return null;
  }
}
Comment 6 Srikanth Sankaran CLA 2009-11-03 00:51:30 EST
We believe eclipse behavior is correct here and the issue has been
reported to Sun compiler team.
Comment 7 Christian Figura CLA 2009-11-03 11:14:07 EST
(In reply to comment #5)
>   @Override public List<V2> put(K2 key, List<V2> value) { return null; }
> ...
>   public V2 put(K2 k, V2 v) {

Hi,
I’m having the same Problem Andre described. It is not the one mentioned in comment #5.
The signatures described initially were:

List<V> put(final K arg0, final List<V> arg1)
List<V> put(final K arg0, final V arg1)

They have the same return type (therefore none of the above mentioned bugs has something to do with it). 
They differ in their signatures. One with the argument arg1 being a List (no matter what type that list has) and the other being whatever is specified when the template is instantiated.
This works fine with previous versions of the eclipse java compiler and is working fine with the sun compiler.

I don’t think this is a clear ‘RESOLVED NOT_ECLIPSE’ bug report ;-)

Thanks Christian
Comment 8 Srikanth Sankaran CLA 2009-11-04 10:39:25 EST
Andre & Christian,

At a minimum, I agree this is worth a second look. I could dig up
several other cases where eclipse reports a name clash and javac
doesn't. 

I am trying to characterize the differences in the algorithms used
by the two compilers. Stay tuned.

Reopening ...
Comment 9 Srikanth Sankaran CLA 2009-11-09 06:18:32 EST
Created attachment 151683 [details]
Potential patch 


This patch bridges the apparent gap between the name clash algorithms
used by eclipse and javac. Here is a characterization based on experiment:

    - if type X has correctly overridden a super type Y's method foo,
then we should not look for a clash between any other foo X may have and
foo of Y that was overridden. In this scenario Y's foo is completely
replaced and is out of the picture.

    e.g in the test attached to comment#0, we should NOT be checking
java.util.Map.put(K, V) for a clash against OverrideBug.put(K, V) at
all since the former is completely overridden and thrown out of the
picture by OverrideBug.put(K, List<V>). Instead we should be checking
OverrideBug.put(K, List<V>) against OverrideBug.put(K, V) for a clash
but there is none here as the erasures are very different.

   - When comparing a user method against a synthetic/bridge method
return type must continue to be used.

     An easier way of understanding this is to say that for the given
type, we should assemble all applicable methods (any method that got
overridden anywhere in the hierarchy leading upto and including the
current type is not applicable). The set of all applicable methods
should include both user methods and compiler generated synthetic methods.

    With the set of all applicable methods thus assembled, we should
look for clashes - a user method clashes with another if the erasure
of the signatures is equal, while a user method clashes with a synthetic
method only if return type erasure is also equal.

    While this fixes the problem reported in comment#0, there are still a
handful of preexisting cases where javac does not report a name clash 
while we do: In org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest

test001a(), test001c(), test002a(), test002c(), test003a() are a few of them.

In these cases though the difference in behavior seems long standing
(going back to at least till 3.4.2) and not a recent regression.

I have not been able to characterize these precisely yet and I am inclined
to treat this as a separate issue from the current one which is a regression
since 3.6M2.
Comment 10 Srikanth Sankaran CLA 2009-11-09 06:20:54 EST
(In reply to comment #7)
> (In reply to comment #5)
> >   @Override public List<V2> put(K2 key, List<V2> value) { return null; }
> > ...
> >   public V2 put(K2 k, V2 v) {
> Hi,
> I知 having the same Problem Andre described. It is not the one mentioned in
> comment #5.

Hello Christian,

Just to be sure, so would the test case reported in comment#0 cover your
problem ? If unsure, please post a smallish test case - Thanks.
Comment 11 Christian Figura CLA 2009-11-09 11:40:12 EST
(In reply to comment #10)
> (In reply to comment #7)
> > (In reply to comment #5)
> > >   @Override public List<V2> put(K2 key, List<V2> value) { return null; }
> > > ...
> > >   public V2 put(K2 k, V2 v) {
> > Hi,
> > I知 having the same Problem Andre described. It is not the one mentioned in
> > comment #5.
> 
> Hello Christian,
> 
> Just to be sure, so would the test case reported in comment#0 cover your
> problem ? If unsure, please post a smallish test case - Thanks.

That testcase works just fine for me.
Thanks for taking care of the problem.

Christian
Comment 12 Srikanth Sankaran CLA 2009-11-11 00:22:41 EST
Created attachment 151916 [details]
proposed patch + tests


Patch to address the problem cited in comment#0.
Comment 13 Srikanth Sankaran CLA 2009-11-11 00:39:27 EST
Released in HEAD for 3.6M4.
Bug #294839 raised to follow up on open issues unrelated to
current bug mentioned in comment#9.
Comment 14 Jay Arthanareeswaran CLA 2009-12-08 03:29:23 EST
Verified for 3.6M4 using build I20091207-1800