Compiling Java 9 (take 2)

Alex Buckley alex.buckley at oracle.com
Tue Jan 10 00:35:35 UTC 2017


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


More information about the jigsaw-dev mailing list