JDK-8043176 : 16.1.10: Add DA/DU rules for lambda expressions
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2014-05-14
  • Updated: 2018-08-03
  • Resolved: 2016-10-13
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.
JDK 9
9Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
Chapter 16 is missing rules for handling DA/DU analysis of lambda expressions.  The existing general expression rules are ambiguous (what are the subexpressions of a lambda?) and not completely correct.

1) A variable is DA/DU after a lambda expression if it is DA/DU before -- lambda expression evaluation never triggers a variable assignment.  The contents of the body are irrelevant.

2) To analyze the lambda body (either an expression or a block), a variable is DA before the body if it is DA before the lambda expression.  This is sort of implied by the existing rules, but not very well.

3) To detect assignments to blank final fields, a field is *never* DU before the lambda body.  (The intuition is that the timing of the body invocation is unknown, so we don't know whether the variable has been initialized or not.)

javac implements (1) and (2) but not (3).  Because it does not implement (3), it allows final fields to be mutated by lambda bodies -- clearly an intolerable state of affairs (see separate javac bug).
Comments
Added a mention of method reference expressions to the list of things that don't have subexpressions. The exception is Primary::m (and ExpressionName::m), in which case the existing rules about the leftmost subexpression are fine as is.
06-10-2016

Changes to 16.1.10: If an expression is not a boolean constant expression, and is not a preincrement expression ++a, predecrement expression --a, postincrement expression a++, postdecrement expression a--, logical complement expression !a, conditional-and expression a && b, conditional-or expression a || b, conditional expression a ? b : c, or assignment expression, then the following rules apply: - If the expression has no subexpressions ***or is a lambda expression***, V is [un]assigned after the expression iff V is [un]assigned before the expression. [Note:] This case applies to literals, names, this (both qualified and unqualified), unqualified class instance creation expressions with no arguments, initialized array creation expressions whose initializers contain no expressions, unqualified superclass field access expressions, named method invocations with no arguments, ***unqualified*** superclass method invocations with no arguments, ***type- or 'super'-qualified method reference expressions, and lambda expressions***. - ***Otherwise***, V is [un]assigned after the expression iff V is [un]assigned after its rightmost immediate subexpression. ... ***For a lambda expression, V is definitely assigned before the expression or block that is the lambda body (15.27.2) iff V is definitely assigned before the lambda expression.*** ***[Note:] No rule allows V to be definitely unassigned before a lambda body. This is by design: a variable that was definitely unassigned before the lambda body may end up being assigned to later on, so we cannot conclude that the variable will be unassigned when the body is executed.*** For any immediate subexpression y of an expression x, ***where x is not a lambda expression,*** V is [un]assigned before y iff one of the following is true: ...
06-10-2016