On 1/8/2017 11:13 AM, Stephan Herrmann wrote:
I'm also surprised that some requirements are indeed specified with
regard to compilation units. Modules export packages, and types are
declared in packages. Isn't it possible to define requirements due to
JPMS solely in those terms (modules, packages, types), and avoid to
mention compilation units in these rules? What do compilation units add
conceptually to JPMS (besides adding complexity)?

Per 7.3: "The ordinary compilation units that are visible to M drive
the packages that are visible to M (§7.4.3), which in turn
drives the top level packages in scope for code in compilation units
associated with M (§6.3)."

Mentioning of top level packages here and in related locations makes
me wonder, whether package nesting (sub packages) is becoming
semantically relevant? I'm even under the impression, that
unnecessarily (?) defining a relation between packages and their
sub-packages leads to the unfortunate hand-waving in 7.4.3 to
discriminate "'really' observable" from "'technically' observable".

Am I missing any of the intended semantics if I consider all packages
as unrelated to each other, no matter whether or not the qualified
name of one package is the prefix of the qualified name of another?

The traditional semantics of subpackages meant that if package P.Q.R was observable (due, say, to an observable compilation unit that declares package P.Q.R), then packages P.Q and P had to be observable too. A compiler processing compilation units in package P.Q.R couldn't turn around and claim to know nothing about package P.Q or P. This enforces the sense of packages forming a hierarchy, because arbitrary "levels" can't be cut out -- a compiler can't claim to know about P.Q.R and P but not P.Q.

I accept that the visible-to-module relation in 7.4.3 essentially mandates a compiler to accept package hierarchies with missing levels, because module exports are exact about packages and care not about subpackages. P.Q.R could be visible to one module and P could be visible to another module, and P.Q is not visible to any module at all.

In addition, the only rule that relied on observability of a package was where 6.3 used it to put the simple name of a top level package in scope (6.5.3 relied on this) -- but that explicitly needed a declaration of package P, not just a declaration of a subpackage. Now that 6.3 and 6.5.3 rely on the visible-to-module relation, there is no need for packages to be "technically" observable in the old sense, and you can consider all packages as unrelated to each other.

As I already mentioned overloading, here's my example of the day:
...

Let me use the example to try validate my understanding of the concepts
involved:

Module Test reads module Base, so when compiling module Test all mentioned
compilation units are observable and visible.

Yes. I don't know what compilation units you mentioned explicitly on the command line, but I'll assume that all interesting compilation units are observable. Because Test reads Base, every package in Base is visible to every compilation unit in Test. I specified it that way as setup for later rules (TBD) that reason about insensible module graphs, e.g., where a package P in module M and a package P in module N are both visible to the same compilation unit (not allowed at run time).

It's just that Base/other.Other is not accessible from any code in
module Test, right?

Right.

I read JLS as associating the *compilation units* with their respective
module.
But then two different compilation units declare types of the same
qualified name, which is an illegal name clash. What am I missing?

It's true that 7.3 also says that all the compilation units of Base
are visible to Other, since Other reads Base. javac is
effectively hiding Base's other.Other type from code in Other, since
Other already has an other.Other type. It's possible we need to
specify this explicitly.

Well, if you don't specify this, it's not part of the language, right?

I'm curious where in the spec this will be integrated.

4.3.4 would be the place to associate types with modules.

Will JLS9 enhance the concept of qualified names for types to include
the module?

No.

If Other/other.Other is visible to module Test it seems we need yet
another term for disambiguation between same-named types from different modules.

OTOH, visibility of this type seems to be crucial for overload resolution
if there's a sub class of Base/other.Other that is accessible from Test.
But: do you *want* Test to be able to invoke Base.test(Other) despite not
having access to the parameter type??

Yes, Test should be able to invoke Base::test(Other) even when Other is not accessible to Test, just like the analogous situation today where Other is package-access and the caller is in a different package but passing an argument whose type extends Other. There is still no conversion between Test's Other type and Base's Other type, so a compiler should still consider Base::test(Other) as inapplicable for Test's invocation.

Lastly, with the interplay of things defined in JLS vs. observability
which is subject to the host system, I wonder if JLS will at least include
"recommendations" regarding the structure of directories and compilation
units. The same holds for "association of a compilation unit to a module".
Otherwise, I'm afraid that different compilers will not be able to compile
projects developed with another compiler simply due to incompatible
directory layouts. Cf. the notion "the filename of the compilation unit is
typically module-info.java", which is still *very* weak, but *much* better
than nothing!

Noted.

Alex

Reply via email to