Просмотр исходного кода

More consistent package syntax (#3927)

Change the syntax for `package` declarations from:

```carbon
[package Foo] [library "bar"] api;
[package Foo] [library "bar"] impl;
```

to

```carbon
[package Foo] [library "bar"];
impl [package Foo] [library "bar"];
```
Richard Smith 1 год назад
Родитель
Сommit
6bbbd4ec1f

+ 46 - 42
docs/design/README.md

@@ -194,7 +194,7 @@ The `import` declaration imports a
 [library from a package](#files-libraries-packages). It must appear at the top
 of a Carbon source file, the first thing after the
 [optional `package` declaration](#package-declaration). Libraries can optionally
-be split into [api and implementation files](#files-libraries-packages), like
+be split into [API and implementation files](#files-libraries-packages), like
 C++'s header and source files but without requiring a source file in any cases.
 This declaration from the example:
 
@@ -963,13 +963,14 @@ forward declaration that introduces the name before it is defined, plus any
 number of declarations in a
 [`match_first` block](generics/details.md#prioritization-rule). Forward
 declarations can be used to separate interface from implementation, such as to
-declare a name in an [api file](#files-libraries-packages) that is defined in an
-[impl file](#files-libraries-packages). Forward declarations also allow entities
-to be used before they are defined, such as to allow cyclic references. A name
-that has been declared but not defined is called _incomplete_, and in some cases
-there are limitations on what can be done with an incomplete name. Within a
-definition, the defined name is incomplete until the end of the definition is
-reached, but is complete in the bodies of member functions because they are
+declare a name in an [API file](#files-libraries-packages) that is defined in an
+[implementation file](#files-libraries-packages). Forward declarations also
+allow entities to be used before they are defined, such as to allow cyclic
+references. A name that has been declared but not defined is called
+_incomplete_, and in some cases there are limitations on what can be done with
+an incomplete name. Within a definition, the defined name is incomplete until
+the end of the definition is reached, but is complete in the bodies of member
+functions because they are
 [parsed as if they appeared after the definition](#class-functions-and-factory-functions).
 
 A name is valid until the end of the innermost enclosing
@@ -2190,13 +2191,15 @@ selected yet.
 ### Files, libraries, packages
 
 -   **Files** are grouped into libraries, which are in turn grouped into
-    packages.
+    packages. There are two kinds of files:
+    -   API files describe the interface of a library.
+    -   Implementation files implement part of the interface of a library.
 -   **Libraries** are the granularity of code reuse through imports.
 -   **Packages** are the unit of distribution.
 
-Each library must have exactly one `api` file. This file includes declarations
-for all public names of the library. Definitions for those declarations must be
-in some file in the library, either the `api` file or an `impl` file.
+Each library must have exactly one API file. This file includes declarations for
+all public names of the library. Definitions for those declarations must be in
+some file in the library, either the API file or an implementation file.
 
 Every package has its own namespace. This means libraries within a package need
 to coordinate to avoid name conflicts, but not across packages.
@@ -2211,11 +2214,12 @@ to coordinate to avoid name conflicts, but not across packages.
 
 Files start with an optional package declaration, consisting of:
 
+-   optionally, the `impl` modifier keyword, indicating the file is an
+    implementation file rather than an API file,
 -   optionally, the `package` keyword followed by an identifier specifying the
     package name,
 -   optionally, the `library` keyword followed by a string with the library
-    name,
--   either `api` or `impl`, and
+    name, and
 -   a terminating semicolon (`;`).
 
 For example:
@@ -2223,25 +2227,25 @@ For example:
 ```carbon
 // Package name is `Geometry`.
 // Library name is "Shapes".
-// This file is an `api` file, not an `impl` file.
-package Geometry library "Shapes" api;
+// This file is an API file, not an implementation file.
+package Geometry library "Shapes";
 ```
 
 Parts of this declaration may be omitted:
 
--   If the package keyword is not specified, as in `library "Widgets" api;`, the
+-   If the package keyword is not specified, as in `library "Widgets";`, the
     file contributes to the `Main` package. No other package may import from the
     `Main` package, and it cannot be named explicitly.
 
--   If the library keyword is not specified, as in `package Geometry api;`, this
+-   If the library keyword is not specified, as in `package Geometry;`, this
     file contributes to the default library.
 
 -   If both keywords are omitted, the package declaration must be omitted
-    entirely. In this case, the file is an `impl` file belonging to the default
-    library of the `Main` package, which implicitly has an empty `api` file.
-    This library is used to define the entry point for the program, and tests
-    and smaller examples may choose to reside entirely within this library. No
-    other library can import this library even from within the default package.
+    entirely. In this case, the file is the API file for the default library of
+    the `Main` package, which cannot have any implementation files. This library
+    is used to define the entry point for the program, and tests and smaller
+    examples may choose to reside entirely within this library. No other library
+    can import this library even from within the default package.
 
 If the default library of the `Main` package contains a function named `Run`,
 that function is the program entry point. Otherwise, the program's entry point
@@ -2282,11 +2286,11 @@ given library to the top-level scope of the current file as
 [`private`](#name-visibility) names, and similarly for names in
 [namespaces](#namespaces).
 
-Every `impl` file automatically imports the `api` file for its library.
+Every implementation file automatically imports the API file for its library.
 Attempting to perform an import of the current library is invalid.
 
 ```
-package MyPackage library "Widgets" impl;
+impl package MyPackage library "Widgets";
 
 // ❌ Error, this import is performed implicitly.
 import MyPackage library "Widgets";
@@ -2309,7 +2313,7 @@ When the package name is specified, the `import` declaration imports a library
 from another package.
 
 ```carbon
-package MyPackage impl;
+impl package MyPackage;
 
 // Import the "Vector" library from the `LinearAlgebra` package.
 import LinearAlgebra library "Vector";
@@ -2344,17 +2348,17 @@ package can only be imported from within that package.
 
 The names visible from an imported library are determined by these rules:
 
--   Declarations in an `api` file are by default _public_, which means visible
-    to any file that imports that library. This matches class members, which are
+-   Declarations in an API file are by default _public_, which means visible to
+    any file that imports that library. This matches class members, which are
     also [default public](#access-control).
--   A `private` prefix on a declaration in an `api` file makes the name _library
-    private_. This means the name is visible in the file and all `impl` files
-    for the same library.
+-   A `private` prefix on a declaration in an API file makes the name _library
+    private_. This means the name is visible in the file and all implementation
+    files for the same library.
 -   The visibility of a name is determined by its first declaration, considering
-    `api` files before `impl` files. The `private` prefix is only allowed on the
-    first declaration.
--   A name declared in an `impl` file and not the corresponding `api` file is
-    _file private_, meaning visible in just that file. Its first declaration
+    API files before implementation files. The `private` prefix is only allowed
+    on the first declaration.
+-   A name declared in an implementation file and not the corresponding API file
+    is _file private_, meaning visible in just that file. Its first declaration
     must be marked with a `private` prefix. **TODO:** This needs to be finalized
     in a proposal to resolve inconsistency between
     [#665](https://github.com/carbon-language/carbon-lang/issues/665#issuecomment-914661914)
@@ -2363,7 +2367,7 @@ The names visible from an imported library are determined by these rules:
     to: two different libraries can have different private names `foo` without
     conflict, but a private name conflicts with a public name in the same scope.
 
-At most one `api` file in a package transitively used in a program may declare a
+At most one API file in a package transitively used in a program may declare a
 given name public.
 
 > References:
@@ -2383,9 +2387,9 @@ given name public.
 The top-level scope in a file is the scope of the package. This means:
 
 -   Within this scope (and its sub-namespaces), all visible names from the same
-    package appear. This includes names from the same file, names from the `api`
-    file of a library when inside an `impl` file, and names from imported
-    libraries of the same package.
+    package appear. This includes names from the same file, names from the API
+    file of a library when inside an implementation file, and names from
+    imported libraries of the same package.
 -   In scopes where package members might have a name conflict with something
     else, the syntax `package.Foo` can be used to name the `Foo` member of the
     current package.
@@ -2441,7 +2445,7 @@ namespace are considered in scope and may be found by
 package `P` defines some of its members inside a namespace `N`:
 
 ```carbon
-package P api;
+package P;
 
 // Defines namespace `N` within the current package.
 namespace N;
@@ -2642,8 +2646,8 @@ fn F();
 
 Common types that we expect to be used universally will be provided for every
 file are made available as if there was a special "prelude" package that was
-imported automatically into every `api` file. Dedicated type literal syntaxes
-like `i32` and `bool` refer to types defined within this package, based on the
+imported automatically into every API file. Dedicated type literal syntaxes like
+`i32` and `bool` refer to types defined within this package, based on the
 ["all APIs are library APIs" principle](/docs/project/principles/library_apis_only.md).
 
 > **TODO:** Prelude provisionally imports the `Carbon` package which includes

+ 1 - 1
docs/design/classes.md

@@ -2137,7 +2137,7 @@ implications:
 However, there are likely to be differences between computed properties and
 other data members, such as the ability to take the address of them. We might
 want to support "read only" data members, that can be read through the public
-api but only modified with private access, for data members which may need to
+API but only modified with private access, for data members which may need to
 evolve into a computed property. There are also questions regarding how to
 support assigning or modifying computed properties, such as using `+=`.
 

+ 108 - 105
docs/design/code_and_name_organization/README.md

@@ -39,7 +39,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
     -   [Package and library name conflicts](#package-and-library-name-conflicts)
     -   [Potential refactorings](#potential-refactorings)
         -   [Update imports](#update-imports)
-        -   [Between `api` and `impl` files](#between-api-and-impl-files)
+        -   [Between API and implementation files](#between-api-and-implementation-files)
         -   [Other refactorings](#other-refactorings)
     -   [Preference for few child namespaces](#preference-for-few-child-namespaces)
     -   [Redundant markers](#redundant-markers)
@@ -107,7 +107,7 @@ _libraries_<sup><small>[[define](/docs/guides/glossary.md#library)]</small></sup
 can be written containing pieces of the program:
 
 ```
-library "Colors" api;
+library "Colors";
 
 choice Color { Red, Green, Blue }
 
@@ -115,7 +115,7 @@ fn ColorName(c: Color) -> String;
 ```
 
 ```
-library "Colors" impl;
+impl library "Colors";
 
 fn ColorName(c: Color) -> String {
   match (c) {
@@ -139,11 +139,11 @@ A library is the basic unit of _dependency_. Separating code into multiple
 libraries can speed up the overall build while also making it clear which code
 is being reused.
 
-A library has a single `api` file which defines its interface, plus zero or more
-`impl` files that can provide any implementation details that were omitted from
-the `api` file. These files are distinguished by the `library` declaration
-ending with `api;` or `impl;`. By convention, implementation files also use a
-file extension of `.impl.carbon`.
+A library has a single API file which defines its interface, plus zero or more
+implementation files that can provide any implementation details that were
+omitted from the API file. These files are distinguished by whether the
+`library` declaration starts with the `impl` modifier. By convention,
+implementation files also use a file extension of `.impl.carbon`.
 
 Separating a library into interface and implementation may help organize code as
 a library grows, or to let the build system distinguish between the dependencies
@@ -168,15 +168,15 @@ single identifier, such as `Geometry`. An example API file in the `Geometry`
 package would start with:
 
 ```
-package Geometry api;
+package Geometry;
 ```
 
-A tiny package may consist of a single library with a single `api` file. As with
+A tiny package may consist of a single library with a single API file. As with
 libraries, additional implementation files can be added to the package by using
 the `impl` keyword in the package declaration:
 
 ```
-package Geometry impl;
+impl package Geometry;
 ```
 
 However, as a package adds more files, it will probably want to separate out
@@ -187,7 +187,7 @@ the `Main` package. For example, an API file adding the library `Shapes` to the
 [shorthand](#shorthand-notation-for-libraries-in-packages), would start with:
 
 ```
-package Geometry library "Shapes" api;
+package Geometry library "Shapes";
 ```
 
 This library can be imported within the same package by using:
@@ -213,7 +213,7 @@ package. Names declared within this package can be found as members of the name
 this syntax, and if omitted, the default (unnamed) library is imported.
 
 ```
-// Imports the source file beginning `package Geometry api;`
+// Imports the source file beginning `package Geometry;`
 import Geometry;
 ```
 
@@ -239,7 +239,7 @@ defines `Circle` then the name path will be `Geometry.Circle`. However, it can
 be named `Geometry.TwoDimensional.Circle` with a `namespace`; for example:
 
 ```
-package Geometry library "Shapes" api;
+package Geometry library "Shapes";
 namespace TwoDimensional;
 struct TwoDimensional.Circle { ... };
 ```
@@ -310,49 +310,50 @@ The `package` directive's syntax may be loosely expressed as a regular
 expression:
 
 ```regex
-package IDENTIFIER (library STRING)? (api|impl);
+(impl)? package IDENTIFIER (library STRING)?;
 ```
 
 For example:
 
 ```carbon
-package Geometry library "Objects/FourSides" api;
+impl package Geometry library "Objects/FourSides";
 ```
 
 Breaking this apart:
 
--   The identifier passed to the `package` keyword, `Geometry`, is the package
-    name and will prefix both library and namespace paths.
+-   The use of the `impl` keyword indicates this is an implementation files as
+    described under [libraries](#libraries). If it were omitted, this would
+    instead be an API file.
+-   The identifier after the `package` keyword, `Geometry`, is the package name
+    and will prefix both library and namespace paths.
     -   The `package` keyword also declares a package entity matching the
         package name. A package entity is almost identical to a namespace
-        entity, except with some package/import-specific handling. In other
-        words, if the file declares `struct Line`, that may be used from within
-        the file as both `Line` directly and `Geometry.TwoDimensional.Line`
+        entity, except with some package/import-specific handling. For example,
+        if the file declares `namespace TwoDimensional;` and
+        `struct TwoDimensional.Line`, the struct may be used from files in other
+        packages that import the library as `Geometry.TwoDimensional.Line`,
         using the `Geometry` package entity created by the `package` keyword.
     -   `Main` is invalid for use as the package name. `Main` libraries must be
         defined by either the [`library` directive](#library-directives) or the
         [`Main//default`](#maindefault) rule.
--   When the optional `library` keyword is specified, sets the name of the
-    library within the package. In this example, the
-    `Geometry//Objects/FourSides` library will be used.
-    -   If the `library` portion is omitted, the file is implicitly part of the
-        default library, which does not have a string name.
--   The use of the `api` keyword indicates this is an API files as described
-    under [libraries](#libraries). If it instead had `impl`, this would be an
-    implementation file.
+-   The string after the `library` keyword sets the name of the library within
+    the package. In this example, the `Geometry//Objects/FourSides` library will
+    be used.
+    -   If the `library` portion were omitted, the file would implicitly be part
+        of the default library, which does not have a string name.
 
 #### `library` directives
 
 The syntax for `library` directives is the same, without the `package` portion:
 
 ```regex
-library STRING (api|impl);
+(impl)? library STRING;
 ```
 
 For example:
 
 ```carbon
-library "PrimeGenerator" impl;
+impl library "PrimeGenerator";
 ```
 
 If the `library` directive is used, the file is implicitly part of the `Main`
@@ -361,7 +362,7 @@ package, whose name cannot be written explicitly.
 #### `Main//default`
 
 If neither a `package` directive nor a `library` directive is provided, the file
-is an `api` file for `Main//default`. An `impl` cannot be provided for
+is an API file for `Main//default`. An `impl` cannot be provided for
 `Main//default`.
 
 #### Files and libraries
@@ -377,8 +378,7 @@ path consists of only the package name. There is no "global" namespace.
 -   Entities within a file may be defined in [child namespaces](#namespaces).
 
 Files contributing to the `Geometry//Objects/FourSides` library must all start
-with `package Geometry library "Objects/FourSides"`, but will differ on
-`api`/`impl` types.
+with [`impl`] `package` `Geometry` `library` `"Objects/FourSides"` `;`.
 
 #### Shorthand notation for libraries in packages
 
@@ -419,8 +419,8 @@ Every Carbon library consists of one or more files. Each Carbon library has a
 primary file that defines its API, and may optionally contain additional files
 that are implementation.
 
--   An API file's `package` directive will have `api`. For example,
-    `package Geometry library "Shapes" api;`
+-   An API file's `package` directive does not include the `impl` modifier. For
+    example, `package Geometry library "Shapes";`
     -   API filenames must have the `.carbon` extension. They must not have a
         `.impl.carbon` extension.
     -   API file paths will correspond to the library name.
@@ -428,13 +428,13 @@ that are implementation.
             be expected to be similar to a "Math/Algebra" library being in a
             "Math/Algebra.carbon" file path.
         -   The package will not be used when considering the file path.
--   An implementation file's `package` directive will have `impl`. For example,
-    `package Geometry library "Shapes" impl;`.
+-   An implementation file's `package` directive includes an `impl` modifier.
+    For example, `impl package Geometry library "Shapes";`.
     -   Implementation filenames must have the `.impl.carbon` extension.
     -   Implementation file paths need not correspond to the library name.
     -   Implementation files implicitly import the library's API. Implementation
-        files cannot import each other. There is no facility for file or
-        non-`api` imports.
+        files cannot import each other. There is no facility for file or non-API
+        imports.
 
 The difference between API and implementation will act as a form of access
 control. API files must compile independently of implementation, only importing
@@ -459,21 +459,19 @@ may be marked as `private` to indicate they should only be visible to other
 parts of the library.
 
 ```carbon
-package Geometry library "Shapes" api;
+package Geometry library "Shapes";
 
-// Circle is an API, and will be available to other libraries as
- Geometry.Circle.
+// Circle is part of the public API of the library, and will be available to
+// other libraries as Geometry.Circle.
 struct Circle { ... }
 
 // CircleHelper is private, and so will not be available to other libraries.
 private fn CircleHelper(circle: Circle) { ... }
 
-// Only entities in namespaces should be marked as an API, not the namespace
-// itself.
 namespace Operations;
 
-// Operations.GetCircumference is an API, and will be available to
-// other libraries as Geometry.Operations.GetCircumference.
+// Operations.GetCircumference is part of the public API of the library, and
+// will be available to other libraries as Geometry.Operations.GetCircumference.
 fn Operations.GetCircumference(circle: Circle) { ... }
 ```
 
@@ -488,15 +486,16 @@ However, separate implementation files are still desirable for a few reasons:
 -   From a code maintenance perspective, having smaller files can make a library
     more maintainable.
 
-Entities in the `impl` file should never have visibility keywords. If they are
-forward declared in the `api` file, they use the declaration's visibility; if
-they are only present in the `impl` file, they are implicitly `private`.
+Entities in an implementation file should never have visibility keywords. If
+they are forward declared in the API file, they use the declaration's
+visibility; if they are only present in an implementation file, they are
+implicitly `private`.
 
 #### Granularity of libraries
 
-The compilation graph of Carbon will generally consist of `api` files depending
-on each other, and `impl` files depending only on `api` files. Compiling a given
-file requires compiling the transitive closure of `api` files first.
+The compilation graph of Carbon will generally consist of API files depending on
+each other, and implementation files depending only on API files. Compiling a
+given file requires compiling the transitive closure of API files first.
 Parallelization of compilation is then limited by how large that transitive
 closure is, in terms of total volume of code rather than quantity. This also
 affects build cache invalidation.
@@ -504,16 +503,15 @@ affects build cache invalidation.
 In order to maximize opportunities to improve compilation performance, we will
 encourage granular libraries. Conceptually, we want libraries to be very small,
 possibly containing only a single class. The choice of only allowing a single
-`api` file per library should help encourage developers to write small
-libraries.
+API file per library should help encourage developers to write small libraries.
 
 #### Exporting namespaces
 
-A namespace declared in an `api` file is only exported if it contains at least
-one `public` non-namespace name. For example, given this code:
+A namespace declared in an API file is only exported if it contains at least one
+`public` non-namespace name. For example, given this code:
 
 ```carbon
-package Checksums library "Sha" api;
+package Checksums library "Sha";
 
 namespace Sha256;
 namespace ImplementationDetails;
@@ -525,7 +523,7 @@ fn Sha256.HexDigest(data: Bytes) -> String { ... }
 Calling code may look like:
 
 ```carbon
-package Caller api;
+package Caller;
 
 import Checksums library "Sha";
 
@@ -564,7 +562,7 @@ entities may be [aliased](/docs/design/aliases.md) if desired.
 For example, given a library:
 
 ```carbon
-package Math api;
+package Math;
 namespace Trigonometry;
 fn Trigonometry.Sin(...);
 ```
@@ -572,7 +570,7 @@ fn Trigonometry.Sin(...);
 Calling code would import it and use it like:
 
 ```carbon
-package Geometry api;
+package Geometry;
 
 import Math;
 
@@ -591,8 +589,8 @@ import Math;
 import Math library "Trigonometry";
 ```
 
-NOTE: A library must never import itself. Any `impl` files in a library
-automatically import the `api`, so a self-import should never be required.
+NOTE: A library must never import itself. Any implementation files in a library
+automatically import the API, so a self-import should never be required.
 
 #### Imports from the current package
 
@@ -607,7 +605,7 @@ namespace.
 For example:
 
 ```carbon
-package Geometry api;
+package Geometry;
 
 // This is required even though it's still in the Geometry package.
 import library "Shapes";
@@ -660,7 +658,7 @@ For example, if the `Geometry//Shapes/ThreeSides` library provides the
 `Geometry.Shapes` namespace, this code is still valid:
 
 ```carbon
-package Geometry library "Shapes/FourSides" api;
+package Geometry library "Shapes/FourSides";
 
 import library "Shapes/ThreeSides";
 
@@ -781,56 +779,58 @@ check build dependencies for where imports should be added from, such as a
 database of possible entities and their libraries. However, adding references
 may require manually adding imports.
 
-#### Between `api` and `impl` files
+#### Between API and implementation files
 
--   Move an implementation of an API from an `api` file to an `impl` file, while
-    leaving a declaration behind.
+-   Move the definition of an entity from an API file to an implementation file,
+    while leaving a declaration behind.
 
     -   This should be a local change that will not affect any calling code.
     -   Inlining will be affected because the implementation won't be visible to
         callers.
     -   [Update imports](#update-imports).
 
--   Split an `api` and `impl` file.
+-   Split an API and implementation file.
 
     -   This is a repeated operation of individual API moves, as noted above.
 
--   Move an implementation of an API from an `impl` file to an `api` file.
+-   Move the definition of an entity from an implementation file to the API
+    file.
 
     -   This should be a local change that will not affect any calling code.
     -   Inlining will be affected because the implementation becomes visible to
         callers.
     -   [Update imports](#update-imports).
 
--   Combine an `api` and `impl` file.
+-   Combine an API and implementation file.
 
     -   This is a repeated operation of individual API moves, as noted above.
 
--   Remove the `api` label from a declaration.
+-   Add the `private` modifier to a declaration.
 
     -   Search for library-external callers, and fix them first.
 
--   Add the `api` label to a declaration.
+-   Remove the `private` modifier from a declaration.
 
     -   This should be a local change that will not affect any calling code.
 
--   Move a non-`api`-labeled declaration from an `api` file to an `impl` file.
+-   Move a `private` declaration from the API file to an implementation file.
 
-    -   The declaration must be moved to the same file as the implementation of
-        the declaration.
-    -   The declaration can only be used by the `impl` file that now contains
-        it. Search for other callers within the library, and fix them first.
+    -   The declaration must be moved to the same file as the definition of the
+        entity.
+    -   The declaration can only be used by the implementation file that now
+        contains it. Search for other callers within the library, and fix them
+        first.
     -   [Update imports](#update-imports).
 
--   Move a non-`api`-labeled declaration from an `impl` file to an `api` file.
+-   Move a `private` declaration from an implementation file to the API file.
 
     -   This should be a local change that will not affect any calling code.
     -   [Update imports](#update-imports).
 
--   Move a declaration and implementation from one `impl` file to another.
+-   Move a declaration and definition from one implementation file to another.
 
-    -   Search for any callers within the source `impl` file, and either move
-        them too, or fix them first.
+    -   Search for any callers within the source implementation file, and either
+        move them too, or fix them first.
     -   [Update imports](#update-imports).
 
 #### Other refactorings
@@ -841,15 +841,14 @@ may require manually adding imports.
     -   All call sites must be changed, as the package name changes.
     -   [Update imports](#update-imports).
 
--   Move an `api`-labeled declaration and implementation between different
-    packages.
+-   Move a public declaration and definition between different packages.
 
     -   The imports of all calling files must be updated accordingly.
     -   All call sites must be changed, as the package name changes.
     -   [Update imports](#update-imports).
 
--   Move an `api`-labeled declaration and implementation between libraries in
-    the same package.
+-   Move a public declaration and definition between libraries in the same
+    package.
 
     -   The imports of all calling files must be updated accordingly.
     -   As long as the namespaces remain the same, no call sites will need to be
@@ -858,20 +857,19 @@ may require manually adding imports.
 
 -   Rename a library.
 
-    -   This is equivalent to a repeated operation of moving an `api`-labeled
-        declaration and implementation between libraries in the same package.
+    -   This is equivalent to a repeated operation of moving a public
+        declaration and definition between libraries in the same package.
 
--   Move a declaration and implementation from one namespace to another.
+-   Move a declaration and definition from one namespace to another.
 
-    -   Ensure the new namespace is declared for the declaration and
-        implementation.
+    -   Ensure the new namespace is declared for the declaration and definition.
     -   Update the namespace used by call sites.
     -   The imports of all calling files may remain the same.
 
 -   Rename a namespace.
 
     -   This is equivalent to a repeated operation of moving a declaration and
-        implementation from one namespace to another.
+        definition from one namespace to another.
 
 -   Rename a file, or move a file between directories.
 
@@ -901,21 +899,21 @@ fewer namespaces.
 
 We use a few possibly redundant markers for packages and libraries:
 
--   The `package` keyword requires one of `api` and `impl`, rather than
-    excluding either or both.
--   The filename repeats the `api` versus `impl` choice.
+-   The filename and the presence or absence of the `impl` keyword duplicate the
+    API versus implementation choice.
+-   The filename and the library name portion of the package declaration
+    duplicate the name of the library.
 -   The `import` keyword requires the full library.
 
 These choices are made to assist human readability and tooling:
 
 -   Being explicit about imports creates the opportunity to generate build
     dependencies from files, rather than having them maintained separately.
--   Being explicit about `api` versus `impl` makes it easier for both humans and
-    tooling to determine what to expect.
--   Repeating the type in the filename makes it possible to check the type
-    without reading file content.
--   Repeating the type in the file content makes non-file-system-based builds
-    possible.
+-   Being explicit about API versus implementation in the filename makes it
+    easier for both humans and tooling to determine what to expect, and makes it
+    possible to check the type without reading file content.
+-   Repeating the type and library name in the file content makes
+    non-file-system-based builds possible.
 
 ## Open questions
 
@@ -972,8 +970,8 @@ import Carbon library "Utilities"
 
 ### Test file type
 
-Similar to `api` and `impl`, we may eventually want a type like `test`. This
-should be part of a larger testing plan.
+Similar to API and implementation files, we may eventually want test-specific
+files. This should be part of a larger testing plan.
 
 ## Alternatives considered
 
@@ -989,7 +987,7 @@ should be part of a larger testing plan.
     -   [Use a different name for the main package](/proposals/p2550.md#use-a-different-name-for-the-main-package)
     -   [Use a different name for the entry point](/proposals/p2550.md#use-a-different-name-for-the-entry-point)
     -   [Distinguish file scope from package scope](/proposals/p2550.md#distinguish-file-scope-from-package-scope)
-    -   [Default to `Main//default impl` instead of `Main//default api`](/proposals/p3403.md#default-to-maindefault-impl-instead-of-maindefault-api)
+    -   [Default to an implementation file for `Main//default` instead of an API file](/proposals/p3403.md#default-to-maindefault-impl-instead-of-maindefault-api)
 -   Libraries
     -   [Allow exporting namespaces](/proposals/p0107.md#allow-exporting-namespaces)
     -   [Allow importing implementation files from within the same library](/proposals/p0107.md#allow-importing-implementation-files-from-within-the-same-library)
@@ -1000,9 +998,10 @@ should be part of a larger testing plan.
     -   [Collapse file and library concepts](/proposals/p0107.md#collapse-file-and-library-concepts)
     -   [Collapse the library concept into packages](/proposals/p0107.md#collapse-the-library-concept-into-packages)
     -   [Collapse the package concept into libraries](/proposals/p0107.md#collapse-the-package-concept-into-libraries)
-    -   [Default `api` to private](/proposals/p0752.md#default-api-to-private)
+    -   [Default API to private](/proposals/p0752.md#default-api-to-private)
     -   [Default `impl` to public](/proposals/p0752.md#default-impl-to-public)
     -   [Different file type labels](/proposals/p0107.md#different-file-type-labels)
+    -   [Don't default to introducing an API file](/proposals/p3927.md#mandatory-api-or-impl-as-suffix)
     -   [Function-like syntax](/proposals/p0107.md#function-like-syntax)
     -   [Inlining from implementation files](/proposals/p0107.md#inlining-from-implementation-files)
     -   [Library-private access controls](/proposals/p0107.md#library-private-access-controls)
@@ -1010,6 +1009,8 @@ should be part of a larger testing plan.
     -   [Managing API versus implementation in libraries](/proposals/p0107.md#managing-api-versus-implementation-in-libraries)
     -   [Multiple API files](/proposals/p0107.md#multiple-api-files)
     -   [Name paths as library names](/proposals/p0107.md#name-paths-as-library-names)
+    -   [Put the `impl` modifier at the end](/proposals/p3927.md#mandatory-api-or-impl-as-suffix)
+    -   [Put the `impl` modifier before `library`](/proposals/p3927.md#put-the-impl-modifier-before-library)
 -   Imports
     -   [Block imports](/proposals/p0107.md#block-imports)
     -   [Block imports of libraries of a single package](/proposals/p0107.md#block-imports-of-libraries-of-a-single-package)
@@ -1034,3 +1035,5 @@ should be part of a larger testing plan.
     [#3403: Change Main//default to an api file](https://github.com/carbon-language/carbon-lang/pull/3403)
 -   Proposal
     [#3453: Clarify name bindings in namespaces.](https://github.com/carbon-language/carbon-lang/pull/3407)
+-   Proposal
+    [#3927: More consistent package syntax](https://github.com/carbon-language/carbon-lang/pull/3927)

+ 1 - 1
docs/design/expressions/README.md

@@ -252,7 +252,7 @@ expression preceding the period. In a struct literal, the entity is the struct
 type. For example:
 
 ```
-package Foo api;
+package Foo;
 namespace N;
 fn N.F() {}
 

+ 1 - 1
docs/design/expressions/literals.md

@@ -220,7 +220,7 @@ package that is automatically imported by the prelude:
 ### Usage
 
 ```carbon
-package sample api;
+package sample;
 
 fn Sum(x: i32, y: i32) -> i32 {
   return x + y;

+ 5 - 5
docs/design/functions.md

@@ -121,11 +121,11 @@ fn Add(a: i64, b: i64) -> i64 {
 
 The corresponding definition may be provided later in the same file or, when the
 declaration is in an
-[`api` file of a library](code_and_name_organization/#libraries), in the `impl`
-file of the same library. The signature of a function declaration must match the
-corresponding definition. This includes the [return clause](#return-clause);
-even though an omitted return type has equivalent behavior to `-> ()`, the
-presence or omission must match.
+[API file of a library](code_and_name_organization/#libraries), in an
+implementation file of the same library. The signature of a function declaration
+must match the corresponding definition. This includes the
+[return clause](#return-clause); even though an omitted return type has
+equivalent behavior to `-> ()`, the presence or omission must match.
 
 ## Function calls
 

+ 1 - 1
docs/design/generics/appendix-rewrite-constraints.md

@@ -261,7 +261,7 @@ constraint resolution, and it is possible for a facet type to be formed for
 which constraint resolution would always fail. For example:
 
 ```carbon
-package Broken api;
+package Broken;
 
 interface X {
   let T:! type;

+ 0 - 1
docs/design/lexical_conventions/words.md

@@ -47,7 +47,6 @@ The following words are interpreted as keywords:
 -   `addr`
 -   `alias`
 -   `and`
--   `api`
 -   `as`
 -   `auto`
 -   `base`

+ 3 - 3
docs/images/snippets.md

@@ -16,7 +16,7 @@ Images are managed in
 A sample of quicksort in Carbon.
 
 ```cpp
-package Sorting api;
+package Sorting;
 
 fn Partition[T:! Comparable & Movable](s: Slice(T))
      -> i64 {
@@ -78,7 +78,7 @@ auto main() -> int {
 
 ```cpp
 // Carbon:
-package Geometry api;
+package Geometry;
 import Math;
 
 class Circle {
@@ -112,7 +112,7 @@ struct Circle {
 };
 
 // Carbon exposing a function for C++:
-package Geometry api;
+package Geometry;
 import Cpp library "circle.h";
 import Math;
 

+ 3 - 3
docs/project/principles/library_apis_only.md

@@ -40,9 +40,9 @@ outside the common case.
 
 ## Principle
 
-In Carbon, every public function is declared in some Carbon `api` file, and
-every public `interface`, `impl`, and first-class type is defined in some Carbon
-`api` file. In some cases, the bodies of public functions will not be defined as
+In Carbon, every public function is declared in some Carbon API file, and every
+public `interface`, `impl`, and first-class type is defined in some Carbon API
+file. In some cases, the bodies of public functions will not be defined as
 Carbon code, or will be defined as hybrid Carbon code using intrinsics that
 aren't available to ordinary Carbon code. However, we will try to minimize those
 situations.

+ 172 - 0
proposals/p3927.md

@@ -0,0 +1,172 @@
+# More consistent package syntax
+
+<!--
+Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+Exceptions. See /LICENSE for license information.
+SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+-->
+
+[Pull request](https://github.com/carbon-language/carbon-lang/pull/3927)
+
+<!-- toc -->
+
+## Table of contents
+
+-   [Abstract](#abstract)
+-   [Problem](#problem)
+-   [Background](#background)
+-   [Proposal](#proposal)
+-   [Details](#details)
+-   [Rationale](#rationale)
+-   [Alternatives considered](#alternatives-considered)
+    -   [Mandatory `api` or `impl` as suffix](#mandatory-api-or-impl-as-suffix)
+    -   [Put the `impl` modifier before `library`](#put-the-impl-modifier-before-library)
+
+<!-- tocstop -->
+
+## Abstract
+
+Change the syntax for `package` declarations from:
+
+```carbon
+[package Foo] [library "bar"] api;
+[package Foo] [library "bar"] impl;
+```
+
+to
+
+```carbon
+[package Foo] [library "bar"];
+impl [package Foo] [library "bar"];
+```
+
+## Problem
+
+The `package` declaration is currently inconsistent with other Carbon
+declarations:
+
+-   Modifier keywords for other declarations precede the introducer keyword.
+    However, for package declarations, the `api` / `impl` modifier appears at
+    the end of the declaration.
+-   For most declarations describing the public interface of a library, we
+    default to `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.
+
+## Background
+
+[Proposal #107: Code and name organization](/proposals/p0107.md) introduced the
+current syntax. It did
+[consider the possibility of omitting the `api` keyword](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0107.md#different-file-type-labels):
+
+> We've considered dropping `api` from naming, but that creates a definition
+> from absence of a keyword. It also would be more unusual if both `impl` and
+> `test` must 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:
+
+-   #107 used the `api` keyword as a marker for exporting names from an API
+    file. Later, [proposal #752: api file default public](/proposals/p0752.md)
+    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.
+-   Rules for modifier keywords were added incrementally by various proposals,
+    with the common syntactic approach that modifier keywords precede an
+    introducer keyword in a declaration.
+
+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`.
+
+## Proposal
+
+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.
+
+## Details
+
+See design changes.
+
+## Rationale
+
+-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)
+    -   Small readability and writability gain for API files.
+    -   More consistency between different kinds of declaration.
+    -   Minor risk that an `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.
+-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)
+    -   Marginally more consistent with C++ modules, which use `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.
+
+## Alternatives considered
+
+### Mandatory `api` or `impl` as suffix
+
+The 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:
+
+```carbon
+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.
+
+### Put the `impl` modifier before `library`
+
+Because 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:
+
+```carbon
+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.