JDK-8038420 : Lambda returning post-increment generates wrong code
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2014-03-26
  • Updated: 2016-05-27
  • Resolved: 2014-04-10
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 8 JDK 9
8u20Fixed 9 teamFixed
Related Reports
Duplicate :  
Description
The following test produces incorrect behavior for the post-increment operator when it is applied to a boxed Integer being returned from a lambda body.

public class LambdaIncrement {

interface IntOp { int apply(int arg); }
interface IntegerOp { Integer apply(Integer arg); }

static Integer field = 0;

public static final void main(String... args) {
  IntOp preInc = x -> ++x;
  IntegerOp preIncBox1 = x -> ++x;
  IntegerOp preIncBox2 = x -> { return ++x; };
  IntegerOp preIncBox3 = x -> { int y = x; return ++y; };
  IntegerOp preIncBox4 = x -> { Integer y = x; return ++y; };
  IntegerOp preIncField = x -> ++field;
  IntOp postInc = x -> x++;
  IntegerOp postIncBox1 = x -> x++;
  IntegerOp postIncBox2 = x -> { return x++; };
  IntegerOp postIncBox3 = x -> { int y = x; return y++; };
  IntegerOp postIncBox4 = x -> { Integer y = x; return y++; };
  IntegerOp postIncField = x -> field++;
  System.out.println("preInc(3): " + preInc.apply(3)); // expected: 4; actual: 4
  System.out.println("preIncBox1(3): " + preIncBox1.apply(3)); // expected: 4; actual: 4
  System.out.println("preIncBox2(3): " + preIncBox2.apply(3)); // expected: 4; actual: 4
  System.out.println("preIncBox3(3): " + preIncBox3.apply(3)); // expected: 4; actual: 4
  System.out.println("preIncBox4(3): " + preIncBox4.apply(3)); // expected: 4; actual: 4
  System.out.println("postInc(3): " + postInc.apply(3)); // expected: 3; actual: 3
  System.out.println("postIncBox1(3): " + postIncBox1.apply(3)); // expected: 3; actual: 4
  System.out.println("postIncBox2(3): " + postIncBox2.apply(3)); // expected: 3; actual: 4
  System.out.println("postIncBox3(3): " + postIncBox3.apply(3)); // expected: 3; actual: 3
  System.out.println("postIncBox4(3): " + postIncBox4.apply(3)); // expected: 3; actual: 4
  System.out.println("preIncField(3): " + preIncField.apply(3)); // expected: 1; actual: 1
  System.out.println("postIncField(3): " + postIncField.apply(3)); // expected: 1; actual: 1
}

}

Comments
I doubt that 'just restructure the code, e.g. don't use the increment operator' can be a valid workaround for a bug in javac, so from my point of view, ILW=HLH=>P2
08-04-2014

Originally reported on lambda-dev: http://mail.openjdk.java.net/pipermail/lambda-dev/2014-March/011983.html
28-03-2014

I think this happens whenever such lambda parameter is incremented in this way, not only inside the return statement. The reason appears to be that LambdaToMethod marks the parameter's Symbol as FINAL, and Lower.abstractRval then goes through the fast path (see the if in the 'case IDENT:'), not generating all the let expressions needed.
27-03-2014

ILW evaluation: Impact=High (breaking specification -- incorrect runtime behavior) Likelihood=Low (uncommon -- there's no good reason to increment a local variable _after_ returning it) Workaround=Low (just restructure the code, e.g. don't use the increment operator)
26-03-2014