mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 13:50:10 +01:00
Enable rumdl markdown line-length enforcement and reflowing (#7667)
This should handle over-long lines. I had tried to make the normalize method work, but it doesn't seem promising and so let's at least enable this version. Assisted-by: Antigravity with Gemini
This commit is contained in:
@@ -62,7 +62,8 @@ project uses Bazelisk.
|
||||
|
||||
You can run the Carbon driver or command line directly via Bazel:
|
||||
|
||||
- `bazelisk run //toolchain -- compile --phase=parse toolchain/parse/testdata/basics/empty.carbon`
|
||||
- `bazelisk run //toolchain -- compile --phase=parse
|
||||
toolchain/parse/testdata/basics/empty.carbon`
|
||||
|
||||
## Advanced configurations
|
||||
|
||||
|
||||
@@ -70,19 +70,19 @@ CARBON_SEM_IR_BUILTIN_FUNCTION_KIND(IntConvertFloat)
|
||||
Inside
|
||||
[builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp):
|
||||
|
||||
1. **Define Parameter Constraints**: If the parameter requires novel constraints
|
||||
(e.g. "must be a float type"), define a template constraint struct checking
|
||||
the matching `SemIR` type instruction (such as `FloatType` or
|
||||
`FloatLiteralType`). Use pre-established semantic helpers:
|
||||
1. **Define Parameter Constraints**: If the parameter requires novel
|
||||
constraints (e.g. "must be a float type"), define a template constraint
|
||||
struct checking the matching `SemIR` type instruction (such as `FloatType`
|
||||
or `FloatLiteralType`). Use pre-established semantic helpers:
|
||||
|
||||
- `TypeParam<I, T>`: Ensures different parameters resolve to identical type
|
||||
structures (e.g., generic constraint matching).
|
||||
- `TypeParam<I, T>`: Ensures different parameters resolve to identical
|
||||
type structures (e.g., generic constraint matching).
|
||||
- `AnyInt`, `AnyFloat`, `AnySizedInt`, `AnySizedFloat`, `CharCompatible`,
|
||||
`StdInitializerList`, `NoReturn`.
|
||||
|
||||
2. **Map Literal Name & Register Constraint Signature**: Declare a `BuiltinInfo`
|
||||
constant inside `namespace BuiltinFunctionInfo` matching the macro-defined
|
||||
name:
|
||||
2. **Map Literal Name & Register Constraint Signature**: Declare a
|
||||
`BuiltinInfo` constant inside `namespace BuiltinFunctionInfo` matching the
|
||||
macro-defined name:
|
||||
|
||||
```cpp
|
||||
// toolchain/sem_ir/builtin_function_kind.cpp
|
||||
@@ -127,7 +127,8 @@ execute compile-time computations:
|
||||
```
|
||||
|
||||
- Extract inputs safely from local value stores (e.g.
|
||||
`context.ints().Get(arg.int_id)` or `context.floats().Get(arg.float_id)`).
|
||||
`context.ints().Get(arg.int_id)` or
|
||||
`context.floats().Get(arg.float_id)`).
|
||||
- Leverage high-precision LLVM mathematical structures (`llvm::APInt`,
|
||||
`llvm::APFloat`, `llvm::APSInt`) to handle custom bits and signedness
|
||||
safely.
|
||||
@@ -142,8 +143,8 @@ execute compile-time computations:
|
||||
CARBON_DIAGNOSTIC_KIND(IntTooLargeForFloatType)
|
||||
```
|
||||
|
||||
- Emplace localized diagnostic formatting messages where they are caught in
|
||||
`eval.cpp`:
|
||||
- Emplace localized diagnostic formatting messages where they are caught
|
||||
in `eval.cpp`:
|
||||
|
||||
```cpp
|
||||
CARBON_DIAGNOSTIC(IntTooLargeForFloatType, Error,
|
||||
@@ -152,8 +153,8 @@ execute compile-time computations:
|
||||
context.emitter().Emit(loc_id, IntTooLargeForFloatType, val, dest_type_id);
|
||||
```
|
||||
|
||||
- Return `SemIR::ErrorInst::ConstantId` to gracefully abort invalid constant
|
||||
generation rather than crashing the compiler.
|
||||
- Return `SemIR::ErrorInst::ConstantId` to gracefully abort invalid
|
||||
constant generation rather than crashing the compiler.
|
||||
|
||||
3. **Fast-Path Range Limits**:
|
||||
- Before evaluating expensive math operations on giant exponents (e.g.
|
||||
@@ -244,11 +245,11 @@ Create validation splits under
|
||||
`toolchain/check/testdata/builtins/char_literal/convert.carbon`.
|
||||
- **Minimal Prelude & Direct Call Isolation**: Builtin tests must **not** test
|
||||
the prelude library or operators. They must use the minimal primitive
|
||||
prelude
|
||||
(`// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon`)
|
||||
or a smaller prelude, and explicitly declare and call the builtin functions
|
||||
under test directly (e.g., `fn Add(a: f64, b: f64) -> f64 = "float.add";`).
|
||||
This isolates the testing of compiler builtins from the library prelude.
|
||||
prelude (`// INCLUDE-FILE:
|
||||
toolchain/testing/testdata/min_prelude/primitives.carbon`) or a smaller
|
||||
prelude, and explicitly declare and call the builtin functions under test
|
||||
directly (e.g., `fn Add(a: f64, b: f64) -> f64 = "float.add";`). This
|
||||
isolates the testing of compiler builtins from the library prelude.
|
||||
- **Min-Prelude Limitations**: Standard operators (like `+`, `-`, `/`, `<`,
|
||||
etc.) are **not** available in minimized preludes because the core operators
|
||||
library isn't imported. To write tests with a minimal footprint, call
|
||||
|
||||
@@ -215,8 +215,8 @@ interoperable code, adhere strictly to these rules:
|
||||
be mentioned if it wouldn't otherwise be clear:
|
||||
- _Situation-only_: `"redeclaration of X"` (implies that redeclaration is
|
||||
not permitted).
|
||||
- _Rule-inclusion_:
|
||||
``"`self` declared in invalid context; can only be declared in implicit parameter list"``.
|
||||
- _Rule-inclusion_: ``"`self` declared in invalid context; can only be
|
||||
declared in implicit parameter list"``.
|
||||
- **Wording Choice ("cannot" vs "allowed")**: Explicitly avoid `"allowed"`,
|
||||
`"legal"`, `"permitted"`, `"valid"`, and related passive wording. You may
|
||||
use `"cannot"` if needed, but try to use phrasing that does not require it:
|
||||
@@ -228,8 +228,8 @@ interoperable code, adhere strictly to these rules:
|
||||
- **Developer Intent Hints**: It is acceptable for a diagnostic to guess at
|
||||
the developer's intent and provide a hint _after_ explaining the situation
|
||||
and the rule, but never as a substitute for that:
|
||||
- _Correct_:
|
||||
``"cannot implicitly convert `i32` to `String`; add `as String` for explicit conversion"``
|
||||
- _Correct_: ``"cannot implicitly convert `i32` to `String`; add `as
|
||||
String` for explicit conversion"``
|
||||
- _Incorrect_: ``"add `as String` to convert `i32` to `String`"`` (Lacks
|
||||
the core violation message).
|
||||
- **Structure for Tooling API**: Try to structure diagnostics such that
|
||||
|
||||
@@ -53,9 +53,9 @@ filename.
|
||||
`error_handling.md`, `one_way.md`).
|
||||
- **Living design**: If the proposal updates design documentation, include
|
||||
those changes in the PR if possible. If deferred, add "TODO" comments
|
||||
pointing to the proposal (e.g.,
|
||||
`> **TODO:** Document ... adopted in [p######](/proposals/p######-title.md)`).
|
||||
For pervasive changes, file a GitHub issue instead of adding many TODOs.
|
||||
pointing to the proposal (e.g., `> **TODO:** Document ... adopted in
|
||||
[p######](/proposals/p######-title.md)`). For pervasive changes, file a
|
||||
GitHub issue instead of adding many TODOs.
|
||||
|
||||
## Alternatives considered and leads decisions
|
||||
|
||||
|
||||
@@ -110,7 +110,8 @@ gh pr diff 1234 | python3 .agents/skills/summarize_testdata_changes/scripts/pars
|
||||
`// CHECK`), along with diagnostic output changes where relevant
|
||||
- Diagnostic Changes: Changes to diagnostic output (lines prefixed with
|
||||
`// CHECK:STDERR`) with no corresponding changes to test inputs
|
||||
- [Output Type] Changes: Changes to STDOUT (lines prefixed with `// CHECK:STDOUT`)
|
||||
- [Output Type] Changes: Changes to STDOUT (lines prefixed with `//
|
||||
CHECK:STDOUT`)
|
||||
- Create one section for each relevant kind of test. For example,
|
||||
parser tests should typically be in a "Parse Tree Changes" section,
|
||||
check tests should typically be in a "SemIR Changes" section, and
|
||||
|
||||
@@ -49,8 +49,8 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
- **Test everything**: `bazelisk test //...`
|
||||
- **Test specific target**: `bazelisk test //toolchain/testing:file_test`
|
||||
- **Test specific file**:
|
||||
`bazelisk test //toolchain/testing:file_test --test_arg=--file_tests=<path_to_carbon_file>`
|
||||
- **Test specific file**: `bazelisk test //toolchain/testing:file_test
|
||||
--test_arg=--file_tests=<path_to_carbon_file>`
|
||||
- **Build toolchain**: `bazelisk build //toolchain/...`
|
||||
|
||||
### Updating test data
|
||||
|
||||
@@ -32,7 +32,7 @@ repos:
|
||||
# Run markdown linting early so that doc style and table-of-contents see the
|
||||
# linted state.
|
||||
- repo: https://github.com/rvben/rumdl-pre-commit
|
||||
rev: v0.2.22
|
||||
rev: v0.2.58
|
||||
hooks:
|
||||
- id: rumdl
|
||||
args: [--fix]
|
||||
@@ -51,7 +51,7 @@ repos:
|
||||
# Re-run markdown linting to fix any issues caused by doc style and TOC. This
|
||||
# is very fast, so it shouldn't be problematic to run twice.
|
||||
- repo: https://github.com/rvben/rumdl-pre-commit
|
||||
rev: v0.2.30
|
||||
rev: v0.2.58
|
||||
hooks:
|
||||
- id: rumdl
|
||||
args: [--fix]
|
||||
|
||||
+15
-1
@@ -15,7 +15,6 @@ respect-gitignore = true
|
||||
# Disable rules that produce the most noise initially. Some of these might make
|
||||
# sense to re-enable.
|
||||
disable = [
|
||||
"MD013", # Line length exceeded
|
||||
"MD033", # Inline HTML - commonly used in real-world markdown
|
||||
"MD036", # Emphasis used instead of heading
|
||||
"MD040", # Code blocks should have a language specified
|
||||
@@ -25,6 +24,21 @@ disable = [
|
||||
"MD028", # Blank line inside blockquote
|
||||
]
|
||||
|
||||
# Line wrapping
|
||||
[MD013]
|
||||
reflow = true
|
||||
# Note that we might want to use the "normalize" reflow mode to have more
|
||||
# consistent line wrapping, however this mode is currently deeply incompatible
|
||||
# with inline HTML that we use reasonably often. For now, we go with the default
|
||||
# mode that doesn't try to normalize wrapping.
|
||||
reflow-mode = "default"
|
||||
ignore-link-urls = false
|
||||
code-blocks = false
|
||||
code-spans = false
|
||||
atomic-spans = false
|
||||
headings = false
|
||||
stern = true
|
||||
|
||||
# Heading style
|
||||
[MD003]
|
||||
style = "atx"
|
||||
|
||||
+16
-16
@@ -250,21 +250,21 @@ below. We also emphasize two additional requirements for contributors operating
|
||||
or using AI-based tools:
|
||||
|
||||
1. **Contributions should not become extractive of the project and community**:
|
||||
the value added should outweigh the overhead of landing the contribution. The
|
||||
overhead of landing contributions ranges from code review, to discussions,
|
||||
distractions from the current project priorities, or growing maintenance
|
||||
burden without growing maintainers.
|
||||
the value added should outweigh the overhead of landing the contribution.
|
||||
The overhead of landing contributions ranges from code review, to
|
||||
discussions, distractions from the current project priorities, or growing
|
||||
maintenance burden without growing maintainers.
|
||||
|
||||
2. **Each PR should be transparent about the tooling used** in proportion to how
|
||||
much of the PR was produced by the tool and whether the tool is a standard
|
||||
one for the project. For example, formatting with the standard tools is
|
||||
reasonable to assume without further comment. But if a PR is largely derived
|
||||
from running a specific Python script, regular expression, or AI-based tool
|
||||
over the codebase, we ask that its commit message is transparent about this
|
||||
and include a description of how the tool was used to formulate the change.
|
||||
For PRs largely derived from AI-based tooling, we suggest following the
|
||||
pattern established by the Fedora Project to mark commits with
|
||||
`Assisted-by: ...`.
|
||||
2. **Each PR should be transparent about the tooling used** in proportion to
|
||||
how much of the PR was produced by the tool and whether the tool is a
|
||||
standard one for the project. For example, formatting with the standard
|
||||
tools is reasonable to assume without further comment. But if a PR is
|
||||
largely derived from running a specific Python script, regular expression,
|
||||
or AI-based tool over the codebase, we ask that its commit message is
|
||||
transparent about this and include a description of how the tool was used to
|
||||
formulate the change. For PRs largely derived from AI-based tooling, we
|
||||
suggest following the pattern established by the Fedora Project to mark
|
||||
commits with `Assisted-by: ...`.
|
||||
|
||||
Our policies and practices here are inspired by and aim to be roughly compatible
|
||||
with several other open source projects:
|
||||
@@ -405,8 +405,8 @@ respectful, and don't drown out other discussion.
|
||||
Changes to Carbon documentation follow the
|
||||
[Google developer documentation style guide](https://developers.google.com/style).
|
||||
|
||||
Markdown files should additionally use [rumdl](https://github.com/rvben/rumdl) for
|
||||
formatting, which we automate with
|
||||
Markdown files should additionally use [rumdl](https://github.com/rvben/rumdl)
|
||||
for formatting, which we automate with
|
||||
[prek](/docs/project/contribution_tools.md#running-prek).
|
||||
|
||||
Other style points to be aware of are:
|
||||
|
||||
@@ -354,9 +354,9 @@ var résultat: String = "Succès";
|
||||
```
|
||||
|
||||
Comments start with two slashes `//` and go to the end of the line. A comment
|
||||
may be the only content on its line, or it may follow other content as a trailing
|
||||
comment. Full-line comments are preferred for documentation, while trailing
|
||||
comments mark or annotate a specific line.
|
||||
may be the only content on its line, or it may follow other content as a
|
||||
trailing comment. Full-line comments are preferred for documentation, while
|
||||
trailing comments mark or annotate a specific line.
|
||||
|
||||
```carbon
|
||||
// Compute an approximation of π.
|
||||
@@ -1204,8 +1204,8 @@ they are used.
|
||||
> [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162)
|
||||
> - Proposal
|
||||
> [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257)
|
||||
> - Proposal
|
||||
> [#339: Add `var <type> <identifier> [ = <value> ];` syntax for variables](https://github.com/carbon-language/carbon-lang/pull/339)
|
||||
> - Proposal [#339: Add `var <type> <identifier> [ = <value> ];` syntax for
|
||||
> variables](https://github.com/carbon-language/carbon-lang/pull/339)
|
||||
> - Proposal
|
||||
> [#618: var ordering](https://github.com/carbon-language/carbon-lang/pull/618)
|
||||
> - Proposal
|
||||
|
||||
+10
-9
@@ -1711,11 +1711,12 @@ class SongByTitle {
|
||||
}
|
||||
```
|
||||
|
||||
An adapter can also preserve the API and interface implementations of the original
|
||||
type using `extend adapt`. For details on how an extending adapter implements
|
||||
interfaces that are implemented for the adapted type, as well as applications of adapters to generics, see
|
||||
[Adapting types](/docs/design/generics/details.md#adapting-types) in the generics
|
||||
design.
|
||||
An adapter can also preserve the API and interface implementations of the
|
||||
original type using `extend adapt`. For details on how an extending adapter
|
||||
implements interfaces that are implemented for the adapted type, as well as
|
||||
applications of adapters to generics, see
|
||||
[Adapting types](/docs/design/generics/details.md#adapting-types) in the
|
||||
generics design.
|
||||
|
||||
**Comparison with other languages:** This is similar to the Rust idiom called
|
||||
"newtype", which is used to implement traits on types while avoiding
|
||||
@@ -1736,10 +1737,10 @@ checks, like `ValidDate` with the same data layout as `Date`. Or to record the
|
||||
units associated with a value, such as `Seconds` versus `Milliseconds` or `Feet`
|
||||
versus `Meters`.
|
||||
|
||||
> **Future work:** We should have some way of restricting the casts between a type
|
||||
> and an adapter to address this use case. One possibility would be to add the
|
||||
> keyword `private` before `adapt`, so you might write
|
||||
> `extend private adapt Date;`.
|
||||
> **Future work:** We should have some way of restricting the casts between a
|
||||
> type and an adapter to address this use case. One possibility would be to add
|
||||
> the keyword `private` before `adapt`, so you might write `extend private adapt
|
||||
> Date;`.
|
||||
|
||||
Haskell has a [`newtype` feature](https://wiki.haskell.org/Newtype) as well.
|
||||
Haskell's feature doesn't directly support reusing implementations either, but
|
||||
|
||||
@@ -52,15 +52,15 @@ A named function definition or declaration has one of the following syntactic
|
||||
forms (where items in square brackets are optional and independent):
|
||||
|
||||
- `fn` _name_ [_implicit-parameters_] [_tuple-pattern_] `=>` _expression_ `;`
|
||||
- `fn` _name_ [_implicit-parameters_] [_tuple-pattern_] [`->` _return-form_] `{`
|
||||
_statements_ `}`
|
||||
- `fn` _name_ [_implicit-parameters_] [_tuple-pattern_] [`->` _return-form_]
|
||||
`{` _statements_ `}`
|
||||
- `fn` _name_ [_implicit-parameters_] _tuple-pattern_ [`->` _return-form_] `;`
|
||||
|
||||
A lambda expression has one of the following syntactic forms:
|
||||
|
||||
- `fn` [_implicit-parameters_] [_tuple-pattern_] `=>` _expression_
|
||||
- `fn` [_implicit-parameters_] [_tuple-pattern_] [`->` _return-form_] `{` _statements_
|
||||
`}`
|
||||
- `fn` [_implicit-parameters_] [_tuple-pattern_] [`->` _return-form_] `{`
|
||||
_statements_ `}`
|
||||
|
||||
Named function definitions are distinguished from lambdas by the presence of a
|
||||
name after the `fn` keyword. If a statement or declaration begins with `fn`, a
|
||||
@@ -758,14 +758,14 @@ parameters. This checking proceeds as follows:
|
||||
- If the parameter is a `template` binding, the argument expression is
|
||||
converted to have the same type as the binding and template constant
|
||||
expression phase.
|
||||
- If the parameter is a checked generic binding, the argument expression is
|
||||
converted to have the same type as the binding and symbolic constant
|
||||
- If the parameter is a checked generic binding, the argument expression
|
||||
is converted to have the same type as the binding and symbolic constant
|
||||
expression phase.
|
||||
- Otherwise, the parameter is pattern-matched against the argument.
|
||||
|
||||
If a parameter is a compile-time binding, its corresponding converted argument
|
||||
expression is evaluated, and its value is added to the list of deduced
|
||||
argument values before any later parameters are processed.
|
||||
If a parameter is a compile-time binding, its corresponding converted
|
||||
argument expression is evaluated, and its value is added to the list of
|
||||
deduced argument values before any later parameters are processed.
|
||||
|
||||
The result of the call expression depends on the callee:
|
||||
|
||||
|
||||
@@ -46,8 +46,9 @@ These last two cases are highlighted as concerns in Rust in
|
||||
Since Carbon is bundling interface implementations into types, for the
|
||||
convenience and expressiveness that provides, we satisfy those use cases by
|
||||
giving the user control over the type of a value. This means having facilities
|
||||
for defining new [compatible types](/docs/design/classes.md#compatible-types) with
|
||||
different interface implementations, and casting between those types as needed.
|
||||
for defining new [compatible types](/docs/design/classes.md#compatible-types)
|
||||
with different interface implementations, and casting between those types as
|
||||
needed.
|
||||
|
||||
## The "Hashtable Problem"
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ This document explains the rationale for choosing to make
|
||||
## Rewrite constraints
|
||||
|
||||
Rewrite constraints are [`where` clauses](details.md#where-constraints) of the
|
||||
form `.AssociatedConstant = Value`. Given a checked generic binding `T: A where .B = C`,
|
||||
references to `T.(A.B)` are rewritten to `C`. This appendix describes the
|
||||
precise rules governing them.
|
||||
form `.AssociatedConstant = Value`. Given a checked generic binding `T: A where
|
||||
.B = C`, references to `T.(A.B)` are rewritten to `C`. This appendix describes
|
||||
the precise rules governing them.
|
||||
|
||||
## Combining constraints with `&`
|
||||
|
||||
|
||||
@@ -1123,7 +1123,8 @@ instead.
|
||||
|
||||
### Constraints that don't depend on `.Self`
|
||||
|
||||
> **TODO:** Link to section explaining when identifying a facet type happens when
|
||||
> **TODO:** Link to section explaining when identifying a facet type happens
|
||||
> when
|
||||
> [#5168: Forward `impl` declaration of an incomplete interface](/proposals/p005168-forward-impl-declaration-of-an-incomplete-interface.md)
|
||||
> is applied to these docs.
|
||||
|
||||
@@ -1139,11 +1140,11 @@ constraint N(T: type) {
|
||||
}
|
||||
```
|
||||
|
||||
When the above named constraint is identified as part of a facet type as
|
||||
`C impls N(.Self)`, the resulting requirement `Z where .Z1 = {}` is only
|
||||
When the above named constraint is identified as part of a facet type as `C
|
||||
impls N(.Self)`, the resulting requirement `Z where .Z1 = {}` is only
|
||||
constraining `C`, and not `.Self` from the top-level top-level facet type. So we
|
||||
require that `C impls (Z where .Z1 = {})` is already true in order to successfully
|
||||
identify.
|
||||
require that `C impls (Z where .Z1 = {})` is already true in order to
|
||||
successfully identify.
|
||||
|
||||
```carbon
|
||||
interface Z(V: type) {
|
||||
@@ -1799,9 +1800,10 @@ be detected in function overloading.
|
||||
Since interfaces may only be implemented for a type once, and we limit where
|
||||
implementations may be added to a type, there is a need to allow the user to
|
||||
switch the type of a value to access different interface implementations. Carbon
|
||||
therefore provides [adapters](/docs/design/classes.md#adapters) as a way to create new types
|
||||
[compatible with](/docs/design/classes.md#compatible-types) existing types with different
|
||||
APIs, in particular with different interface implementations:
|
||||
therefore provides [adapters](/docs/design/classes.md#adapters) as a way to
|
||||
create new types [compatible with](/docs/design/classes.md#compatible-types)
|
||||
existing types with different APIs, in particular with different interface
|
||||
implementations:
|
||||
|
||||
```carbon
|
||||
interface Printable {
|
||||
@@ -2675,9 +2677,9 @@ member of another. The `where` operator is not associative, so a type expression
|
||||
using multiple must use round parens `(`...`)` to specify grouping.
|
||||
|
||||
The scope of a facet type formed by a `where` declaration
|
||||
[extends](/docs/design/expressions/member_access.md#extend) the scope of its first
|
||||
operand, and the resulting facet type is complete if that scope it extends is
|
||||
complete.
|
||||
[extends](/docs/design/expressions/member_access.md#extend) the scope of its
|
||||
first operand, and the resulting facet type is complete if that scope it extends
|
||||
is complete.
|
||||
|
||||
> **Comparison with other languages:** Both Swift and Rust use `where` clauses
|
||||
> on declarations instead of in the expression syntax. These happen after the
|
||||
@@ -2863,7 +2865,8 @@ constraint ContainerIsSlice {
|
||||
|
||||
The `.Self` construct follows these rules:
|
||||
|
||||
- A checked binding `X` introduces a checked generic binding `.Self: type`, where
|
||||
- A checked binding `X` introduces a checked generic binding `.Self: type`,
|
||||
where
|
||||
|
||||
references to `.Self` are resolved to `X`. This allows you to use `.Self` as
|
||||
an interface parameter as in `X: I(.Self)`.
|
||||
@@ -3967,11 +3970,11 @@ fn DownCast[T: type](p: T*, generic U: type where .Self extends T) -> U*;
|
||||
|
||||
Given a type `U`, define the facet type `CompatibleWith(U)` as follows:
|
||||
|
||||
> `CompatibleWith(U)` is a facet type whose values are facets `T` such that
|
||||
> `T as type` and `U as type` are
|
||||
> [compatible types](/docs/design/classes.md#compatible-types). That is values of `T` and
|
||||
> `U` as types can be cast back and forth without any change in representation
|
||||
> (for example `T` is an [adapter](#adapting-types) for `U`).
|
||||
> `CompatibleWith(U)` is a facet type whose values are facets `T` such that `T
|
||||
> as type` and `U as type` are
|
||||
> [compatible types](/docs/design/classes.md#compatible-types). That is values
|
||||
> of `T` and `U` as types can be cast back and forth without any change in
|
||||
> representation (for example `T` is an [adapter](#adapting-types) for `U`).
|
||||
|
||||
`CompatibleWith` determines an equivalence relationship between types.
|
||||
Specifically, given two types `T1` and `T2`, they are equivalent if
|
||||
@@ -4819,7 +4822,8 @@ difference.
|
||||
#### Prioritization rule
|
||||
|
||||
> **TODO:** Document the changes to prioritization adopted in
|
||||
> [#5337: Interface extension and `final impl` update](/proposals/p005337-interface-extension-and-final-impl-update.md) and
|
||||
> [#5337: Interface extension and `final impl` update](/proposals/p005337-interface-extension-and-final-impl-update.md)
|
||||
> and
|
||||
> [#7493: Disallow impl in match_first twice](/proposals/p007493-disallow-impl-in-match-first-twice.md).
|
||||
|
||||
Since at most one library can contain `impl` definitions with a given type
|
||||
|
||||
@@ -142,8 +142,8 @@ fn SortVector(generic T: Comparable, a: Vector(T)*) { ... }
|
||||
```
|
||||
|
||||
The syntax above uses the `generic` keyword to indicate that the parameter named
|
||||
`T` is a _checked generic_ parameter. The `template` keyword may be added instead to
|
||||
make it a _template generic_.
|
||||
`T` is a _checked generic_ parameter. The `template` keyword may be added
|
||||
instead to make it a _template generic_.
|
||||
|
||||
Given an `i32` vector `iv`, `SortVector(i32, &iv)` is equivalent to
|
||||
`SortInt32Vector(&iv)`. Similarly for a `String` vector `sv`,
|
||||
@@ -527,9 +527,10 @@ cast from `T` to `CDCover`.
|
||||
### Adapting types
|
||||
|
||||
Carbon has a mechanism called [adapting types](/docs/design/classes.md#adapters)
|
||||
to create new types that are [compatible](/docs/design/classes.md#compatible-types) with
|
||||
existing types but with different interface implementations. This could be used
|
||||
to add or replace implementations, or define implementations for reuse.
|
||||
to create new types that are
|
||||
[compatible](/docs/design/classes.md#compatible-types) with existing types but
|
||||
with different interface implementations. This could be used to add or replace
|
||||
implementations, or define implementations for reuse.
|
||||
|
||||
In this example, we have multiple ways of sorting a collection of `Song` values.
|
||||
|
||||
|
||||
@@ -551,14 +551,16 @@ make it clear that the data representation of the value is not changing, just
|
||||
its type as reflected in the API available to manipulate the value.
|
||||
|
||||
Casting is indicated explicitly by way of some syntax in the source code. You
|
||||
might use a cast to switch between [type adaptations](/docs/design/classes.md#adapters), or to
|
||||
be explicit where an implicit conversion would otherwise occur. For now, we are
|
||||
saying "`x as y`" is the provisional syntax in Carbon for casting the value `x`
|
||||
to the type `y`. Note that outside of generics, the term "casting" includes any
|
||||
explicit type change, including those that change the data representation.
|
||||
might use a cast to switch between
|
||||
[type adaptations](/docs/design/classes.md#adapters), or to be explicit where an
|
||||
implicit conversion would otherwise occur. For now, we are saying "`x as y`" is
|
||||
the provisional syntax in Carbon for casting the value `x` to the type `y`. Note
|
||||
that outside of generics, the term "casting" includes any explicit type change,
|
||||
including those that change the data representation.
|
||||
|
||||
In contexts where an expression of one type is provided and a different type is
|
||||
required, an [implicit conversion](/docs/design/expressions/implicit_conversions.md) is
|
||||
required, an
|
||||
[implicit conversion](/docs/design/expressions/implicit_conversions.md) is
|
||||
performed if it is considered safe to do so. Such an implicit conversion, if
|
||||
permitted, always has the same meaning as an explicit cast.
|
||||
|
||||
@@ -824,9 +826,9 @@ express, for example:
|
||||
element type.
|
||||
- An interface may define an associated facet that needs to be constrained to
|
||||
implement some interfaces.
|
||||
- This type must be [compatible](/docs/design/classes.md#compatible-types) with another type. You
|
||||
might use this to define alternate implementations of a single interfaces,
|
||||
such as sorting order, for a single type.
|
||||
- This type must be [compatible](/docs/design/classes.md#compatible-types)
|
||||
with another type. You might use this to define alternate implementations of
|
||||
a single interfaces, such as sorting order, for a single type.
|
||||
|
||||
Note that type constraints can be a restriction on one facet parameter or
|
||||
associated facet, or can define a relationship between multiple facets.
|
||||
|
||||
@@ -860,8 +860,8 @@ Evaluation of the last line involves 6 function calls:
|
||||
1. Call `MakeA`.
|
||||
2. Call `A.(Core.ImplicitAsPrimitive(C)).Convert`, to convert the `A` object to
|
||||
a `C` value, as part of type conversion.
|
||||
3. Call `A.(Core.Copy).Op` to copy the `C` value into the storage for `cd.0`, as
|
||||
part of category conversion.
|
||||
3. Call `A.(Core.Copy).Op` to copy the `C` value into the storage for `cd.0`,
|
||||
as part of category conversion.
|
||||
4. Call `MakeB`.
|
||||
5. Call `B.(Core.ImplicitAsPrimitive(D)).Convert`.
|
||||
6. Call `B.(Core.Copy).Op`.
|
||||
|
||||
@@ -26,10 +26,10 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
## Overview
|
||||
|
||||
One of Carbon's core goals is [practical safety]. This is referring to _[code
|
||||
safety]_
|
||||
as opposed to the larger space of [systems safety]. The largest aspect of code safety
|
||||
at the language level is [memory safety], but this also applies to other aspects
|
||||
of code safety such as avoiding undefined behavior in other forms.
|
||||
safety]_ as opposed to the larger space of [systems safety]. The largest aspect
|
||||
of code safety at the language level is [memory safety], but this also applies
|
||||
to other aspects of code safety such as avoiding undefined behavior in other
|
||||
forms.
|
||||
|
||||
[practical safety]:
|
||||
/docs/project/goals.md#practical-safety-and-testing-mechanisms
|
||||
@@ -45,9 +45,9 @@ guarantees. Our safety strategy has to address how C++ code fits into it, and
|
||||
provide an incremental path from where the code is at today towards increasing
|
||||
levels of safety.
|
||||
|
||||
Ultimately, Carbon will both provide a [memory-safe language], _and_ provide a language
|
||||
that is a target for mechanical migration from C++ and optimizes even further for
|
||||
interop with unsafe C++ with minimal friction.
|
||||
Ultimately, Carbon will both provide a [memory-safe language], _and_ provide a
|
||||
language that is a target for mechanical migration from C++ and optimizes even
|
||||
further for interop with unsafe C++ with minimal friction.
|
||||
|
||||
[memory-safe language]: /docs/design/safety/terminology.md#memory-safe-language
|
||||
|
||||
@@ -55,9 +55,9 @@ interop with unsafe C++ with minimal friction.
|
||||
|
||||
Carbon will have both _safe_ and _unsafe_ code. Safe code provides limits on the
|
||||
potential behavior of the program even in the face of bugs in order to prevent
|
||||
[safety bugs] from becoming [vulnerabilities]. Unsafe code is any code or operation
|
||||
which lacks limits or guarantees on behavior, and as a consequence may have undefined
|
||||
behavior or be a safety bug.
|
||||
[safety bugs] from becoming [vulnerabilities]. Unsafe code is any code or
|
||||
operation which lacks limits or guarantees on behavior, and as a consequence may
|
||||
have undefined behavior or be a safety bug.
|
||||
|
||||
[safety bugs]: /docs/design/safety/terminology.md#safety-bugs
|
||||
[vulnerabilities]:
|
||||
@@ -128,8 +128,8 @@ expressivity is available at that finer granularity through explicitly marking
|
||||
Carbon will use a hybrid of different techniques to achieve memory safety in its
|
||||
safe code, largely broken down by the categories of memory safety:
|
||||
|
||||
- [Type safety]: compile-time enforcement, the same as other statically typed languages
|
||||
with generic type systems.
|
||||
- [Type safety]: compile-time enforcement, the same as other statically typed
|
||||
languages with generic type systems.
|
||||
- [Initialization safety]: hybrid of run-time and compile-time enforcement.
|
||||
- [Spatial safety]: run-time enforcement.
|
||||
- [Temporal safety]: compile-time enforcement through its type system.
|
||||
@@ -161,7 +161,8 @@ also involve a temporal memory safety violation. For example, despite both Go
|
||||
and non-strict-concurrency Swift only providing temporal safety, the rate of
|
||||
memory safety vulnerabilities in software written in both matches the expected
|
||||
low rate for memory-safe languages. As a consequence, Carbon has some
|
||||
flexibility while still being a [memory-safe language] according to our definition:
|
||||
flexibility while still being a [memory-safe language] according to our
|
||||
definition:
|
||||
|
||||
- Carbon might choose to _not_ prevent data race bugs that are not
|
||||
_themselves_ also temporal safety bugs, even though the data race may lead
|
||||
@@ -173,8 +174,8 @@ flexibility while still being a [memory-safe language] according to our definiti
|
||||
free.
|
||||
|
||||
Despite having this flexibility, preventing data race bugs remains _highly
|
||||
valuable_ for correctness, debugging, and achieving [fearless concurrency]. If Carbon
|
||||
can, it should work to prevent data races as well.
|
||||
valuable_ for correctness, debugging, and achieving [fearless concurrency]. If
|
||||
Carbon can, it should work to prevent data races as well.
|
||||
|
||||
[fearless concurrency]: https://doc.rust-lang.org/book/ch16-00-concurrency.html
|
||||
|
||||
@@ -220,8 +221,9 @@ run-time enforcement components of our
|
||||
[memory safety model](#memory-safety-model) above. This means, for example, that
|
||||
bounds checking is enabled in the release build. There is [evidence] that the
|
||||
cost of these hardening steps is low. Following the specific guidance of our top
|
||||
priority for [performance control], Carbon will provide ways to write unsafe code
|
||||
that disables the run-time enforcement, enabling the control of any overhead incurred.
|
||||
priority for [performance control], Carbon will provide ways to write unsafe
|
||||
code that disables the run-time enforcement, enabling the control of any
|
||||
overhead incurred.
|
||||
|
||||
[evidence]: https://chandlerc.blog/posts/2024/11/story-time-bounds-checking/
|
||||
[performance control]: /docs/project/goals.md#performance-critical-software
|
||||
|
||||
@@ -1044,10 +1044,10 @@ applied to phases uses the ordering "runtime" < "symbolic" < "template"):
|
||||
`(<T1, C, P1, V1>, <T2, C, P2, V2>, ... <TN, C, PN, VN>)` can be converted
|
||||
to a primitive extended type
|
||||
`<(T1, T2, ..., TN), C, min(P1, P2, ..., PN), (V1, V2, ... VN)>`.
|
||||
- An expression of struct extended type
|
||||
`{.a = <Ta, C, Pa, Va>, .b = <Tb, C, Pb, Vb>, ... .z = <Tz, C, Pz, Vz>}` can
|
||||
be converted to a primitive extended type
|
||||
`<{.a = Ta, .b = Tb, ... .z = Tz}, C, min(Pa, Pb, ... Pz), {.a = Va, .b = Vb, ... .z = Vz}>`.
|
||||
- An expression of struct extended type `{.a = <Ta, C, Pa, Va>, .b = <Tb, C,
|
||||
Pb, Vb>, ... .z = <Tz, C, Pz, Vz>}` can be converted to a primitive extended
|
||||
type `<{.a = Ta, .b = Tb, ... .z = Tz}, C, min(Pa, Pb, ... Pz), {.a = Va,
|
||||
.b = Vb, ... .z = Vz}>`.
|
||||
|
||||
When `C` is "value", composition forms a value representation of the aggregate
|
||||
from value representations of the elements. When `C` is "initializing", it
|
||||
@@ -1169,8 +1169,8 @@ alternatives considered section of [P2006]:
|
||||
### Pointer syntax
|
||||
|
||||
The type of a pointer to a type `T` is written with a postfix `*` as in `T*`.
|
||||
Dereferencing a pointer is a [_reference expression_] and is written with a prefix
|
||||
`*` as in `*p`:
|
||||
Dereferencing a pointer is a [_reference expression_] and is written with a
|
||||
prefix `*` as in `*p`:
|
||||
|
||||
```carbon
|
||||
var i: i32 = 42;
|
||||
|
||||
@@ -210,8 +210,8 @@ To use it:
|
||||
|
||||
A typical commit workflow looks like:
|
||||
|
||||
1. `git commit` to try committing files. This automatically executes `prek run`,
|
||||
which may fail and leave files modified for cleanup.
|
||||
1. `git commit` to try committing files. This automatically executes `prek
|
||||
run`, which may fail and leave files modified for cleanup.
|
||||
2. `git add .` to add the automatic modifications done by hooks.
|
||||
3. `git commit` again.
|
||||
|
||||
@@ -235,16 +235,16 @@ considering if they fit your workflow.
|
||||
- **WARNING**: Bugs in `rs-git-fsmonitor` and/or Watchman can result in
|
||||
`prek` deleting files. If you see files being deleted, disable
|
||||
`rs-git-fsmonitor` with `git config --unset core.fsmonitor`.
|
||||
- [rumdl](https://github.com/rvben/rumdl): A Markdown formatter, which we use for
|
||||
formatting Markdown files. If you want to format files directly or use it in
|
||||
your editor, you can install it:
|
||||
- [rumdl](https://github.com/rvben/rumdl): A Markdown formatter, which we use
|
||||
for formatting Markdown files. If you want to format files directly or use
|
||||
it in your editor, you can install it:
|
||||
- With `cargo` (preferred): `cargo install --locked rumdl`
|
||||
- With `brew` (on macOS): `brew install rumdl`
|
||||
- For Vim/Neovim, it is recommended to connect using its built-in Language
|
||||
Server Protocol (LSP) capabilities (by way of `rumdl server`). It is supported
|
||||
by [Mason](https://github.com/williamboman/mason.nvim) (as `rumdl`) and
|
||||
can be configured by way of `nvim-lspconfig` or formatting plugins like
|
||||
`conform.nvim`. For more details, see the
|
||||
Server Protocol (LSP) capabilities (by way of `rumdl server`). It is
|
||||
supported by [Mason](https://github.com/williamboman/mason.nvim) (as
|
||||
`rumdl`) and can be configured by way of `nvim-lspconfig` or formatting
|
||||
plugins like `conform.nvim`. For more details, see the
|
||||
[rumdl editor integration documentation](https://github.com/rvben/rumdl#editor-integration).
|
||||
- [vim-prettier](https://github.com/prettier/vim-prettier): A vim integration
|
||||
for [Prettier](https://prettier.io/), which we use for formatting.
|
||||
|
||||
@@ -37,8 +37,8 @@ documentation.
|
||||
|
||||
- Links to issues and to complete proposals should use the text `#nnnn`, where
|
||||
`nnnn` is the issue number, optionally followed by the proposal title, and
|
||||
should link to the issue or pull request on GitHub. For example,
|
||||
`[#123: widget painting](https://github.com/carbon-language/carbon-lang/pull/123)`.
|
||||
should link to the issue or pull request on GitHub. For example, `[#123:
|
||||
widget painting](https://github.com/carbon-language/carbon-lang/pull/123)`.
|
||||
- Links to specific sections of a proposal should link to the repository copy
|
||||
of the proposal file, using the section title or other appropriate link
|
||||
text. For example,
|
||||
|
||||
@@ -73,12 +73,14 @@ in order to maintain the same behaviour.
|
||||
## Alternatives considered
|
||||
|
||||
This rule was originally stated that any two files could be concatenated in some
|
||||
order without changing the meaning of the code. However this creates (at least) two problems:
|
||||
order without changing the meaning of the code. However this creates (at least)
|
||||
two problems:
|
||||
|
||||
- Under separate compilation, `impl` declarations in an impl file are not
|
||||
visible to other Carbon files. Concatenating them into another file would make
|
||||
them visible, and could change the meaning of code that can now find them.
|
||||
visible to other Carbon files. Concatenating them into another file would
|
||||
make them visible, and could change the meaning of code that can now find
|
||||
them.
|
||||
- Packages introduce a named scope, so the symbols within the package are
|
||||
qualified by the package name. Concatenating the contents of one package into
|
||||
another would change the name by which any moved entities would be found. This
|
||||
would necessitate changes to the code to resolve name lookups.
|
||||
qualified by the package name. Concatenating the contents of one package
|
||||
into another would change the name by which any moved entities would be
|
||||
found. This would necessitate changes to the code to resolve name lookups.
|
||||
|
||||
@@ -93,9 +93,9 @@ split up pull requests:
|
||||
right": not too big, not too small. You don't want to separate a pattern of
|
||||
tightly related changes into separate requests when they're easier to review
|
||||
as a set or batch, and you don't want to bundle unrelated changes together.
|
||||
Typically you should try to keep the pull request as small as you can without
|
||||
breaking apart tightly coupled changes. However, listen to your code reviewer
|
||||
if they ask to split things up or combine them.
|
||||
Typically you should try to keep the pull request as small as you can
|
||||
without breaking apart tightly coupled changes. However, listen to your code
|
||||
reviewer if they ask to split things up or combine them.
|
||||
|
||||
While the default is to squash pull requests into a single commit, _during_ the
|
||||
review you typically want to leave the development history undisturbed until the
|
||||
|
||||
@@ -39,12 +39,12 @@ This achieves two goals:
|
||||
|
||||
1. Replaces the term `master`. This term, while only used in isolation in Git,
|
||||
[was used](https://mail.gnome.org/archives/desktop-devel-list/2019-May/msg00066.html)
|
||||
in immediately preceding and related systems as part of extremely problematic
|
||||
"master/slave" terminology. That background associates the term with
|
||||
unacceptable historical and cultural meanings. The intent of those using or
|
||||
adopting the term isn't relevant to this association. The less overtly
|
||||
problematic term being isolated from the rest doesn't erase its history, and
|
||||
doesn't completely avoid painful associations.
|
||||
in immediately preceding and related systems as part of extremely
|
||||
problematic "master/slave" terminology. That background associates the term
|
||||
with unacceptable historical and cultural meanings. The intent of those
|
||||
using or adopting the term isn't relevant to this association. The less
|
||||
overtly problematic term being isolated from the rest doesn't erase its
|
||||
history, and doesn't completely avoid painful associations.
|
||||
|
||||
2. It directly anchors and reinforces contributors on the trunk-based workflow.
|
||||
|
||||
|
||||
@@ -667,13 +667,13 @@ may create them for bucketing work, they are non-essential):
|
||||
|
||||
1. Create the PR, for example #456, naming the proposal p0456.md.
|
||||
2. Update the labels of #456 when progressing a proposal.
|
||||
1. Don't bother putting the status in p0456.md: people should rely on the PR
|
||||
labels since it's in the same place.
|
||||
1. Don't bother putting the status in p0456.md: people should rely on the
|
||||
PR labels since it's in the same place.
|
||||
3. When a decision is made, add it as a comment to #456.
|
||||
1. This does not replace the Discourse Forum topic announcing a decision.
|
||||
2. Comments on the decision should go in Discourse Forums.
|
||||
3. The author is asked to link to the decision in p0456.md before the commit
|
||||
is approved.
|
||||
3. The author is asked to link to the decision in p0456.md before the
|
||||
commit is approved.
|
||||
4. If declined/deferred proposals are committed, it would be best to add a
|
||||
status in p0456.md before committing.
|
||||
|
||||
|
||||
@@ -757,13 +757,13 @@ approaches looks like:
|
||||
- Alternative: `library "Boost/Random.Uniform" namespace Boost;`
|
||||
- Specifying namespaces:
|
||||
- Proposal: `package BoostRandom namespace Distributions;`
|
||||
- Alternative:
|
||||
`library "Boost/Random.Uniform" namespace Boost.Random.Distributions;`
|
||||
- Alternative: `library "Boost/Random.Uniform" namespace
|
||||
Boost.Random.Distributions;`
|
||||
- Combined:
|
||||
- Proposal:
|
||||
`package BoostRandom library "Uniform" namespace Distributions;`
|
||||
- Alternative:
|
||||
`library "Boost/Random.Uniform" namespace Boost.Random.Distributions;`
|
||||
- Alternative: `library "Boost/Random.Uniform" namespace
|
||||
Boost.Random.Distributions;`
|
||||
- `import` changes:
|
||||
- Trivial:
|
||||
- Proposal: `import BoostRandom;`
|
||||
|
||||
@@ -107,9 +107,10 @@ The choice to require NFC is really four choices:
|
||||
same glyph, such as with pre-combined diacritics versus with diacritics
|
||||
expressed as separate combining characters, or with combining characters
|
||||
in a different order, would be considered different characters.
|
||||
- If we use a canonical normalization form, all ways of encoding diacritics
|
||||
are considered to form the same character, but ligatures such as `ffi` are
|
||||
considered distinct from the character sequence that they decompose into.
|
||||
- If we use a canonical normalization form, all ways of encoding
|
||||
diacritics are considered to form the same character, but ligatures such
|
||||
as `ffi` are considered distinct from the character sequence that they
|
||||
decompose into.
|
||||
- If we use a compatibility normalization form, ligatures are considered
|
||||
equivalent to the character sequence that they decompose into.
|
||||
|
||||
@@ -124,19 +125,19 @@ The choice to require NFC is really four choices:
|
||||
See also the discussion of [homoglyphs](#homoglyphs) below.
|
||||
|
||||
2. Composition: we use a composed normalization form rather than a decomposed
|
||||
normalization form. For example, `ō` is encoded as U+014D (LATIN SMALL LETTER
|
||||
O WITH MACRON) in a composed form and as U+006F (LATIN SMALL LETTER O),
|
||||
U+0304 (COMBINING MACRON) in a decomposed form. The composed form results in
|
||||
smaller representations whenever the two differ, but the decomposed form is a
|
||||
little easier for algorithmic processing (for example, typo correction and
|
||||
homoglyph detection).
|
||||
normalization form. For example, `ō` is encoded as U+014D (LATIN SMALL
|
||||
LETTER O WITH MACRON) in a composed form and as U+006F (LATIN SMALL LETTER
|
||||
O), U+0304 (COMBINING MACRON) in a decomposed form. The composed form
|
||||
results in smaller representations whenever the two differ, but the
|
||||
decomposed form is a little easier for algorithmic processing (for example,
|
||||
typo correction and homoglyph detection).
|
||||
|
||||
3. We require source files to be in our chosen form, rather than converting to
|
||||
that form as necessary.
|
||||
|
||||
4. We require that the entire contents of the file be normalized, rather than
|
||||
restricting our attention to only identifiers, or only identifiers and string
|
||||
literals.
|
||||
restricting our attention to only identifiers, or only identifiers and
|
||||
string literals.
|
||||
|
||||
### Characters in identifiers and whitespace
|
||||
|
||||
|
||||
@@ -463,9 +463,9 @@ The proposal does not include declarations for uninitialized variables, leaving
|
||||
that to a later proposal.
|
||||
|
||||
In this proposal, assignment is a statement. It could instead be an expression
|
||||
as it is in C and C++. The arguments against assignment-as-an-expression
|
||||
include (1) it complicates reasoning about the ordering of side-effects and (2) it
|
||||
can cause confusion between `=` and `==`
|
||||
as it is in C and C++. The arguments against assignment-as-an-expression include
|
||||
(1) it complicates reasoning about the ordering of side-effects and (2) it can
|
||||
cause confusion between `=` and `==`
|
||||
[(SEI CERT C Coding Standard)](https://wiki.sei.cmu.edu/confluence/display/c/EXP45-C.+Do+not+perform+assignments+in+selection+statements)
|
||||
[Visual Studio Warning](https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-4-c4706?view=vs-2019).
|
||||
|
||||
|
||||
@@ -555,9 +555,10 @@ fn ReturnVarWithControlFlow() -> Point {
|
||||
We propose a set of restrictions to give simple and understandable behavior
|
||||
which remains reasonably expressive.
|
||||
|
||||
1. Once a `returned var` is in scope, another `returned var` cannot be declared.
|
||||
2. Any `return` with a `returned var` in scope must be `return var;` and returns
|
||||
the declared `returned var`.
|
||||
1. Once a `returned var` is in scope, another `returned var` cannot be
|
||||
declared.
|
||||
2. Any `return` with a `returned var` in scope must be `return var;` and
|
||||
returns the declared `returned var`.
|
||||
3. If control flow exits the scope of a `returned var` in any way other than a
|
||||
`return var;`, it ends the lifetime of the declared `returned var` exactly
|
||||
like it would end the lifetime of a `var` declaration.
|
||||
|
||||
@@ -286,12 +286,12 @@ Disadvantages:
|
||||
expectations, for example in some important bit-manipulation cases.
|
||||
- Give integer types a range of values rather than simply a bit-width. For
|
||||
example, we can say that negation on `i32` produces a type that can
|
||||
represent [-2<sup>31</sup>+1, 2<sup>31</sup>], which still fits in 32 bits.
|
||||
However, this would add significant complexity to the type system, and with
|
||||
this approach, division would still increase the bit width: for example,
|
||||
`a / b`, where `a` and `b` are `iN`s, has 2<sup>`N`</sup>+1 distinct possible
|
||||
values. This is especially surprising because integer division is usually
|
||||
expected to make a number smaller!
|
||||
represent [-2<sup>31</sup>+1, 2<sup>31</sup>], which still fits in 32
|
||||
bits. However, this would add significant complexity to the type system,
|
||||
and with this approach, division would still increase the bit width: for
|
||||
example, `a / b`, where `a` and `b` are `iN`s, has 2<sup>`N`</sup>+1
|
||||
distinct possible values. This is especially surprising because integer
|
||||
division is usually expected to make a number smaller!
|
||||
- Refactoring code becomes more challenging, as the appropriate intermediate
|
||||
type must be determined. Mitigating this, the type system would inform the
|
||||
programmer when they make a mistake.
|
||||
@@ -379,9 +379,9 @@ cases are:
|
||||
difference of such unsigned quantities, and it's generally preferable for
|
||||
such subtractions to produce a negative result rather than a subtle bug.
|
||||
Moreover, while a restriction to non-negative values is common, supporting
|
||||
only the case of a range restriction to [0, 2<sup>N</sup>-1], but not any other
|
||||
range, does not do a good job of addressing the general desire to capture intent
|
||||
and to make invalid states unrepresentable.
|
||||
only the case of a range restriction to [0, 2<sup>N</sup>-1], but not any
|
||||
other range, does not do a good job of addressing the general desire to
|
||||
capture intent and to make invalid states unrepresentable.
|
||||
- Ability to reduce storage size. Spending a sign bit every time a number is
|
||||
stored, even when it's known to be non-negative is wasteful. This is an
|
||||
important concern, and one we should address, but it's thought to be better
|
||||
|
||||
@@ -84,28 +84,27 @@ the code, in support of these goals:
|
||||
> Summary of options for implicit parameters / arrays ambiguity discussed so
|
||||
> far:
|
||||
>
|
||||
> 1. Just make it work as-is: `impl [a; b]` parses as an array type,
|
||||
> `impl [a, b]` parses as an implicit parameter. Theoretically this is
|
||||
> unambiguous given that a `;` is required inside the `[`...`]` in the former
|
||||
> and disallowed in the latter. Concerns: it's likely to be visually
|
||||
> ambiguous.
|
||||
> 1. Just make it work as-is: `impl [a; b]` parses as an array type, `impl [a,
|
||||
> b]` parses as an implicit parameter. Theoretically this is unambiguous
|
||||
> given that a `;` is required inside the `[`...`]` in the former and
|
||||
> disallowed in the latter. Concerns: it's likely to be visually ambiguous.
|
||||
> 2. Add mandatory parentheses: `impl [T:! Type] (Vector(T) as Container)`.
|
||||
> Concerns: it's hard to avoid requiring them in cases that don't start with
|
||||
> a `[` if we want an unambiguous grammar. Requiring them always would impose
|
||||
> a small ergonomic hit.
|
||||
> 3. Add an introducer keyword for implicit parameters:
|
||||
> `impl where [T:! Type] Vector(T) as Container`. Unambiguous. Concerns:
|
||||
> still some visual ambiguity due to reuse of `[`...`]`, concern over whether
|
||||
> we'd uniformly use this syntax (`fn F where [T:! Type](x: T)`) or have
|
||||
> non-uniform syntax for implicit parameters.
|
||||
> 4. Use a different syntax for array types in general:
|
||||
> `impl Array(T) as Container` or `impl Array[N] as Container`. Concerns: may
|
||||
> want a first-class syntax here, especially if (per @geoffromer 's variadics
|
||||
> work, we want some special behavior for a deduced bound), and there's a
|
||||
> strong convention to use `[`...`]` for this. The latter syntax is messy
|
||||
> because of our types-as-expressions approach, but we could imagine
|
||||
> providing a `impl Type as Indexable where .Result = Type` to construct
|
||||
> array types. `T[]` might be a special case of some kind.
|
||||
> a `[` if we want an unambiguous grammar. Requiring them always would
|
||||
> impose a small ergonomic hit.
|
||||
> 3. Add an introducer keyword for implicit parameters: `impl where [T:! Type]
|
||||
> Vector(T) as Container`. Unambiguous. Concerns: still some visual
|
||||
> ambiguity due to reuse of `[`...`]`, concern over whether we'd uniformly
|
||||
> use this syntax (`fn F where [T:! Type](x: T)`) or have non-uniform syntax
|
||||
> for implicit parameters.
|
||||
> 4. Use a different syntax for array types in general: `impl Array(T) as
|
||||
> Container` or `impl Array[N] as Container`. Concerns: may want a
|
||||
> first-class syntax here, especially if (per @geoffromer 's variadics work,
|
||||
> we want some special behavior for a deduced bound), and there's a strong
|
||||
> convention to use `[`...`]` for this. The latter syntax is messy because
|
||||
> of our types-as-expressions approach, but we could imagine providing a
|
||||
> `impl Type as Indexable where .Result = Type` to construct array types.
|
||||
> `T[]` might be a special case of some kind.
|
||||
> 5. Use a different syntax for implicit parameters in general:
|
||||
> `impl<T:! Type> Vector(T) as Container`. Concerns: we don't have many
|
||||
> delimiter options unless we start using multi-character delimiters; `()`,
|
||||
|
||||
@@ -542,8 +542,8 @@ class MyIntContainer {
|
||||
Mixins are currently in early design stages. This section highlights possible
|
||||
uses speculating on the final design. Some may include:
|
||||
|
||||
- Improved semantics for views compared to getter methods: no direct side effect
|
||||
from using the view
|
||||
- Improved semantics for views compared to getter methods: no direct side
|
||||
effect from using the view
|
||||
- Facilitate code reuse, compared to reimplementing an interface
|
||||
- Direct access to `self`, limiting needs for pointers and address resolution
|
||||
|
||||
@@ -624,8 +624,8 @@ author chooses between value and reference).
|
||||
For reference, range-based `for` loops in C++ requires:
|
||||
|
||||
- `begin()` and `end()` methods or free functions, and
|
||||
- the type returned supports pre-increment `++`, indirection `*`, and inequality
|
||||
`!=` operations
|
||||
- the type returned supports pre-increment `++`, indirection `*`, and
|
||||
inequality `!=` operations
|
||||
|
||||
See [range-based for statement](https://eel.is/c++draft/stmt.iter#stmt.ranged)
|
||||
for more details.
|
||||
@@ -799,8 +799,8 @@ This would work similarly to [Python generator functions](#python).
|
||||
|
||||
This has the following advantages:
|
||||
|
||||
- Removes the need for an `Optional`, and the associated overheads, copies, and
|
||||
unwrapping.
|
||||
- Removes the need for an `Optional`, and the associated overheads, copies,
|
||||
and unwrapping.
|
||||
- No boundary checks needed at the `for` level
|
||||
- Compatible with R-value containers
|
||||
|
||||
@@ -850,13 +850,13 @@ value, or [inverting control](#inversion-of-control).
|
||||
The iterator approach was considered but proved to have key limitations that a
|
||||
cursor approach does not have:
|
||||
|
||||
- It requires implementing 2 interfaces instead of 1, and is more complex due to
|
||||
having the iteration logic separated from the container itself
|
||||
- It requires implementing 2 interfaces instead of 1, and is more complex due
|
||||
to having the iteration logic separated from the container itself
|
||||
- More difficult to harden or troubleshoot, compared to a cursor that allows
|
||||
bounds checking in debug & hardened build modes
|
||||
- Can pose problems with ranges that consumes their input (See Barry Revzin’s
|
||||
"take(5)" presentation from C++Now 2023), when compared to a combined `Next()`
|
||||
approach.
|
||||
"take(5)" presentation from C++Now 2023), when compared to a combined
|
||||
`Next()` approach.
|
||||
- Higher overhead
|
||||
- Proves to be difficult to support for R-values
|
||||
|
||||
|
||||
@@ -103,8 +103,8 @@ 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.
|
||||
- `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
|
||||
|
||||
@@ -43,8 +43,8 @@ Statements need some system for separation. There are two main options for this:
|
||||
|
||||
1. Require semicolons to terminate statements.
|
||||
2. Automatically determine where statements terminate.
|
||||
- Some languages, such as Python, define a syntax where a newline terminates
|
||||
statements.
|
||||
- Some languages, such as Python, define a syntax where a newline
|
||||
terminates statements.
|
||||
- Other languages, such as Javascript, require semicolons but define rules
|
||||
for semicolon insertion.
|
||||
|
||||
|
||||
@@ -56,9 +56,10 @@ evaluation. We executed on this really well, but with mixed results.
|
||||
https://github.com/carbon-language/carbon-lang/blob/840cb1bed7cf9bd57e000cb4a61e986c383d3038/docs/project/roadmap.md
|
||||
|
||||
On getting ready for evaluation, we made fantastic progress on getting the
|
||||
language (design) ready. We have [milestone definitions], and closed the most critical
|
||||
gaps in the design from the start of the year. The remaining gaps are either lower
|
||||
risk, almost finished, or really need interop to effectively explore.
|
||||
language (design) ready. We have [milestone definitions], and closed the most
|
||||
critical gaps in the design from the start of the year. The remaining gaps are
|
||||
either lower risk, almost finished, or really need interop to effectively
|
||||
explore.
|
||||
|
||||
[milestone definitions]: /docs/project/milestones.md
|
||||
|
||||
|
||||
@@ -239,8 +239,8 @@ How does this arise?
|
||||
operator is applied.
|
||||
- If it is a reference expression, the "member binding to reference"
|
||||
(`BindToRef`) operator is applied.
|
||||
- If it is a value expression, the "member binding to value" (`BindToValue`)
|
||||
operator is applied.
|
||||
- If it is a value expression, the "member binding to value"
|
||||
(`BindToValue`) operator is applied.
|
||||
3. The result of the member binding has a type that implements the call
|
||||
interface.
|
||||
|
||||
|
||||
@@ -281,10 +281,10 @@ on advantages and disadvantages for each option.
|
||||
|
||||
Disadvantages:
|
||||
|
||||
- Prevents placing `export name` next to the import that is expected to add
|
||||
the name.
|
||||
- Means `export import` and `export name` will be in different sections: no
|
||||
single place to look for re-exports.
|
||||
- Prevents placing `export name` next to the import that is expected to
|
||||
add the name.
|
||||
- Means `export import` and `export name` will be in different sections:
|
||||
no single place to look for re-exports.
|
||||
|
||||
3. No ordering for `export name`
|
||||
|
||||
|
||||
@@ -189,10 +189,11 @@ From this, we derive that we want:
|
||||
- We should try to avoid special syntax.
|
||||
- Everything else should be written as idiomatic types with descriptive names.
|
||||
|
||||
[^1]:
|
||||
"[chandlerc] Prioritize: slices first, then [resizable storage], then compile-time
|
||||
sized storage, then everything else is vastly less common. Between those three,
|
||||
the difference in frequency between the first two is the biggest." from [open discussion on 2024-12-05](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0)
|
||||
[^1]: "[chandlerc] Prioritize: slices first, then [resizable storage], then
|
||||
compile-time sized storage, then everything else is vastly less common.
|
||||
Between those three, the difference in frequency between the first two is
|
||||
the biggest." from
|
||||
[open discussion on 2024-12-05](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0)
|
||||
|
||||
[^2]:
|
||||
Slices are included with fundamental types for simplicity, since they will
|
||||
|
||||
@@ -116,7 +116,8 @@ Such a name lookup only finds names that were declared prior to the lookup, in
|
||||
line with the
|
||||
[information accumulation principle](/docs/project/principles/information_accumulation.md).
|
||||
If the name is first declared after the point at which it is looked up, the
|
||||
later declaration of the name is rejected by to the poisoning rule [described earlier](#background].
|
||||
later declaration of the name is rejected by to the poisoning rule [described
|
||||
earlier](#background].
|
||||
|
||||
```carbon
|
||||
base class A {
|
||||
|
||||
@@ -859,28 +859,28 @@ we found a number of problems with that approach:
|
||||
|
||||
- There are multiple possible semantics you might want, and having a single
|
||||
`impl` does not provide the affordances for choosing between those options,
|
||||
where one `impl` per interface would. For example, in
|
||||
`impl forall [T:! type] C(T) as I & J where .(I.x) = i32 and .(J.y) = .(I.x)`,
|
||||
if there is a specialization of `C(T)` for `I`, will `J.y` have the value
|
||||
`i32` or the `I.x` from the specialization? In practice, the semantics of
|
||||
rewrites mean that `.(I.x)` is replaced with `i32` at an early stage in the
|
||||
compiler (to support things like `.(J.y) = .(I.x).D`), and so only the first
|
||||
option is consistent. This is a particular concern for the "Independent
|
||||
impls" option above. If this `impl` is split into two, then the different
|
||||
possible meanings have different spellings:
|
||||
where one `impl` per interface would. For example, in `impl forall [T:!
|
||||
type] C(T) as I & J where .(I.x) = i32 and .(J.y) = .(I.x)`, if there is a
|
||||
specialization of `C(T)` for `I`, will `J.y` have the value `i32` or the
|
||||
`I.x` from the specialization? In practice, the semantics of rewrites mean
|
||||
that `.(I.x)` is replaced with `i32` at an early stage in the compiler (to
|
||||
support things like `.(J.y) = .(I.x).D`), and so only the first option is
|
||||
consistent. This is a particular concern for the "Independent impls" option
|
||||
above. If this `impl` is split into two, then the different possible
|
||||
meanings have different spellings:
|
||||
|
||||
- `impl forall [T:! type] C(T) as J where .(J.y) = i32` means `J.y` will
|
||||
be `i32` independent of any specialization of `C(T)` for `I`
|
||||
|
||||
- `impl forall [T:! type where C(T) impls I] C(T) as J where .(J.y) = .(I.x)`
|
||||
means `J.y` matches `I.x` even if `C(T)` is specialized
|
||||
- `impl forall [T:! type where C(T) impls I] C(T) as J where .(J.y) =
|
||||
.(I.x)` means `J.y` matches `I.x` even if `C(T)` is specialized
|
||||
|
||||
- `impl forall [T:! type where C(T) impls (I where .x = i32)] C(T) as J where .(J.y) = .(I.x)`
|
||||
means this impl won't be used unless `I.x` is `i32`. Note this last form
|
||||
approximates the "Constrained impls" approach above, but with an
|
||||
explicit ordering to determine the semantics, and the existing language
|
||||
rules preventing the code from declaring cycles that would make it
|
||||
ambiguous.
|
||||
- `impl forall [T:! type where C(T) impls (I where .x = i32)] C(T) as J
|
||||
where .(J.y) = .(I.x)` means this impl won't be used unless `I.x` is
|
||||
`i32`. Note this last form approximates the "Constrained impls" approach
|
||||
above, but with an explicit ordering to determine the semantics, and the
|
||||
existing language rules preventing the code from declaring cycles that
|
||||
would make it ambiguous.
|
||||
|
||||
- If an interface `J` extends `I` but they are defined in distinct libraries,
|
||||
there is no guarantee that an implementation of `J` belongs in the same
|
||||
|
||||
@@ -114,23 +114,17 @@ However the [problems](#problem) discussed above result from this situation. We
|
||||
can gain the benefit of access to the codebase while reducing its impact on
|
||||
developers and users by moving it into a separate git repository.
|
||||
|
||||
[^5]:
|
||||
https://discord.com/channels/655572317891461132/998959756045713438/1225116234199203860
|
||||
[^5]: https://discord.com/channels/655572317891461132/998959756045713438/1225116234199203860
|
||||
|
||||
[^6]:
|
||||
https://discord.com/channels/655572317891461132/998959756045713438/1237143981150830673
|
||||
[^6]: https://discord.com/channels/655572317891461132/998959756045713438/1237143981150830673
|
||||
|
||||
[^7]:
|
||||
https://discord.com/channels/655572317891461132/709488742942900284/1250577021474443376
|
||||
[^7]: https://discord.com/channels/655572317891461132/709488742942900284/1250577021474443376
|
||||
|
||||
[^8]:
|
||||
https://discord.com/channels/655572317891461132/748959784815951963/1255669935439482993
|
||||
[^8]: https://discord.com/channels/655572317891461132/748959784815951963/1255669935439482993
|
||||
|
||||
[^9]:
|
||||
https://discord.com/channels/655572317891461132/655578254970716160/1302033729761443963
|
||||
[^9]: https://discord.com/channels/655572317891461132/655578254970716160/1302033729761443963
|
||||
|
||||
[^10]:
|
||||
https://discord.com/channels/655572317891461132/941071822756143115/1349523309682753606
|
||||
[^10]: https://discord.com/channels/655572317891461132/941071822756143115/1349523309682753606
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
|
||||
@@ -115,7 +115,8 @@ include: `__cplusplus`, `__FILE__`, `__LINE__`, `__DATE__`, `__TIME__` etc.
|
||||
|
||||
See the Swift
|
||||
[implementation](https://github.com/swiftlang/swift/blob/main/lib/ClangImporter/ImportMacro.cpp)
|
||||
and [documentation](https://developer.apple.com/documentation/swift/using-imported-c-macros-in-swift).
|
||||
and
|
||||
[documentation](https://developer.apple.com/documentation/swift/using-imported-c-macros-in-swift).
|
||||
|
||||
Swift supports importing object-like C macros as global constants. Macros that
|
||||
use integer, floating-point and string literals are supported. Also simple
|
||||
@@ -231,10 +232,10 @@ imported. For example, the following macro won’t have a Carbon equivalent:
|
||||
|
||||
### Implementation
|
||||
|
||||
1. _Name lookup_: When a C++ macro name is encountered in Carbon it is looked-up
|
||||
before any other name. Following the C++ rules, this allows the macro to be
|
||||
found in case there is a non-macro with the same name (for example named
|
||||
variable).
|
||||
1. _Name lookup_: When a C++ macro name is encountered in Carbon it is
|
||||
looked-up before any other name. Following the C++ rules, this allows the
|
||||
macro to be found in case there is a non-macro with the same name (for
|
||||
example named variable).
|
||||
|
||||
2. _Macro import_: If a macro is found, it is imported as a constant to Carbon,
|
||||
by parsing the tokens of the replacement list to a constant expression and
|
||||
|
||||
@@ -327,13 +327,13 @@ The comment notes that three options were proposed:
|
||||
2. `char` models a UTF-8 code unit, although it may not necessarily be valid,
|
||||
and may appear in a sequence that is not a valid UTF-8 encoding.
|
||||
|
||||
As with the first option, `char` can represent an integer in [0, 255], although
|
||||
it is not an integer type. Higher-level abstractions would likely (eventually)
|
||||
be provided to represent different views of the code unit sequence as (for example)
|
||||
a sequence of code points or a sequence of graphemes, but the fundamental model
|
||||
exposes the encoding. Functions taking `char` or `char` sequences would assume
|
||||
UTF-8 encoding, and would need to consider how to handle invalid `char`s and
|
||||
invalid `char` sequences.
|
||||
As with the first option, `char` can represent an integer in [0, 255],
|
||||
although it is not an integer type. Higher-level abstractions would likely
|
||||
(eventually) be provided to represent different views of the code unit
|
||||
sequence as (for example) a sequence of code points or a sequence of
|
||||
graphemes, but the fundamental model exposes the encoding. Functions taking
|
||||
`char` or `char` sequences would assume UTF-8 encoding, and would need to
|
||||
consider how to handle invalid `char`s and invalid `char` sequences.
|
||||
|
||||
3. Use a foundation that enforces Unicode string validity, for some definition
|
||||
of "Unicode string validity".
|
||||
|
||||
@@ -191,8 +191,8 @@ will have to be inside `F` since it uses the name `C` which is introduced inside
|
||||
the scope of `F`. Thus if `F` is generic, all users of the `impl` will share a
|
||||
consistent view of any generic bindings used by the `impl` declaration.
|
||||
|
||||
3. A name is introduced in a scope nested within the scope containing the `impl`
|
||||
declaration.
|
||||
3. A name is introduced in a scope nested within the scope containing the
|
||||
`impl` declaration.
|
||||
|
||||
```carbon
|
||||
fn F() {
|
||||
|
||||
@@ -71,8 +71,9 @@ literals was defined as producing `i32`, with the rationale:
|
||||
> two `Core.CharLiteral` values.
|
||||
|
||||
`CharLiteral` values are in the range [0, 0x10FFFF], so the smallest fixed-width
|
||||
power-of-two-sized type their differences fit within is indeed `i32`. However, we
|
||||
did not consider using a literal type, nor the layering impact of this choice.
|
||||
power-of-two-sized type their differences fit within is indeed `i32`. However,
|
||||
we did not consider using a literal type, nor the layering impact of this
|
||||
choice.
|
||||
|
||||
## Proposal
|
||||
|
||||
|
||||
@@ -512,15 +512,19 @@ file_test infrastructure; see
|
||||
There are several supported ways to run Carbon on a given test file. For
|
||||
example, with `toolchain/parse/testdata/basics/empty.carbon`:
|
||||
|
||||
- `bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/basics/empty.carbon`
|
||||
- `bazel test //toolchain/testing:file_test
|
||||
--test_arg=--file_tests=toolchain/parse/testdata/basics/empty.carbon`
|
||||
- Executes an individual test.
|
||||
- `bazel run //toolchain -- compile --phase=parse --dump-parse-tree toolchain/parse/testdata/basics/empty.carbon`
|
||||
- `bazel run //toolchain -- compile --phase=parse --dump-parse-tree
|
||||
toolchain/parse/testdata/basics/empty.carbon`
|
||||
- Explicitly runs `carbon` with the provided arguments.
|
||||
- `bazel-bin/toolchain/carbon compile --phase=parse --dump-parse-tree toolchain/parse/testdata/basics/empty.carbon`
|
||||
- `bazel-bin/toolchain/carbon compile --phase=parse --dump-parse-tree
|
||||
toolchain/parse/testdata/basics/empty.carbon`
|
||||
- Similar to the previous command, but without using `bazel run`. This can
|
||||
be useful with a debugger or other tool that needs to directly run the
|
||||
binary.
|
||||
- `bazel run //toolchain -- -v compile --phase=check toolchain/check/testdata/basics/run.carbon`
|
||||
- `bazel run //toolchain -- -v compile --phase=check
|
||||
toolchain/check/testdata/basics/run.carbon`
|
||||
- Runs using `-v` for verbose log output, and running through the `check`
|
||||
phase.
|
||||
|
||||
|
||||
@@ -128,14 +128,15 @@ instead we call it directly. Otherwise, we generate a thunk as follows.
|
||||
On the C++ side, we have two `clang::FunctionDecl`s:
|
||||
|
||||
- The original callee.
|
||||
- The thunk with a simplified ABI, which is defined to call the original callee.
|
||||
- The thunk with a simplified ABI, which is defined to call the original
|
||||
callee.
|
||||
|
||||
On the Carbon side, we have two `SemIR::Function`s:
|
||||
|
||||
- The function representing the original C++ function signature. This is marked
|
||||
as `SpecialFunctionKind::HasCppThunk`. Attempts to call this function generate
|
||||
a call through the thunk instead. This is returned when Carbon invokes C++
|
||||
overload resolution.
|
||||
- The function representing the original C++ function signature. This is
|
||||
marked as `SpecialFunctionKind::HasCppThunk`. Attempts to call this function
|
||||
generate a call through the thunk instead. This is returned when Carbon
|
||||
invokes C++ overload resolution.
|
||||
- The function representing the C++ thunk. This is the target of SemIR `call`
|
||||
instructions, and is marked as `SpecialFunctionKind::CppThunk`. This has the
|
||||
same symbol name as the C++ thunk.
|
||||
@@ -164,16 +165,16 @@ When C++ code calls into Carbon, we always generate a thunk on each side.
|
||||
On the Carbon side, we have two `SemIR::Function`s:
|
||||
|
||||
- The original callee.
|
||||
- The thunk with a simplified ABI, which is defined to call the original callee.
|
||||
This is marked as `SpecialFunctionKind::CppThunk`.
|
||||
- The thunk with a simplified ABI, which is defined to call the original
|
||||
callee. This is marked as `SpecialFunctionKind::CppThunk`.
|
||||
|
||||
On the C++ side, we have two `clang::FunctionDecl`s:
|
||||
|
||||
- A C++ function representing the original Carbon function signature. This
|
||||
function is defined in the C++ AST with a body that calls the thunk; from
|
||||
Clang's perspective this is a normal C++ function.
|
||||
- A C++ function representing the Carbon thunk. This has the same symbol name as
|
||||
the Carbon thunk.
|
||||
- A C++ function representing the Carbon thunk. This has the same symbol name
|
||||
as the Carbon thunk.
|
||||
|
||||
`Context::clang_decls` can be used to map between the corresponding C++ and
|
||||
Carbon functions above. `Function::cpp_thunk_callee` can be used to map from the
|
||||
@@ -211,8 +212,8 @@ class Derived {
|
||||
|
||||
This is implemented by combining three other kinds of thunk, as follows:
|
||||
|
||||
- A declaration of the C++ function in the base class is imported into Carbon as
|
||||
a member of the derived class. This function is marked as being a
|
||||
- A declaration of the C++ function in the base class is imported into Carbon
|
||||
as a member of the derived class. This function is marked as being a
|
||||
[signature adaptation thunk](#signature-adaptation-thunks) for the Carbon
|
||||
overrider.
|
||||
- The signature adaptation thunk is [exported to C++](#c-calling-carbon). This
|
||||
@@ -220,9 +221,9 @@ This is implemented by combining three other kinds of thunk, as follows:
|
||||
adaptation thunk, and a C++-side definition.
|
||||
- The Carbon-side thunk's call to the signature adaptation thunk is inlined in
|
||||
SemIR.
|
||||
- The C++-side function definition uses the exact signature of the original C++
|
||||
function. We know to do this because it is a thunk generated for a signature
|
||||
adaptation thunk whose signature is itself imported from C++.
|
||||
- The C++-side function definition uses the exact signature of the original
|
||||
C++ function. We know to do this because it is a thunk generated for a
|
||||
signature adaptation thunk whose signature is itself imported from C++.
|
||||
|
||||
In `clang_decls`, the signature adaptation thunk corresponds to the C++ virtual
|
||||
override function.
|
||||
@@ -240,8 +241,8 @@ We are concerned with two vtables:
|
||||
used for constant evaluation on the Carbon side.
|
||||
- The C++-side vtable representation. In this case, because the vptr was
|
||||
originally introduced by a C++ class, this will be used for code generation.
|
||||
This is generated by Clang based on our exporting a suitable set of overriding
|
||||
functions when we export the Carbon class to C++.
|
||||
This is generated by Clang based on our exporting a suitable set of
|
||||
overriding functions when we export the Carbon class to C++.
|
||||
|
||||
The Carbon-side vtable contains the signature adaptation thunk. The C++-side
|
||||
vtable contains the corresponding C++ virtual override function.
|
||||
@@ -293,6 +294,7 @@ We can't synthesize the definition of the C++-side virtual overrider until the
|
||||
enclosing class is complete in the C++ AST. Therefore we split the
|
||||
responsibility for generating the thunks in two:
|
||||
|
||||
- When we complete the Carbon class, we generate the signature adaptation thunk.
|
||||
- When we form a corresponding complete C++ class type, we generate the C++-side
|
||||
virtual overrider thunk.
|
||||
- When we complete the Carbon class, we generate the signature adaptation
|
||||
thunk.
|
||||
- When we form a corresponding complete C++ class type, we generate the
|
||||
C++-side virtual overrider thunk.
|
||||
|
||||
@@ -264,12 +264,12 @@ if %equal then br !if.then else br !if.else
|
||||
## Parser-driven pattern block pushing
|
||||
|
||||
In order to produce correct pattern blocks, we need to ensure that a new pattern
|
||||
block is pushed onto the stack at the start of every full-pattern, and popped
|
||||
at the end. We attempt to do this precisely rather than speculatively, by leveraging
|
||||
the parser to precisely mark the nodes immediately before full-patterns, and
|
||||
pushing the pattern block stack when we handle those nodes. We then rely on
|
||||
signals from both the parser and the node stack to determine when to pop from
|
||||
the pattern block stack.
|
||||
block is pushed onto the stack at the start of every full-pattern, and popped at
|
||||
the end. We attempt to do this precisely rather than speculatively, by
|
||||
leveraging the parser to precisely mark the nodes immediately before
|
||||
full-patterns, and pushing the pattern block stack when we handle those nodes.
|
||||
We then rely on signals from both the parser and the node stack to determine
|
||||
when to pop from the pattern block stack.
|
||||
|
||||
In the case of `let` and `var` decls, this is fairly straightforward: the
|
||||
beginning is marked by the `LetIntroducer` or `VarIntroducer` node, and the end
|
||||
|
||||
@@ -97,9 +97,9 @@ complexity in the number of specifics for that generic.
|
||||
We define two fingerprints for each specific:
|
||||
|
||||
1. `specific_fingerprint`: Includes all specific-dependent information.
|
||||
2. `common_fingerprint`: Includes the same except for `specific_id` information,
|
||||
as `specific_id`s can only be determined to be equivalent after building an
|
||||
equivalence SCC.
|
||||
2. `common_fingerprint`: Includes the same except for `specific_id`
|
||||
information, as `specific_id`s can only be determined to be equivalent after
|
||||
building an equivalence SCC.
|
||||
|
||||
Two specific functions are equivalent if their `specific_fingerprint`s are equal
|
||||
and are not equivalent if their `common_fingerprint`s differs. If the
|
||||
|
||||
@@ -176,7 +176,8 @@ support for debugging the toolchain tests. To set that up:
|
||||
|
||||
A typical debug session looks like:
|
||||
|
||||
1. `bazel build -c dbg --features=-lldb_flags --features=gdb_flags //toolchain/testing:file_test`
|
||||
1. `bazel build -c dbg --features=-lldb_flags --features=gdb_flags
|
||||
//toolchain/testing:file_test`
|
||||
2. Open a `.carbon` testdata file to debug. This must be the active file in VS
|
||||
Code.
|
||||
3. Go to the "Run and debug" panel in VS Code.
|
||||
|
||||
@@ -279,16 +279,15 @@ Carbon's diagnostic style aims to balance these concerns. Our style is:
|
||||
- `"redeclaration of X"` describes the situation and implies that
|
||||
redeclarations are not permitted.
|
||||
|
||||
- ``"`self` declared in invalid context; can only be declared in implicit parameter list"``
|
||||
describes the language rule.
|
||||
- ``"`self` declared in invalid context; can only be declared in implicit
|
||||
parameter list"`` describes the language rule.
|
||||
|
||||
- It's OK for a diagnostic to guess at the developer's intent and provide
|
||||
a hint after explaining the situation and the rule, but not as a
|
||||
substitute for that. For example,
|
||||
``"add `as String` to convert `i32` to `String`"`` is not sufficient as
|
||||
an error message, but
|
||||
``"cannot implicitly convert `i32` to `String`; add `as String` for explicit conversion"``
|
||||
could be acceptable.
|
||||
substitute for that. For example, ``"add `as String` to convert `i32` to
|
||||
`String`"`` is not sufficient as an error message, but ``"cannot
|
||||
implicitly convert `i32` to `String`; add `as String` for explicit
|
||||
conversion"`` could be acceptable.
|
||||
|
||||
- Use "cannot" if needed, but try to use phrasing that doesn't require it.
|
||||
Avoid "allowed", "legal", "permitted", "valid", and related wording. For
|
||||
|
||||
@@ -15,9 +15,10 @@ This extension is currently experimental, and being developed alongside Carbon.
|
||||
|
||||
1. Download and install a `carbon`
|
||||
[release](https://github.com/carbon-language/carbon-lang/releases).
|
||||
- By default, the extension will look for `carbon` under `./bazel-bin`. This
|
||||
is for developers actively working on Carbon and running VS Code inside a
|
||||
[carbon-lang](https://github.com/carbon-language/carbon-lang) clone.
|
||||
- By default, the extension will look for `carbon` under `./bazel-bin`.
|
||||
This is for developers actively working on Carbon and running VS Code
|
||||
inside a [carbon-lang](https://github.com/carbon-language/carbon-lang)
|
||||
clone.
|
||||
2. Install the
|
||||
[Carbon Language extension](https://marketplace.visualstudio.com/items?itemName=carbon-lang.carbon-vscode).
|
||||
3. Configure the installed path to `carbon`.
|
||||
|
||||
@@ -52,8 +52,8 @@ This installs `vsce` and `ovsx` to `/usr/local/bin`. Ensure that
|
||||
2. Go to
|
||||
https://marketplace.visualstudio.com/manage/publishers/carbon-lang
|
||||
- We use `infra-role@carbon-lang.dev` for publishing; the GitHub
|
||||
account `CarbonInfraBot` can also be used for login. Contact leads
|
||||
if you require access.
|
||||
account `CarbonInfraBot` can also be used for login. Contact
|
||||
leads if you require access.
|
||||
3. Next to the extension name, click the "..." and select "Update".
|
||||
4. Select the `carbon.vsix` file.
|
||||
3. Build and publish to the Open VSX Registry by following the
|
||||
|
||||
Reference in New Issue
Block a user