mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-02 22:02:51 +01:00
Also updates a few spots with some subtle aspects changed in `lambdas.md` and `namespace_cleanliness.md`. Assisted-by: Antigravity with Gemini
123 lines
6.4 KiB
Markdown
123 lines
6.4 KiB
Markdown
# Principle: Namespace cleanliness
|
|
|
|
<!--
|
|
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
|
|
-->
|
|
|
|
<!-- toc -->
|
|
|
|
## Table of contents
|
|
|
|
- [Background](#background)
|
|
- [Principle](#principle)
|
|
- [Applications of this principle](#applications-of-this-principle)
|
|
- [Exceptions](#exceptions)
|
|
- [Alternatives considered](#alternatives-considered)
|
|
|
|
<!-- tocstop -->
|
|
|
|
## Background
|
|
|
|
Names and entities in a program can come from multiple sources -- from a local
|
|
declaration, from an import, from the standard library, or from the prelude.
|
|
Names can be imported from Carbon code or imported or derived from code written
|
|
in another language such as C++ or an interface description language such as
|
|
that of Protobuf, MIDL, or CORBA. Names can be selected for use in a program
|
|
that language designers later decide they want to use as keywords. And in order
|
|
to use a library, it is sometimes necessary to redeclare the same name that that
|
|
library chose.
|
|
|
|
This puts a lot of pressure on the language to support a free choice of naming
|
|
for entities. Different languages make different choices in this space:
|
|
|
|
- Many languages have a set of keywords that are not usable as identifiers,
|
|
with no workaround. If this set collides with a name needed by user code,
|
|
the user is left to solve this problem, often by rewriting the identifier in
|
|
some way (`klass` or `class_`), which sometimes conflicts with the general
|
|
naming convention used by the code. And conversely, suboptimal choices are
|
|
made for new language keywords to avoid causing problems for existing code.
|
|
- C and C++ reserve a family of identifiers, such as those beginning with an
|
|
underscore and a capital letter. However, it's not clear which audiences the
|
|
reserved identifiers are for, and this leads to collisions between standard
|
|
library vendors and compiler authors, as well as between implementation
|
|
extensions and language extensions.
|
|
- MSVC provides a `__identifier(keyword)` extension that allows using a
|
|
keyword as an identifier. This extension is also implemented by Clang in
|
|
`-fms-extensions` mode.
|
|
- GCC provides an `__asm__(symbol)` extension that allows a specific
|
|
symbol to be assigned to an object or function, which provides ABI
|
|
compatibility but not source compatibility with code that uses a keyword
|
|
as a symbol name. This extension is also implemented by Clang.
|
|
- Python reserves some identifiers but still allows them to be freely
|
|
overwritten (such as `bool`) and reserves some identifiers but rejects
|
|
assignment to them (such as `True`).
|
|
- Rust provides a raw identifier syntax to allow most identifiers with
|
|
reserved meaning to be used by a program, but
|
|
[not all](https://internals.rust-lang.org/t/raw-identifiers-dont-work-for-all-identifiers/9094):
|
|
`self`, `Self`, `super`, `extern`, and `crate` cannot be used as raw
|
|
identifiers. Rust also predeclares a large number of library names in every
|
|
file, but allows them to be shadowed by user declarations with the same
|
|
name.
|
|
- Swift provides a raw identifier syntax using backticks: `` `class` ``, and
|
|
is
|
|
[considering](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0451-escaped-identifiers.md)
|
|
extending this to allow arbitrary non-word-shaped character sequences
|
|
between the `` ` ``s.
|
|
|
|
Carbon provides
|
|
[raw identifier syntax](/docs/design/lexical_conventions/words.md#raw-identifiers),
|
|
for example `r#for`, to allow using keywords as identifiers. Carbon also intends
|
|
to have strict shadowing rules that may make predeclared identifiers that are
|
|
_not_ keywords difficult or impossible to redeclare and use in inner scopes.
|
|
|
|
## Principle
|
|
|
|
In Carbon, the language does not encroach on the developer's namespace. There
|
|
are no predeclared or reserved identifiers. In cases where the language gives
|
|
special meaning to a word or to word-shaped syntax such as `i32`, that special
|
|
meaning can always be undone with raw identifier syntax, `r#`.
|
|
|
|
Conversely, when adding language keywords, we will not select an inferior
|
|
keyword merely to avoid the risk of breaking existing programs. We will still
|
|
take into account how often it is desirable to use the word as an identifier,
|
|
including in domain-specific contexts, because that is a factor in whether it
|
|
would make a good keyword, and will manage the rollout of new keywords to make
|
|
it straightforward to migrate existing uses to `r#` or a different name.
|
|
|
|
## Applications of this principle
|
|
|
|
- Words like `final` and `base` that only have special meaning in a few
|
|
contexts, and could otherwise be made available as identifiers, are keywords
|
|
in Carbon. `{.base = ...}` and `{.r#base = ...}` specify different member
|
|
names.
|
|
- Words like `self` that are declared by the developer but nonetheless have
|
|
special language-recognized meaning are keywords in Carbon. `(self)`
|
|
introduces a self parameter; `(r#self: Self)` introduces a parameter with
|
|
the name `self` as a raw identifier.
|
|
- Words like `Self` that are implicitly declared by the language in some
|
|
contexts are keywords, even though we could treat them as user-declared
|
|
identifiers that are merely implicitly declared in some cases.
|
|
- Words like `i32` that are treated as type literals rather than keywords can
|
|
be used as identifiers with raw identifier syntax `r#i32`.
|
|
- There are no predeclared identifiers imported from the prelude. If an entity
|
|
is important enough to be available by default, we should add a keyword, and
|
|
allow the name of the entity to be used for other purposes with `r#`.
|
|
- The predeclared package name `Core` is a keyword. A package named `r#Core`
|
|
is an unrelated package, and `Core.foo` always refers to members of the
|
|
predeclared `Core` package.
|
|
|
|
## Exceptions
|
|
|
|
For now, we reserve the package names `Main` and `Cpp`. These names aren't
|
|
predeclared in any scope, and the name `Main` is not even usable from within
|
|
source files to refer to the main package. However, there is currently no way to
|
|
avoid collisions between the package name `Cpp` and a top-level entity named
|
|
`Cpp` if they are both used in the same source file.
|
|
|
|
## Alternatives considered
|
|
|
|
- [Have both predeclared identifiers and keywords](/proposals/p4864.md#have-both-predeclared-identifiers-and-keywords)
|
|
- [Reserve words with a certain spelling](/proposals/p4864.md#reserve-words-with-a-certain-spelling)
|