United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6734819 Javac performs flows analysis on already translated classes
JDK-6734819 : Javac performs flows analysis on already translated classes

Details
Type:
Bug
Submit Date:
2008-08-07
Status:
Closed
Updated Date:
2011-05-18
Project Name:
JDK
Resolved Date:
2011-05-18
Component:
tools
OS:
generic
Sub-Component:
javac
CPU:
unknown
Priority:
P3
Resolution:
Fixed
Affected Versions:
7
Fixed Versions:

Related Reports
Backport:
Relates:

Sub Tasks

Description
STEP TO REPRODUCE THE PROBLE

class Y extends W {}
class W extends Z {}

class Z {
   static void m(Z z) {
       W w = (W)z;
   }
}

put all the classes in a single file (e.g. Test.java) and then execute the command:
javac Test.java -Xlint:all -XDverboseCompilePolicy

EXPECTED BEHAVIOUR

compilation passes with no warning

ACTUAL BEHAVIOR

the compiler generates a warning:

Test.java:6: warning: [cast] redundant cast to W
       W w = (W)z;
                   ^


It seems like Z's flow analysis is executed *after* Y's erasure - that is when Z itself has already been recursively erased.

                                    

Comments
SUGGESTED FIX

A webrev of this fix is available at http://sa.sfbay.sun.com/projects/langtools_data/7/6734819/
                                     
2008-08-08
EVALUATION

This is a regression that has been introduced by 6726015; that fix changed the order in which classes get desugared in the compiler pipeline. Let's have a look at the pipeline when compling the attached test case (those info have been generated by using -XDverboseCompilePolicy option)

The current (erroneous) behavior is:

1) Attr Y
2) Flow Y
3) Lower Y
3b) Attr W
3c) Flow W
4) Gen Y //at this point both Y, W and Z are erased (that is after Y's Lowering)
5) Lower W
5b) Attr Z
5c) Flow Z (Flow is executed on an erased AST!!)
6) Gen W
7) Lower Z - do nothing
8) Gen Z

It can be seen that flow analysis is indeed performed on Z only *after* Z has been erased (as a side-effect of erasing its supertype Y). This happens because the ScanNested visitor in JavaCompiler doesn't add all Y's supertypes in the dependency list that is then used in order to perform attribution and flow analysis on all the classes the class being desgugared depends on - only the direct supertype is added to the list.

This means that when desugaring Y, javac realizes that also W has to be attributed and analyzed - but that's it; instead javac should force also the attribution and analysis of Z (which is another, indirect,  supertype of Y).  If we do so the execution flows changes as follows:

1) Attr Y
2) Flow Y
3) Lower Y //Y is delayed because  Y's supertype  has not been lowered yet
3b) Attr W
3c) Flow W
3d) Attr Z
3e) Flow Z
4) Gen Y //at this point both Y, W and Z are erased (that is after Y's Lowering)
5) Lower W
6) Gen W
7) Lower Z
8) Gen Z

Note: javac used to defer desugaring of classes that have non-trivial supertype dependencies - which means that those classes were effectively moved at the end of the compiler pipeline. We want to avoid this behavior, as it poses severe problems wrt to future multi-threading patch that might improve the compiler pipeline.
                                     
2008-08-07



Hardware and Software, Engineered to Work Together