Bug 79798 - [compiler] Wrong compiler error when interface overrides two methods with same signature but different exceptions
Summary: [compiler] Wrong compiler error when interface overrides two methods with sam...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.4 M7   Edit
Assignee: Kent Johnson CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 99986 133734 187621 209429 221637 (view as bug list)
Depends on:
Blocks:
 
Reported: 2004-11-30 13:27 EST by Markus Keller CLA
Modified: 2011-07-06 09:19 EDT (History)
8 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Keller CLA 2004-11-30 13:27:58 EST
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 { } }
Comment 1 Kent Johnson CLA 2004-12-01 14:14:02 EST
This is not a MethodVerifier problem.

This error is thrown from FlowContext.checkExceptionHandlers()
Comment 2 Philipe Mulet CLA 2004-12-01 15:35:44 EST
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.
Comment 3 Markus Keller CLA 2004-12-13 04:38:57 EST
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 { } }
Comment 4 Kent Johnson CLA 2004-12-14 11:28:43 EST
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.
Comment 5 Philipe Mulet CLA 2005-05-17 13:02:41 EDT
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).

Comment 6 Markus Keller CLA 2005-10-13 16:36:36 EDT
(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
    }
Comment 7 Philipe Mulet CLA 2006-03-29 14:04:05 EST
*** Bug 133734 has been marked as a duplicate of this bug. ***
Comment 8 Philipe Mulet CLA 2006-03-30 11:55:58 EST
Kent suggested to have #mostSpecificMethod create the binding artifact on the fly.
Comment 9 Olivier Thomann CLA 2006-04-05 14:12:20 EDT
*** Bug 135097 has been marked as a duplicate of this bug. ***
Comment 10 Markus Keller CLA 2006-04-05 14:40:21 EDT
> 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. . 


Comment 11 Kent Johnson CLA 2006-05-02 11:00:53 EDT
The testcase from comment #0 is fixed in latest but not the case in comment #3
Comment 12 Philipe Mulet CLA 2006-08-29 04:32:47 EDT
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);
						}
Comment 13 Kent Johnson CLA 2007-05-18 11:32:51 EDT
*** Bug 187621 has been marked as a duplicate of this bug. ***
Comment 14 Olivier Thomann CLA 2008-03-06 08:59:57 EST
*** Bug 221637 has been marked as a duplicate of this bug. ***
Comment 15 Kent Johnson CLA 2008-04-23 14:03:57 EDT
*** Bug 209429 has been marked as a duplicate of this bug. ***
Comment 16 Kent Johnson CLA 2008-04-23 14:14:37 EDT
Added Compliance_1_3/4/5.test106()

Released for 3.4M7

Backported to 3.3.x stream
Comment 17 David Audel CLA 2008-04-29 07:31:08 EDT
Verified for 3.4M7 using I20080427-2000
Comment 18 Kent Johnson CLA 2008-11-25 14:55:05 EST
*** Bug 99986 has been marked as a duplicate of this bug. ***