poly-expression type inference pothole

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Jul 4 02:27:35 PDT 2013

On 04/07/13 10:16, John Rose wrote:
> P.P.P.S.  I just noticed this commentary in Part D:
>> 	• The receiver in a method invocation, field access, etc. (exp.foo()) is not a poly expression because the target type is unknown—it would be impossible to enumerate every type that has a particular member (foo, in this case). There has been some interest in allowing inference to "chain": ina().b(), passing type information from the invocation of b to the invocation of a. This adds another dimension to the complexity of the inference algorithm, as partial information has to pass in both directions; it only works when the erasure of the return type of a() is fixed for all instantiations (e.g.List<T>). This feature would not fit very well into the poly expression model, since the target type cannot be easily derived.
> It looks like what I'm asking for is allowing inference to chain through dot.  In that case, my two examples are some what illusory.
> The high-level point is that unless inference can chain through dot, default methods will be much weaker (w.r.t. inference) than static methods, and so APIs will be driven to non-fluent (function-oriented) notations.  This is the time to fix it, not later, after we've invented lots of APIs.
Hi John
the problem with your code is that when you have something like:

String r = function(Object::toString).apply(42);

The compiler is type-checking the receiver in isolation, i.e. w/o 
looking at the target type - this is a result of the section you quote 

Now, w/o a target-type, there aren't enough constraints to type-check 
the method reference; type-checking the method reference in fact 
requires knowledge of the instantiated functional descriptor parameter 
types; however, instantiation on those types depends on being able to 
type-check the method reference itself. Hence the loop. You are right 
that the spec doesn't talk about inference loops - javac is giving up in 
those situations, while the spec comes up with a default instantiation 
for the unconstrained variables - which is probably not what you want. 
That's just a cosmetic difference anyway.

Now, to cheer you up; the first example you posted works now as a result 
of the improvements we added to handle unoverloaded method references. 
Here there's a trick at our disposal to unblock the loop: since 
Object::toString is unambiguously pointing to a given method 
(Object.toString), there's no reason why the compiler should block 
type-checking of that method reference waiting for the descriptor 
parameter types. In fact, the compiler now goes ahead and uses the 
information derived during the type-checking of the method reference in 
order to derive a possibly meaningful) instantiation for the inference 
variables in the target functional descriptor.


More information about the lambda-dev mailing list