Overload resolution regression
Vicente-Arturo Romero-Zaldivar
vicente.romero at oracle.com
Tue Nov 19 09:16:01 PST 2013
On 19/11/13 16:43, Jonathan Ross wrote:
> Or a pickMe(String) for that matter?
>
> Thanks for the explanation, Remi. Indeed, we were just using the
> coincidence of the Object fallback; it seems to predominantly affect our
> test fixtures - I hope, at least. The nasty thing about it is that it
> leads to a runtime exception rather than a compilation error, so we may not
> find out for certain for a while.
Hi Jonathan,
There is an undocumented, unsupported, test only, etc, compiler option
that can be helpful to analyze what method resolution is doing:
-XDverboseResolution=success,failure,applicable
it's verbose, very verbose, but it can give you a "static" method
resolution analysis,
for example for the code you reported:
javac -XDverboseResolution=success,failure,applicable
OverloadingRegression.java
OverloadingRegression.java:10: Note: resolving method pickMe in type
OverloadingRegression to candidate 1
pickMe(unsafeCast(new String()));
^
phase: BASIC
with actuals: BigInteger
with type-args: no arguments
candidates:
#0 applicable method found: pickMe(Object)
#1 applicable method found: pickMe(BigInteger) <---- this one
is selected
OverloadingRegression.java:10: Note: resolving method <init> in type
String to candidate 0
pickMe(unsafeCast(new String()));
^
phase: BASIC
with actuals: no arguments
with type-args: no arguments
candidates:
#0 applicable method found: String() <-- only option
OverloadingRegression.java:10: Note: resolving method unsafeCast in type
OverloadingRegression to candidate 0
pickMe(unsafeCast(new String()));
^
phase: BASIC
with actuals: String
with type-args: no arguments
candidates:
#0 applicable method found: <T>unsafeCast(Object) <--- only option
(partially instantiated to: (Object)Object)
where T is a type-variable:
T extends Object declared in method <T>unsafeCast(Object)
Note: OverloadingRegression.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details
HTH,
Vicente
>
>
> On Tue, Nov 19, 2013 at 9:02 AM, Paul Benedict <pbenedict at apache.org> wrote:
>
>> Ah, okay, that makes sense now. Filling me in on the background was a big
>> helper.
>>
>> For the sake of clarity, what would happen to Jonathan's example if there
>> was also a third pickMe(BigDecimal)?
>>
>>
>> On Tue, Nov 19, 2013 at 8:39 AM, Remi Forax <forax at univ-mlv.fr> wrote:
>>
>>> On 11/19/2013 02:53 PM, Paul Benedict wrote:
>>>
>>>> I don't see how you can call the compiler "smarter" in this example.
>>>>
>>> 'smarter' because this is not the only use case :)
>>> Here is an example that fails to compile with 7 but compiles with 8
>>> (comparingByValue is also a method that only uses type variables to
>>> specify the return type)
>>> Map<String,String> map = ...
>>> map.entrySet().stream().sorted(Map.Entry.comparingByValue());
>>>
>>> For pickMe(unsafe()) the inference fails in 7 and uses Object as a
>>> fallback,
>>> it appears that it's what the user want but that's just a coincidence.
>>>
>>> It is choosing pickMe(BigInteger) without >: BigInteger type being
>>>> present.
>>>>
>>>
>>> Don't forget that pickMe(null) also choose pickMe(BigInteger),
>>> it's the way the algorithm that choose the most specific method works
>>> since the beginning.
>>> here, the constraint is that T is a subtype of Object, so both
>>> pickMe(Object) and pickMe(BigInteger) are applicable,
>>> then the most specific algorithm chooses that pickMe(BigInteger) is
>> better
>>> than pickMe(Object).
>>>
>>> cheers,
>>> Rémi
>>>
>>>
>>>> On Tue, Nov 19, 2013 at 5:30 AM, Remi Forax <forax at univ-mlv.fr <mailto:
>>>> forax at univ-mlv.fr>> wrote:
>>>>
>>>> On 11/19/2013 01:43 AM, Jonathan Ross wrote:
>>>> > Hi,
>>>>
>>>> Hi Johnathan,
>>>>
>>>> >
>>>> > I recently started porting a 150k-line project to jdk 8 to try
>>>> my hand at
>>>> > the recent changes in the collection libraries. (Hadn't done
>>>> this since
>>>> > last year, my apologies!)
>>>> >
>>>> > I have run in to a large number of compilation errors:
>>>> regressions in type
>>>> > inference and overload resolution. A lot of these are in unit
>>>> tests using
>>>> > mockito and fest and other similar monadic apis that rely heavily
>> on
>>>> > overload resolution.
>>>>
>>>> It's not a regression, it's an enhancement :)
>>>>
>>>> >
>>>> > The code snippet below is a distilled version of my typical
>>>> compilation
>>>> > error: our test code relying on the compiler choosing the Object
>>>> overload
>>>> > by default.
>>>> >
>>>> >
>>>> > import java.math.BigInteger;
>>>> >
>>>> > public class OverloadingRegression {
>>>> >
>>>> > static <T> T unsafeCast(Object anObject) {
>>>> > return (T) anObject;
>>>> > }
>>>> >
>>>> > public void showOverloadResolutionIssue() {
>>>> > pickMe(unsafeCast(new String()));
>>>> > }
>>>> >
>>>> > private void pickMe(BigInteger o) { /* ClassCastException in
>>>> > 1.8.0-ea-b115 */ }
>>>> >
>>>> > private void pickMe(Object o) { /* fine, picked in 1.6 &
>>>> 1.7 */ }
>>>> > }
>>>> >
>>>> >
>>>> > Obviously the unsafeCast is not going to win any beauty prizes,
>> but
>>>> > sometimes you just have to do this sort of thing. My main point
>>>> is: it
>>>> > used to work in java 7, it doesn't any more.
>>>> >
>>>> > Is this a known issue (or is it even expected behaviour)?
>>>>
>>>> Yes, it's the expected behavior, when you try do inference inside a
>>>> method call,
>>>> here unsafeCast is inside pickMe, in that case with jdk6 & 7, the
>>>> inference
>>>> is not done and T is replaceb by its bound (Object), with jdk8, the
>>>> compiler is smarter,
>>>> and find the most specific method first, here pickMe(BigInteger)
>>>> is more
>>>> specific than pickMe(Object) and then infers T (T = BigInteger).
>>>>
>>>> >
>>>> > I'm using 1.8.0-ea-b115, but I verified that it fails with all
>>>> 1.8 jdks I
>>>> > have my box. When I pass in -source 1.7 it does work. And when
>>>> I do an
>>>> > explicit cast to Object (of course).
>>>>
>>>> so this is the correct behavior for 8, the new stream API heavily
>>>> relies
>>>> on that,
>>>> and yes, this new semantics is not compatible with 1.7 in the case
>> the
>>>> inference was failing,
>>>> this is a known compatibility issue.
>>>>
>>>> >
>>>> > -- Jonathan Ross
>>>> >
>>>>
>>>> cheers,
>>>> Rémi
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Cheers,
>>>> Paul
>>>>
>>>
>>
>> --
>> Cheers,
>> Paul
>>
>>
>> ________________________________
>>
>> The information in this e-mail is intended only for the person or entity
>> to which it is addressed.
>>
>> It may contain confidential and /or privileged material. If someone other
>> than the intended recipient should receive this e-mail, he / she shall not
>> be entitled to read, disseminate, disclose or duplicate it.
>>
>> If you receive this e-mail unintentionally, please inform us immediately
>> by "reply" and then delete it from your system. Although this information
>> has been compiled with great care, neither IMC Financial Markets & Asset
>> Management nor any of its related entities shall accept any responsibility
>> for any errors, omissions or other inaccuracies in this information or for
>> the consequences thereof, nor shall it be bound in any way by the contents
>> of this e-mail or its attachments. In the event of incomplete or incorrect
>> transmission, please return the e-mail to the sender and permanently delete
>> this message and any attachments.
>>
>> Messages and attachments are scanned for all known viruses. Always scan
>> attachments before opening them.
>>
More information about the lambda-dev
mailing list