Overload resolution regression

Remi Forax forax at univ-mlv.fr
Tue Nov 19 06:39:00 PST 2013


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



More information about the lambda-dev mailing list