Bug 229928 - [1.5][compiler] compiler wrongly resolves a call when it should complain on ambiguity
Summary: [1.5][compiler] compiler wrongly resolves a call when it should complain on a...
Status: VERIFIED INVALID
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.4   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 3.4 RC1   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-05-02 06:04 EDT by A B CLA
Modified: 2011-06-02 03:54 EDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description A B CLA 2008-05-02 06:04:50 EDT
The java compiler fails to issue an error on the following condition.

public class MyClass {
    public MyClass set( String name, String value ) {
   	return this;
    }
    public <T extends Enum<T>> MyClass set( String name, T value ) {
   	return this;
    }
}

// caller code
// the eclipse compiler resolves the following call to set(String, String) 
// although it should have complained on an ambiguity

new MyClass().set("HI", null); // compiler fault here
Comment 1 Kent Johnson CLA 2008-05-05 11:51:38 EDT
This bug exists in 3.3.x, as well as 3.4M7
Comment 2 Kent Johnson CLA 2008-05-06 15:25:04 EDT
We have an issue in one case :

class X {
	void foo(String name, String value) {}
	<T extends M> void foo(String name, T value) {}

	void foo2(String name, String value) {}
	<T extends N<T>> void foo2(String name, T value) {}
}

class M {}
class N<T> {}

class Test {
	void test() {
		new X().foo("HI", null); // correctly report error
		new X().foo2("HI", null); // miss ambiguous error
	}
}
Comment 3 Kent Johnson CLA 2008-05-06 15:58:54 EDT
Philippe - I think we're failing in ParameterizedGenericMethodBinding inferFromExpectedType()

We end up creating a substitute : void foo2(java.lang.String, N<N<T>>)

and then we fail the bounds check against T extends N<T>
Comment 4 Philipe Mulet CLA 2008-05-07 06:56:33 EDT
This could be a bug in javac, considering that it agrees with us on the following:

class X {
        <T extends N<T>> void foo2(String name, T value) {}
}
class N<T> {}
class Test {
        void test() {
                new X().foo2("HI", null);
        }
}

X.java:7: incompatible types; inferred type argument(s) java.lang.Object do not conform to bounds of type variable(s) T
found   : <T>void
required: void
                new X().foo2("HI", null);
                            ^
1 error

(tried javac6 and javac7)

So in essence the second method is not applicable; why would it be ambiguous then ?
Comment 5 Kent Johnson CLA 2008-05-07 10:00:48 EDT
Oops - you're right.

The error message (when the first method is not available) for the original testcase from javac 6 is :

X.java:8: incompatible types; inferred type argument(s) java.lang.Object do not
conform to bounds of type variable(s) T
found   : <T>MyClass
required: java.lang.Object
                new MyClass().set("HI", null);


So why does javac report an ambiguous error ?
Comment 6 Philipe Mulet CLA 2008-05-07 12:09:47 EDT
Added GenericTypeTest#test1317-1321
Comment 7 Philipe Mulet CLA 2008-05-07 12:21:20 EDT
Closing as a javac bug.
Comment 8 A B CLA 2008-05-12 11:00:46 EDT
hi again,

i didn't understand, was this bug solved? in my original example, it's clearly a bug. 

i'm referring to my original example.

javac rightfully complains on the ambiguity, while Eclipse's compiler quietly resolves the call to 
   set("HI", null) 
to 
   set(String, String)
    
because of the null argument, the compiler doesn't have enough type information to resolve correctly. why doesn't the eclipse complier complain about it too?

    
Comment 9 Kent Johnson CLA 2008-05-12 11:09:39 EDT
In your original example, comment out the first set method so you only have :

public class MyClass {
    public MyClass set( String name, String value ) { return this; }
}
// and a call from somewhere
new MyClass().set("HI", null);

Now try compiling that with javac and you'll get an error :

X.java:8: incompatible types; inferred type argument(s) java.lang.Object do not
conform to bounds of type variable(s) T
found   : <T>MyClass
required: java.lang.Object
                new MyClass().set("HI", null);

Since the method is NOT applicable, why does the ambiguous error make sense? There is only 1 applicable method to choose from.


So your comment "javac rightfully complains on the ambiguity, while Eclipse's compiler quietly resolves the call to" is incorrect.
Comment 10 Kent Johnson CLA 2008-05-12 11:15:49 EDT
Sorry that should have read - In your original example, comment out the first set method so you only have :

class MyClass {
   <T extends Enum<T>> MyClass set( String name, T value ) { return null; }
}
class X {
   void test() { new MyClass().set("HI", null); }
}
Comment 11 A B CLA 2008-05-12 11:42:48 EDT
you have a point.

is it the language specification? that the inferred type of null is java.lang.Object?
Comment 12 David Audel CLA 2008-05-13 09:07:41 EDT
Verified for 3.4RC1.
Comment 13 Srikanth Sankaran CLA 2011-06-02 03:54:35 EDT
For posterity's sakes: I have recently fixed a cluster of bugs
around type inference in generic method invocation. As a part of
this exercise, many of the tests discussed here and added to the
test suite capturing the then eclipse behavior presuming it to be
valid have had to be remastered - happily matching JDK7 compiler's
behavior. So the issues debated here are indeed valid ones.

See 
    https://bugs.eclipse.org/bugs/show_bug.cgi?id=242159
    https://bugs.eclipse.org/bugs/show_bug.cgi?id=341795
    https://bugs.eclipse.org/bugs/show_bug.cgi?id=347600
    https://bugs.eclipse.org/bugs/show_bug.cgi?id=347145
    https://bugs.eclipse.org/bugs/show_bug.cgi?id=347746