Change the syntax for package declarations from:
[package Foo] [library "bar"] api;
[package Foo] [library "bar"] impl;
to
[package Foo] [library "bar"];
impl [package Foo] [library "bar"];
The package declaration is currently inconsistent with other Carbon
declarations:
api / impl modifier appears at
the end of the declaration.public because we prioritize the readability of the public
interface over other concerns. However, the api tag in a package API
declaration is mandatory, making the library interface more verbose than
necessary.Proposal #107: Code and name organization introduced the
current syntax. It did
consider the possibility of omitting the api keyword:
We've considered dropping
apifrom naming, but that creates a definition from absence of a keyword. It also would be more unusual if bothimplandtestmust be required, that api would be excluded. We prefer the more explicit name.
However, this argument did not and could not consider the inconsistencies between the choice made for package declaration and the choices made for other declarations, because those inconsistencies were created by later changes:
api keyword as a marker for exporting names from an API
file. Later, proposal #752: api file default public
removed this use of the api keyword, with the new rule being that
declarations are in the public API by default, with an explicit keyword used
to mark non-public declarations. This removed all uses of the api keyword
other than in package declarations.In addition, the idea of having test files in addition to api and impl
files has not yet been realised, and we have no current plans to add such a
feature. While that may be an interesting avenue to pursue in future, using
test as a modifier keyword may also be an interesting avenue to explore in
that case too -- for example, to allow functions and types within an API file to
be declared as test-only with a test modifier -- and so the possibility of
test files isn't a robust rationale for choosing the syntax for api and
impl.
Remove the api keyword from package and library declarations. Consistent
with #752, the way we define a public interface is by saying nothing at all.
Turn the impl keyword on such declarations into a modifier keyword, consistent
with its use in impl fn declarations. This reorders the impl keyword to the
start of the declaration.
In documentation, we refer to API files as "API files", not as "api files".
For consistency, we also refer to implementation files as "implementation
files", not as "impl files". We were previously inconsistent and used both
terms.
See design changes.
impl file will be interpreted as an API file due to
missing the impl modifier. However, this is likely to be caught
quickly, whether by file naming conventions, the lack of an implicit
import of the "real" API file, or by duplicate API file detection in the
toolchain.module Foo vs
export module Foo for the two cases -- with a leading keyword.
However, C++ defaults to not exporting, so the case with a keyword is
reversed, both here and in all other declarations.api or impl as suffixThe rationale for changing from the status quo ante of having a mandatory impl
or api keyword as a suffix is documented above.
This proposal also harmonizes the impl package syntax with the
import package syntax:
impl package Foo library "bar";
import package Baz library "quux";
We consistently use a prefix for the package declaration for both of these
cases. We also anticipate doing so for the import reexport package ... or
export import package ... syntax that is currently under discussion.
As a trivial side benefit, the degenerate case of the package declaration for
the default library in the Main package would now be expressed as simply ;
rather than api;. We retain the rule that the package declaration is omitted
entirely in this case, which is slightly easier to justify given that the
omitted declaration would comprise only a semicolon.
impl modifier before libraryBecause an implementation file is implementing part of a library, we can
consider placing the impl keyword before the library keyword -- as a
modifier on the library portion of the declaration -- instead of at the start
of the overall package declaration.
This leads to constructs such as:
package Foo impl library "bar";
package Foo impl;
impl library "bar";
While there is a logical rationale and consistent explanation for this approach,
it results in the impl keyword's positioning appearing inconsistent: sometimes
at the start, middle, or end of the declaration. This also doesn't make the
impl declaration consistent with import, where the same argument can be
made: an import imports the library, not the package.
As a result, we do not pursue this direction.