Bug 162026 - [1.5][compiler] Erroneous Report of an Ambiguous Method
Summary: [1.5][compiler] Erroneous Report of an Ambiguous Method
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.3   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P3 critical (vote)
Target Milestone: 3.3 M4   Edit
Assignee: Maxime Daniel CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-10-23 20:28 EDT by Robert Simmons Jr. CLA
Modified: 2007-07-29 09:21 EDT (History)
1 user (show)

See Also:


Attachments
Tentative fix + test cases modifications (also includes patch for 162073) (8.09 KB, patch)
2006-10-27 01:48 EDT, Maxime Daniel CLA
no flags Details | Diff
Safer patch (more conservative) (2.50 KB, patch)
2006-11-07 09:56 EST, Maxime Daniel CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Robert Simmons Jr. CLA 2006-10-23 20:28:27 EDT
The following code erroneously generates an Error stating the call to fetch() is ambigous. 

------------------------------------------------------

package demo;
public interface SomeInterface {
	<TYPE extends Number> TYPE fetch(final Number value);
}

------------------------------------------------------

package demo;
public interface SomeOtherInterface extends SomeInterface {
	@SuppressWarnings("unchecked")
    Float fetch(final Number value);
}

------------------------------------------------------

package demo;
public class SomeClass implements SomeOtherInterface {
	/** @see demo.SomeInterface#fetchStringified(java.lang.Number) */
	@SuppressWarnings("unchecked")
	public Float fetch(final Number value) {
		return 50.5f;
	}
}

------------------------------------------------------

package demo;
public class SomeUser {
	public SomeOtherInterface foo = new SomeClass();
	
	public void bar () {
		this.foo.fetch(305.5f); // -- error here --
	}
}

------------------------------------------------------

This does not happen under javac. 

Reported bug is: 

The method fetch(Number) is ambiguous for the type SomeOtherInterface	zzzscrap/src/demo	SomeUser.java	line 6	1161647933143	5604

The mothod is not ambigous as it should be calling the one in the interface with hte most specificity, namely the one without the generic parameters. Interestingly the following code works around the problem. 

	public void bar () {
		this.foo.fetch((Number)305.5f);
	}

Odd to say the least and a really bad side effect is that only Eclipse seems to have this problem.

-- Robert
Comment 1 Robert Simmons Jr. CLA 2006-10-23 20:35:58 EDT
Addendum: 

The code

this.foo.fetch((Number)305.5f);

Should result in an unnecessary cast warning.
Comment 2 Olivier Thomann CLA 2006-10-23 22:28:55 EDT
Reproduced with HEAD.
Comment 3 Olivier Thomann CLA 2006-10-23 22:30:12 EDT
This is not a regression from 3.2.0.
Comment 4 Maxime Daniel CLA 2006-10-24 06:50:48 EDT
Added test cases AmbiguousMethodTest#25 (inactive) and 26.
Comment 5 Maxime Daniel CLA 2006-10-26 07:59:49 EDT
162065 is at most loosely related to this one. It may depend on 162073 being fixed though.
Investigating further.
Comment 6 Maxime Daniel CLA 2006-10-26 08:47:33 EDT
From JLS 3 15.12.2, I infer that, in the context of AmbiguousMethodTest#25, m.foo(1.0f), the type into which we must search foo is J. Since J#foo overrides I#foo, we should consider a single method, that is J#foo, and avoid using mostSpecificMethodBinding. Or else if we want to collect both J#foo and I#foo at that step of the algorithm for other reasons, the semantics of mostSpecificMethodBinding are inappropriate for the post selection.
Experimenting with a more selective collection process.
Comment 7 Maxime Daniel CLA 2006-10-27 01:48:56 EDT
Created attachment 52818 [details]
Tentative fix + test cases modifications (also includes patch for 162073)

This patch passes all existing tests by eliminating overridden methods more thoroughly in the case of abstract methods (in Scope#mostSpecificMethodBinding). There remains a few things to do:
- document the fact that Scope#mostSpecificMethodBinding is not an implementation of the algorithm described by JLS3; amongst other differences, it takes more methods in its input, and uses additional exclusion rules to trim it down;
- exhibit a test case that would leverage the code that this patch suppresses, and refine the patch; I suspect that the code the patch suppresses may be useful in some cases (most probably involving binary type bindings), and that the real fix must be more cautious; if I am wrong, at least I need to improve the test coverage...
Comment 8 Maxime Daniel CLA 2006-11-07 09:48:10 EST
Further analysis
- if (original2 == null || !original.areParameterErasuresEqual(original2)
  guards the cases when there is no override between the compared methods, as
  far as parameters are concerned;
- only the return type remaines; at very least,
  original.returnType.isCompatibleWith(original2.returnType), which
  tests whether the return types are assignment compatible, is not the test to
  perform; this is because, while returning Float is compatible with returning
  T extends Number according to the return type compatibility definition,
  assigning a Float to a T extends Number is not always valid (take T ==
  Integer); if the test is needed, it must be of a different nature;
- by the way, this clears isCompatibleWith responsibility in the bug: its 
  current (and correct) semantics are not the ones needed at the calling point;
- I believe that the right test is performed during the method verification 
  process for source files, leaving us with methods that are in effect 
  return type compatible; the question now would be to find another path by
  which we could get there with incompatible return types (again, no current 
  test case gets us there); looking at the source more closely, that would need
  that I, J and Y (or some of them) be compiled in advance in such a way that
  the J#foo or Y#foo would not be return type compatible with I#foo; this would
  demand that the compiler used to do that be incorrect (for the test case at
  hand);
- there may exist other ways to reach that point though, if 
  mostSpecificMethodBinding was to be called in another context; hence we'd
  better play safe and complete the test by a test on boundaries.

Safer patch will test types boundaries compatibility when they are not compatible.
Comment 9 Maxime Daniel CLA 2006-11-07 09:56:10 EST
Created attachment 53369 [details]
Safer patch (more conservative)
Comment 10 Maxime Daniel CLA 2006-11-08 02:33:54 EST
Released for 3.3 M4.
Comment 11 Olivier Thomann CLA 2006-12-11 14:59:02 EST
Verified for 3.3M4 with I20061211-1119
Comment 12 Eclipse Webmaster CLA 2007-07-29 09:21:03 EDT
Changing OS from Mac OS to Mac OS X as per bug 185991