JDK-6734819 : Javac performs flows analysis on already translated classes
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: unknown
  • Submitted: 2008-08-07
  • Updated: 2011-05-18
  • Resolved: 2011-05-18
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 7 Other
7 b34Fixed OpenJDK6Fixed
Related Reports
Relates :  
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/
08-08-2008

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.
07-08-2008