On 4/30/2017 4:10 AM, Stephan Herrmann wrote:
No. (B) may be true for your example, but it is not for the following
(which is similar to examples we had in our January thread):

//-- M/module-info.java
module M { exports pm; }

//-- M/impl/Other.java
package impl;
public class Other { }

//-- M/pm/C1.java
package pm;
import impl.Other;
public class C1 extends Other {
     public void m1(Other o) {}
}
//--
//-- O/module-info.java
module O { requires M; }

//-- O/impl/Other.java
package impl;
public class Other { }

//-- O/po/Client.java
package po;
import pm.C1;
public class Client {
     void test1(C1 one) {
         one.m1(one);
     }
}
//--

Looking at O, and trying to determine whether the method invocation
one.m1(one)
is legal, M's type impl.Other is *relevant*, because analysis must ...
- detect that the type reference "Other" in the signature of m1 refers
to the
   type defined in M, not to the same-named type in O.
- similarly detect that the type reference in C1's class header (or
superclass
   classfile attribute) refers to M's impl.Other.
- conclude from the above, that C1 is compatible to m1's parameter.

Ergo, the set of types relevant from the perspective of O contains two
same-named types.

Per 7.3, it's true that when compiling any observable ordinary compilation units associated with O (such as O/po/Client.java), the host system must limit the ordinary compilation units that would otherwise be observable, to only those that are visible to O. Since O requires M, and since M/impl/Other.java is an observable ordinary compilation unit associated with M, we have that M/impl/Other.java is visible to O.

Then, by 6.3, the scope of M's top-level impl package is all observable compilation units in O.

Then, we get the difficulty in 6.5.3.2, because two top-level packages called impl are visible to code in O.

I specified package visibility in 7.3 in the way I did -- not considering exports -- in order to encourage compilers to take a "wide view" of what packages are physically present in required modules, even if a package isn't exported (M's package impl) and thus its types won't be accessible (M's type impl.Other isn't accessible to code in O).

For example, if M's author forgets to export impl (quite possible when M is first declared), I'd like a tool processing O to have the words to say: "impl is /visible/ in M, but not exported, so none of its types -- not even its 'public' types -- can be accessed".

If Java 9 permits this situation, it not only hugely increases the
complexity
of all tools that need to "understand" this program, it also wastes a
unique
opportunity that JPMS has, which existing module systems did not have:

Java 9 could make "API leaks" either illegal or ineffective and thus
rule out
an entire category of ill-formed programs, which to-date must unfortunately
be accepted by module-unaware compilers:

   (A) Java 9 has the opportunity to say that the declaration of m1 is
illegal,
   because it publicly exposes a non-accessible type, which is broken in
   every regard.

   (B) Alternatively, Java 9 has the opportunity to say that any attempt to
   invoke m1 from outside M is illegal, because clients would need to know
   about an inaccessible type.

Understood, but we didn't take those directions. More here: https://bugs.openjdk.java.net/browse/JDK-8153362

Alex

Reply via email to