[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-lambda-spec-observers
Subject:    Re: Minor wording issue around effectively final definition
From:       Dan Smith <daniel.smith () oracle ! com>
Date:       2013-02-12 22:41:09
Message-ID: 0F4995BE-8898-4027-970C-4E22BBB4493B () oracle ! com
[Download RAW message or body]

Thanks for the feedback, Neal.

Note that the constraint about DA/DU is about the point of assignment, not the point \
of capture.

Here, the only assignment to 'i' occurs when it is (!DA)&&DU; and at the only use of \
'i', it is DA:

int i;
i = 2;
if (false) {
    Runnable r = () -> { int j = i; };
}

So everything's okay.

The (!DA)&&DU restriction was introduced to handle situations like this:

int i;
i = 2;
if (false) {
  i = 3;
  Runnable r = () -> { int j = i; };
}

Here, 'i' is DU wherever it is assigned to; but if we were to declare 'i' 'final', \
there would be an error at the point of the second assignment, per JLS 7 6.5.6.1, \
precisely because it is also DA.  That's bad, because we want "effectively final" to \
mean "could have been declared final".

(The treatment of final variables in situations like this was unclear previously, so \
this is a spec change (bug #4721499).  I don't think it has made its way into the \
javac code yet.  Ultimately, the goal will be to make the spec for "final", the spec \
for "effectively final", and the implementation all be in sync.)

Now, back to your original example:

if (false) {
    int i;
    i = 2; // i is both definitely assigned and definitely unassigned here
    Runnable r = () -> { int j = i; }; // error: i not effectively final
}

Here, again, 'i' is both DA&&DU at the assignment, so if it were to be declared \
'final', there would be an error -- you can't assign to a DA final variable.  So 'i' \
shouldn't be effectively final.

But maybe that just pushes the criticism back to the rules about final variables.  It \
is somewhat surprising that this would be illegal:

if (false) {
  int i;
  i = 2; // i is DA, represents a "value", can't be assigned to (per 6.5.6.1)
}

I'll investigate that further.

—Dan

On Feb 12, 2013, at 9:46 AM, Neal Gafter <neal@gafter.com> wrote:

> Sorry, the example should have been
> 
> int i;
> i = 2;
> if (false) {
> // i is both definitely assigned and definitely unassigned here
> Runnable r = () => { int j = i; }; // error: i not effectively final
> }
> 
> Cheers,
> Neal
> 
> On Mon, Feb 11, 2013 at 4:36 PM, Neal Gafter <neal@gafter.com> wrote:
> Here is one example that does not work right according to the spec:
> 
> if (false) {
> int i;
> i = 2; // i is both definitely assigned and definitely unassigned here
> Runnable r = () => { int j = i; }; // error: i not effectively final
> }
> 
> One way to fix this section of the spec is to remove the words "and not definitely \
> assigned" twice where they appear in the definition of effectively final. 
> On Mon, Feb 11, 2013 at 10:53 AM, Dan Smith <daniel.smith@oracle.com> wrote:
> On Feb 11, 2013, at 7:00 AM, Srikanth S Adayapalam <srikanth_sankaran@in.ibm.com> \
> wrote: 
> > Hello !
> > 
> > 0.6.1 (4.12.4) reads:
> > 
> > A local variable or a method, constructor, lambda, or exception parameter is \
> > effectively final if it is not final but it never occurs as the left hand operand \
> > of an assignment operator (15.26) or as the operand of an increment or decrement \
> > operator (15.14, 15.15). [jsr335-4.12.4-10]
> 
> > In addition, a local variable whose declaration lacks an initializer is \
> > effectively final if all of the following are true: [jsr335-4.12.4-20] 
> > • It is not final. [jsr335-4.12.4-20-A]
> > • Whenever it occurs as the left-hand operand of an assignment operator, it is \
> > definitely unassigned and not definitely assigned before the assignment (that is, \
> > it is definitely unassigned and not definitely assigned after the right-hand \
> > operand of the assignment) (16). 
> > I think the first sentence meant to say, never occurs as the left hand operand of \
> > a *compound* assignment operator.
> 
> The intent is to cover both compound and simple assignments.
> 
> The first sentence says that if you never assign to a variable, it's effectively \
> final. 
> The second sentence says that if you _do_ assign to a variable, it may still be \
> effectively final if the assignment is the _first_ assignment. 
> Note that there's a restriction, separate from "effectively final," that a variable \
> must be definitely assigned wherever it is referenced, including in a compound \
> assignment. 
> I think the complexities you're worried about are bundled up inside the definitions \
> of "definitely unassigned" and "definitely assigned".  But if you're unsure, feel \
> free to share a concrete example of something you don't think will work right. 
> —Dan
> 
> 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic