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