Java Forum / General / July 2007
Compiler bug? "reference to addAll is ambiguous"
Oliver Wong - 13 Jul 2007 16:26 GMT I've got a piece of code which compiles fine in Eclipse, but seems to have problem with Sun's compiler. I'm not sure of the exact version of Sun's compiler being used, the error was reported to me by a coworker. Here's the error message:
<errorMessage> Rewriting\src\java\gov\sc\eip\report\birt\ChangesRowGenerator.java:116: reference to addAll is ambiguous, both method addAll(java.util.Collection<? extends E>) in java.util.Collection<capture#420 of ? super gov.sc.eip.report.birt.items.ChangeRow> and method addAll(java.util.Collection<? extends E>) in java.util.List<capture#420 of ? super gov.sc.eip.report.birt.items.ChangeRow> match </errorMessage>
I didn't post an SSCCE because (1) I'm not sure I'm allowed to and (2) because I think the error message is sufficient to demonstrate that there may be a bug... either in the compiler, or in my understanding of overwriting.
It seems to me that the error message is saying that it cannot determine, from my code, whether the .addAll() which I am calling refers to the .addAll in java.util.Collection or the .addAll() in java.util.List. But doesn't the .addAll() in java.util.List overwrite the .addAll() in java.utilCollection, so that the "List-version" always be the one invoked? And anyway, aren't these both interfaces, and thus provide zero implementation, and thus it doesn't really matter which of these two methods are being called, since they will eventually point to the exact same implementation depending on what underlying concrete type is involved?
In case it's relevant, I'll include the statement where the error is generated:
<veryShortSnippet> rows.addAll(getRowForGenericChange(changeSet.getCountyChange(), CommonFieldNamesEnum.COUNTY.getCode())); </veryShortSnippet>
"rows" is a parameter past into the method of type "List<? super ChangeRow>". As you can see, I'm not doing any weird casting to bypass the overwriting (e.g. I'm not doing something like "((Collection)rows).addAll(whatever)", which in my opinion should work even if I did do that anyway).
- Oliver
Tom Hawtin - 13 Jul 2007 17:10 GMT > <errorMessage> > Rewriting\src\java\gov\sc\eip\report\birt\ChangesRowGenerator.java:116: [quoted text clipped - 5 lines] > ? super gov.sc.eip.report.birt.items.ChangeRow> match > </errorMessage> I assume E extends ChangeRow.
> And anyway, aren't these both interfaces, and thus provide zero > implementation, and thus it doesn't really matter which of these two > methods are being called, since they will eventually point to the exact > same implementation depending on what underlying concrete type is > involved? It doesn't matter if the (non-private, non-static) method is being called is defined in an interface or a class (other than the instruction is invokeinterface vs invokevirtul).
> <veryShortSnippet> > rows.addAll(getRowForGenericChange(changeSet.getCountyChange(), > CommonFieldNamesEnum.COUNTY.getCode())); > </veryShortSnippet> That rules out the only tenuous explanation I could think of (that it was something wacky to do with inner classes).
> "rows" is a parameter past into the method of type "List<? super > ChangeRow>". As you can see, I'm not doing any weird casting to bypass the > overwriting (e.g. I'm not doing something like > "((Collection)rows).addAll(whatever)", which in my opinion should work > even if I did do that anyway). The obvious work around is to assign rows to a Collection<? super ChangeRow> variable. (I assume ChangeRow has no generic parameters.)
Tom Hawtin
Oliver Wong - 13 Jul 2007 17:26 GMT >> <errorMessage> >> Rewriting\src\java\gov\sc\eip\report\birt\ChangesRowGenerator.java:116: [quoted text clipped - 7 lines] > > I assume E extends ChangeRow. There is no actual "E" in my code. I think the "E" comes from Sun's implementation onf java.util.List.class and java.util.collection.class. The variable "rows" involed here is declared as "List<? super ChangeRow> rows", so I guess "E" is "? super ChangeRow" and so the method addAll's generic type is "? extends (? super ChangeRow)" (not sure if that even makes sense). But anyway, I think, from a language-specification point of view, the error doesn't really have anything to do with generics.
However, from a practical-implementation point of view, if this is indeed a bug in the compiler and not in my understanding, I can imagine how throwing generics in the mix might have introduced this bug.
>> And anyway, aren't these both interfaces, and thus provide zero >> implementation, and thus it doesn't really matter which of these two [quoted text clipped - 5 lines] > called is defined in an interface or a class (other than the instruction > is invokeinterface vs invokevirtul). Right, but what I meant is that we have a class hierarchy like:
public interface Collection<E> { public void addAll(Collection<? extends E> stuffToAdd); }
public interface List<E> extends Collection { public void addAll(Collection<? extends E> stuffToAdd); }
public class ArrayList<E> implements List<E> { /* etc. */ }
so that when you have code like:
public void myMethod(List<? super ChangeRow> rows) { rows.addAll(getSomeData()); }
public List<? super ChangeRow> getSomeData() { List<ChangeRow> returnValue = new ArrayList<ChangeRow>(); return returnValue; }
there should be no reason to ask whether the .addAll() refers to the one in Collection, or the one in List. I've got a multiple-interface-inheritance situation, and *not* a multiple-implementation-inheritance situation; thus the "diamond problem" does not come up, and thus there should be no ambiguity about which method I'm invoking when I call .addAll().
>> <veryShortSnippet> >> rows.addAll(getRowForGenericChange(changeSet.getCountyChange(), [quoted text clipped - 3 lines] > That rules out the only tenuous explanation I could think of (that it > was something wacky to do with inner classes). Right, the code is structurally very straightforward (it's essentially a CRUD web app). No inner classes anywhere to be seen.
>> "rows" is a parameter past into the method of type "List<? super >> ChangeRow>". As you can see, I'm not doing any weird casting to bypass [quoted text clipped - 4 lines] > The obvious work around is to assign rows to a Collection<? super > ChangeRow> variable. (I assume ChangeRow has no generic parameters.) I'll give that a try and ask my coworker to compile again and see what happens.
- Oliver
Oliver Wong - 13 Jul 2007 18:13 GMT > I've got a piece of code which compiles fine in Eclipse, but seems to > have problem with Sun's compiler. I'm not sure of the exact version of > Sun's compiler being used, the error was reported to me by a coworker. > Here's the error message: At this point, I'm relatively confident it's a compiler bug. I can't reproduce the error using 1.5.0_06-b05, 1.6.0-b105, 1.6.0_01-b06 nor 1.6.0_02-b06. My coworker's version is 1.6.0_02-b05 which I can't seem to find online.
- Oliver
Steven Simpson - 14 Jul 2007 20:22 GMT > reference to addAll is ambiguous, both method > addAll(java.util.Collection<? extends E>) in [quoted text clipped - 3 lines] > ? super gov.sc.eip.report.birt.items.ChangeRow> match > Could it be this?:
<http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6356673>
That's for a 1.5 version, but note the comments and one of the related bugs. It's been present in all the 1.6 versions I've tried.
As it's a List, perhaps you could try using addAll(int, ...) as a workaround.
 Signature ss at comp dot lancs dot ac dot uk |
Oliver Wong - 16 Jul 2007 16:17 GMT >> reference to addAll is ambiguous, both method >> addAll(java.util.Collection<? extends E>) in [quoted text clipped - 10 lines] > That's for a 1.5 version, but note the comments and one of the related > bugs. It's been present in all the 1.6 versions I've tried. It looks very similar to my issue, except that I think my situation is much simpler than the part which goes "<L extends List<? super A>>"; instead, it's simply "List<? super ActualClassNotATypeVariable>"
> As it's a List, perhaps you could try using addAll(int, ...) as a > workaround. I couldn't get the bug to reproduce on my machine, so I advised my coworker to try updating to a newer version of Java. He hasn't told me whether or not that made the problem go away. If it's still present, your solution sounds like the least messy one so far.
- Oliver
Steven Simpson - 16 Jul 2007 17:52 GMT >> <http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6356673> >> > It looks very similar to my issue, except that I think my situation is > much simpler than the part which goes "<L extends List<? super A>>"; > instead, it's simply "List<? super ActualClassNotATypeVariable>" > Note the GenericCaptureAddingTest example further down, which I think is more similar (although it's for Set, but I get the same problem when I change it to List).
 Signature ss at comp dot lancs dot ac dot uk |
Piotr Kobzda - 17 Jul 2007 15:17 GMT >>> <http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6356673> >>> [quoted text clipped - 6 lines] > more similar (although it's for Set, but I get the same problem when I > change it to List). I think, that's the same bug.
Just for fun, I've slightly modified that example to reflect as close as possible the Oliver's situation, here is the SSCCE:
import java.util.List;
public abstract class Test {
public interface ChangeRow {}
public void addData(List<? super ChangeRow> rows) { rows.addAll(getSomeData()); }
protected abstract List<? extends ChangeRow> getSomeData(); }
On my machine (Windows XP, Intel 32bit), compiling the above example produce the following output:
Test.java:8: reference to addAll is ambiguous, both method addAll(java.util.Collection<? extends E>) in java.util.Collection<capture#156 of ? super Test.ChangeRow> and method addAll(java.util.Collection<? extends E>) in java.util.List<capture#156 of ? super Test.ChangeRow> match rows.addAll(getSomeData()); ^ 1 error
This bug is reproducible using 1.6.0-beta2-b86, 1.6.0-b105, and 1.6.0_02-b06. Example compiles successfully with 1.5.0_04-b05, 1.5.0_06-b05, and 1.6.0-beta2-b73. (I have no other Java 5+ VMs installed to test it)
piotr
Oliver Wong - 17 Jul 2007 22:14 GMT > Just for fun, I've slightly modified that example to reflect as close as > possible the Oliver's situation, here is the SSCCE: [quoted text clipped - 11 lines] > protected abstract List<? extends ChangeRow> getSomeData(); > } Bingo, you've found it. I tried your example, and it compiles fine with:
javac 1.5.0_06
But triggers the bug in:
javac 1.6.0 javac 1.6.0_01 javac 1.6.0_02
- Oliver
Steven Simpson - 19 Jul 2007 17:30 GMT > >> public void addData(List<? super ChangeRow> rows) { [quoted text clipped - 9 lines] > javac 1.6.0_01 > javac 1.6.0_02 FYI, I submitted a new bug report to Sun on this just before this thread started, and they've got back to me to say it has been fixed in JDK7, and will also be fixed in a future JDK6 update.
 Signature ss at comp dot lancs dot ac dot uk |
Twisted - 21 Jul 2007 10:15 GMT > FYI, I submitted a new bug report to Sun on this just before this thread > started, and they've got back to me to say it has been fixed in JDK7, > and will also be fixed in a future JDK6 update. I don't know about you, but personally, I find "a future JDK6 update" to be somewhat vague and unhelpful ...
Roedy Green - 14 Jul 2007 21:15 GMT On Fri, 13 Jul 2007 11:26:37 -0400, "Oliver Wong" <owong@castortech.com> wrote, quoted or indirectly quoted someone who said :
>Rewriting\src\java\gov\sc\eip\report\birt\ChangesRowGenerator.java:116: >reference to addAll is ambiguous, both method [quoted text clipped - 4 lines] >? super gov.sc.eip.report.birt.items.ChangeRow> match ></errorMessage> This sort of problem happens when you use java.util.List and java.awt.List in the same program. You have to fully qualify each reference with package name to avoid ambiguity.
However, your case is more peculiar.
It looks as if are doing x.addall(
where x is both a Collection and a List.
Yet this should not cause trouble. List is a subinterface of Collection.
The practical way out of this is to define x concretely, e.g.
ArrayList<Thing> x = new ArrayList<Thing>( 2000); x.addAll (myThingCollection);
Please post code, at least your imports, where you define x, where you define the collection and the type of the collection and the addall. This is intriguing.
-- Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Oliver Wong - 16 Jul 2007 16:21 GMT > On Fri, 13 Jul 2007 11:26:37 -0400, "Oliver Wong" > <owong@castortech.com> wrote, quoted or indirectly quoted someone who [quoted text clipped - 15 lines] > > However, your case is more peculiar. Right, there's no reference to java.awt.* at all: It's a web application, not a desktop one.
> It looks as if are doing x.addall( > > where x is both a Collection and a List. > > Yet this should not cause trouble. List is a subinterface of > Collection. Agreed.
> The practical way out of this is to define x concretely, e.g. > [quoted text clipped - 4 lines] > you define the collection and the type of the collection and the > addall. This is intriguing. We (the company I work for) actually don't fully own the code. It's shared among a couple of developers working for several different companies all collaborating on one big project, so I'm not sure I can post the full code. Furthermore, since I can't actually replicate the problem on my machine, I can't really compose an SSCCE, because I can't test whether the parts which I consider "unimportant" actually affect the bug or not: No matter what I add or remove, the code compiles fine on *my* machine.
- Oliver
Twisted - 17 Jul 2007 05:13 GMT On Jul 14, 4:15 pm, Roedy Green <see_webs...@mindprod.com.invalid> wrote:
> This sort of problem happens when you use java.util.List and > java.awt.List in the same program. You have to fully qualify each > reference with package name to avoid ambiguity. While Java 7 proposed features remains a hot topic, let's propose making this legal:
import java.util.List; import java.awt.List AList;
...
List x = new LinkedList(); // a java.util.List AList y = new AList(); // a java.awt.List
It just means adding an alternate legal form of import statement, without losing backward source compatibility:
import fully-qualified-class alias;
and the stock import is then essentially just an elliptical form that defaults "alias" to the last chunk of the fq class name.
Roedy Green - 17 Jul 2007 05:21 GMT >While Java 7 proposed features remains a hot topic, let's propose >making this legal: > >import java.util.List; >import java.awt.List AList; that is reminiscent of the way Eiffel lets you get around the problem of duplicate names with multiple inheritance.
 Signature Roedy Green Canadian Mind Products The Java Glossary http://mindprod.com
Twisted - 17 Jul 2007 09:29 GMT On Jul 17, 12:21 am, Roedy Green <see_webs...@mindprod.com.invalid> wrote:
> >While Java 7 proposed features remains a hot topic, let's propose > >making this legal: [quoted text clipped - 4 lines] > that is reminiscent of the way Eiffel lets you get around the problem > of duplicate names with multiple inheritance. Yes, but multiple inheritance is evil, and this is closer to some C++ "using" and "typedef" usages and won't introduce any real cruftiness.
Well, unless someone goes out of their way with gratuitously aliasing common standard library classes in e.g. java.util or java.io to wacky names just to be a pain or maybe in the vain hope of job security through indispensibility if the code is ever to be maintained; but that's always going to be possible, whether by hairy use of imports, hairy entangled masses of nested and anonymous inner classes, or just hairy entangled messes of for and while loops full of break and continue statements to recreate the bad old days of GOTO-ridden ROM- BASIC-inspired spaghetti code.
Mind you they should get extra bonus points* for confusingly aliasing classes in java.lang, especially String and the basic exception classes, and referring to each under both the usual name AND the alias and picking which to use at each site in a random fashion.
* Each bonus point redeemable for one (1) free pink slip of course.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|