Community
Participate
Working Groups
I20041130-0800 Wrong compiler error when interface overrides two methods with same signature but different thrown exceptions: The call to ij.m() is OK, but eclipse flags it with "Unhandled exception type IOException". public class Over { void x() throws ZipException { IandJ ij= new K(); ij.m(); //wrong compile error } void y() throws ZipException { K k= new K(); k.m(); } } interface I { void m() throws IOException; } interface J { void m() throws ZipException; } interface IandJ extends I, J {} // swap I and J to make compile error disappear class K implements IandJ { public void m() throws ZipException { } }
This is not a MethodVerifier problem. This error is thrown from FlowContext.checkExceptionHandlers()
I suspect the method lookup should have picked the most specific m() definition, since when implementing it, you have to implement the most specific one. The exception analysis is just performing on the selected method.
Note that the "most specific" method may not be declared anywhere: import java.awt.print.PrinterAbortException; import java.awt.print.PrinterException; import java.io.IOException; import java.util.zip.ZipException; class Over { void x() throws ZipException { IandJ ij= new K(); ij.m(); //wrong compile error } } interface I { void m() throws IOException, PrinterAbortException; } interface J { void m() throws ZipException, PrinterException; } interface IandJ extends I, J {} // swapping I and J does not help class K implements IandJ { public void m() throws ZipException { } }
So from Markus' last example, its clear we cannot answer one of the 2 methods. And if we add a 'fake' method binding to the interface IandJ or just answer it during method lookup, then we make it appear that IandJ declares its own method... which could adversely affect method dispatch. I think FlowContext.checkExceptionHandlers() should detect the case of the receiver not defining the interface method & check it against its inherited methods.
I don't see why it would need to check receiver implementing the interface method. The fact lookup answered interface method proves it did not implement it. This likely would be deadly slow. One thing which we could imagine is to tag the offending interface method, and if bit is set, then flow analysis could perform some query to get all related methods it should consider. Kent ? Now I suspect that having name lookup not handle this situation, would also cause all tooling relying on method binding to fail in a similar way (think of DOM AST source manipulation such as: surround with try/catch).
(In reply to comment #5) > Now I suspect that having name lookup not handle this situation, would also > cause all tooling relying on method binding to fail in a similar way (think of > DOM AST source manipulation such as: surround with try/catch). I think so, yes. Life is really hard without a binding for the 'married' method IandJ#m(). ;-) BTW: the method declaration in comment 3 should read: void x() throws ZipException, PrinterAbortException { IandJ ij= new K(); ij.m(); //wrong compile error }
*** Bug 133734 has been marked as a duplicate of this bug. ***
Kent suggested to have #mostSpecificMethod create the binding artifact on the fly.
*** Bug 135097 has been marked as a duplicate of this bug. ***
> Kent suggested to have #mostSpecificMethod create the binding artifact on the > fly. I guess this would have to be a synthetic method in order to not break contracts like ITypeBinding#getDeclaredMethods(), etc. .
The testcase from comment #0 is fixed in latest but not the case in comment #3
Changes described in comment 11 are implemented in: Scope#mostSpecificMethodBinding(...) doing: if (original.thrownExceptions != original2.thrownExceptions) { if (mostSpecificExceptions == null) mostSpecificExceptions = original.thrownExceptions; if (possibleMethods == null) possibleMethods = new SimpleSet(3); int mostSpecificLength = mostSpecificExceptions.length; int original2Length = original2.thrownExceptions.length; SimpleSet temp = new SimpleSet(mostSpecificLength); nextException : for (int t = 0; t < mostSpecificLength; t++) { ReferenceBinding exception = mostSpecificExceptions[t]; for (int s = 0; s < original2Length; s++) { if (exception.isCompatibleWith(original2.thrownExceptions[s])) { possibleMethods.add(current); temp.add(exception); continue nextException; } else if (original2.thrownExceptions[s].isCompatibleWith(exception)) { possibleMethods.add(next); temp.add(original2.thrownExceptions[s]); continue nextException; } } } mostSpecificExceptions = temp.elementSize == 0 ? Binding.NO_EXCEPTIONS : new ReferenceBinding[temp.elementSize]; temp.asArray(mostSpecificExceptions); }
*** Bug 187621 has been marked as a duplicate of this bug. ***
*** Bug 221637 has been marked as a duplicate of this bug. ***
*** Bug 209429 has been marked as a duplicate of this bug. ***
Added Compliance_1_3/4/5.test106() Released for 3.4M7 Backported to 3.3.x stream
Verified for 3.4M7 using I20080427-2000
*** Bug 99986 has been marked as a duplicate of this bug. ***