[Jastadd] [bug report] two different instances of TypeDecl for a single type.

From: Na, Hyunik <hina_at_kaist.ac.kr>
Date: Thu, 26 Apr 2012 17:23:25 +0900

Hello JastAddJ developers,

Make two directories pkgA and pkgB and put the following two java files to
each directories pkgA and pkgB, respectively.

-=-=-= A.java -=-=-=
package pkgA;

public class A {
  A test() {
    return new pkgB.B();

-=-=-= B.java -=-=-=
package pkgB;

import pkgA.*;

public class B extends A {

and try to compile pkgA/A.java with JastAddJ (rev. 9238).
In my case, I met the following error message.

  Semantic Error: return value must be an instance of pkgA.A which pkgB.B is

But, you can easily see that pkgB.B is declared as a subclass of pkgA.A, and
that this is a correct program.

Tracking the cause of this problem showed that the TypeDecl instance of A
the one of B's superclass (which is also A) are different.
Subtype check B <: A eventually led to Object <: A which is false.
It should stop at A <: A which returns true. The 'true' is supposed to be
returned by the following line

        syn boolean TypeDecl.isSupertypeOfClassDecl(ClassDecl type) = type
== this;

in TypeAnalysis.jrag in case of Java 1.4, or by

        syn boolean TypeDecl.supertypeClassDecl(ClassDecl type) = type ==

in GenericsSubtype.jrag in case of Java 1.5.

In short, TypeDecl instances corresponding to class A and B's superclass are
not the same.

Compiling with -verbose option gave me a hint about the cause of the

Loading .java file: pkgA/A.java in 159 ms
Loading .class file: java.lang.Object from
/home/hina/myWork/openjdk_classes/java/lang/Object.class in 8 ms
Loading .class file: java.lang.Throwable from
/home/hina/myWork/openjdk_classes/java/lang/Throwable.class in 4 ms
Loading .class file: java.lang.Deprecated from
/home/hina/myWork/openjdk_classes/java/lang/Deprecated.class in 3 ms
Loading .java file: pkgB.B in 1 ms
Loading .java file: pkgA.A in 1 ms // <== A is loaded again!
  Semantic Error: return value must be an instance of pkgA.A which pkgB.B is

There seems to be a recent change in how types are looked up.
The following four lines in LookupType.jrag of rev. 9238:

        // Type requests from the library stays in the library
        eq Program.getChild().lookupType(String packageName, String
typeName) = lookupLibType(packageName, typeName);
        // Type requests from the source checks the source and then the
        eq Program.getCompilationUnit(int i).lookupType(String packageName,
String typeName) = lookupType(packageName, typeName);

were the following single line in rev. 9211 which my work is based on:

        eq Program.getChild().lookupType(String packageName, String
typeName) = lookupType(packageName, typeName);

Probably, in current JastAddJ, type requests from a library will search
the existing library or loads a class/java file even when the type is in one

of the CompilationUnits of the program.
Perhaps, this is the cause of the reloading pkg.A and two copies of TypeDecl
instances for a single type A.

So, I just restored the original Program.getChild().lookupType(), tried the
example again, and got the correct result.
I believe the original let the CompilationUnits of a program be searched
first even when a
type request comes from a library, which is desirable.

The above A and B classes example is simplified from
org.ietf.jgss.GSSManager and sun.security.jgss.GSSManagerImpl classes
in the OpenJDK1.6 which produced the same error message.

Many error messages which are seemingly related to subtyping disappeared
with this restoration,
when compiling whole java files.

Of course, I'm not sure about this modification.
Is it appropriate? Does it cause a problem with other parts of the compiler?
Please check.

- Hyunik
Received on Thu Apr 26 2012 - 10:23:38 CEST

This archive was generated by hypermail 2.3.0 : Wed Apr 16 2014 - 17:19:06 CEST