Bug 420660 - [1.8][api] Make "effectively final" state of local variables available
Summary: [1.8][api] Make "effectively final" state of local variables available
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.3   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: BETA J8   Edit
Assignee: Jay Arthanareeswaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 420665 421348 421564 421846
  Show dependency tree
 
Reported: 2013-10-29 14:43 EDT by Markus Keller CLA
Modified: 2013-11-15 10:44 EST (History)
2 users (show)

See Also:


Attachments
Patch with test (7.01 KB, patch)
2013-11-12 02:39 EST, Jay Arthanareeswaran CLA
no flags Details | Diff
Updated patch (11.89 KB, patch)
2013-11-13 05:54 EST, Jay Arthanareeswaran CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Keller CLA 2013-10-29 14:43:59 EDT
Make the "effectively final" state of local variables available. Should be easy to do in IVariableBinding. Would also be very handy in ILocalVariable if possible.

We could sneak this into getModifiers()/getFlags() with an internal flag, but I guess it's better to add a boolean isEffectivelyFinal() API instead.
Comment 1 Srikanth Sankaran CLA 2013-11-11 00:02:10 EST
Jay, this is blocking 2 UI work items. Thanks for taking a look.
I wonder if we should change this snippet in Assignment.resolveType:

if (localVariableBinding != null && localVariableBinding.isCatchParameter()) { 


to also include localVariableBinding.isParameter()

Not strictly necessary for this ER, but ...
Comment 2 Jay Arthanareeswaran CLA 2013-11-12 02:39:25 EST
Created attachment 237384 [details]
Patch with test

Patch includes new API IVariableBinding with its implementation and new test. I haven't introduced the API in ILocalVariable since it's not straight forward in some of the cases, esp. when we recreate the element from the memento or binaries.

Markus, let me know if you would like changes in ILocalVariable as well. Perhaps we can take that up via a new bug.
Comment 3 Markus Keller CLA 2013-11-12 13:40:25 EST
You probably got tricked by the abbreviated definition of "effectively final" in the non-normative "Summary" section of the jsr335 document, which is not complete enough for an API (where incomplete == wrong).

Since the full definition is too long, the API should just refer to JLS8, e.g.:

 * Returns whether this binding corresponds to an effectively final local
 * variable (JLS8 4.12.4). Informally, an effectively final local variable is
 * not final and it is never assigned to after its initialization.

The implementation needs to be adapted to the spec definition. Please check if it would make sense to fix the internal usage of TagBits.IsEffectivelyFinal as well.

Example to test:

    void m() {
        final int finalVar = 1; // not effectively final!
        int effectivelyFinalVar = 2;
        int nonFinalVar = 3;
        nonFinalVar = 4;
        try {
            
        } catch (java.io.IOError | IllegalStateException implicitlyFinalExc) {
            // implicitlyFinalExc is not effectively final!
        } catch (Exception effectivelyFinalExc) {
        }
    }

> Markus, let me know if you would like changes in ILocalVariable as well.
> Perhaps we can take that up via a new bug.

Yes. A separate bug is also fine.
Comment 4 Srikanth Sankaran CLA 2013-11-13 03:29:19 EST
(In reply to Markus Keller from comment #3)

> The implementation needs to be adapted to the spec definition. Please check
> if it would make sense to fix the internal usage of
> TagBits.IsEffectivelyFinal as well.

I think the compiler implementation sets this bits eagerly on any local
variable under the presumed innocent until proven guilty model and the 
meaning is also a bit loose but "effectively correct" for our purposes :)

It simply encompasses final, effectively final and implicitly final. This
is perfect enough for the compiler and I would not change it. For the API,
we could make other checks to discriminate.

> Example to test:

Jay, could you also add a resource variable to the test below ?
Comment 5 Srikanth Sankaran CLA 2013-11-13 04:12:26 EST
(In reply to Srikanth Sankaran from comment #4)

> meaning is also a bit loose but "effectively correct" for our purposes :)

"Effectively correct" is too strong perhaps, "effectively effective" could
be a better description.

> Jay, could you also add a resource variable to the test below ?

You may also want to add a test for enhanced for loop. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=382721#c7
Comment 6 Jay Arthanareeswaran CLA 2013-11-13 05:54:16 EST
Created attachment 237419 [details]
Updated patch

Patch includes updated doc - have added 'not final' to the doc. Note: I have not specified that 'final' includes both implicit and explicit as this this implied.

Also added more test cases and removed one unnecessary piece of code in LocalVariableBinding.
Comment 7 Markus Keller CLA 2013-11-13 06:57:31 EST
> Patch includes updated doc - have added 'not final' to the doc. Note: I have
> not specified that 'final' includes both implicit and explicit as this this
> implied.

In general, I agree that keywords in Javadocs should be enclosed in <code>, but as you said, the 'final' in this case also includes implicitly final variables, so it would be better to not mark 'final' as a keyword here.

> "effectively effective"

Sounds good ;-). Maybe add a comment like
// includes explicitly and implicitly final
to TagBits#IsEffectivelyFinal to avoid surprises in a few years?
Comment 8 Srikanth Sankaran CLA 2013-11-13 09:09:49 EST
(In reply to Markus Keller from comment #7)

> Sounds good ;-). Maybe add a comment like
> // includes explicitly and implicitly final
> to TagBits#IsEffectivelyFinal to avoid surprises in a few years?

Jay, please incorporate this suggestion before releasing, thanks.
Comment 9 Srikanth Sankaran CLA 2013-11-14 00:08:58 EST
(In reply to Srikanth Sankaran from comment #8)
> (In reply to Markus Keller from comment #7)
> 
> > Sounds good ;-). Maybe add a comment like
> > // includes explicitly and implicitly final
> > to TagBits#IsEffectivelyFinal to avoid surprises in a few years?
> 
> Jay, please incorporate this suggestion before releasing, thanks.

Alternately, we can rename TagBits#IsEffectivelyFinal to be TagBits.IsImmutable
Comment 10 Jay Arthanareeswaran CLA 2013-11-14 00:27:06 EST
(In reply to Srikanth Sankaran from comment #9)
> Alternately, we can rename TagBits#IsEffectivelyFinal to be
> TagBits.IsImmutable

That sounds misleading to me. If it's not explicitly or implicitly final it's not really immutable, right? Since this is internal, I think we can just go with additional comment.
Comment 11 Srikanth Sankaran CLA 2013-11-14 00:30:45 EST
(In reply to Jayaprakash Arthanareeswaran from comment #10)
> (In reply to Srikanth Sankaran from comment #9)
> > Alternately, we can rename TagBits#IsEffectivelyFinal to be
> > TagBits.IsImmutable
> 
> That sounds misleading to me. If it's not explicitly or implicitly final
> it's not really immutable, right? 

Correct, but why do you think it is misleading ? We start out with IsImmutable 
set to true as we do now with IsEffectivelyFinal set to true and clear it on 
the first assignment we see after a definite or potential assignment.
Comment 12 Jay Arthanareeswaran CLA 2013-11-14 00:34:19 EST
(In reply to Srikanth Sankaran from comment #11)
> Correct, but why do you think it is misleading ? We start out with
> IsImmutable 
> set to true as we do now with IsEffectivelyFinal set to true and clear it on 
> the first assignment we see after a definite or potential assignment.

I always thought immutable meant 'something that can't be changed'. But here we need something like, 'something that has not been changed', right?
Comment 13 Srikanth Sankaran CLA 2013-11-14 00:44:33 EST
(In reply to Jayaprakash Arthanareeswaran from comment #12)

> I always thought immutable meant 'something that can't be changed'. But here
> we need something like, 'something that has not been changed', right?

OK, I see what you mean. I was looking for a word that would not call for
change in code (other than the rename propagation) by having to invert polarity.
Does either of IsCaptureableByLambda or IsUnmutated sound good ?

Otherwise we can leave it as is + a comment explaining it also signifies
final variables of explicit/implicit finality.
Comment 14 Jay Arthanareeswaran CLA 2013-11-14 01:10:25 EST
All tests passed and pushed the changes (with just a comment for isEffectivelyFinal) :

http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=6c7de59cc4e8b7d3ff952cb73eea6ba69e83b190
Comment 15 Jay Arthanareeswaran CLA 2013-11-14 01:17:23 EST
Marking as resolved.