JDK-8145614 : 9.9: Fix non-wildcard parameterization process to match javac
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 8
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2015-12-17
  • Updated: 2019-09-19
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbd_majorUnresolved
Related Reports
Blocks :  
Relates :  
Relates :  
Description
The "non-wildcard parameterization" process, used to map types to their function types, explicitly gives up whenever it encounters an F-bound:

"If Ai is a wildcard, and the corresponding type parameter's bound, Bi, mentions one of P1...Pn, then Ti is undefined and there is no function type."

javac's behavior in this scenario has been, instead, to use the wildcard's bound, and hope it ends up being in-bounds -- a well-formedness check occurs at the end to see if the type is valid.

JLS should be updated to describe this behavior.
Comments
Some options: 1) I believe javac's behavior can be described as follows (given a type T mentioning ivars ��1...��n, and P1...Pn are the type parameters corresponding to these ��s): - Let T' be [��1:=P1, ..., ��n:=Pn] T - Find the function type of T', if any exists - If so, apply [P1:=��1, ..., Pn:=��n] to the function type to get the actual types we need This seems reasonable, but does not work very well in the spec: there is no notion of "type parameters corresponding to" inference variables, and no mechanism to carry that substitution around with the inference constraint. We could invent something, of course, but that would be a really invasive change for a corner case. 2) Generate function types when the constraint is being created -- something like "x -> expr --> (String)void" rather than "x -> expr --> I<String>". When we create these constraints, we're working with declaration-site types (before substituting in ivars), so this is possible. And we can tell that we're looking at a lambda/mref. Except: other poly expressions that wrap lambdas/mrefs -- worst case is a lambda that returns another lambda, where we end up creating a new constraint in the middle of reduction (18.2.1). 3) Refine the rules for proper types (matching javac), but leave them as is (i.e., current JLS) for types that involve inference variables. This wouldn't be the first time inference makes some ad hoc simplifications when it encounters a problem that is too hard to solve. I worry about surprises, though -- innocent-looking types that have "obvious" function types, but that fail due to their being "polluted" by a random inference variable. Kind of a "falling off a cliff" situation. 4) Like (3), but make the choice per type argument. Feels more intuitive, because failures happen only where there's (hopefully) a clearly problematic bound/ivar interaction. But: we have to assert that the result is well-formed, and an ivar may get substituted into another type arg's bound during this check. Either we introduce another ad hoc failure condition ("if a type argument that mentions an inference variable corresponds to a type parameter that appears in one of the bounds, /false/"), or we teach inference how to get constraints out of a bounds check. Since all of these seem to have fatal flaws, I'm not sure if anything is better than just keeping the spec as is...
11-08-2016

I think the main reason it is defined so conservatively is to interact safely with inference. interface Iface<A1, A2 extends A1> { String m(A1 t); } <T> void m(Iface<Number, ? extends T> arg) {} m(x -> "hi"); Inference gets: x -> "hi" --> Iface<Number, ? extends alpha> In order to handle this, we need to produce 'glb(Number, alpha)', which isn't an operation that works on inference variables; or we need to assert that Iface<Number, alpha> is a well-formed type���which would amount to a constraint on alpha, but inference doesn't know how to do that. All of this is in the context of very shakily-defined well-formedness rules for wildcard-parameterized types. (Is "Iface<Number, ? extends T>" a well-formed type to start with?)
13-07-2016