mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
Make the preamble of simple programs more ergonomic, by removing the `package Main` from the main package and removing the `package` declaration entirely from the main source file. Imports within a single package no longer need to, and are not permitted to, specify the package name. Partially covers #2001 / #1136. Covers #1869. Supersedes #2265. Addresses design idea #2323. --------- Co-authored-by: Jon Ross-Perkins <jperkins@google.com> Co-authored-by: josh11b <josh11b@users.noreply.github.com>
334 lines
15 KiB
Markdown
334 lines
15 KiB
Markdown
# Simplified package declaration for the `Main` package
|
|
|
|
<!--
|
|
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/2550)
|
|
|
|
<!-- toc -->
|
|
|
|
## Table of contents
|
|
|
|
- [Abstract](#abstract)
|
|
- [Problem](#problem)
|
|
- [Background](#background)
|
|
- [Proposal](#proposal)
|
|
- [Details](#details)
|
|
- [Rationale](#rationale)
|
|
- [Alternatives considered](#alternatives-considered)
|
|
- [Require the use of the identifier `Main` in package declarations](#require-the-use-of-the-identifier-main-in-package-declarations)
|
|
- [Permit the use of the identifier `Main` in package declarations](#permit-the-use-of-the-identifier-main-in-package-declarations)
|
|
- [Distinguish file scope from package scope](#distinguish-file-scope-from-package-scope)
|
|
- [Keep the package name in imports](#keep-the-package-name-in-imports)
|
|
- [Make the main package be unnamed](#make-the-main-package-be-unnamed)
|
|
- [Use a different name for the entry point](#use-a-different-name-for-the-entry-point)
|
|
- [Use a different name for the main package](#use-a-different-name-for-the-main-package)
|
|
- [Acknowledgements](#acknowledgements)
|
|
|
|
<!-- tocstop -->
|
|
|
|
## Abstract
|
|
|
|
Make the preamble of simple programs more ergonomic, by removing the
|
|
`package Main` from the main package and removing the `package` declaration
|
|
entirely from the main source file. Imports within a single package no longer
|
|
need to, and are not permitted to, specify the package name.
|
|
|
|
## Problem
|
|
|
|
Every Carbon source file is required to start with a `package` declaration:
|
|
|
|
```
|
|
package Main impl;
|
|
```
|
|
|
|
This introduces complexity and syntactic overhead to very simple programs, such
|
|
as might be encountered by beginners learning Carbon. This is also inconvenient
|
|
for slide code and small examples in teaching material, where the author must
|
|
choose between including boilerplate or providing an example that Carbon
|
|
implementations will reject.
|
|
|
|
In addition, imports within a single package are required to restate the name of
|
|
the package:
|
|
|
|
```
|
|
package Geometry library "Shapes" api;
|
|
import Geometry library "Points";
|
|
```
|
|
|
|
This creates additional syntactic overhead for a common operation, and misses
|
|
the opportunity to visually distinguish between different categories of imports
|
|
-- "our library" versus "their library". Additionally, under
|
|
[#1136](https://github.com/carbon-language/carbon-lang/issues/1136), imports
|
|
from the same package have different semantics than imports from a different
|
|
package, so giving the two operations the same syntax seems confusing.
|
|
|
|
Given that every package has an arbitrary, developer-selected identifier name,
|
|
it is also unclear how to determine which package contains the entry point of
|
|
the program. The name `Main` could be reserved for this, but no such decision
|
|
has been made.
|
|
|
|
## Background
|
|
|
|
Proposal
|
|
[#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107/files)
|
|
introduced our current `package` syntax.
|
|
|
|
In issue
|
|
[#1869: What is the main entry point for execution? `Main` or `Run`?](https://github.com/carbon-language/carbon-lang/issues/1869)
|
|
the leads decided that the entry point of a Carbon program is named `Main.Run`.
|
|
That decision is implemented by this proposal.
|
|
|
|
In issue
|
|
[#1136: what is the top-level scope in a source file, and what names are found there?](https://github.com/carbon-language/carbon-lang/issues/1136),
|
|
the leads decided that a package's name should not be injected into the scope of
|
|
its files, and that same-package `import`s should not mention the package name.
|
|
Those decisions are also implemented by this proposal. Note that other decisions
|
|
were also made in #1136 regarding name access (`private`) and the behavior of
|
|
unqualified name lookup that are not part of this proposal.
|
|
|
|
## Proposal
|
|
|
|
A Carbon program has a `Main` package, which is the package that contains the
|
|
entry point of the program. The entry point is a function named `Run`.
|
|
|
|
It is also possible to link Carbon libraries into programs written in other
|
|
languages, and in particular, Carbon libraries can be used from C++ programs. In
|
|
this case, there will be no Carbon `Run` function, and the C++ program will
|
|
provide a `main` function that is used as the entry point.
|
|
|
|
In the `Main` package, the package declaration does not explicitly specify a
|
|
package name. The package declaration syntax becomes:
|
|
|
|
- `package` _Foo_ [`library "`_Bar_`"`] \(`api` | `impl`) `;`, unchanged from
|
|
#107, for a file that is part of a package other than the `Main` package.
|
|
- `library "`_Bar_`"` (`api` | `impl`) `;` for a library that is part of the
|
|
`Main` package.
|
|
- Omitted entirely for an `impl` file in the `Main` package that is not part
|
|
of a named library.
|
|
|
|
There is no way to define an `api` file for the `Main` package that is not part
|
|
of a named library -- there is no equivalent of `package Main api;`.
|
|
|
|
The import syntax becomes:
|
|
|
|
- `import` _Foo_ `;` to import the default library of package _Foo_, or
|
|
`import` _Foo_ `library "`_Bar_`"` `;` to import library _Bar_. This
|
|
introduces the name _Foo_ in the current source file as a name for that
|
|
package, containing whatever subset of the package was imported. `Foo` is
|
|
not allowed to be the name of the current package.
|
|
- `import library "`_Bar_`";` to import library _Bar_ of the current package.
|
|
This introduces the names from that library at file scope. _Bar_ is not
|
|
allowed to be the name of the current library.
|
|
- `import library default;` to import the default library of the current
|
|
package. This is not allowed within the default library.
|
|
|
|
It is an error to explicitly specify the package name `Main` in a package
|
|
declaration or an import declaration. As a result, there is no way to import
|
|
libraries of the `Main` package from any other package.
|
|
|
|
It is permitted for a Carbon program to contain a source file that has no
|
|
`package` declaration and does not contain a `Run` function -- or even to
|
|
contain multiple such source files. Such a source file cannot implement any
|
|
importable functionality, as there is no corresponding `api` file, but may still
|
|
be useful to support Carbon features that have not yet been designed, such as:
|
|
|
|
- Global registration mechanisms.
|
|
- Some way of defining functions with well-known symbols, analogous to
|
|
`extern "C"` declarations in C++.
|
|
|
|
## Details
|
|
|
|
See design changes.
|
|
|
|
## Rationale
|
|
|
|
- [Goal: Community and culture](/docs/project/goals.md#community-and-culture)
|
|
- This change allows small complete programs and source files to be
|
|
discussed in Carbon forums without the overhead of `package`
|
|
declarations. Cumbersome top-level syntax hampers technical discussion.
|
|
- [Goal: Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)
|
|
- Test cases for language tools are made unnecessarily verbose by the
|
|
mandatory inclusion of a `package` declaration and a `Main` function.
|
|
This proposal makes these components optional.
|
|
- [Goal: Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)
|
|
- Simple programs, such as `"hello, world"` examples written by beginners,
|
|
have less boilerplate.
|
|
- Reduction of verbosity that is not contributing to increased
|
|
understanding of the program.
|
|
- [Goal: Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)
|
|
- This proposal explicitly acknowledges and permits the entry point for a
|
|
program that includes Carbon code to be written in a different language.
|
|
- The use of the name `Main.Run` for the entry point is intended to be
|
|
similar enough to the use of the name `main` in C++ to be familiar.
|
|
- [Principle: Prefer providing only one way to do a given thing](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/principles/one_way.md)
|
|
- Each `package` and `import` declaration has only one valid spelling. We
|
|
do not allow redundantly specifying the current package in an `import`,
|
|
nor using `library default` in any context where the `library` stanza
|
|
can be omitted with the same meaning, and we do not allow explicitly
|
|
writing a `package` declaration within the `Main` package.
|
|
|
|
## Alternatives considered
|
|
|
|
### Require the use of the identifier `Main` in package declarations
|
|
|
|
Instead of the name `Main` being implied in `package` declarations, we could
|
|
require it to be explicitly written:
|
|
|
|
```
|
|
package Main impl;
|
|
import SimpleIO;
|
|
|
|
fn Main() {
|
|
SimpleIO.Print("Hello, Carbon!");
|
|
}
|
|
```
|
|
|
|
This would keep the Carbon language more consistent, and remove a special case.
|
|
However, it would also increase verbosity in the simplest of programs, where the
|
|
added verbosity has the most cost.
|
|
|
|
### Permit the use of the identifier `Main` in package declarations
|
|
|
|
We could allow the name `Main` to be used in package declarations and treat it
|
|
the same as if the name were omitted, making the other forms merely shorthand.
|
|
However, this would introduce a syntactic choice that doesn't correspond to any
|
|
difference in intent, creating the opportunity for meaningless stylistic
|
|
divergence, and we
|
|
[prefer to leave only one syntactic choice](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/principles/one_way.md)
|
|
in order to enforce consistency.
|
|
|
|
### Distinguish file scope from package scope
|
|
|
|
Under this proposal, the names from the current package that are visible, either
|
|
by being declared locally or by being imported, are visible at the top level
|
|
file scope. We could pick a different rule that distinguishes package scope from
|
|
file scope, such as by introducing only locally-declared names into file scope
|
|
and requiring a `PackageName.` prefix on all other names in the package.
|
|
|
|
This was discussed at length in
|
|
[#1136](https://github.com/carbon-language/carbon-lang/issues/1136). We found
|
|
that distinguishing the package from the subset of the package visible at file
|
|
scope led to problems that were more substantial than the potential
|
|
simplification of treating imports of the current package as being the same as
|
|
imports of any other package. See that issue for the full discussion.
|
|
|
|
In [#1136](https://github.com/carbon-language/carbon-lang/issues/1136), it was
|
|
also decided to add a `package.Name` syntax to allow shadowed names from the
|
|
package scope to be referenced. That is not part of this proposal; until we add
|
|
such a mechanism, its absence can be worked around by using private aliases:
|
|
|
|
```
|
|
fn Foo();
|
|
private alias OuterFoo = Foo;
|
|
|
|
class Bar {
|
|
fn Foo() {
|
|
// 🤷 Either ambiguous or calls `Bar.Foo`.
|
|
Foo();
|
|
// Calls `Foo` from package scope.
|
|
OuterFoo();
|
|
}
|
|
}
|
|
```
|
|
|
|
### Keep the package name in imports
|
|
|
|
We could consistently name the package targeted by an import in the `import`
|
|
declaration:
|
|
|
|
```
|
|
package Foo api;
|
|
import Foo library "Bar";
|
|
```
|
|
|
|
This would lead to a more uniform syntax and, as noted in
|
|
[a very similar alternative considered by #107](/proposals/p0107.md#optional-package-names),
|
|
would make it easier to search for all imports of a given library with a simple
|
|
tool.
|
|
|
|
There are two reasons to want to avoid this:
|
|
|
|
- Use of the same syntax suggests that same-package imports and cross-package
|
|
imports have the same semantics. But they do not: a same-package import
|
|
introduces the set of public names in the nominated library, whereas a
|
|
cross-package import of package `Bar` introduces exactly the name `Bar`.
|
|
- This would require writing a name for the `Main` package, in order to allow
|
|
libraries of that package to be imported within the same package. Adding
|
|
that name would provide a syntax to import those libraries from another
|
|
package, which we wanted to disallow.
|
|
|
|
### Make the main package be unnamed
|
|
|
|
We don't allow writing the name `Main` of the main package in `package`
|
|
declarations nor in `import` declarations, so we could say that the main package
|
|
has no name or has the empty name. We chose to give it a specific name for a few
|
|
reasons:
|
|
|
|
- Conversationally and in documentation, it is clearer to talk about the main
|
|
package than the unnamed package, and we expect people to call it "the main
|
|
package" or similar regardless of which name we pick.
|
|
- There may still be reasons we need an identifier name to refer to this
|
|
package. For example, this need may arise in name mangling, in attributes,
|
|
in error messages, in conventions for naming source files, and in other
|
|
technical contexts that require an identifier referring to the package.
|
|
|
|
One downside of picking a name is that it causes us to reserve an identifier and
|
|
assign it special meaning, but we felt that using the name `Main` for any other
|
|
package would be confusing, so this cost is small.
|
|
|
|
Ultimately this decision was marginal, and the painter made the choice to use a
|
|
named package in
|
|
[#1869](https://github.com/carbon-language/carbon-lang/issues/1869).
|
|
|
|
### Use a different name for the entry point
|
|
|
|
We could use a variety of different names for the entry point and for the
|
|
package that contains it. `Main` was the obvious first choice, as it is the name
|
|
used in C and C++. However, we generally want to use verbs and verb phrases as
|
|
function names, because functions describe actions and we find that verb phrases
|
|
are easier to read and understand as function names as a result.
|
|
|
|
Some other function names were considered but rejected:
|
|
|
|
- `Start` -- we preferred to use a word that describes the entire action of
|
|
the function, and the `Main.Run` function covers the complete execution of
|
|
the program, not just the beginning of that execution.
|
|
- `Entry` or `Entrypoint` -- same problems as `Start`, plus less discoverable,
|
|
potentially longer, not a familiar term to beginners, and not verbs.
|
|
- `Exec` or `Execute` -- we were concerned about a semantic collision between
|
|
the action of executing _some other_ program, as is performed by the C
|
|
`exec` function, and the action of executing the current program.
|
|
|
|
See [#1869](https://github.com/carbon-language/carbon-lang/issues/1869) for more
|
|
information about this decision.
|
|
|
|
### Use a different name for the main package
|
|
|
|
We considered other options for the main package name. The primary option
|
|
considered was `Program`, but there were no decisive technical arguments to
|
|
select one name over another. The painter selected `Main` with the following
|
|
rough rationale:
|
|
|
|
> - We weren't using `Main` for the function name, so it seemed available.
|
|
> - Given that it is the "main package" and in fact contains the entry point,
|
|
> it didn't seem likely to have any confusion with `main` functions in other
|
|
> languages.
|
|
> - It is shorter than `Program`.
|
|
> - I guess that it will work better to indicate a conventional filename of
|
|
> `main.carbon`.
|
|
> - For folks looking for a `main` function, it may help them find our
|
|
> version.
|
|
|
|
See [#1869](https://github.com/carbon-language/carbon-lang/issues/1869) for more
|
|
information about this decision.
|
|
|
|
## Acknowledgements
|
|
|
|
Thanks to [Allison Poppe](https://github.com/acpoppe) for authoring proposal
|
|
[#2265 Name of application entry point](https://github.com/carbon-language/carbon-lang/pull/2265)
|
|
which explored another option for naming the entry point.
|