Преглед изворни кода

Change Main//default to an api file (#3403)

When there is no `package` directive, default to `Main//default api`
instead of
`Main//default impl`. This means:

- The extension will be `.carbon`, not `.impl.carbon`.
- There can only be one such file when compiling.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
Jon Ross-Perkins пре 2 година
родитељ
комит
5943208f75
2 измењених фајлова са 137 додато и 18 уклоњено
  1. 38 18
      docs/design/code_and_name_organization/README.md
  2. 99 0
      proposals/p3403.md

+ 38 - 18
docs/design/code_and_name_organization/README.md

@@ -18,8 +18,11 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 -   [Details](#details)
 -   [Details](#details)
     -   [Source file introduction](#source-file-introduction)
     -   [Source file introduction](#source-file-introduction)
     -   [Name paths](#name-paths)
     -   [Name paths](#name-paths)
-        -   [`package` directives](#package-directives)
     -   [Packages](#packages-1)
     -   [Packages](#packages-1)
+        -   [`package` directives](#package-directives)
+        -   [`library` directives](#library-directives)
+        -   [`Main//default`](#maindefault)
+        -   [Files and libraries](#files-and-libraries)
         -   [Shorthand notation for libraries in packages](#shorthand-notation-for-libraries-in-packages)
         -   [Shorthand notation for libraries in packages](#shorthand-notation-for-libraries-in-packages)
         -   [Package name conflicts](#package-name-conflicts)
         -   [Package name conflicts](#package-name-conflicts)
     -   [Libraries](#libraries)
     -   [Libraries](#libraries)
@@ -220,8 +223,9 @@ by using:
 import library default;
 import library default;
 ```
 ```
 
 
-This is not permitted within the `Main` package, because the default library of
-the `Main` package has no `api` file.
+The `Main` package can only be imported from other parts of the `Main` package,
+never other packages. Importing `Main//default` is invalid, regardless of which
+package is used.
 
 
 As code becomes more complex, and users pull in more code, it may also be
 As code becomes more complex, and users pull in more code, it may also be
 helpful to add
 helpful to add
@@ -297,10 +301,10 @@ IDENTIFIER(\.IDENTIFIER)*
 
 
 Name conflicts are addressed by [name lookup](/docs/design/name_lookup.md).
 Name conflicts are addressed by [name lookup](/docs/design/name_lookup.md).
 
 
-#### `package` directives
-
 ### Packages
 ### Packages
 
 
+#### `package` directives
+
 The `package` directive's syntax may be loosely expressed as a regular
 The `package` directive's syntax may be loosely expressed as a regular
 expression:
 expression:
 
 
@@ -324,13 +328,20 @@ Breaking this apart:
         words, if the file declares `struct Line`, that may be used from within
         words, if the file declares `struct Line`, that may be used from within
         the file as both `Line` directly and `Geometry.TwoDimensional.Line`
         the file as both `Line` directly and `Geometry.TwoDimensional.Line`
         using the `Geometry` package entity created by the `package` keyword.
         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
 -   When the optional `library` keyword is specified, sets the name of the
     library within the package. In this example, the
     library within the package. In this example, the
     `Geometry//Objects/FourSides` library will be used.
     `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
 -   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
     under [libraries](#libraries). If it instead had `impl`, this would be an
     implementation file.
     implementation file.
 
 
+#### `library` directives
+
 The syntax for `library` directives is the same, without the `package` portion:
 The syntax for `library` directives is the same, without the `package` portion:
 
 
 ```regex
 ```regex
@@ -343,15 +354,18 @@ For example:
 library "PrimeGenerator" impl;
 library "PrimeGenerator" impl;
 ```
 ```
 
 
-If the `package` portion is omitted, the file is implicitly part of the `Main`
-package, whose name cannot be written explicitly. If the `library` portion is
-omitted, the file is implicitly part of the default library, which does not have
-an identifier name. If neither a `package` directive nor a `library` directive
-is provided, the file is an `impl` file for the default library in the `Main`
-package. That library implicitly has an empty `api` file.
+If the `library` directive is used, the file is implicitly part of the `Main`
+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
+`Main//default`.
 
 
-As a consequence, every file is in exactly one library, which is always part of
-a package.
+#### Files and libraries
+
+Every file is in exactly one library, which is always part of a package.
 
 
 Because every file is within a package, and packages act as top-level
 Because every file is within a package, and packages act as top-level
 namespaces, every entity in Carbon will be in a namespace, even if its namespace
 namespaces, every entity in Carbon will be in a namespace, even if its namespace
@@ -538,9 +552,13 @@ import library default;
 
 
 An import with a package name `IDENTIFIER` declares a package entity named after
 An import with a package name `IDENTIFIER` declares a package entity named after
 the imported package, and makes API entities from the imported library available
 the imported package, and makes API entities from the imported library available
-through it. The full name path is a concatenation of the names of the package
-entity, any namespace entities applied, and the final entity addressed. Child
-namespaces or entities may be [aliased](/docs/design/aliases.md) if desired.
+through it. `Main` cannot be imported from other packages; in other words, only
+`import library NAME_PATH` syntax can be used to import from `Main`. Imports of
+`Main//default` are invalid.
+
+The full name path is a concatenation of the names of the package entity, any
+namespace entities applied, and the final entity addressed. Child namespaces or
+entities may be [aliased](/docs/design/aliases.md) if desired.
 
 
 For example, given a library:
 For example, given a library:
 
 
@@ -578,8 +596,7 @@ automatically import the `api`, so a self-import should never be required.
 #### Imports from the current package
 #### Imports from the current package
 
 
 An import without a package name imports the public names from the given library
 An import without a package name imports the public names from the given library
-of the same package. It is not valid to import the default library of the `Main`
-package, because that library always has an empty `api`.
+of the same package.
 
 
 Entities defined in the API of the current library and in imported libraries in
 Entities defined in the API of the current library and in imported libraries in
 the current package may be used without mentioning the package prefix. However,
 the current package may be used without mentioning the package prefix. However,
@@ -922,6 +939,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 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)
     -   [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)
     -   [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)
 -   Libraries
 -   Libraries
     -   [Allow exporting namespaces](/proposals/p0107.md#allow-exporting-namespaces)
     -   [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)
     -   [Allow importing implementation files from within the same library](/proposals/p0107.md#allow-importing-implementation-files-from-within-the-same-library)
@@ -958,3 +976,5 @@ should be part of a larger testing plan.
     [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107)
     [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107)
 -   Proposal
 -   Proposal
     [#2550: Simplified package declaration for the main package](https://github.com/carbon-language/carbon-lang/pull/2550)
     [#2550: Simplified package declaration for the main package](https://github.com/carbon-language/carbon-lang/pull/2550)
+-   Proposal
+    [#3403: Change Main//default to an api file](https://github.com/carbon-language/carbon-lang/pull/3403)

+ 99 - 0
proposals/p3403.md

@@ -0,0 +1,99 @@
+# Change Main//default to an api file
+
+<!--
+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/3403)
+
+<!-- toc -->
+
+## Table of contents
+
+-   [Abstract](#abstract)
+-   [Problem](#problem)
+-   [Background](#background)
+-   [Proposal](#proposal)
+-   [Rationale](#rationale)
+-   [Alternatives considered](#alternatives-considered)
+    -   [Default to `Main//default impl` instead of `Main//default api`](#default-to-maindefault-impl-instead-of-maindefault-api)
+
+<!-- tocstop -->
+
+## Abstract
+
+When there is no `package` directive, default to `Main//default api` instead of
+`Main//default impl`. This has two user-visible consequences:
+
+-   The extension will be `.carbon`, not `.impl.carbon`.
+-   Only one `Main//default api` is allowed.
+
+## Problem
+
+[Code and name organization](/docs/design/code_and_name_organization/#libraries)
+says:
+
+-   API filenames must have the `.carbon` extension. They must not have a
+    `.impl.carbon` extension.
+-   Implementation filenames must have the `.impl.carbon` extension.
+
+The `Main//default` library is currently specified as an `impl` file. This means
+that it should be something like `main.impl.carbon`.
+
+## Background
+
+More generally in Carbon, a single-file library can be an `api` file, not an
+`impl` file. This comes as a side-effect from `impl` files implicitly importing
+the `api`, which would fail if there were an `impl` file without an `api`. On
+the other hand, there is no requirement that an `api` file have an `impl`.
+
+Proposal
+[#2550: Simplified package declaration for the `Main` package](https://github.com/carbon-language/carbon-lang/pull/2550)
+chose `impl` as the default, providing an empty `api` file that cannot otherwise
+be imported. The proposal doesn't provide rationale for this choice; it likely
+wasn't considered key to the proposal.
+
+In C++, we often see `main.cpp`. This might be where the `impl` choice for
+`Main//default` comes from, as it has a more equivalent feel.
+
+## Proposal
+
+Omitting the package directive means `Main//default api`, rather than `impl`. As
+a consequence:
+
+-   The `.carbon` extension applies instead of the `.impl.carbon` extension.
+-   An `api` can only be defined once, so there is a limit of one such file per
+    executable.
+
+Mentions of `Main//default api` as being an empty file are removed.
+
+The rules preventing use of `Main//default` in `package`, `library`, or `import`
+remain. The library can only be defined by omission of `package` and `library`,
+and cannot be imported.
+
+## Rationale
+
+-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)
+
+    -   Writing `Run` logic in a `main.carbon` file is expected to be more
+        intuitive than `main.impl.carbon`.
+
+## Alternatives considered
+
+### Default to `Main//default impl` instead of `Main//default api`
+
+`Main//default impl`, the status quo, is now a declined alternative. Key
+considerations are:
+
+-   Using `Main//default api` is consistent with single-file libraries in other
+    contexts.
+-   `main.carbon` is preferred over `main.impl.carbon`, and using
+    `Main//default api` allows the `main.carbon` extension without
+    special-casing the file extension choices.
+-   The special-case definition of `Main//default api` as an empty file is no
+    longer needed.
+-   Being able to have multiple `Main//default impl` files is of limited
+    utility. `Run` could only be defined in one such file, and the
+    `Main//default api` was defined as empty so no sharing was allowed.