Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "JDT Core/Java9/JLS9"

Line 50: Line 50:
 
Generalizing from this observation, we may have to respect '''overloading''' of all kinds of notions,
 
Generalizing from this observation, we may have to respect '''overloading''' of all kinds of notions,
 
i.e., ''property-x'' of ''element-a'' need not be related to ''property-x'' of ''element-b''.
 
i.e., ''property-x'' of ''element-a'' need not be related to ''property-x'' of ''element-b''.
 +
 +
=Dealing with ambiguous names=
 +
Let's now try to find out how a compiler is supposed to handle ambiguous names, in particular with regard to package names and qualified type names, possibly referring to elements from different modules.
 +
 +
Let's assume that this question will be answered in section 6.5 ("Determining the meaning of a name").
 +
 +
;6.5.3.2 Qualified Package Names:
 +
:If a package name is of the form Q.Id, then Q must also be a package name. The package name Q.Id names a package that is the member named Id within the package named by Q.
 +
:If Q.Id does not name a package visible to the current module, then a compile-time error occurs.
 +
 +
Nothing hints at the possibility for multiple packages of the same name (per module), so if two modules would try to declare the same package we should probably consider this as one '''split package'''. This is also in line with this sentence:
 +
;6.4.1 Shadowing
 +
:[...] A package declaration never shadows any other declaration.
 +
implying that in particular a package from one module cannot shadow a same-named package from another module.
 +
 +
From hear-say we know that split packages should be banned from Java 9, but where would this be defined and what kind of error should be signalled?
 +
 +
;6.5.5.2 Qualified Type Names
 +
:If a type name is of the form Q.Id, then Q must be either a type name or a package name.
 +
:If a type name is of the form Q.Id, then Q must be either the name of a visible type or the name of a visible package.
 +
:If Id names exactly one accessible type (§6.6) that is a member of the type or package denoted by Q, then the qualified type name denotes that type.
 +
 +
The last sentence could accommodate the situation that a package Q might contain multiple accessible types named Id, in which case the qualified type name Q.Id cannot be resolved.
 +
* Does this mean a name clash (wrt fully qualified names) between two types from different modules should be flagged as a compile error?
 +
* Does this mean a name clash involving one accessible type and one or more inaccessible types is ''not'' an error?
 +
* If the latter, does this mean that split packages (across modules) without clashing type names are ''not'' an error?
 +
 +
The above definitions are also based on visibility of packages and accessibility of types. We already discussed accessibility of types, but how is visibility of packages defined?
 +
 +
When speaking of "visible", the JLS text typically refers to 6.4.1 (Shadowing), with the following exception:
 +
;6.3 Scope of a declaration
 +
:[...] The scope of the declaration of an observable top level package (§7.4.3) is all observable compilation units associated with modules to which the package is visible (§7.3).
 +
Hence, visibility of packages should be defined in 7.3.
 +
 +
;7.3 Compilation Units
 +
:[...] The ordinary compilation units that are visible to M are the observable ordinary compilation units associated with modules read by M. The host system must use the Java Platform Module System to determine which modules are read by M (§7.7.1).
 +
: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).
 +
The first sentence was already discussed above. What's new is the fact that a package p is visible to M if any compilation unit declaring the package p is visible to M.
 +
 +
Ergo, in the hypothetical case that multiple modules declare types in the same package p, p will be visible to M if only one type from a module M1 is visible to M, disregarding the possibility that M2 may define more types in p, which may be invisible to M.
 +
 +
Let's look into the section referenced from 7.3:
 +
;7.4.3 Observability of a Package
 +
:A package is visible to a module if and only if an ordinary compilation unit containing a declaration of the package is visible to the module.
 +
 +
Yep, no contradiction to my hypothesis.
 +
  
 
''to be continued''
 
''to be continued''
 +
 +
=Critique=
 +
==Confusion==
 +
JLS introduces many terms, but "visibility" is not always the same, visibility of declarations significantly differs from visibility of compilation units.
 +
 +
Also the term "observability" comes in different flavors, as 7.4.3 introduces a distinction between "'technically' observable" and "'really' observable". I ''believe'' this distinction only works around the legacy that packages are defined to span a containment tree (packages as members of other packages), whereas JPMS wants to regard all packages as independent, disregarding "containment" / "membership".

Revision as of 12:14, 29 December 2016

This page is a working document of attempts to map current drafts of JLS to the semantics as it should be implemented by the compiler.

To determine legal program structures a number of concepts must be considered, including:

  • scope
  • visibility
  • importing
  • accessibility
  • observability

Due to lots of cross-references between definitions, it is difficult (impossible?) to introduce and define one concept at a time without already defining all the other concepts. E.g., scoping and visibility are defined in what looks like a cyclic definition:

  • 6.3: The scope of a declaration is the region of the program within which the entity declared by the declaration can be referred to using a simple name, provided it is visible (§6.4.1).
  • 6.4.1: A declaration d is said to be visible at point p in a program if the scope of d includes p, and d is not shadowed by any other declaration at p.

I.e., scoping depends on visibility and visibility depends on scoping.

Accessibility of a type

Let's try to define the algorithm for determining accessibility of a type.

Start at 6.6.1 Determining Accessibility:

If a top level class or interface type is declared public and is a member of a package that is exported by a module, then the type may be accessed by any code in the same module, and by any code in another module to which the package is exported, provided that the compilation unit in which the type is declared is visible to that other module (§7.3).

so our checklist for cross-module accessibility is

  • type is public
  • containing package is exported by a module
  • referring code location is within another module to which the package is exported
  • compilation unit is visible to the other module

When is a compilation unit visible to a given module?

7.3 Compilation Units

[...] The ordinary compilation units that are visible to M are the observable ordinary compilation units associated with modules read by M. […]

Most of this is determined by "the host system" (i.e., not specified by JLS):

  • observability of a compilation unit (7.3)
  • association of a compilation unit to a module (7.3)

Remains: source and target modules have a reads connection.

The host system must use the Java Platform Module System to determine which modules are read by M (§7.7.1).

7.7.1 is still empty as of 2016-12-16

JLS has another definition of visibility in 6.4.1:

A declaration d is said to be visible at point p in a program if the scope of d includes p, and d is not shadowed by any other declaration at p.

but this seems to be a different concept than the visibility between a module and a compilation unit, maybe because a compilation unit is not a declaration. Generalizing from this observation, we may have to respect overloading of all kinds of notions, i.e., property-x of element-a need not be related to property-x of element-b.

Dealing with ambiguous names

Let's now try to find out how a compiler is supposed to handle ambiguous names, in particular with regard to package names and qualified type names, possibly referring to elements from different modules.

Let's assume that this question will be answered in section 6.5 ("Determining the meaning of a name").

6.5.3.2 Qualified Package Names
If a package name is of the form Q.Id, then Q must also be a package name. The package name Q.Id names a package that is the member named Id within the package named by Q.
If Q.Id does not name a package visible to the current module, then a compile-time error occurs.

Nothing hints at the possibility for multiple packages of the same name (per module), so if two modules would try to declare the same package we should probably consider this as one split package. This is also in line with this sentence:

6.4.1 Shadowing
[...] A package declaration never shadows any other declaration.

implying that in particular a package from one module cannot shadow a same-named package from another module.

From hear-say we know that split packages should be banned from Java 9, but where would this be defined and what kind of error should be signalled?

6.5.5.2 Qualified Type Names
If a type name is of the form Q.Id, then Q must be either a type name or a package name.
If a type name is of the form Q.Id, then Q must be either the name of a visible type or the name of a visible package.
If Id names exactly one accessible type (§6.6) that is a member of the type or package denoted by Q, then the qualified type name denotes that type.

The last sentence could accommodate the situation that a package Q might contain multiple accessible types named Id, in which case the qualified type name Q.Id cannot be resolved.

  • Does this mean a name clash (wrt fully qualified names) between two types from different modules should be flagged as a compile error?
  • Does this mean a name clash involving one accessible type and one or more inaccessible types is not an error?
  • If the latter, does this mean that split packages (across modules) without clashing type names are not an error?

The above definitions are also based on visibility of packages and accessibility of types. We already discussed accessibility of types, but how is visibility of packages defined?

When speaking of "visible", the JLS text typically refers to 6.4.1 (Shadowing), with the following exception:

6.3 Scope of a declaration
[...] The scope of the declaration of an observable top level package (§7.4.3) is all observable compilation units associated with modules to which the package is visible (§7.3).

Hence, visibility of packages should be defined in 7.3.

7.3 Compilation Units
[...] The ordinary compilation units that are visible to M are the observable ordinary compilation units associated with modules read by M. The host system must use the Java Platform Module System to determine which modules are read by M (§7.7.1).
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).

The first sentence was already discussed above. What's new is the fact that a package p is visible to M if any compilation unit declaring the package p is visible to M.

Ergo, in the hypothetical case that multiple modules declare types in the same package p, p will be visible to M if only one type from a module M1 is visible to M, disregarding the possibility that M2 may define more types in p, which may be invisible to M.

Let's look into the section referenced from 7.3:

7.4.3 Observability of a Package
A package is visible to a module if and only if an ordinary compilation unit containing a declaration of the package is visible to the module.

Yep, no contradiction to my hypothesis.


to be continued

Critique

Confusion

JLS introduces many terms, but "visibility" is not always the same, visibility of declarations significantly differs from visibility of compilation units.

Also the term "observability" comes in different flavors, as 7.4.3 introduces a distinction between "'technically' observable" and "'really' observable". I believe this distinction only works around the legacy that packages are defined to span a containment tree (packages as members of other packages), whereas JPMS wants to regard all packages as independent, disregarding "containment" / "membership".

Back to the top