mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:10:12 +01:00
Principle: information accumulation (#875)
This proposal addresses the question of whether we should perform a fully top-down compilation (like in C), a mostly top-down compilation (like in C++), or whether we should allow information from later in the same source file to be used in earlier program constructs (like in Rust, Swift, Java, C#, Haskell, and so on).
The proposed direction is:
- Entities declared later in the same source file cannot be used earlier; top-down semantics apply everywhere.
- As an exception, class member function bodies are parsed as if they appeared after the class.
- Forward declarations can be used to separate interface from implementation and to allow entities to be used before they are defined.
- The behavior of the program is nonetheless required to be the same as if we had a globally-consistent rule: it's always a hard error to depend on any information that is not known or that is provided later.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# Principle: Information accumulation
|
||||
|
||||
<!--
|
||||
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
|
||||
|
||||
There are many different sources of information in a program, and a tool or a
|
||||
human interpreting code will not in general have full information, but will
|
||||
still want to draw conclusions about the code.
|
||||
|
||||
Different languages take different approaches to this problem. For example:
|
||||
|
||||
- In C, information is accumulated linearly in each source file independently,
|
||||
and only information from earlier in the same file is available. A program
|
||||
can observe that information is incomplete at one point and complete at
|
||||
another.
|
||||
- In C++, the behavior is largely similar to C, except:
|
||||
- Within certain contexts in a class, information from later in the class
|
||||
definition is available.
|
||||
- With C++20 modules, information from other source files can be made
|
||||
available.
|
||||
- It is easier to observe -- perhaps even accidentally -- that information
|
||||
is accumulated incrementally.
|
||||
- In Rust, all information from the entire crate is available everywhere
|
||||
within that crate, with exceptions for constructs like proc macros that can
|
||||
see the state of the program being incrementally built.
|
||||
- In Swift, all information from the entire source file is available within
|
||||
that source file.
|
||||
|
||||
## Principle
|
||||
|
||||
In Carbon, information is accumulated incrementally within each source file.
|
||||
Carbon programs are invalid if they would have a different meaning if more
|
||||
information were available.
|
||||
|
||||
Carbon source files can be interpreted top-down, without referring to
|
||||
information that appears substantially later in a file. Source files are
|
||||
expected to be organized into a topological order where that makes sense, with
|
||||
forward declarations used to introduce names before they are first referenced
|
||||
when necessary.
|
||||
|
||||
If a program attempts to use information that has not yet been provided, the
|
||||
program is invalid. There are multiple options for how this can be reported:
|
||||
|
||||
- The program can be rejected as soon as it tries to use information that
|
||||
might not be known yet.
|
||||
- For the case where the information can only be provided in the same source
|
||||
file, an assumption about the information can be made at the point where it
|
||||
is needed, and the program can be rejected only if that assumption turns out
|
||||
to be incorrect.
|
||||
|
||||
Disallowing programs from changing meaning in the context of more information
|
||||
ensures that the program is interpreted consistently or is rejected. This is
|
||||
especially important to the coherence of generics and templates.
|
||||
|
||||
## Applications of this principle
|
||||
|
||||
- As in C++, and unlike in Rust and Swift, name lookup only finds names
|
||||
declared earlier.
|
||||
- Classes are incomplete until the end of their definition. Unlike in C++, any
|
||||
attempt to observe a property of an incomplete class that is not known until
|
||||
the class is complete renders the program invalid.
|
||||
- When an `impl` needs to be resolved, only those `impl`s that have already
|
||||
been declared are considered. However, if a later `impl` would change the
|
||||
result of any earlier `impl` lookup, the program is invalid.
|
||||
|
||||
## Exceptions
|
||||
|
||||
Because a class is not complete until its definition has been fully parsed,
|
||||
applying this rule would make it impossible to define most member functions
|
||||
within the class definition. In order to still provide the convenience of
|
||||
defining class member functions inline, such member function bodies are deferred
|
||||
and processed as if they appeared immediately after the end of the outermost
|
||||
enclosing class, like in C++.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- Allow information to be used before it is provided
|
||||
[globally](/proposals/p0875.md#strict-global-consistency),
|
||||
[within a file](/proposals/p0875.md#context-sensitive-local-consistency), or
|
||||
[within a top-level declaration](/proposals/p0875.md#top-down-with-minimally-deferred-type-checking).
|
||||
- [Do not allow inline method bodies to use members before they are declared](/proposals/p0875.md#strict-top-down)
|
||||
- [Do not allow separate declaration and definition](/proposals/p0875.md#disallow-separate-declaration-and-definition)
|
||||
+1001
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user