# No predeclared identifiers, `Core` is a keyword

<!--
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/4864)

<!-- toc -->

## Table of contents

-   [Abstract](#abstract)
-   [Problem](#problem)
-   [Background](#background)
-   [Proposal](#proposal)
-   [Details](#details)
-   [Rationale](#rationale)
-   [Future work](#future-work)
    -   [Package name `Cpp`](#package-name-cpp)
    -   [Package name `Main`](#package-name-main)
-   [Alternatives considered](#alternatives-considered)
    -   [Have both predeclared identifiers and keywords](#have-both-predeclared-identifiers-and-keywords)
    -   [Reserve words with a certain spelling](#reserve-words-with-a-certain-spelling)

<!-- tocstop -->

## Abstract

Introduce a principle that the Carbon language should not encroach on the
developer's namespace. Satisfy this principle by making `Core` a keyword.

## Problem

Ongoing design work needs rules for how to expose types such as a primitive
array type to Carbon code, and in particular, if we choose to make it available
by default, whether that should be accomplished by a keyword or a predeclared
identifier.

## Background

See the
[Background section of the added principle](/docs/project/principles/namespace_cleanliness.md#background).

## Proposal

We choose to not have any predeclared identifiers in Carbon. If a word has
special meaning to the language, then that word is a keyword, and a plain
identifier with no special meaning is always available using raw identifier
syntax.

## Details

See [the principle document](/docs/project/principles/namespace_cleanliness.md)
for details of the added principle. In addition, we make one change and one
clarification:

-   `Core` is changed from being an identifier that happens to be the name of
    the Carbon standard library, and happens to be predeclared in every source
    file as naming that library, to being a keyword. The keyword can only be
    used:

    -   When importing the `Core` package.
    -   When implementing the `Core` package as part of the language
        implementation.
    -   As a keyword naming the `Core` package, much like the `package` keyword.

    The identifier `r#Core` can be used freely and does not conflict with the
    keyword. This includes use of `r#Core` as the name of a package. Language
    constructs that are defined in terms of entities in the `Core` package refer
    specifically to the package named with the _keyword_ `Core`, not to any
    other entity named `Core`.

-   The `self` keyword is now included in the list of keywords. It is already
    treated as a keyword by the toolchain.

## Rationale

-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)
    -   Code generation tools can have a uniform handling for all words with
        special meaning, with no need to alter the spelling of names from other
        languages.
    -   Language tools can determine the meaning of `Core.<name>` without
        needing to do any name lookup or sophisticated analysis.
-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)
    -   Migration between versions of Carbon with a changed set of reserved
        words can be done uniformly.
    -   Adding names to the prelude remains a non-breaking change. Adding new
        predeclared names requires adding a keyword, with the same cost and
        value tradeoffs regardless of whether the keyword names a library
        declaration or introduces new language syntax.
-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)
    -   Syntax highlighting tools can easily distinguish between words with
        special meaning and words with program-defined meaning.
    -   The meaning of core language constructs can be defined as a rewrite in
        terms of `Core.<name>` without concern that `Core` may have some
        different local interpretation.
-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)
    -   All C++ identifiers are nameable from Carbon code without conflicts.
        Virtual functions introduced in Carbon can be overridden in Carbon
        regardless of their name. C++ code can be migrated to Carbon even if its
        name in C++ has special meaning in Carbon.
-   [Principle: Prefer providing only one way to do a given thing](/docs/project/principles/one_way.md)
    -   This proposal specifies that there is only one way to give words special
        meaning in Carbon, and one way to resolve issues if that special meaning
        conflicts with another desired meaning.

## Future work

### Package name `Cpp`

The special package name `Cpp` that refers to code written in C++ is not made a
keyword by this proposal, but this proposal is also not deciding that it should
_not_ be a keyword. While this name has special meaning to the language, it's
not predeclared in any context, so it's considered to be out of scope. A future
proposal that describes the details of C++ import should determine whether this
name becomes a keyword. Notably, making `Cpp` a keyword would also allow an
`import Cpp` declaration to have custom syntax, which may be useful.

### Package name `Main`

The special package name `Main` that is currently reserved in all package name
contexts is not made a keyword in this proposal either. There would be no
meaning in making it a keyword, as it is never used as a special package name in
Carbon source files. However, we could consider using an empty package name as
the name of the main package, and unreserving the package name `Main`, if it
becomes a concern that we reserve this name.

## Alternatives considered

### Have both predeclared identifiers and keywords

We could provide both predeclared identifiers and keywords. Many languages
follow this path. However, predeclared identifiers have some problems compared
to keywords:

-   In order to locally declare a name matching a predeclared identifier, the
    name would need to be shadowed.
    -   Such shadowing may be invalid, depending on how the name is used.
    -   Readability is harmed by using a name used as basic vocabulary with a
        different, local meaning.
    -   Shadowing a predeclared identifier typically makes the original name
        hard to access -- an alias or similar must be established in advance.
-   There need to be two different stories for how to deal with adding a new
    word with special meaning to the language, depending on whether it is a
    keyword.
-   For each word with special meaning, we must make an arbitrary decision as to
    which kind it is, resulting in a largely meaningless distinction that
    nonetheless is visible and would need to be known by developers in some
    contexts.

### Reserve words with a certain spelling

We could reserve words with certain spellings for future use as keywords or as
vendor extensions. Some languages do this:

-   C reserves words starting with an underscore followed by a capital letter or
    an underscore.
-   C++ additionally reserves words containing a double underscore anywhere.
-   Python uses the `__name__` namespace for certain special names, and by
    convention these names are reserved for that purpose.

In Carbon we could accomplish this by saying that all words of the reserved
forms are keywords, with no meaning ascribed to them yet.

However, we do not have a clear need for such reserved words at this time, and
we would not want to use such spellings when we do add language keywords later.
Moreover, C++ programs frequently declare reserved words in practice, and we
should expect the same in Carbon. Without enforcement, the names are not
effectively reserved.

If we find a need at a later time to introduce vendor-specific language
extension keywords, we can revisit this, but should also consider alternatives
such as a `k#foo` spelling to turn what is normally an identifier into a
(potentially vendor-specific) keyword.
