mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 09:10:13 +01:00
Switch from Prettier to Rumdl for Markdown formatting (#7423)
Rumdl already appears to have _significantly_ fewer bugs than prettier, and a solid LSP for editor integration. The tool is: https://github.com/rvben/rumdl/ I've separated out the change across three commits for easier review. The configuration tries to match the existing formatting, the changes to the all the files are to correct issues found by the new tool. Assisted-by: Antigravity with Gemini --------- Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
co-authored by
Richard Smith
parent
6181259cf1
commit
cfd1ed8484
+113
-104
@@ -36,18 +36,18 @@ graph TD
|
||||
|
||||
Adding a builtin function involves a 5-step integration:
|
||||
|
||||
1. **Define the Builtin Kind**: Register the enum in
|
||||
[builtin_function_kind.def](../../../toolchain/sem_ir/builtin_function_kind.def).
|
||||
2. **Signature & Compile-Time Registry**: Declare the mapping name, parameter
|
||||
constraints, and compile-time evaluation residency in
|
||||
[builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp).
|
||||
3. **Compile-Time Interpreter Support**: Wire constant evaluation hooks and
|
||||
bounds/exception diagnostics in
|
||||
[eval.cpp](../../../toolchain/check/eval.cpp).
|
||||
4. **LLVM IR Lowering Support**: Connect target machine generation in
|
||||
[handle_call.cpp](../../../toolchain/lower/handle_call.cpp).
|
||||
5. **Prelude Library Mapping**: Bind primitive interfaces to named builtins
|
||||
under [core/prelude/](../../../core/prelude/).
|
||||
1. **Define the Builtin Kind**: Register the enum in
|
||||
[builtin_function_kind.def](../../../toolchain/sem_ir/builtin_function_kind.def).
|
||||
2. **Signature & Compile-Time Registry**: Declare the mapping name, parameter
|
||||
constraints, and compile-time evaluation residency in
|
||||
[builtin_function_kind.cpp](../../../toolchain/sem_ir/builtin_function_kind.cpp).
|
||||
3. **Compile-Time Interpreter Support**: Wire constant evaluation hooks and
|
||||
bounds/exception diagnostics in
|
||||
[eval.cpp](../../../toolchain/check/eval.cpp).
|
||||
4. **LLVM IR Lowering Support**: Connect target machine generation in
|
||||
[handle_call.cpp](../../../toolchain/lower/handle_call.cpp).
|
||||
5. **Prelude Library Mapping**: Bind primitive interfaces to named builtins
|
||||
under [core/prelude/](../../../core/prelude/).
|
||||
|
||||
---
|
||||
|
||||
@@ -70,37 +70,37 @@ 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).
|
||||
- `AnyInt`, `AnyFloat`, `AnySizedInt`, `AnySizedFloat`, `CharCompatible`,
|
||||
`StdInitializerList`, `NoReturn`.
|
||||
- `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
|
||||
```cpp
|
||||
// toolchain/sem_ir/builtin_function_kind.cpp
|
||||
|
||||
constexpr BuiltinInfo IntConvertFloat = {
|
||||
"int.convert_float", ValidateSignature<auto(AnyInt)->AnyFloat>};
|
||||
```
|
||||
constexpr BuiltinInfo IntConvertFloat = {
|
||||
"int.convert_float", ValidateSignature<auto(AnyInt)->AnyFloat>};
|
||||
```
|
||||
|
||||
3. **Establish Compile-Time Residency Status**: Update
|
||||
`BuiltinFunctionKind::IsCompTimeOnly` to determine if a call requires
|
||||
compile-time evaluation:
|
||||
- **Checked/Diagnostics Primitives**: Return `true` immediately. Runtime
|
||||
lowering of these is illegal (e.g. `IntConvertFloatChecked`).
|
||||
- **Runtime Primitives**: Return
|
||||
`AnyLiteralTypes(sem_ir, arg_ids, return_type_id)` to enforce that
|
||||
expressions involving unsized literal values (like `IntLiteral` or
|
||||
`FloatLiteral`) are evaluated exclusively at compile-time (as they lack
|
||||
runtime representation).
|
||||
3. **Establish Compile-Time Residency Status**: Update
|
||||
`BuiltinFunctionKind::IsCompTimeOnly` to determine if a call requires
|
||||
compile-time evaluation:
|
||||
- **Checked/Diagnostics Primitives**: Return `true` immediately. Runtime
|
||||
lowering of these is illegal (e.g. `IntConvertFloatChecked`).
|
||||
- **Runtime Primitives**: Return
|
||||
`AnyLiteralTypes(sem_ir, arg_ids, return_type_id)` to enforce that
|
||||
expressions involving unsized literal values (like `IntLiteral` or
|
||||
`FloatLiteral`) are evaluated exclusively at compile-time (as they lack
|
||||
runtime representation).
|
||||
|
||||
---
|
||||
|
||||
@@ -109,51 +109,57 @@ Inside
|
||||
Wire the interpreter inside [eval.cpp](../../../toolchain/check/eval.cpp) to
|
||||
execute compile-time computations:
|
||||
|
||||
1. **Implement Constant Evaluation Logic**:
|
||||
1. **Implement Constant Evaluation Logic**:
|
||||
|
||||
- Handle the builtin case inside `MakeConstantForBuiltinCall` (which
|
||||
processes the compile-time execution of the call).
|
||||
- Confirm type validation phase is `Phase::Concrete` to reject incomplete
|
||||
bindings:
|
||||
```cpp
|
||||
case SemIR::BuiltinFunctionKind::IntConvertFloat: {
|
||||
if (phase != Phase::Concrete) {
|
||||
return MakeConstantResult(context, call, phase);
|
||||
}
|
||||
return PerformIntToFloatConvert(context, loc_id, arg_ids[0], call.type_id,
|
||||
/*require_exact=*/false);
|
||||
}
|
||||
```
|
||||
- Extract inputs safely from local value stores (e.g.
|
||||
`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.
|
||||
- Handle the builtin case inside `MakeConstantForBuiltinCall` (which
|
||||
processes the compile-time execution of the call).
|
||||
- Confirm type validation phase is `Phase::Concrete` to reject incomplete
|
||||
bindings:
|
||||
|
||||
2. **Diagnose Invalid Parameters or Exceptions**:
|
||||
```cpp
|
||||
case SemIR::BuiltinFunctionKind::IntConvertFloat: {
|
||||
if (phase != Phase::Concrete) {
|
||||
return MakeConstantResult(context, call, phase);
|
||||
}
|
||||
return PerformIntToFloatConvert(context, loc_id, arg_ids[0], call.type_id,
|
||||
/*require_exact=*/false);
|
||||
}
|
||||
```
|
||||
|
||||
- Define compile-time diagnostics inside
|
||||
[kind.def](../../../toolchain/diagnostics/kind.def):
|
||||
```cpp
|
||||
// toolchain/diagnostics/kind.def
|
||||
CARBON_DIAGNOSTIC_KIND(IntTooLargeForFloatType)
|
||||
```
|
||||
- Emplace localized diagnostic formatting messages where they are caught in
|
||||
`eval.cpp`:
|
||||
```cpp
|
||||
CARBON_DIAGNOSTIC(IntTooLargeForFloatType, Error,
|
||||
"integer value {0} too large for floating-point type {1}",
|
||||
llvm::APSInt, SemIR::TypeId);
|
||||
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.
|
||||
- Extract inputs safely from local value stores (e.g.
|
||||
`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.
|
||||
|
||||
3. **Fast-Path Range Limits**:
|
||||
- Before evaluating expensive math operations on giant exponents (e.g.
|
||||
`1.0e1000000`), executing range limits check against `dest_width + 64`
|
||||
(sized) or `IntStore::MaxIntWidth` (unsized) is mandatory to prevent
|
||||
out-of-bounds calculations and compile-time memory exhaustion.
|
||||
2. **Diagnose Invalid Parameters or Exceptions**:
|
||||
|
||||
- Define compile-time diagnostics inside
|
||||
[kind.def](../../../toolchain/diagnostics/kind.def):
|
||||
|
||||
```cpp
|
||||
// toolchain/diagnostics/kind.def
|
||||
CARBON_DIAGNOSTIC_KIND(IntTooLargeForFloatType)
|
||||
```
|
||||
|
||||
- Emplace localized diagnostic formatting messages where they are caught in
|
||||
`eval.cpp`:
|
||||
|
||||
```cpp
|
||||
CARBON_DIAGNOSTIC(IntTooLargeForFloatType, Error,
|
||||
"integer value {0} too large for floating-point type {1}",
|
||||
llvm::APSInt, SemIR::TypeId);
|
||||
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.
|
||||
|
||||
3. **Fast-Path Range Limits**:
|
||||
- Before evaluating expensive math operations on giant exponents (e.g.
|
||||
`1.0e1000000`), executing range limits check against `dest_width + 64`
|
||||
(sized) or `IntStore::MaxIntWidth` (unsized) is mandatory to prevent
|
||||
out-of-bounds calculations and compile-time memory exhaustion.
|
||||
|
||||
---
|
||||
|
||||
@@ -161,33 +167,34 @@ execute compile-time computations:
|
||||
|
||||
Inside [handle_call.cpp](../../../toolchain/lower/handle_call.cpp):
|
||||
|
||||
1. **Map to Native LLVM Instructions**: For runtime-eligible builtins, map the
|
||||
call inside `HandleBuiltinCall` to native LLVM IR builder methods:
|
||||
1. **Map to Native LLVM Instructions**: For runtime-eligible builtins, map the
|
||||
call inside `HandleBuiltinCall` to native LLVM IR builder methods:
|
||||
|
||||
```cpp
|
||||
case SemIR::BuiltinFunctionKind::IntConvertFloat: {
|
||||
auto* operand = context.GetValue(arg_ids[0]);
|
||||
auto* dest_type = context.GetTypeOfInst(inst_id);
|
||||
bool is_signed = IsSignedInt(context, arg_ids[0]);
|
||||
context.SetLocal(
|
||||
inst_id, is_signed
|
||||
? context.builder().CreateSIToFP(operand, dest_type)
|
||||
: context.builder().CreateUIToFP(operand, dest_type));
|
||||
return;
|
||||
}
|
||||
```
|
||||
```cpp
|
||||
case SemIR::BuiltinFunctionKind::IntConvertFloat: {
|
||||
auto* operand = context.GetValue(arg_ids[0]);
|
||||
auto* dest_type = context.GetTypeOfInst(inst_id);
|
||||
bool is_signed = IsSignedInt(context, arg_ids[0]);
|
||||
context.SetLocal(
|
||||
inst_id, is_signed
|
||||
? context.builder().CreateSIToFP(operand, dest_type)
|
||||
: context.builder().CreateUIToFP(operand, dest_type));
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
2. **Assert on Compile-Time-Only Builtins**: Throw a hard assertion on
|
||||
lowering-cases for checked validator builtins that should never hit code
|
||||
generation:
|
||||
```cpp
|
||||
case SemIR::BuiltinFunctionKind::IntConvertFloatChecked: {
|
||||
CARBON_CHECK(builtin_kind.IsCompTimeOnly(
|
||||
context.sem_ir(), arg_ids,
|
||||
context.sem_ir().insts().Get(inst_id).type_id()));
|
||||
CARBON_FATAL("Missing constant value for call to comptime-only function");
|
||||
}
|
||||
```
|
||||
2. **Assert on Compile-Time-Only Builtins**: Throw a hard assertion on
|
||||
lowering-cases for checked validator builtins that should never hit code
|
||||
generation:
|
||||
|
||||
```cpp
|
||||
case SemIR::BuiltinFunctionKind::IntConvertFloatChecked: {
|
||||
CARBON_CHECK(builtin_kind.IsCompTimeOnly(
|
||||
context.sem_ir(), arg_ids,
|
||||
context.sem_ir().insts().Get(inst_id).type_id()));
|
||||
CARBON_FATAL("Missing constant value for call to comptime-only function");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -198,9 +205,11 @@ builtins under [core/prelude/](../../../core/prelude/):
|
||||
|
||||
- **Primitive Mappings**: Bind Carbon methods directly to string-literal
|
||||
builtin equivalents:
|
||||
|
||||
```carbon
|
||||
fn Convert[self: Self]() -> Float(To) = "int.convert_float";
|
||||
```
|
||||
|
||||
- **Strict Orphan Rule Compliance**: Carbon's orphan rules prohibit
|
||||
implementing interfaces where neither the type nor the interface is locally
|
||||
defined in the backing source module.
|
||||
|
||||
@@ -74,6 +74,7 @@ declaration (`CARBON_DIAGNOSTIC` or `CARBON_DIAGNOSTIC_ON_SCOPE`).
|
||||
- **Local Scope (Recommended)**: If the diagnostic is unique to a single
|
||||
block/function body, declare it **locally** inside the function body
|
||||
adjacent to its `Emit` trigger:
|
||||
|
||||
```cpp
|
||||
void ConvertFloatValueToInt(...) {
|
||||
CARBON_DIAGNOSTIC(FloatNaNConvertedToInt, Error,
|
||||
@@ -81,6 +82,7 @@ declaration (`CARBON_DIAGNOSTIC` or `CARBON_DIAGNOSTIC_ON_SCOPE`).
|
||||
context.emitter().Emit(loc_id, FloatNaNConvertedToInt, dest_type_id);
|
||||
}
|
||||
```
|
||||
|
||||
- **File Scope**: If the diagnostic is shared among multiple functions inside
|
||||
the _same_ file, declare it at **file scope** inside the anonymous namespace
|
||||
of the `.cpp` file.
|
||||
@@ -177,12 +179,14 @@ scopes:
|
||||
|
||||
- `ContextScope`: Automatically converts any diagnostics emitted within its
|
||||
scope into sub-notes under a high-level operation descriptor:
|
||||
|
||||
```cpp
|
||||
ContextScope context_scope(&context.emitter(), [&](ContextBuilder& builder) {
|
||||
builder.Context(eval_loc, InCallToEvalFn);
|
||||
});
|
||||
// any checker error emitted here will automatically append the 'InCallToEvalFn' note
|
||||
```
|
||||
|
||||
- `AnnotationScope`: RAII block scope that automatically attaches blanket note
|
||||
annotations to all scoped diagnostics.
|
||||
|
||||
@@ -246,10 +250,12 @@ Carbon strictly enforces testing coverage at build-time.
|
||||
2. **Stderr Checklist Matchers**: The testcase split verifying the diagnostic
|
||||
must catch it using standard CHECK matchers, explicitly tracking the
|
||||
matching enum tag in standard error comments:
|
||||
|
||||
```carbon
|
||||
// CHECK:STDERR: fail_bounds.carbon:[[@LINE+1]]:15: error: cannot convert NaN to integer type `i32` [FloatNaNConvertedToInt]
|
||||
let a: i32 = Convert(nan_val);
|
||||
```
|
||||
|
||||
3. **Build Enforcement**: Failing to provide a diagnostic test check matcher
|
||||
triggers a build compilation error on the target test
|
||||
`//toolchain/diagnostics:coverage_test`.
|
||||
|
||||
+19
-1
@@ -28,6 +28,15 @@ repos:
|
||||
exclude: '^(.*/fuzzer_corpus/.*|.*\.svg)$'
|
||||
- id: trailing-whitespace
|
||||
exclude: '^(.*/fuzzer_corpus/.*|.*/testdata/.*\.golden|.*\.svg)$'
|
||||
|
||||
# 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
|
||||
hooks:
|
||||
- id: rumdl
|
||||
args: [--fix]
|
||||
|
||||
- repo: https://github.com/google/pre-commit-tool-hooks
|
||||
rev: efaea7c61c774c0b1a9805fd999e754a2d19dbd1 # frozen: v1.2.5
|
||||
hooks:
|
||||
@@ -38,6 +47,15 @@ repos:
|
||||
.*AGENTS.md
|
||||
)$
|
||||
- id: markdown-toc
|
||||
|
||||
# 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.22
|
||||
hooks:
|
||||
- id: rumdl
|
||||
args: [--fix]
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: fix-cc-deps
|
||||
@@ -79,7 +97,7 @@ repos:
|
||||
# TODO: Not upgrading to/past 3.4.0 due to list indent changes that may
|
||||
# get fixed. See: https://github.com/prettier/prettier/issues/16929
|
||||
additional_dependencies: ['prettier@3.3.3']
|
||||
types_or: [html, javascript, json, markdown, yaml]
|
||||
types_or: [html, javascript, json, yaml]
|
||||
entry: npx prettier@3.3.3 --write --log-level=warn
|
||||
- repo: local
|
||||
hooks:
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
# 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
|
||||
|
||||
[global]
|
||||
exclude = [
|
||||
".git",
|
||||
".jj",
|
||||
"CHANGELOG.md",
|
||||
"LICENSE.md",
|
||||
".github/pull_request_template.md",
|
||||
]
|
||||
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
|
||||
"MD014", # Commands in code blocks should show output
|
||||
"MD034", # Bare URLs
|
||||
"MD059", # Link text should be descriptive
|
||||
"MD028", # Blank line inside blockquote
|
||||
]
|
||||
|
||||
# Heading style
|
||||
[MD003]
|
||||
style = "atx"
|
||||
|
||||
# Narrow restriction on trailing punctuation in headings -- allows ':' and '!'.
|
||||
[MD026]
|
||||
punctuation = ".,;"
|
||||
|
||||
# Unordered list marker style
|
||||
[MD004]
|
||||
style = "dash"
|
||||
|
||||
# Ordered list numbering
|
||||
[MD029]
|
||||
style = "one-or-ordered"
|
||||
|
||||
# Unordered list indentation
|
||||
[MD007]
|
||||
indent = 4
|
||||
|
||||
[MD077]
|
||||
style = "aligned"
|
||||
|
||||
# Spaces after list markers
|
||||
[MD030]
|
||||
ul-single = 3
|
||||
ul-multi = 3
|
||||
ol-align-column = 4
|
||||
|
||||
# Code block style
|
||||
[MD046]
|
||||
style = "fenced"
|
||||
|
||||
# Emphasis style
|
||||
[MD049]
|
||||
style = "underscore"
|
||||
|
||||
# Strong style
|
||||
[MD050]
|
||||
style = "asterisk"
|
||||
Vendored
+1
@@ -4,6 +4,7 @@
|
||||
"bierner.github-markdown-preview",
|
||||
"carbon-lang.carbon-vscode",
|
||||
"esbenp.prettier-vscode",
|
||||
"rvben.rumdl",
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"charliermarsh.ruff",
|
||||
"astral-sh.ty"
|
||||
|
||||
+16
-16
@@ -249,22 +249,22 @@ and our [guidelines and standards](#contribution-guidelines-and-standards)
|
||||
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.
|
||||
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.
|
||||
|
||||
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,7 +405,7 @@ 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 [Prettier](https://prettier.io) for
|
||||
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).
|
||||
|
||||
|
||||
@@ -251,10 +251,10 @@ challenge for C++ and something a successor language needs to address.
|
||||
|
||||
We plan to support a two step migration process:
|
||||
|
||||
1. Highly automated, minimal supervision migration from C++ to a dialect of
|
||||
Carbon designed for C++ interop and migration.
|
||||
2. Incremental refactoring of the Carbon code to adopt memory-safe designs,
|
||||
patterns, and APIs.
|
||||
1. Highly automated, minimal supervision migration from C++ to a dialect of
|
||||
Carbon designed for C++ interop and migration.
|
||||
2. Incremental refactoring of the Carbon code to adopt memory-safe designs,
|
||||
patterns, and APIs.
|
||||
|
||||
We also want to address important, low-hanging fruit in the safety space
|
||||
immediately when migrating into Carbon:
|
||||
|
||||
@@ -942,6 +942,7 @@ Some common expressions in Carbon include:
|
||||
- [Move](#move): `~x`
|
||||
|
||||
- [Conditionals](expressions/if.md): `if c then t else f`
|
||||
|
||||
- Parentheses: `(7 + 8) * (3 - 1)`
|
||||
|
||||
When an expression appears in a context in which an expression of a specific
|
||||
|
||||
@@ -283,9 +283,9 @@ in many cases.
|
||||
|
||||
Every source file will consist of, in order:
|
||||
|
||||
1. Either a `package` directive, a `library` directive, or no introduction.
|
||||
2. A section of zero or more `import` directives.
|
||||
3. Source file body, with other code.
|
||||
1. Either a `package` directive, a `library` directive, or no introduction.
|
||||
2. A section of zero or more `import` directives.
|
||||
3. Source file body, with other code.
|
||||
|
||||
Comments and blank lines may be intermingled with these sections.
|
||||
[Metaprogramming](/docs/design/metaprogramming.md) code may also be
|
||||
|
||||
@@ -2705,10 +2705,13 @@ binary operator:
|
||||
And there are two positions that `where` can be written:
|
||||
|
||||
- At the end of an `impl as` declaration, before the body of the impl.
|
||||
|
||||
```carbon
|
||||
impl Class as Interface where .A = i32 { ... }
|
||||
```
|
||||
|
||||
- Inside a type expression.
|
||||
|
||||
```carbon
|
||||
fn F[T: Interface where .A impls OtherInterface](t: T) { ... }
|
||||
```
|
||||
@@ -4276,15 +4279,9 @@ includes:
|
||||
|
||||
The syntax for an out-of-line parameterized `impl` declaration is:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
<!-- The following triggers a bug in prettier where it adds an `>` -->
|
||||
|
||||
> `impl forall [`_<parameter-bindings>_`]` _<type-expression>_ `as`
|
||||
> `impl forall [` _<parameter-bindings>_ `]` _<type-expression>_ `as`
|
||||
> _<facet-type-expression> [_ `where` _<optional-rewrite-constraints> ]_ `;`
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
This may also be called a _generic `impl` declaration_.
|
||||
|
||||
### Impl for a parameterized type
|
||||
@@ -5040,18 +5037,12 @@ let U:! B = bool;
|
||||
let V:! B = i32;
|
||||
```
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
<!-- The following triggers a bug in prettier where it adds an `>` -->
|
||||
|
||||
> **Note:**
|
||||
> [Issue #2880](https://github.com/carbon-language/carbon-lang/issues/2880) is a
|
||||
> tracking bug for known issues with this "strictly more complex" rule for
|
||||
> [Issue #2880](https://github.com/carbon-language/carbon-lang/issues/2880) is
|
||||
> a tracking bug for known issues with this "strictly more complex" rule for
|
||||
> `impl` termination. We are using that issue to track any code that arises in
|
||||
> practice that would terminate but is rejected by this rule.
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
> **Comparison with other languages:** Rust solves this problem by imposing a
|
||||
> recursion limit, much like C++ compilers use to terminate template recursion.
|
||||
> This goes against
|
||||
|
||||
@@ -144,9 +144,11 @@ This syntax is used for both standard library headers and user-defined headers:
|
||||
This import makes entities like `putchar` available.
|
||||
|
||||
- **C++ User-Defined Header:**
|
||||
|
||||
```carbon
|
||||
import Cpp library "circle.h";
|
||||
```
|
||||
|
||||
This import makes user-defined declarations and definitions available.
|
||||
|
||||
### TODO: Importing C++ code (inline)
|
||||
|
||||
@@ -29,7 +29,6 @@ A _lexical element_ is one of the following:
|
||||
- a [numeric literal](numeric_literals.md)
|
||||
- a [string literal](string_literals.md)
|
||||
- a [character literal](character_literals.md)
|
||||
|
||||
- a [comment](comments.md)
|
||||
- a [symbolic token](symbolic_tokens.md)
|
||||
|
||||
|
||||
@@ -834,14 +834,14 @@ var cd: (C, D) = (MakeA(), MakeB());
|
||||
|
||||
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.
|
||||
4. Call `MakeB`.
|
||||
5. Call `B.(Core.ImplicitAsPrimitive(D)).Convert`.
|
||||
6. Call `B.(Core.Copy).Op`.
|
||||
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.
|
||||
4. Call `MakeB`.
|
||||
5. Call `B.(Core.ImplicitAsPrimitive(D)).Convert`.
|
||||
6. Call `B.(Core.Copy).Op`.
|
||||
|
||||
> **Note:** These `Core` interfaces haven't been specified yet, and their
|
||||
> details may change.
|
||||
|
||||
@@ -220,7 +220,7 @@ 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
|
||||
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/
|
||||
|
||||
@@ -552,17 +552,21 @@ following conditions hold:
|
||||
declarations. For example, we can't apply this rewrite to `⟬X, each Y⟭` in
|
||||
this code, because the resulting signature would have return type `X` but no
|
||||
declaration of `X`:
|
||||
|
||||
```carbon
|
||||
fn F[... ⟬X, each Y⟭:! «type; ‖each next‖+1»]
|
||||
(... each __args: each ⟬X, each Y⟭) -> X;
|
||||
```
|
||||
|
||||
- The pack expansions being rewritten do not contain any pack literals other
|
||||
than the name pack being replaced. For example, we can't apply this rewrite
|
||||
to `⟬X, each Y⟭` in this code, because the pack expansion in the deduced
|
||||
parameter list also contains the pack literal `⟬I, each type⟭`:
|
||||
|
||||
```carbon
|
||||
fn F[... ⟬X, each Y⟭:! ⟬I, each type⟭](... each __args: each ⟬X, each Y⟭);
|
||||
```
|
||||
|
||||
Notice that as a corollary of this rule, all the names in the name pack must
|
||||
have the same type.
|
||||
|
||||
|
||||
@@ -502,12 +502,12 @@ be productive and has a high risk of becoming acrimonious or worse.
|
||||
There are two techniques to use to resolve these situations that should be tried
|
||||
early on:
|
||||
|
||||
1. Bring another person into the review to help address the specific issue.
|
||||
Typically they should at least be an owner, and may usefully be a
|
||||
[Carbon lead](groups.md#carbon-leads).
|
||||
1. Bring another person into the review to help address the specific issue.
|
||||
Typically they should at least be an owner, and may usefully be a
|
||||
[Carbon lead](groups.md#carbon-leads).
|
||||
|
||||
2. Ask the specific question in a broader forum, such as Discord, in order to
|
||||
get a broad set of perspectives on a particular area or issue.
|
||||
2. Ask the specific question in a broader forum, such as Discord, in order to
|
||||
get a broad set of perspectives on a particular area or issue.
|
||||
|
||||
The goal of these steps isn't to override the author or the reviewer, but to get
|
||||
more perspectives and voices involved. Often this will clarify the issue and its
|
||||
|
||||
@@ -194,15 +194,15 @@ replacement for [pre-commit](https://pre-commit.com/).
|
||||
|
||||
To use it:
|
||||
|
||||
1. Install it by way of `cargo install --locked prek`.
|
||||
2. Run `prek install` to set up the git hooks.
|
||||
1. Install it by way of `cargo install --locked prek`.
|
||||
2. Run `prek install` to set up the git hooks.
|
||||
|
||||
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.
|
||||
2. `git add .` to add the automatic modifications done by hooks.
|
||||
3. `git commit` again.
|
||||
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.
|
||||
|
||||
You can also use `prek run` to check pending changes without `git commit`, or
|
||||
`prek run -a` to run on all files in the repository.
|
||||
@@ -224,12 +224,24 @@ 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:
|
||||
- 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
|
||||
[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.
|
||||
- [Visual Studio Code](https://code.visualstudio.com/): A code editor.
|
||||
- We provide [recommended extensions](/.vscode/extensions.json) to assist
|
||||
Carbon development. Some settings changes must be made separately:
|
||||
- Python › Formatting: Provider: `ruff`
|
||||
- Markdown › Formatting: Default Formatter: `rumdl`
|
||||
- **WARNING:** Visual Studio Code modifies the `PATH` environment
|
||||
variable, particularly in the terminals it creates. The `PATH`
|
||||
difference can cause `bazel` to detect different startup options,
|
||||
|
||||
@@ -16,7 +16,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Language features](#language-features)
|
||||
- [Code organization and structuring](#code-organization-and-structuring)
|
||||
- [Type system](#type-system)
|
||||
- [Functions, statements, expressions, ...](#functions-statements-expressions-)
|
||||
- [Functions, statements, expressions, etc](#functions-statements-expressions-etc)
|
||||
- [Standard library components](#standard-library-components)
|
||||
- [Project features](#project-features)
|
||||
- [Milestone 0.2: feature complete product for evaluation](#milestone-02-feature-complete-product-for-evaluation)
|
||||
@@ -149,7 +149,7 @@ into Carbon.
|
||||
- Mapping C++20 concepts into named predicates, and named predicates
|
||||
into C++20 concepts
|
||||
|
||||
#### Functions, statements, expressions, ...
|
||||
#### Functions, statements, expressions, etc
|
||||
|
||||
- Functions
|
||||
- Separate declaration and definition
|
||||
|
||||
@@ -85,17 +85,17 @@ integration, and bisection. This means we typically squash pull requests into a
|
||||
single commit when landing. We use two fundamental guides for deciding how to
|
||||
split up pull requests:
|
||||
|
||||
1. Ensure that each pull request builds and passes any tests cleanly when you
|
||||
request review and when it lands. This will ensure bisection and continuous
|
||||
integration can effectively process them.
|
||||
1. Ensure that each pull request builds and passes any tests cleanly when you
|
||||
request review and when it lands. This will ensure bisection and continuous
|
||||
integration can effectively process them.
|
||||
|
||||
2. Without violating the first point, try to get each pull request to be "just
|
||||
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.
|
||||
2. Without violating the first point, try to get each pull request to be "just
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
@@ -28,9 +28,9 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
We have two areas of focus for 2025:
|
||||
|
||||
1. Get a major chunk of our C++ interop working to the point where we can
|
||||
demonstrate it in realistic scenarios.
|
||||
2. Build a concrete and specific design for memory safety in Carbon.
|
||||
1. Get a major chunk of our C++ interop working to the point where we can
|
||||
demonstrate it in realistic scenarios.
|
||||
2. Build a concrete and specific design for memory safety in Carbon.
|
||||
|
||||
We will scope the first one to non-template C++ APIs, and prioritize accessing
|
||||
C++ APIs from Carbon. This still will require major progress on the
|
||||
|
||||
@@ -37,16 +37,16 @@ the core motivation.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
2. It directly anchors and reinforces contributors on the trunk-based workflow.
|
||||
2. It directly anchors and reinforces contributors on the trunk-based workflow.
|
||||
|
||||
### Longer discussion of linear history
|
||||
|
||||
|
||||
@@ -639,15 +639,15 @@ In a workflow where there's always a tracking issue:
|
||||
1. Create the tracking issue, for example #123.
|
||||
2. Create the PR, for example #456, naming the proposal p0123.md after the
|
||||
tracking issue.
|
||||
1. Use GitHub features to link #123 and #456.
|
||||
1. Use GitHub features to link #123 and #456.
|
||||
3. Update the status in p0123.md and labels of #123 when progressing a
|
||||
proposal.
|
||||
4. When a decision is made, create a new PR, for example #789, containing the
|
||||
decision p0123-decision.md.
|
||||
1. This does not replace the Discourse Forum topic announcing a decision.
|
||||
2. Use GitHub features to link #123 and #789.
|
||||
3. Comments on the decision may go on the decision PR, similar to the
|
||||
proposal PR discussion.
|
||||
1. This does not replace the Discourse Forum topic announcing a decision.
|
||||
2. Use GitHub features to link #123 and #789.
|
||||
3. Comments on the decision may go on the decision PR, similar to the
|
||||
proposal PR discussion.
|
||||
5. Declined/deferred proposals may be committed or not; it doesn't matter.
|
||||
|
||||
Advantages:
|
||||
@@ -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.
|
||||
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.
|
||||
4. If declined/deferred proposals are committed, it would be best to add a
|
||||
status in p0456.md before committing.
|
||||
|
||||
@@ -785,35 +785,35 @@ comments together, as in a review.
|
||||
|
||||
[Google Docs](https://support.google.com/docs/answer/65129?co=GENIE.Platform%3DDesktop&hl=en):
|
||||
|
||||
1. Follow the link to the doc
|
||||
2. Select text to comment on
|
||||
3. Click on "+" to add a comment (or use keyboard shortcut)
|
||||
4. Enter text
|
||||
5. Click "Comment"
|
||||
1. Follow the link to the doc
|
||||
2. Select text to comment on
|
||||
3. Click on "+" to add a comment (or use keyboard shortcut)
|
||||
4. Enter text
|
||||
5. Click "Comment"
|
||||
|
||||
[GitHub](https://help.github.com/en/enterprise/2.14/user/articles/commenting-on-a-pull-request):
|
||||
|
||||
1. Follow the link to a pull request
|
||||
2. Click on "+" next to line to comment on
|
||||
3. Enter text
|
||||
4. Click "Add single comment"
|
||||
1. Follow the link to a pull request
|
||||
2. Click on "+" next to line to comment on
|
||||
3. Enter text
|
||||
4. Click "Add single comment"
|
||||
|
||||
#### Suggesting edits
|
||||
|
||||
[Google Docs](https://support.google.com/docs/answer/6033474?co=GENIE.Platform%3DDesktop&hl=en):
|
||||
|
||||
1. Follow the link to the doc
|
||||
2. Select text to suggest edit on
|
||||
3. Type suggested edit
|
||||
1. Follow the link to the doc
|
||||
2. Select text to suggest edit on
|
||||
3. Type suggested edit
|
||||
|
||||
[GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request):
|
||||
|
||||
1. Follow the link to a pull request
|
||||
2. Click on "+" next to line to comment on
|
||||
3. Optionally select multiple lines
|
||||
4. Click on the left-most button
|
||||
5. Edit quoted text
|
||||
6. Click "Add single comment"
|
||||
1. Follow the link to a pull request
|
||||
2. Click on "+" next to line to comment on
|
||||
3. Optionally select multiple lines
|
||||
4. Click on the left-most button
|
||||
5. Edit quoted text
|
||||
6. Click "Add single comment"
|
||||
|
||||
### Google Docs add-ons
|
||||
|
||||
@@ -934,7 +934,6 @@ etc. In general, the PR-centric model was favored.
|
||||
- Less to learn
|
||||
- Fewer steps in the process
|
||||
- No outdated versions in the old format left behind
|
||||
|
||||
- The technical flow seems on balance better than the Google Docs-based
|
||||
workflow. The proposal does a really good job explaining advantages and
|
||||
disadvantages. In summary, the Google Docs-centric workflow has a lot of
|
||||
|
||||
@@ -82,12 +82,12 @@ rarely be compromises between goals, irrespective of the priority of
|
||||
interoperability. For example, considering the readability of C++
|
||||
interoperability syntax, it could be viewed in two ways:
|
||||
|
||||
1. An edge-case syntax that can be avoided in most code, thus not significantly
|
||||
affecting the readability goal.
|
||||
2. A readability issue that risks making _all_ code less readable, representing
|
||||
the interoperability goal as subverting the readability goal, in which case
|
||||
either interoperability must be higher priority than readability, or we must
|
||||
have no interoperability.
|
||||
1. An edge-case syntax that can be avoided in most code, thus not significantly
|
||||
affecting the readability goal.
|
||||
2. A readability issue that risks making _all_ code less readable, representing
|
||||
the interoperability goal as subverting the readability goal, in which case
|
||||
either interoperability must be higher priority than readability, or we must
|
||||
have no interoperability.
|
||||
|
||||
While the proposers prefer the first interpretation, the second all-or-nothing
|
||||
interpretation may be what's leading to the desire of treating interoperability
|
||||
|
||||
@@ -626,9 +626,9 @@ library.
|
||||
For example, it may preprocess files to split out an API, reducing the number of
|
||||
imports propagated for _actual_ APIs. For example:
|
||||
|
||||
1. Extract `api` declarations within the `api` file.
|
||||
2. Remove all implementation bodies.
|
||||
3. Add only the imports that are referenced.
|
||||
1. Extract `api` declarations within the `api` file.
|
||||
2. Remove all implementation bodies.
|
||||
3. Add only the imports that are referenced.
|
||||
|
||||
Even under the proposed model, compilation will do some of this work as an
|
||||
optimization. However, determining which imports are referenced requires
|
||||
|
||||
@@ -8,8 +8,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
[Pull request](https://github.com/carbon-language/carbon-lang/pull/140)
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
## Table of contents
|
||||
@@ -19,7 +17,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Details](#details)
|
||||
- [Conventions](#conventions)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
- [Maintain the specification in a different language.](#maintain-the-specification-in-a-different-language)
|
||||
- [Maintain the specification in a different language](#maintain-the-specification-in-a-different-language)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
@@ -67,7 +65,7 @@ Hyperlinks between sections of the specification are used liberally.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
### Maintain the specification in a different language.
|
||||
### Maintain the specification in a different language
|
||||
|
||||
Advantages:
|
||||
|
||||
|
||||
@@ -100,18 +100,18 @@ convert source files to NFC as necessary to satisfy this constraint.
|
||||
|
||||
The choice to require NFC is really four choices:
|
||||
|
||||
1. Equivalence classes: we use a canonical normalization form rather than a
|
||||
compatibility normalization form or no normalization form at all.
|
||||
1. Equivalence classes: we use a canonical normalization form rather than a
|
||||
compatibility normalization form or no normalization form at all.
|
||||
|
||||
- If we use no normalization, invisibly-different ways of representing the
|
||||
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 compatibility normalization form, ligatures are considered
|
||||
equivalent to the character sequence that they decompose into.
|
||||
- If we use no normalization, invisibly-different ways of representing the
|
||||
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 compatibility normalization form, ligatures are considered
|
||||
equivalent to the character sequence that they decompose into.
|
||||
|
||||
For a fixed-width font, a canonical normalization form is most likely to
|
||||
consider characters to be the same if they look the same. Unicode annexes
|
||||
@@ -123,20 +123,20 @@ 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).
|
||||
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).
|
||||
|
||||
3. We require source files to be in our chosen form, rather than converting to
|
||||
that form as necessary.
|
||||
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.
|
||||
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.
|
||||
|
||||
### Characters in identifiers and whitespace
|
||||
|
||||
@@ -297,7 +297,6 @@ Con:
|
||||
and do the conversion only when necessary. However, if non-canonical source
|
||||
is formally valid, there are more stringent performance constraints on such
|
||||
conversion than if it is only done for error recovery.
|
||||
|
||||
- Tools such as `grep` do not perform normalization themselves, and so would
|
||||
be unreliable when applied to a codebase with inconsistent normalization.
|
||||
- GCC already diagnoses identifiers that are not in NFC, and WG21 is in the
|
||||
|
||||
@@ -8,8 +8,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
[Pull request](https://github.com/carbon-language/carbon-lang/pull/144)
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
## Table of contents
|
||||
@@ -267,18 +265,24 @@ Advantages:
|
||||
types.
|
||||
- Writing a function that takes any integer literal can be done with more
|
||||
obvious syntax and less syntactic overhead. Instead of:
|
||||
|
||||
```
|
||||
fn OneHigher(L: IntLiteral(template _:! BigInt));
|
||||
```
|
||||
|
||||
we could write
|
||||
|
||||
```
|
||||
fn OneHigher(template L:! Integer);
|
||||
```
|
||||
|
||||
However, with this proposal, a function taking any integer expression that
|
||||
can be evaluated to a constant can be written as
|
||||
|
||||
```
|
||||
fn F(template N:! BigInt);
|
||||
```
|
||||
|
||||
and such a function would accept all integer literals, as well as
|
||||
non-literal constants.
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
[Pull request](https://github.com/carbon-language/carbon-lang/pull/157)
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
## Table of contents
|
||||
|
||||
@@ -8,8 +8,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
[Pull request](https://github.com/carbon-language/carbon-lang/pull/162)
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
## Table of contents
|
||||
@@ -156,7 +154,9 @@ expression: expression ':' identifier
|
||||
|
||||
is for pattern variables. For example, in a variable definition such as
|
||||
|
||||
var Int: x = 0;
|
||||
```
|
||||
var Int: x = 0;
|
||||
```
|
||||
|
||||
the `Int: x` is parsed with the grammar rule for pattern variables. In the
|
||||
right-hand side of the above grammar rule, the `expression` to the left of the
|
||||
@@ -286,7 +286,9 @@ member: "var" expression ':' identifier ';'
|
||||
the `expression` must evaluate to a type at compile time. The same is true for
|
||||
the `tuple` in the grammar rule for an alternative:
|
||||
|
||||
alternative: identifier tuple ';'
|
||||
```
|
||||
alternative: identifier tuple ';'
|
||||
```
|
||||
|
||||
### Precedence and Associativity
|
||||
|
||||
@@ -298,13 +300,15 @@ lowest to highest precedence, with operators on the same line having equal
|
||||
precedence. Proposal 168 differs in that the operator groups are partially
|
||||
ordered instead of being totally ordered.
|
||||
|
||||
nonassoc '{' '}'
|
||||
nonassoc ':' ','
|
||||
left "or" "and"
|
||||
nonassoc "==" "not"
|
||||
left '+' '-'
|
||||
left '.' "->"
|
||||
nonassoc '(' ')' '[' ']'
|
||||
```
|
||||
nonassoc '{' '}'
|
||||
nonassoc ':' ','
|
||||
left "or" "and"
|
||||
nonassoc "==" "not"
|
||||
left '+' '-'
|
||||
left '.' "->"
|
||||
nonassoc '(' ')' '[' ']'
|
||||
```
|
||||
|
||||
### Abstract Syntax
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Create a toolchain team.
|
||||
# Create a toolchain team
|
||||
|
||||
<!--
|
||||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
|
||||
@@ -378,9 +378,11 @@ context of the complete language design.
|
||||
|
||||
### Multi-line text comments
|
||||
|
||||
<!-- rumdl-disable -->
|
||||
No support is provided for multi-line text comments. Instead, the intent is that
|
||||
such comments are expressed by prepending each line with the same `// ` comment
|
||||
marker.
|
||||
<!-- rumdl-enable -->
|
||||
|
||||
Requiring each line to repeat the comment marker will improve readability, by
|
||||
removing a source of non-local state, and removes a needless source of stylistic
|
||||
|
||||
@@ -66,7 +66,7 @@ easily be replaced with a different, more effective libraries to achieve the
|
||||
fundamental result of demonstrating a compelling body of cohesive design and the
|
||||
overarching value proposition.
|
||||
|
||||
#### Language design covers the syntax and semantics of the example port code.
|
||||
#### Language design covers the syntax and semantics of the example port code
|
||||
|
||||
We should have a clear understanding of the syntax and semantics used by these
|
||||
example ports. While this should include accepted proposals, it doesn't
|
||||
|
||||
@@ -120,8 +120,8 @@ equally for moved-from objects and objects without an explicit initializer:
|
||||
|
||||
We propose two fundamental concepts:
|
||||
|
||||
1. An _unformed state_ for objects.
|
||||
2. Raw, uninitialized storage.
|
||||
1. An _unformed state_ for objects.
|
||||
2. Raw, uninitialized storage.
|
||||
|
||||
The first of these is a new concept and is discussed in detail below. However,
|
||||
uninitialized storage in Carbon should work in the same way as an uninitialized
|
||||
@@ -555,14 +555,14 @@ 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`.
|
||||
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.
|
||||
4. There must be a `returned var` declaration in scope when the function does a
|
||||
`return 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.
|
||||
4. There must be a `returned var` declaration in scope when the function does a
|
||||
`return var;`.
|
||||
|
||||
A consequence of these rules allows code like:
|
||||
|
||||
|
||||
@@ -401,8 +401,8 @@ Ordering is essentially a question of pairing identifiers and types. This can be
|
||||
cast as asking which question developers consider more important when reading
|
||||
code:
|
||||
|
||||
1. What is the type of variable `x`?
|
||||
2. What is the identifier of the `Int` variable?
|
||||
1. What is the type of variable `x`?
|
||||
2. What is the identifier of the `Int` variable?
|
||||
|
||||
We assert the first question is the more important one: developers will see an
|
||||
identifier in later code, and want to know its type. However, how do we
|
||||
|
||||
@@ -209,16 +209,20 @@ fn F() -> var (): _ = () { ... }
|
||||
integration.
|
||||
- **Interoperability with and migration from existing C++ code**
|
||||
- This proposal rejects some constructs that would be valid in C++:
|
||||
|
||||
```
|
||||
return F();
|
||||
```
|
||||
|
||||
in a function with `void` return type would no longer be valid in a
|
||||
corresponding Carbon function with no specified return type, and would
|
||||
need to be translated into
|
||||
|
||||
```
|
||||
F();
|
||||
return;
|
||||
```
|
||||
|
||||
(possibly with braces added). However, the fact that this construct is
|
||||
valid in C++ is surprising to many, and the constructs that would be
|
||||
idiomatic in C++ are still valid under these rules.
|
||||
|
||||
@@ -134,7 +134,6 @@ Disadvantages:
|
||||
- If Carbon were to reuse `if` and `else` keywords for a ternary operator,
|
||||
that could omit braces in order to avoid ambiguity. For example,
|
||||
`int x = if y then 3 else 7;`.
|
||||
|
||||
- Developers are known to make mistakes adding statements to conditionals
|
||||
missing braces, keeping consistent indentation, and missing the incorrect
|
||||
behavior due to cognitive load. For example:
|
||||
|
||||
@@ -33,7 +33,7 @@ that talks about their approach to context dependence.
|
||||
## Proposal
|
||||
|
||||
We propose adding
|
||||
(`docs/project/principles/low_context_sensitivity.md`)[/docs/project/principles/low_context_sensitivity.md],
|
||||
[`docs/project/principles/low_context_sensitivity.md`](/docs/project/principles/low_context_sensitivity.md),
|
||||
which has the details.
|
||||
|
||||
## Rationale based on Carbon's goals
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ Exceptions. See /LICENSE for license information.
|
||||
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
-->
|
||||
|
||||
## Problem
|
||||
## Context
|
||||
|
||||
For generics, users will define _interfaces_ that describe types. These
|
||||
interfaces may have associated types (see
|
||||
|
||||
@@ -34,14 +34,17 @@ We would like to provide a notation for the following operations:
|
||||
|
||||
- Requesting a type conversion in order to select an operation to perform, or
|
||||
to resolve an ambiguity between possible operations:
|
||||
|
||||
```
|
||||
fn Ratio(a: i32, b: i32) -> f64 {
|
||||
// Note that a / b would invoke a different / operation.
|
||||
return a / (b as f64);
|
||||
}
|
||||
```
|
||||
|
||||
- Specifying the type that an expression will have or will be converted into,
|
||||
for documentation purposes.
|
||||
|
||||
```
|
||||
class Thing {
|
||||
var id: i32;
|
||||
@@ -51,8 +54,10 @@ We would like to provide a notation for the following operations:
|
||||
Print(t.id as i32);
|
||||
}
|
||||
```
|
||||
|
||||
- Specifying the type that an expression is expected to have, potentially
|
||||
after implicit conversions, as a form of static assertion.
|
||||
|
||||
```
|
||||
fn Munge() {
|
||||
// I expect this expression to produce a Widget but I'm getting compiler
|
||||
@@ -364,6 +369,7 @@ Advantage:
|
||||
implicitly. `as` conversions will likely be fairly common and routine in
|
||||
Carbon code due to their use in generics. As such, they may be written
|
||||
without much thought and not given much scrutiny in code review.
|
||||
|
||||
```
|
||||
var found: bool = false;
|
||||
var total_found: i32 = 0;
|
||||
|
||||
@@ -48,21 +48,29 @@ C-family languages provide a `cond ? value1 : value2` operator.
|
||||
- This operator has confusing syntax, because both `cond` and `value2` are
|
||||
undelimited, and it's often unclear to developers how much of the adjacent
|
||||
expressions are part of the conditional expression. For example:
|
||||
|
||||
```
|
||||
int n = has_thing1 && cond ? has_thing2 : has_thing3 && has_thing4;
|
||||
```
|
||||
|
||||
is parsed as
|
||||
|
||||
```
|
||||
int n = (has_thing1 && cond) ? has_thing2 : (has_thing3 && has_thing4);
|
||||
```
|
||||
|
||||
Also, `value1` and `value2` are parsed with different rules:
|
||||
|
||||
```
|
||||
cond ? f(), g() : h(), i();
|
||||
```
|
||||
|
||||
is parsed as
|
||||
|
||||
```
|
||||
(cond ? f(), g() : h()), i();
|
||||
```
|
||||
|
||||
- In C++, this operator has confusing semantics, due to having a complicated
|
||||
set of rules governing how the target type is determined.
|
||||
- Despite the complications of the rules, the result type of `?:` is not
|
||||
@@ -89,7 +97,6 @@ being an important case of this: `Use(if cond { v1 } else { v2 })`.
|
||||
```
|
||||
|
||||
... because the two arms of the `if` don't have the same type.
|
||||
|
||||
- We have already
|
||||
[decided](https://github.com/carbon-language/carbon-lang/issues/430) that we
|
||||
do not want Carbon to treat statements such as `if` as being expressions
|
||||
@@ -201,6 +208,7 @@ We could provide no conditional expression, and instead ask people to use a
|
||||
different mechanism to achieve this functionality. Some options include:
|
||||
|
||||
- Use of an `if` statement:
|
||||
|
||||
```
|
||||
var v: Result;
|
||||
if (cond) {
|
||||
@@ -210,15 +218,21 @@ different mechanism to achieve this functionality. Some options include:
|
||||
}
|
||||
Use(v);
|
||||
```
|
||||
|
||||
- A function call syntax:
|
||||
|
||||
```
|
||||
Use(cond.Select(value1, value2));
|
||||
```
|
||||
|
||||
or, with short-circuiting and lambdas:
|
||||
|
||||
```
|
||||
Use(cond.LazySelect($(value1), $(value2)));
|
||||
```
|
||||
|
||||
- An `if` statement in a lambda:
|
||||
|
||||
```
|
||||
Use(${ if (cond) { return value1; } else { return value2; } });
|
||||
```
|
||||
@@ -278,6 +292,7 @@ Advantages:
|
||||
- Looks more like an `if` statement, albeit one with unbraced operands.
|
||||
- Slightly shorter.
|
||||
- Better line-wrapping for chained `if` expressions:
|
||||
|
||||
```
|
||||
Print(if (guess < value)
|
||||
"Too low!"
|
||||
@@ -286,7 +301,9 @@ Advantages:
|
||||
else
|
||||
"Correct!")
|
||||
```
|
||||
|
||||
may be more readable than
|
||||
|
||||
```
|
||||
Print(if guess < value
|
||||
then "Too low!"
|
||||
@@ -294,7 +311,9 @@ Advantages:
|
||||
then "Too high!"
|
||||
else "Correct!")
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
Print(if guess < value
|
||||
then "Too low!"
|
||||
@@ -308,18 +327,22 @@ Disadvantages:
|
||||
- Potentially worse line wrapping. The `else` would presumably be wrapped onto
|
||||
a line by itself, wasting vertical space, whereas `then` and `else` when
|
||||
paired can both comfortably precede their values on the same line; consider
|
||||
|
||||
```
|
||||
F(if (cond)
|
||||
value1
|
||||
else
|
||||
value2)
|
||||
```
|
||||
|
||||
occupies more space than
|
||||
|
||||
```
|
||||
F(if cond
|
||||
then value1
|
||||
else value2)
|
||||
```
|
||||
|
||||
- May create confusion between `if` statements and `if` expressions by
|
||||
resembling an `if` statement but not matching the semantics.
|
||||
- May cause evolutionary problems due to syntactic conflict if we ever make
|
||||
@@ -410,6 +433,7 @@ ambiguous. If the author of `A` or `B` wishes to change this behavior:
|
||||
provided specifying the common type is `B`.
|
||||
- If the common type should be something else, then both `impl`s need to be
|
||||
provided:
|
||||
|
||||
```
|
||||
impl A as CommonTypeWith(B) { let Result:! Type = C; }
|
||||
impl B as CommonTypeWith(A) { let Result:! Type = C; }
|
||||
@@ -503,13 +527,17 @@ Disadvantages:
|
||||
- Mutable inputs to operations ("out parameters") in Carbon are expected to be
|
||||
expressed as pointers under #821, so there will be a `&` somewhere anyway;
|
||||
given the choice between an lvalue conditional:
|
||||
|
||||
```
|
||||
F(&(if cond then a else b));
|
||||
```
|
||||
|
||||
and an rvalue-only conditional:
|
||||
|
||||
```
|
||||
F(if cond then &a else &b);
|
||||
```
|
||||
|
||||
the latter option would likely be preferred even if the former were
|
||||
available.
|
||||
- This would create an inconsistency in behavior, which would be particularly
|
||||
|
||||
@@ -117,7 +117,6 @@ conditional conformance options:
|
||||
|
||||
This was too different from how those same impls would be declared
|
||||
out-of-line.
|
||||
|
||||
- Another approach that was too different between inline and out-of-line, is
|
||||
to use pattern matching instead of boolean conditions. This might look like:
|
||||
|
||||
|
||||
@@ -175,6 +175,7 @@ Disadvantages:
|
||||
for them in practice.
|
||||
- Likely to result in complexity and inconsistency for operations falling
|
||||
between the two options. For example, in C++:
|
||||
|
||||
```
|
||||
struct A {
|
||||
static void F();
|
||||
@@ -187,6 +188,7 @@ Disadvantages:
|
||||
b.e; // Error.
|
||||
}
|
||||
```
|
||||
|
||||
- Does not provide an obvious syntax for `impl` lookup.
|
||||
`Type::Interface::method` would be ambiguous and `Type.Interface::method`
|
||||
would be inconsistent with using `::` for static lookup, so we would likely
|
||||
|
||||
@@ -530,7 +530,7 @@ signed integers (whether we provide those operations as operators or library
|
||||
functions). Assuming operator notation for now, and that we define modulo as
|
||||
`a % b == a - a / b * b`, the following options all have merit:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<!-- rumdl-disable -->
|
||||
| Property | Round towards zero (truncating division) | Round towards negative infinity (floor division) | Round based on sign of divisor\[1] (Euclidean division) |
|
||||
| ------------------------------------ | -------- | -------- | --------- |
|
||||
| `(-a) / b ==`<br>` a / (-b)` | :+1: Yes | :+1: Yes | No |
|
||||
@@ -541,6 +541,7 @@ functions). Assuming operator notation for now, and that we define modulo as
|
||||
| x86 instruction? | :+1: Yes: `cqo` (or similar) + `idiv` | First option + fixup:<br> `s * (a / (s * b))` where `s` is `sign(a) * sign(b)`[2] | First option + fixup:<br>`a / b - (a % b < 0)` |
|
||||
| LLVM IR + optimization support | :+1: Yes | No | No |
|
||||
| Use in existing languages | C, C++, Rust, Swift <br> `quotRem` in Haskell | `//` and `%` in Python <br> `/` in Python 2 only <br> `divMod` in Haskell | None? |
|
||||
<!-- rumdl-enable -->
|
||||
|
||||
The cells marked :+1: suggest generally desirable properties. For further
|
||||
reading, see
|
||||
|
||||
@@ -346,9 +346,11 @@ We considered the following options:
|
||||
right-hand operand as runtime state, and allow that type to be converted in
|
||||
the same way as its integer constant. However, this would introduce
|
||||
substantial complexity: reasonable and expected uses such as
|
||||
|
||||
```
|
||||
var mask: u32 = (1 << a) - 1;
|
||||
```
|
||||
|
||||
would require a second new type for a shifted value plus an offset, and
|
||||
general support would require a facility analogous to
|
||||
[expression templates](https://en.wikipedia.org/wiki/Expression_templates).
|
||||
|
||||
@@ -84,44 +84,44 @@ 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.
|
||||
> 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.
|
||||
> 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; `()`,
|
||||
> `[]`, and `{}` are all used for types, leaving `<>` as the only remaining
|
||||
> bracket. Use of `<>` as brackets as a long history but not a good one. ...
|
||||
> 6. Remove the implicit parameter list from impls and force them to be
|
||||
> introduced where they're first used: `impl Vector(T:! Type) as Container`.
|
||||
> Concerns: harms readability in some cases, eg
|
||||
> `impl Optional(T:! As(U:! Type)) as As(Optional(U))` versus
|
||||
> `impl [U:! Type, T:! As(U)] Optional(T) as As(Optional(U))`.
|
||||
> 7. Move the implicit parameter list before the impl keyword, perhaps with an
|
||||
> introducer: `generic [T:! Type] impl Vector(T) as Container`. Concerns:
|
||||
> increases verbosity; would be inconsistent if we put everything but me
|
||||
> there, and surprising if we put me there. Also not clear what a good
|
||||
> keyword is, given that the existence of deduced parameters isn't the same
|
||||
> as an entity being generic.
|
||||
> 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.
|
||||
> 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; `()`,
|
||||
> `[]`, and `{}` are all used for types, leaving `<>` as the only remaining
|
||||
> bracket. Use of `<>` as brackets as a long history but not a good one. ...
|
||||
> 6. Remove the implicit parameter list from impls and force them to be
|
||||
> introduced where they're first used: `impl Vector(T:! Type) as Container`.
|
||||
> Concerns: harms readability in some cases, eg
|
||||
> `impl Optional(T:! As(U:! Type)) as As(Optional(U))` versus
|
||||
> `impl [U:! Type, T:! As(U)] Optional(T) as As(Optional(U))`.
|
||||
> 7. Move the implicit parameter list before the impl keyword, perhaps with an
|
||||
> introducer: `generic [T:! Type] impl Vector(T) as Container`. Concerns:
|
||||
> increases verbosity; would be inconsistent if we put everything but me
|
||||
> there, and surprising if we put me there. Also not clear what a good
|
||||
> keyword is, given that the existence of deduced parameters isn't the same
|
||||
> as an entity being generic.
|
||||
|
||||
Ultimately we adopted approach 3, but changed to the new keyword `forall` to
|
||||
avoid overloading the meaning of a keyword used for something else.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Remove LLVM from the repository, and clean up history.
|
||||
# Remove LLVM from the repository, and clean up history
|
||||
|
||||
<!--
|
||||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
@@ -26,7 +26,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Rationale](#rationale)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
- [Do nothing](#do-nothing)
|
||||
- [Don't rewrite the repository history.](#dont-rewrite-the-repository-history)
|
||||
- [Don't rewrite the repository history](#dont-rewrite-the-repository-history)
|
||||
- [Go back to submodules](#go-back-to-submodules)
|
||||
- [Rename the repository, and create a new one](#rename-the-repository-and-create-a-new-one)
|
||||
- [Manually extract and archive some review comments](#manually-extract-and-archive-some-review-comments)
|
||||
@@ -266,7 +266,7 @@ Disadvantages:
|
||||
|
||||
We think this problem is worth solving.
|
||||
|
||||
### Don't rewrite the repository history.
|
||||
### Don't rewrite the repository history
|
||||
|
||||
We could fix this without rewriting history. If we choose not to rewrite history
|
||||
now, it should be noted that the cost of rewriting history only grows and so we
|
||||
|
||||
@@ -23,7 +23,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Too many cooks in the kitchen](#too-many-cooks-in-the-kitchen)
|
||||
- [Community management overload](#community-management-overload)
|
||||
- [Added distraction or confusion to the C++ evolution process](#added-distraction-or-confusion-to-the-c-evolution-process)
|
||||
- [Added distractions from existing new programming languages.](#added-distractions-from-existing-new-programming-languages)
|
||||
- [Added distractions from existing new programming languages](#added-distractions-from-existing-new-programming-languages)
|
||||
- [Friction with existing LLVM and Clang communities](#friction-with-existing-llvm-and-clang-communities)
|
||||
- [Labeled as vaporware](#labeled-as-vaporware)
|
||||
- [Rationale](#rationale)
|
||||
@@ -296,7 +296,7 @@ Planned mitigations:
|
||||
as possible from the Carbon experiment and incorporate any and all of our
|
||||
ideas into C++ where they see a path to do so.
|
||||
|
||||
#### Added distractions from existing new programming languages.
|
||||
#### Added distractions from existing new programming languages
|
||||
|
||||
- Another programming language in the world might dilute some of the efforts
|
||||
going towards new and exciting but existing languages, especially ones with
|
||||
|
||||
@@ -376,7 +376,7 @@ could be a hashmap index, a string, or pointer to a node, without changing the
|
||||
usage for users.
|
||||
|
||||
The `ElementType` can be a tuple, such as a `(key, value)` for maps, or a single
|
||||
value. See [Future work][#future-work] for other examples.
|
||||
value. See [Future work](#future-work) for other examples.
|
||||
|
||||
#### R-value containers
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ are examples of character literals for each specific type:
|
||||
- `Char8`: The character literal consists of a single Unicode code point that
|
||||
can be represented within 8 bits. For example:
|
||||
|
||||
`let allowed: Char8 = ‘a’ `
|
||||
`let allowed: Char8 = 'a'`
|
||||
|
||||
In this example, the character literal `’a’` corresponds to the Unicode code
|
||||
point `97`, which is within the valid range of `Char8` since `97` is less than
|
||||
|
||||
@@ -130,12 +130,11 @@ Leads questions which informed the design proposed here:
|
||||
- [What syntax should we use for pointer types? (#523)][#523]
|
||||
|
||||
It also builds on the design of the proposal ["Initialization of memory and
|
||||
variables"][#257] ([#257]), implementing part of [#1993].
|
||||
variables" (#257)][#257], implementing part of [#1993].
|
||||
|
||||
[#257]: https://github.com/carbon-language/carbon-lang/pull/257
|
||||
[#523]: https://github.com/carbon-language/carbon-lang/issues/523
|
||||
[#1993]: https://github.com/carbon-language/carbon-lang/issues/1993
|
||||
[#257]: /proposals/p000257-initialization-of-memory-and-variables.md
|
||||
|
||||
## Proposal
|
||||
|
||||
@@ -468,8 +467,6 @@ memory is accessed and potentially mutated.
|
||||
The syntax both for declaring a pointer type and dereferencing a pointer has
|
||||
been extensively discussed in the leads question [#523].
|
||||
|
||||
[#523]: https://github.com/carbon-language/carbon-lang/issues/523
|
||||
|
||||
The primary sources of concern over a C++-based syntax:
|
||||
|
||||
1. A prefix dereference operator composes poorly with postfix and infix
|
||||
@@ -733,8 +730,8 @@ that should be covered by the proposed design.
|
||||
C++ provides overlapping but importantly separable semantic models which
|
||||
interact with `const` references.
|
||||
|
||||
1. An _immutable view_ of a value
|
||||
2. A _thread-safe interface_ of a [thread-compatible type][]
|
||||
1. An _immutable view_ of a value
|
||||
2. A _thread-safe interface_ of a [thread-compatible type][]
|
||||
|
||||
[thread-compatible type]:
|
||||
https://abseil.io/blog/20180531-regular-types#:~:text=restrictions%20or%20both,No%20concurrent%20call
|
||||
|
||||
@@ -222,6 +222,7 @@ constraints and restrict the syntax of `where A = B` as follows:
|
||||
`SameAs` relations. Same-type constraints are not used automatically by the
|
||||
language rules for any purpose, but a blanket `ImplicitAs` impl permits
|
||||
conversions between types that are known to be the same:
|
||||
|
||||
```
|
||||
impl forall [T:! type, U:! type where .Self == T] T as ImplicitAs(U);
|
||||
```
|
||||
|
||||
@@ -162,7 +162,6 @@ terminology:
|
||||
|
||||
We previously referred to a facet type as a type-of-type, but that is no
|
||||
longer accurate, as the type of any type is now by definition `type`.
|
||||
|
||||
- A _facet_ is a value of a facet type. For example, `i32 as Hashable` is a
|
||||
facet, and `Hashable` is a facet type. Note that all types are facets.
|
||||
- A facet value can be thought of as a tuple of a possibly-symbolic
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Remove artificial version ceiling on C++ interop.
|
||||
# Remove artificial version ceiling on C++ interop
|
||||
|
||||
<!--
|
||||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
|
||||
@@ -41,12 +41,12 @@ assumption explicit.
|
||||
|
||||
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.
|
||||
- Other languages, such as Javascript, require semicolons but define rules
|
||||
for semicolon insertion.
|
||||
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.
|
||||
- Other languages, such as Javascript, require semicolons but define rules
|
||||
for semicolon insertion.
|
||||
|
||||
Although Carbon's design currently assumes semicolons are required, it hasn't
|
||||
been directly addressed by a proposal.
|
||||
|
||||
@@ -19,9 +19,9 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Details](#details)
|
||||
- [Rationale](#rationale)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
- [Narrowing the proposed milestone definitions to just 0.1 initially.](#narrowing-the-proposed-milestone-definitions-to-just-01-initially)
|
||||
- [Make a more incremental, less ambitious initial milestone.](#make-a-more-incremental-less-ambitious-initial-milestone)
|
||||
- [Skip the 0.1 milestone and aim for feature completeness.](#skip-the-01-milestone-and-aim-for-feature-completeness)
|
||||
- [Narrowing the proposed milestone definitions to just 0.1 initially](#narrowing-the-proposed-milestone-definitions-to-just-01-initially)
|
||||
- [Make a more incremental, less ambitious initial milestone](#make-a-more-incremental-less-ambitious-initial-milestone)
|
||||
- [Skip the 0.1 milestone and aim for feature completeness](#skip-the-01-milestone-and-aim-for-feature-completeness)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
@@ -123,7 +123,7 @@ on-going language evolution:
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
### Narrowing the proposed milestone definitions to just 0.1 initially.
|
||||
### Narrowing the proposed milestone definitions to just 0.1 initially
|
||||
|
||||
While this would narrow the scope of the proposal and remove some of the more
|
||||
vague aspects, it would make it difficult for readers to understand when
|
||||
@@ -134,7 +134,7 @@ We also expect that explicitly deferring things in this way will make it easier
|
||||
to focus our energy and efforts on the next milestone by avoiding distractions
|
||||
of features that _might_ be interesting absent that deferral.
|
||||
|
||||
### Make a more incremental, less ambitious initial milestone.
|
||||
### Make a more incremental, less ambitious initial milestone
|
||||
|
||||
The initial milestone currently proposed is relatively ambitious, and much
|
||||
larger than most programming language MVPs. Carbon could have a much less
|
||||
@@ -147,7 +147,7 @@ end up in somewhat of an "apples versus oranges" comparison where the feature
|
||||
sets are so different as to thwart any attempt at in-depth comparison and
|
||||
evaluation.
|
||||
|
||||
### Skip the 0.1 milestone and aim for feature completeness.
|
||||
### Skip the 0.1 milestone and aim for feature completeness
|
||||
|
||||
We could have fewer milestones overall and aim for the more ambitious goal. We
|
||||
know that 0.1 will be insufficient to finish most real evaluations of the Carbon
|
||||
|
||||
@@ -310,9 +310,10 @@ An `impl` declaration, with this proposal, must have one of these two forms:
|
||||
- Without an `extend` keyword prefix, used for non-extended `impl`
|
||||
declarations and for all `impl` declarations outside of a class body:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<!-- rumdl-disable -->
|
||||
> `impl` [`forall` `[` _deduced-parameters_ `]`] [_type-expression_] `as`
|
||||
> _facet-type-expression_ (`;`|`{` _impl-body_ `}`)
|
||||
<!-- rumdl-enable -->
|
||||
|
||||
The _type-expression_ is required outside of a class body, otherwise it
|
||||
defaults to `Self`.
|
||||
@@ -487,7 +488,6 @@ Notes:
|
||||
a `require` declaration must use `Self`, either to the left or right of
|
||||
`impls`. Note that `require` only supports this subset of `where` clause
|
||||
expressions. Adding other kinds of constraints is future work.
|
||||
|
||||
- Syntax for an `extend` declaration in an interface or named constraint:
|
||||
|
||||
> `extend` _facet-type-expression_ `;`
|
||||
@@ -524,9 +524,10 @@ class C {
|
||||
The declaration that a class uses a mixin is called a "mix" declaration. The
|
||||
syntax of a mix declaration is:
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<!-- rumdl-disable -->
|
||||
> `extend` [`private`|`protected`] (`_`|_id_) `:` _mixin-expression_ [`=`
|
||||
> _initializer-expression_] `;`
|
||||
<!-- rumdl-enable -->
|
||||
|
||||
The _id_ part of the mix declaration defines the name assigned to that mixin
|
||||
subobject. This name is may be used to access members of the mixin and to
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Clarify name bindings in namespaces.
|
||||
# Clarify name bindings in namespaces
|
||||
|
||||
<!--
|
||||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
|
||||
@@ -52,11 +52,11 @@ out our energy across both.
|
||||
|
||||
Originally, the Carbon Explorer served two major purposes:
|
||||
|
||||
1. A high-level or "abstract machine" executable semantic model for the design
|
||||
of the language.
|
||||
1. A high-level or "abstract machine" executable semantic model for the design
|
||||
of the language.
|
||||
|
||||
2. A rapid prototyping platform with a generated parser and maximally simple &
|
||||
traditional internal architecture (ASTs, etc.).
|
||||
2. A rapid prototyping platform with a generated parser and maximally simple &
|
||||
traditional internal architecture (ASTs, etc.).
|
||||
|
||||
The first purpose and use case remains extremely important and something that we
|
||||
should support. However, long-term it may make more sense to build on the same
|
||||
|
||||
@@ -229,20 +229,20 @@ Assert((r as __Binding_C_Static).(Call(()).Op)() == 2);
|
||||
|
||||
How does this arise?
|
||||
|
||||
1. First the simple member access is resolved using the type of the receiver: \
|
||||
`v.F` -> `v.(C.F)`, `v.Static` -> `v.(C.Static)`, `r.F` -> `r.(C.F)`,
|
||||
`r.Static` -> `r.(C.Static)`. \
|
||||
Note that `C.F` is `__C_F` with type `__TypeOf_C_F`, and `C.Static` is
|
||||
`__C_Static` with type `__TypeOf_C_Static`.
|
||||
2. It then looks at the expression to the left of the `.`:
|
||||
- If it is a facet value, the "member binding to type" (`BindToType`)
|
||||
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.
|
||||
3. The result of the member binding has a type that implements the call
|
||||
interface.
|
||||
1. First the simple member access is resolved using the type of the receiver: \
|
||||
`v.F` -> `v.(C.F)`, `v.Static` -> `v.(C.Static)`, `r.F` -> `r.(C.F)`,
|
||||
`r.Static` -> `r.(C.Static)`. \
|
||||
Note that `C.F` is `__C_F` with type `__TypeOf_C_F`, and `C.Static` is
|
||||
`__C_Static` with type `__TypeOf_C_Static`.
|
||||
2. It then looks at the expression to the left of the `.`:
|
||||
- If it is a facet value, the "member binding to type" (`BindToType`)
|
||||
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.
|
||||
3. The result of the member binding has a type that implements the call
|
||||
interface.
|
||||
|
||||
> **Note:** The current wording in
|
||||
> [member_access.md](/docs/design/expressions/member_access.md) says that
|
||||
|
||||
@@ -192,11 +192,11 @@ declaration, only access modifiers are valid (see
|
||||
|
||||
When considering whether a declaration is allowed, we apply the rules:
|
||||
|
||||
1. A declaration should always add new information.
|
||||
- No declarations after a definition.
|
||||
2. Only one library can declare an entity without `extern`.
|
||||
3. Support moving declarations between already-imported `api` files without
|
||||
affecting compilation of client libraries.
|
||||
1. A declaration should always add new information.
|
||||
- No declarations after a definition.
|
||||
2. Only one library can declare an entity without `extern`.
|
||||
3. Support moving declarations between already-imported `api` files without
|
||||
affecting compilation of client libraries.
|
||||
|
||||
#### No forward declarations after declarations
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
## Table of contents
|
||||
|
||||
- [Abstract](#abstract)
|
||||
- [Background](#background)
|
||||
- [Syntax Overview](#syntax-overview)
|
||||
- [Syntax Defined](#syntax-defined)
|
||||
- [Introducer](#introducer)
|
||||
@@ -55,7 +56,7 @@ Associated discussion docs:
|
||||
- [Lambdas Discussion 3](https://docs.google.com/document/d/1VVOlRuPGt8GQpjsygMwH2B7Wd0mBsS3Qif8Ve2yhX_A/)
|
||||
- [Lambdas Discussion 4](https://docs.google.com/document/d/1Sevhvjo06Bc6wTigNL1pK-mlF3IXvzmU1lI2X1W9OYA/)
|
||||
|
||||
# Background
|
||||
## Background
|
||||
|
||||
Refer to the following documentation about lambdas in other languages. What
|
||||
separates these three and makes them more analegous to Carbon's direction is the
|
||||
|
||||
@@ -249,7 +249,7 @@ A couple keyword alternatives discussed (alongside placement options) were:
|
||||
We see several options for `export name` placement. This compares them, focusing
|
||||
on advantages and disadvantages for each option.
|
||||
|
||||
1. `export name` with `import`s
|
||||
1. `export name` with `import`s
|
||||
|
||||
`export name` can (only) appear in the preamble, with the imports, and
|
||||
cannot appear with the other declarations in the library. Note this option
|
||||
@@ -259,44 +259,44 @@ on advantages and disadvantages for each option.
|
||||
|
||||
Advantages:
|
||||
|
||||
- No need to teach developers they cannot (don't need to) `export` locally
|
||||
introduced names.
|
||||
- No need to teach developers they cannot (don't need to) `export` locally
|
||||
introduced names.
|
||||
|
||||
Disadvantages:
|
||||
|
||||
- Although the restricted placement might imply placement is tied to
|
||||
specific libraries, that's not the case. This could mislead developers.
|
||||
- In theory, we could enforce this, but then we could end up breaking
|
||||
code if the path a name is imported through changes.
|
||||
- Although the restricted placement might imply placement is tied to
|
||||
specific libraries, that's not the case. This could mislead developers.
|
||||
- In theory, we could enforce this, but then we could end up breaking
|
||||
code if the path a name is imported through changes.
|
||||
|
||||
2. `export name` with other declarations
|
||||
2. `export name` with other declarations
|
||||
|
||||
`export name` can only appear after imports. This means that all names valid
|
||||
for `export` will already be made available.
|
||||
|
||||
Advantages:
|
||||
|
||||
- `import` remains very special.
|
||||
- Makes it unambiguous that names valid for `export` are already imported.
|
||||
- `import` remains very special.
|
||||
- Makes it unambiguous that names valid for `export` are already imported.
|
||||
|
||||
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`
|
||||
3. No ordering for `export name`
|
||||
|
||||
Let developers choose what the prefer.
|
||||
|
||||
Advantages:
|
||||
|
||||
- Maximum flexibility, HOA rule.
|
||||
- Maximum flexibility, HOA rule.
|
||||
|
||||
Disadvantages:
|
||||
|
||||
- Most inconsistent with the desire to treat `import` as special.
|
||||
- Most inconsistent with the desire to treat `import` as special.
|
||||
|
||||
We're choosing option (2). The name lookup issues avoided by requiring `export`
|
||||
be below `import` directives seem worthwhile.
|
||||
|
||||
@@ -22,10 +22,10 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Long-Term Stable (LTS) versions and standardization](#long-term-stable-lts-versions-and-standardization)
|
||||
- [Rationale](#rationale)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
- [Do nothing, or just talk about a minimal nightly version.](#do-nothing-or-just-talk-about-a-minimal-nightly-version)
|
||||
- [Make no breaking changes past 1.0.](#make-no-breaking-changes-past-10)
|
||||
- [Version different parts of the language separately.](#version-different-parts-of-the-language-separately)
|
||||
- [Use a custom versioning scheme rather than SemVer.](#use-a-custom-versioning-scheme-rather-than-semver)
|
||||
- [Do nothing, or just talk about a minimal nightly version](#do-nothing-or-just-talk-about-a-minimal-nightly-version)
|
||||
- [Make no breaking changes past 1.0](#make-no-breaking-changes-past-10)
|
||||
- [Version different parts of the language separately](#version-different-parts-of-the-language-separately)
|
||||
- [Use a custom versioning scheme rather than SemVer](#use-a-custom-versioning-scheme-rather-than-semver)
|
||||
- [Include more pre-release variations](#include-more-pre-release-variations)
|
||||
|
||||
<!-- tocstop -->
|
||||
@@ -195,7 +195,7 @@ to meet the needs of candidate Carbon users.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
### Do nothing, or just talk about a minimal nightly version.
|
||||
### Do nothing, or just talk about a minimal nightly version
|
||||
|
||||
Advantages:
|
||||
|
||||
@@ -219,7 +219,7 @@ and all of this if and when we need to. This does not lock Carbon into using
|
||||
this exact versioning scheme. We will listen to any feedback from potential
|
||||
users and can adapt our approach if needed.
|
||||
|
||||
### Make no breaking changes past 1.0.
|
||||
### Make no breaking changes past 1.0
|
||||
|
||||
Advantages:
|
||||
|
||||
@@ -239,7 +239,7 @@ Disadvantages:
|
||||
This complexity inherently comes with an increased risk and importance
|
||||
of being able to improve and fix issues.
|
||||
|
||||
### Version different parts of the language separately.
|
||||
### Version different parts of the language separately
|
||||
|
||||
Advantages:
|
||||
|
||||
@@ -260,7 +260,7 @@ Disadvantages:
|
||||
over the years. As a consequence, while it is tempting to hope for a sharp
|
||||
difference here we don't in practice anticipate one.
|
||||
|
||||
### Use a custom versioning scheme rather than SemVer.
|
||||
### Use a custom versioning scheme rather than SemVer
|
||||
|
||||
Advantages:
|
||||
|
||||
|
||||
@@ -351,7 +351,7 @@ without requiring special-casing.
|
||||
|
||||
We introduced some more specific sub-goals above:
|
||||
|
||||
1. Privileging the most common type names
|
||||
1. Privileging the most common type names
|
||||
|
||||
This proposal privileges `Core.Array` as it will appear frequently in code, by
|
||||
placing it in the `prelude` library. This avoids the need for developers to
|
||||
@@ -367,7 +367,7 @@ In this proposal, we avoid introducing additional syntax (such as with `[T; N]`
|
||||
or `(1, 2)`) because the frequency of use of arrays will be lower than that of
|
||||
fundamental types and tuples.
|
||||
|
||||
2. Absence of syntax should make clear defaults
|
||||
2. Absence of syntax should make clear defaults
|
||||
|
||||
We introduce a type name, with a keyword that has a clear relationship to the
|
||||
generic type name, rather than making arrays look more like slices but without
|
||||
@@ -375,7 +375,7 @@ being a pointer. This is maent to avoid the confusion raised when removing
|
||||
syntax changes the meaning significantly, and especially in ways that differ
|
||||
from defaults/options for a single language concept.
|
||||
|
||||
3. Avoiding confusion with other languages
|
||||
3. Avoiding confusion with other languages
|
||||
|
||||
We propose using the `Array` type name, and `array` shorthand, in line with how
|
||||
other languages use the same term. When a direct-storage array type is part of
|
||||
@@ -386,7 +386,7 @@ Most importantly, the name is consistent with the meaning in C++ and its
|
||||
standard library (`std::array<T, N>`) as well as with Rust, the languages which
|
||||
we expect Carbon code to interact with the most.
|
||||
|
||||
4. Avoiding confusion with other domains
|
||||
4. Avoiding confusion with other domains
|
||||
|
||||
The name `Vector` is a possible choice for a fixed-length set of values, due to
|
||||
its mathematical meaning, as was originally proposed for the direct-storage
|
||||
|
||||
@@ -342,8 +342,8 @@ remain:
|
||||
| `impl C as Y where .A =` ... | `Y` complete | `C impls Y` | |
|
||||
| `impl C as Y {` ... `}` | `Y` complete | `C impls Y` | `C` |
|
||||
| `interface I;` | | `I` declared | `I` |
|
||||
| `interface Y {` <br> ` require Self impls Z;` <br> `}` | **`Z` declared** | **`Y` complete** | `Z` |
|
||||
| `interface Y {` <br> ` require Self impls Z;` <br> `}` <br> `impl C as Y {` ... `}` | **open question [\#4579](https://github.com/carbon-language/carbon-lang/issues/4579)** | **open question [\#4579](https://github.com/carbon-language/carbon-lang/issues/4579)** | |
|
||||
| `interface Y {` <br> `require Self impls Z;` <br> `}` | **`Z` declared** | **`Y` complete** | `Z` |
|
||||
| `interface Y {` <br> `require Self impls Z;` <br> `}` <br> `impl C as Y {` ... `}` | **open question [\#4579](https://github.com/carbon-language/carbon-lang/issues/4579)** | **open question [\#4579](https://github.com/carbon-language/carbon-lang/issues/4579)** | |
|
||||
| `fn F[T:! I](x: T);` | `I` declared | | `F`, `I` |
|
||||
| `fn F[T:! I](x: T) {` ... `}` | `I` complete | `F` complete | |
|
||||
| `interface I;` <br> `class C;` <br> `class D(T:! I);` <br> `fn F(x: D(C));` | `C impls I` | | `I`, `C`?, `D` |
|
||||
@@ -357,8 +357,8 @@ remain:
|
||||
| `impl C as Y where .A =` ... | `Y` complete | `C impls Y` | **`impl C as Y` ...** |
|
||||
| `impl C as Y {` ... `}` | `Y` complete | `C impls Y` | `C` |
|
||||
| `interface I;` | | `I` declared | `I` |
|
||||
| `interface Y {` <br> ` require Self impls Z;` <br> `}` | **`Z` identified** | **for any symbolic type `T`, <br> `T impls Y` implies `T impls Z`; <br> `Y` complete** | `Z` |
|
||||
| `interface Y {` <br> ` require Self impls Z;` <br> `}` <br> `impl C as Y {` ... `}` | **`C impls Z`** | **`C impls Y`** | |
|
||||
| `interface Y {` <br> `require Self impls Z;` <br> `}` | **`Z` identified** | **for any symbolic type `T`, <br> `T impls Y` implies `T impls Z`; <br> `Y` complete** | `Z` |
|
||||
| `interface Y {` <br> `require Self impls Z;` <br> `}` <br> `impl C as Y {` ... `}` | **`C impls Z`** | **`C impls Y`** | |
|
||||
| `fn F[T:! I](x: T);` | `I` declared | | `F`, `I` |
|
||||
| `fn F[T:! I](x: T) {` ... `}` | `I` complete | `F` complete | |
|
||||
| `interface I;` <br> `class C;` <br> `class D(T:! I);` <br> `fn F(x: D(C));` | `C impls I` | | `I`, `C`?, `D` |
|
||||
|
||||
@@ -125,11 +125,11 @@ We would like an easy way for folks to flag things that are interesting to
|
||||
include into the summaries, especially PRs that might otherwise be missed. We
|
||||
suggest one or both of two options far flagging these:
|
||||
|
||||
1. Create a dedicated discord channel that folks can post links / snippets to
|
||||
that they find interesting.
|
||||
2. Create a discord channel that automatically gets bot postings for each PR
|
||||
that is merged, and encourage folks to use reactions to signal interest in
|
||||
that being included in the summary.
|
||||
1. Create a dedicated discord channel that folks can post links / snippets to
|
||||
that they find interesting.
|
||||
2. Create a discord channel that automatically gets bot postings for each PR
|
||||
that is merged, and encourage folks to use reactions to signal interest in
|
||||
that being included in the summary.
|
||||
|
||||
### Discussion / demo session every two months
|
||||
|
||||
|
||||
@@ -68,18 +68,18 @@ explorer tests[^2][^3][^4].
|
||||
|
||||
## Proposal
|
||||
|
||||
1. Add a tag `explorer-archived` in the main `carbon-lang` git repository.
|
||||
2. Create a new `explorer` repository under the `carbon-language` organization
|
||||
that only contains the `//explorer` and `//installers` directories and their
|
||||
dependencies at head.
|
||||
3. Locally ensure the explorer tests build and pass under the `explorer`
|
||||
repository.
|
||||
4. Add a `README.md` to the `explorer` repository that explains explorer is
|
||||
archived and not under active development.
|
||||
5. Stop building, or remove the "Explorer (trunk)" compiler option from
|
||||
[carbon.compiler-explorer.com](https://carbon.compiler-explorer.com).
|
||||
6. Delete `//explorer` and `//installers` in the main `carbon-lang` repository.
|
||||
7. Archive the `explorer` repository in GitHub, making it read-only.
|
||||
1. Add a tag `explorer-archived` in the main `carbon-lang` git repository.
|
||||
2. Create a new `explorer` repository under the `carbon-language` organization
|
||||
that only contains the `//explorer` and `//installers` directories and their
|
||||
dependencies at head.
|
||||
3. Locally ensure the explorer tests build and pass under the `explorer`
|
||||
repository.
|
||||
4. Add a `README.md` to the `explorer` repository that explains explorer is
|
||||
archived and not under active development.
|
||||
5. Stop building, or remove the "Explorer (trunk)" compiler option from
|
||||
[carbon.compiler-explorer.com](https://carbon.compiler-explorer.com).
|
||||
6. Delete `//explorer` and `//installers` in the main `carbon-lang` repository.
|
||||
7. Archive the `explorer` repository in GitHub, making it read-only.
|
||||
|
||||
Note that fuzzer test cases from the explorer are already relocated under
|
||||
`//toolchain/*/fuzzer_corpus/`.
|
||||
|
||||
@@ -339,9 +339,9 @@ same type due to the different spellings of the types in C++ being the same:
|
||||
|
||||
- `Cpp.[unsigned_](long_long|long|int|short|double|float)`
|
||||
|
||||
that is signedness, then size keyword(s), then a type keyword only if
|
||||
there are no size keywords. For example `Cpp.unsigned_int` not
|
||||
`Cpp.unsigned`, `Cpp.long` not `Cpp.long_int`.
|
||||
that is signedness, then size keyword(s), then a type keyword only if
|
||||
there are no size keywords. For example `Cpp.unsigned_int` not
|
||||
`Cpp.unsigned`, `Cpp.long` not `Cpp.long_int`.
|
||||
|
||||
- They will be available when an `import Cpp` declaration is present.
|
||||
|
||||
@@ -365,7 +365,6 @@ same type due to the different spellings of the types in C++ being the same:
|
||||
|
||||
- `Cpp.float` and `Cpp.double` will be the same type as `f32` and `f64`
|
||||
correspondingly.
|
||||
|
||||
- The type aliases `[u]int_fastN_t`, `[u]int_leastN_t`, `[u]intmax_t`,
|
||||
`[u]intptr_t`, `ptrdiff_t` and `size_t` will be available in Carbon in the
|
||||
`Cpp` namespace if the C++ header declaring them is imported (for example
|
||||
|
||||
@@ -33,7 +33,7 @@ disclosure", but that approach has not been codified as a design principle.
|
||||
## Proposal
|
||||
|
||||
See
|
||||
(`docs/project/principles/progressive_disclosure.md`)[/docs/project/principles/progressive_disclosure.md],
|
||||
[`docs/project/principles/progressive_disclosure.md`](/docs/project/principles/progressive_disclosure.md),
|
||||
which is introduced by this proposal.
|
||||
|
||||
## Rationale
|
||||
|
||||
@@ -72,10 +72,10 @@ but also on C and even Rust.
|
||||
|
||||
We plan to support a two step migration process:
|
||||
|
||||
1. Highly automated, minimal supervision migration from C++ to a dialect of
|
||||
Carbon designed for C++ interop and migration.
|
||||
2. Incremental refactoring of the Carbon code to adopt memory safe designs,
|
||||
patterns, and APIs.
|
||||
1. Highly automated, minimal supervision migration from C++ to a dialect of
|
||||
Carbon designed for C++ interop and migration.
|
||||
2. Incremental refactoring of the Carbon code to adopt memory safe designs,
|
||||
patterns, and APIs.
|
||||
|
||||
From this framing of our problem statement and end-goal, we can extract detailed
|
||||
requirements on the memory safety design in Carbon:
|
||||
|
||||
@@ -182,13 +182,13 @@ There are no suffixes for the integer literal types.
|
||||
|
||||
Carbon supports **decimal and hexadecimal** floating-point literals. Example:
|
||||
|
||||
1. Decimal:
|
||||
1. Decimal:
|
||||
|
||||
- `123.456`
|
||||
- `1.23456e791`
|
||||
- `123.456`
|
||||
- `1.23456e791`
|
||||
|
||||
2. Hexadecimal:
|
||||
- `0x1.Ap123`
|
||||
2. Hexadecimal:
|
||||
- `0x1.Ap123`
|
||||
|
||||
#### Literal types
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Object-like macros](#object-like-macros)
|
||||
- [Function-like macros](#function-like-macros)
|
||||
- [Predefined macros](#predefined-macros)
|
||||
- [Swift / C interop [GitHub][documentation]](#swift--c-interop-githubdocumentation)
|
||||
- [Swift / C interop](#swift--c-interop)
|
||||
- [Proposal](#proposal)
|
||||
- [Details](#details)
|
||||
- [Namespace](#namespace)
|
||||
@@ -111,7 +111,11 @@ In function-like macros, the operators `#` and `##` enable:
|
||||
There are also predefined macros available in every translation unit. Examples
|
||||
include: `__cplusplus`, `__FILE__`, `__LINE__`, `__DATE__`, `__TIME__` etc.
|
||||
|
||||
### Swift / C interop [[GitHub](https://github.com/swiftlang/swift/blob/main/lib/ClangImporter/ImportMacro.cpp)][[documentation](https://developer.apple.com/documentation/swift/using-imported-c-macros-in-swift)]
|
||||
### Swift / C interop
|
||||
|
||||
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).
|
||||
|
||||
Swift supports importing object-like C macros as global constants. Macros that
|
||||
use integer, floating-point and string literals are supported. Also simple
|
||||
@@ -227,14 +231,14 @@ 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
|
||||
evaluating the result.
|
||||
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
|
||||
evaluating the result.
|
||||
|
||||
For example, given a macro:
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@ Alternatives were discussed in
|
||||
|
||||
The comment notes that three options were proposed:
|
||||
|
||||
1. `char` is fully aligned with C++.
|
||||
1. `char` is fully aligned with C++.
|
||||
|
||||
There is no universal convention for what the value in a `char` means, and
|
||||
the numerical encoding of Unicode characters into `char` sequences might
|
||||
@@ -324,8 +324,8 @@ The comment notes that three options were proposed:
|
||||
`char`. It might also be reasonable to use an array of `char` for things
|
||||
that aren't necessarily text, such as file contents.
|
||||
|
||||
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.
|
||||
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)
|
||||
@@ -335,8 +335,8 @@ The comment notes that three options were proposed:
|
||||
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".
|
||||
3. Use a foundation that enforces Unicode string validity, for some definition
|
||||
of "Unicode string validity".
|
||||
|
||||
The `char` type is a Unicode character. Strings would notionally be a
|
||||
sequence of Unicode characters, possibly also maintaining some higher-level
|
||||
|
||||
@@ -23,7 +23,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
- [Considering a facet type of a named constraint to be identified in its definition](#considering-a-facet-type-of-a-named-constraint-to-be-identified-in-its-definition)
|
||||
- [Restricting to `Self`](#restricting-to-self)
|
||||
- [Allowing limited conversions to partially identified facet types.](#allowing-limited-conversions-to-partially-identified-facet-types)
|
||||
- [Allowing limited conversions to partially identified facet types](#allowing-limited-conversions-to-partially-identified-facet-types)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
@@ -240,7 +240,7 @@ partially identified facet type. But by differentiating the the partially
|
||||
identified state from identified, we can form the rules around the state of the
|
||||
facet type instead of the identity of the facet.
|
||||
|
||||
### Allowing limited conversions to partially identified facet types.
|
||||
### Allowing limited conversions to partially identified facet types
|
||||
|
||||
We considered allowing conversions from `N & J` to `N & K` where `N` is
|
||||
partially identified, and `J` and `K` are identified.
|
||||
|
||||
@@ -242,18 +242,18 @@ parameters of any kind, implicit or explicit.
|
||||
1. We could place `self` in an independent position with a different set of
|
||||
delimiters such as:
|
||||
|
||||
```carbon
|
||||
class Point {
|
||||
var x: i32;
|
||||
var y: i32;
|
||||
```carbon
|
||||
class Point {
|
||||
var x: i32;
|
||||
var y: i32;
|
||||
|
||||
// `self` as a separate component, likely in between the implicit and
|
||||
// explicit parameter lists.
|
||||
fn Create[T:! type]<self>(x: T) -> Self {
|
||||
return {.x = x as i32, .y = 0};
|
||||
}
|
||||
}
|
||||
```
|
||||
// `self` as a separate component, likely in between the implicit and
|
||||
// explicit parameter lists.
|
||||
fn Create[T:! type]<self>(x: T) -> Self {
|
||||
return {.x = x as i32, .y = 0};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. We could make `self` implicit, similar to C++.
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ interface Z {}
|
||||
|
||||
There are three cases allowed by the new rule:
|
||||
|
||||
1. An anchor name is introduced by the scope containing the `impl` declaration.
|
||||
1. An anchor name is introduced by the scope containing the `impl` declaration.
|
||||
|
||||
```carbon
|
||||
fn F() {
|
||||
@@ -176,7 +176,7 @@ Here the `Self` is resolved to `C`, and `C` is being introduced by the scope
|
||||
containing the `impl` declaration. If `C` is generic, any use of the impl will
|
||||
require naming a specific `C`.
|
||||
|
||||
2. A name is introduced in the same scope as the `impl` declaration.
|
||||
2. A name is introduced in the same scope as the `impl` declaration.
|
||||
|
||||
```carbon
|
||||
fn F() {
|
||||
@@ -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() {
|
||||
@@ -214,8 +214,8 @@ bindings used by the `impl` declaration.
|
||||
|
||||
This rule forbids the following:
|
||||
|
||||
1. An `impl` declaration where all names are declared outside the scope
|
||||
containing the `impl`.
|
||||
1. An `impl` declaration where all names are declared outside the scope
|
||||
containing the `impl`.
|
||||
|
||||
```carbon
|
||||
class A {}
|
||||
@@ -250,8 +250,8 @@ fn G() {
|
||||
}
|
||||
```
|
||||
|
||||
2. An `impl` declaration where all names have their owning declaration in a
|
||||
different file than the `impl`.
|
||||
2. An `impl` declaration where all names have their owning declaration in a
|
||||
different file than the `impl`.
|
||||
|
||||
```carbon
|
||||
// Library api file.
|
||||
|
||||
@@ -27,14 +27,14 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
> TIP: Run `./new_proposal.py "TITLE"` to do new proposal setup.
|
||||
|
||||
1. Copy this template to `new.md`, and create a commit.
|
||||
2. Create a GitHub pull request, to get a pull request number.
|
||||
- Add the `proposal draft` label to the pull request.
|
||||
3. Rename `new.md` to `/proposals/p####.md`, where `####` should be the pull
|
||||
request number.
|
||||
4. Update the title of the proposal (the `TODO` on line 1).
|
||||
5. Update the link to the pull request (the `####` on line 11).
|
||||
6. Delete this section.
|
||||
1. Copy this template to `new.md`, and create a commit.
|
||||
2. Create a GitHub pull request, to get a pull request number.
|
||||
- Add the `proposal draft` label to the pull request.
|
||||
3. Rename `new.md` to `/proposals/p####.md`, where `####` should be the pull
|
||||
request number.
|
||||
4. Update the title of the proposal (the `TODO` on line 1).
|
||||
5. Update the link to the pull request (the `####` on line 11).
|
||||
6. Delete this section.
|
||||
|
||||
TODOs indicate where content should be updated for a proposal. See
|
||||
[Carbon Governance and Evolution](/docs/project/evolution.md) for more details.
|
||||
|
||||
@@ -84,6 +84,9 @@ they have an associated error. An exception is that the main test file may omit
|
||||
|
||||
## Content replacement
|
||||
|
||||
<!-- TODO: Re-enable once rumdl's bugs with complex nested lists are fixed. -->
|
||||
<!-- rumdl-disable -->
|
||||
|
||||
Some keywords can be inserted for content:
|
||||
|
||||
- ```
|
||||
@@ -289,6 +292,8 @@ Supported comment markers are:
|
||||
run the test directly. Tips have no impact on validation; the marker informs
|
||||
autoupdate that it can update or remove them as needed.
|
||||
|
||||
<!-- rumdl-enable -->
|
||||
|
||||
<!--
|
||||
{% endraw %}
|
||||
-->
|
||||
|
||||
+11
-11
@@ -43,17 +43,17 @@ The main components are:
|
||||
- [Diagnostics](diagnostics.md): Produces diagnostic output.
|
||||
- Compilation flow:
|
||||
|
||||
1. Source: Load the file into a
|
||||
[SourceBuffer](/toolchain/source/source_buffer.h).
|
||||
2. [Lex](lex.md): Transform a SourceBuffer into a
|
||||
[Lex::TokenizedBuffer](/toolchain/lex/tokenized_buffer.h).
|
||||
3. [Parse](parse.md): Transform a TokenizedBuffer into a
|
||||
[Parse::Tree](/toolchain/parse/tree.h).
|
||||
4. [Check](check): Transform a Tree to produce
|
||||
[SemIR::File](/toolchain/sem_ir/file.h).
|
||||
5. [Lower](lower.md): Transform the SemIR to an
|
||||
[LLVM Module](https://llvm.org/doxygen/classllvm_1_1Module.html).
|
||||
6. CodeGen: Transform the LLVM Module into an Object File.
|
||||
1. Source: Load the file into a
|
||||
[SourceBuffer](/toolchain/source/source_buffer.h).
|
||||
2. [Lex](lex.md): Transform a SourceBuffer into a
|
||||
[Lex::TokenizedBuffer](/toolchain/lex/tokenized_buffer.h).
|
||||
3. [Parse](parse.md): Transform a TokenizedBuffer into a
|
||||
[Parse::Tree](/toolchain/parse/tree.h).
|
||||
4. [Check](check): Transform a Tree to produce
|
||||
[SemIR::File](/toolchain/sem_ir/file.h).
|
||||
5. [Lower](lower.md): Transform the SemIR to an
|
||||
[LLVM Module](https://llvm.org/doxygen/classllvm_1_1Module.html).
|
||||
6. CodeGen: Transform the LLVM Module into an Object File.
|
||||
|
||||
### Design patterns
|
||||
|
||||
|
||||
@@ -61,9 +61,9 @@ constant declaration handling proceeds as follows:
|
||||
`StartAssociatedConstant` is called at the start of an interface-scope `let`
|
||||
declaration. This:
|
||||
|
||||
- Starts a generic declaration region.
|
||||
- Pushes an instruction block to hold instructions within the declaration
|
||||
of the constant. These form the body of the generic.
|
||||
- Starts a generic declaration region.
|
||||
- Pushes an instruction block to hold instructions within the declaration
|
||||
of the constant. These form the body of the generic.
|
||||
|
||||
2. ```carbon
|
||||
let NAME:! TYPE [= INITIALIZER] ;
|
||||
@@ -91,10 +91,10 @@ constant declaration handling proceeds as follows:
|
||||
either because we reached the `=` or because we reached the `;` and there
|
||||
was no initializer, `EndAssociatedConstantDeclRegion` is called. This:
|
||||
|
||||
- Ends the generic declaration region.
|
||||
- Builds an `AssociatedEntity` object, reserving a slot in the interface's
|
||||
witness table for the constant.
|
||||
- Adds the associated constant to name lookup.
|
||||
- Ends the generic declaration region.
|
||||
- Builds an `AssociatedEntity` object, reserving a slot in the interface's
|
||||
witness table for the constant.
|
||||
- Adds the associated constant to name lookup.
|
||||
|
||||
_Note:_ The pattern might not be valid for an associated constant. In this
|
||||
case, we won't have built an `AssociatedConstantDecl` in the previous step.
|
||||
@@ -116,14 +116,14 @@ constant declaration handling proceeds as follows:
|
||||
At the end of the declaration, `FinishAssociatedConstant` is called to
|
||||
finalize the declaration. This:
|
||||
|
||||
- Diagnoses if the pattern handling didn't create an
|
||||
`AssociatedConstantDecl`.
|
||||
- Finishes handling the initializer, if it's present:
|
||||
- Converts the initializer to the type of the constant.
|
||||
- Ends the generic definition region.
|
||||
- Pops the inst block created by `StartAssociatedConstant` and attaches it
|
||||
to the `AssociatedConstantDecl`.
|
||||
- Adds the `AssociatedConstantDecl` to the enclosing inst block.
|
||||
- Diagnoses if the pattern handling didn't create an
|
||||
`AssociatedConstantDecl`.
|
||||
- Finishes handling the initializer, if it's present:
|
||||
- Converts the initializer to the type of the constant.
|
||||
- Ends the generic definition region.
|
||||
- Pops the inst block created by `StartAssociatedConstant` and attaches it
|
||||
to the `AssociatedConstantDecl`.
|
||||
- Adds the `AssociatedConstantDecl` to the enclosing inst block.
|
||||
|
||||
## Specifying rewrite constraints
|
||||
|
||||
|
||||
@@ -29,13 +29,13 @@ concepts.
|
||||
|
||||
The SemIR for a pattern-matching operation is emitted in three steps:
|
||||
|
||||
1. **Pattern:** Traverse the parse tree of the pattern to emit SemIR that
|
||||
abstractly describes the pattern.
|
||||
2. **Scrutinee:** Traverse the parse tree of the scrutinee expression to emit
|
||||
SemIR that evaluates it.
|
||||
3. **Match:** Traverse the pattern SemIR from step 1 (sometimes in conjunction
|
||||
with the scrutinee SemIR) to emit SemIR that actually performs pattern
|
||||
matching.
|
||||
1. **Pattern:** Traverse the parse tree of the pattern to emit SemIR that
|
||||
abstractly describes the pattern.
|
||||
2. **Scrutinee:** Traverse the parse tree of the scrutinee expression to emit
|
||||
SemIR that evaluates it.
|
||||
3. **Match:** Traverse the pattern SemIR from step 1 (sometimes in conjunction
|
||||
with the scrutinee SemIR) to emit SemIR that actually performs pattern
|
||||
matching.
|
||||
|
||||
## Pattern instructions
|
||||
|
||||
@@ -98,10 +98,12 @@ Currently this happens in two cases, which are handled using two maps in
|
||||
instruction IDs:
|
||||
|
||||
- A name binding can be used within the same pattern that declares it:
|
||||
|
||||
```carbon
|
||||
match (x) {
|
||||
case (n: i32, n) => ...
|
||||
```
|
||||
|
||||
For this to work, the name `n` needs to be added to the scope as soon as we
|
||||
handle its declaration, and it needs to resolve to the `ValueBinding`
|
||||
instruction that binds a value to that name. This means that the
|
||||
|
||||
@@ -96,10 +96,10 @@ 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.
|
||||
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.
|
||||
|
||||
Two specific functions are equivalent if their `specific_fingerprint`s are equal
|
||||
and are not equivalent if their `common_fingerprint`s differs. If the
|
||||
|
||||
+10
-10
@@ -109,11 +109,11 @@ support for debugging the toolchain tests. To set that up:
|
||||
|
||||
A typical debug session looks like:
|
||||
|
||||
1. `bazel build -c dbg //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.
|
||||
4. Select and run the `file_test (lldb)` configuration.
|
||||
1. `bazel build -c dbg //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.
|
||||
4. Select and run the `file_test (lldb)` configuration.
|
||||
|
||||
For debugging on MacOS using VSCode, some people have had success using the
|
||||
CodeLLDB extension. In order for LLDB to connect the project source files with
|
||||
@@ -176,11 +176,11 @@ 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`
|
||||
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.
|
||||
4. Select and run the `file_test (gdb)` configuration.
|
||||
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.
|
||||
4. Select and run the `file_test (gdb)` configuration.
|
||||
|
||||
## Toolchain-specific debugging techniques
|
||||
|
||||
|
||||
@@ -250,7 +250,6 @@ supported in `Check` diagnostics are:
|
||||
|
||||
- `InstIdAsRawType`
|
||||
- `TypeIdAsRawType`
|
||||
|
||||
- For integer constants, `TypedInt` can be used to format an `APInt` given its
|
||||
type. The type is used to determine the signedness to use for the value.
|
||||
|
||||
|
||||
@@ -100,8 +100,8 @@ fn foo() -> f64 {
|
||||
|
||||
The node order is (with indentation to indicate nesting):
|
||||
|
||||
<!-- Prevent prettier from changing indents. -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- Prevent changing indents. -->
|
||||
<!-- rumdl-disable -->
|
||||
|
||||
```yaml
|
||||
[
|
||||
@@ -121,7 +121,7 @@ The node order is (with indentation to indicate nesting):
|
||||
]
|
||||
```
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
<!-- rumdl-enable -->
|
||||
|
||||
In this example, `FileStart`, `FunctionDefinition`, and `FileEnd` are "root"
|
||||
nodes for the tree. Function components are children of `FunctionDefinition`.
|
||||
@@ -175,6 +175,7 @@ var x: i32 = y + 1;
|
||||
Lexing creates distinct tokens for each syntactic element, which will form the
|
||||
basis of the parse tree:
|
||||
|
||||
<!-- rumdl-disable -->
|
||||
<pre>
|
||||
<b>Tokens:</b>
|
||||
|
||||
@@ -371,6 +372,7 @@ respect to the depth of the parse tree.
|
||||
| var | | x | | i32 | | : | | = | | y | | 1 | | + | | ; |
|
||||
+-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
|
||||
</pre>
|
||||
<!-- rumdl-enable -->
|
||||
|
||||
The structural concepts of bracketing nodes (`var` and `;`) and parent nodes
|
||||
with a known child count (`:` and `+` with 2 children, but also `=` with 0
|
||||
|
||||
@@ -11,8 +11,8 @@ Treesitter based syntax highlighting and language server client for Neovim.
|
||||
This requires neovim >= 0.9 and
|
||||
[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) to be installed.
|
||||
|
||||
1. Run `bazel build //toolchain` in project root.
|
||||
2. Run `utils/nvim/setup.sh`.
|
||||
3. Start nvim in carbon-lang root folder and open a carbon file.
|
||||
4. View document symbols. If you have telescope.nvim installed, you can use
|
||||
`:Telescope lsp_document_symbols`
|
||||
1. Run `bazel build //toolchain` in project root.
|
||||
2. Run `utils/nvim/setup.sh`.
|
||||
3. Start nvim in carbon-lang root folder and open a carbon file.
|
||||
4. View document symbols. If you have telescope.nvim installed, you can use
|
||||
`:Telescope lsp_document_symbols`
|
||||
|
||||
@@ -42,11 +42,11 @@ bazel test //utils/tree_sitter:string_tests \
|
||||
|
||||
### Helix
|
||||
|
||||
1. Install
|
||||
[tree-sitter](https://tree-sitter.github.io/tree-sitter/creating-parsers#installation)
|
||||
and Nodejs.
|
||||
2. Install [Helix](https://docs.helix-editor.com/install.html).
|
||||
3. Run `./helix.sh`
|
||||
1. Install
|
||||
[tree-sitter](https://tree-sitter.github.io/tree-sitter/creating-parsers#installation)
|
||||
and Nodejs.
|
||||
2. Install [Helix](https://docs.helix-editor.com/install.html).
|
||||
3. Run `./helix.sh`
|
||||
|
||||
### Emacs
|
||||
|
||||
|
||||
@@ -13,14 +13,14 @@ This extension is currently experimental, and being developed alongside Carbon.
|
||||
|
||||
## Quickstart
|
||||
|
||||
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.
|
||||
2. Install the
|
||||
[Carbon Language extension](https://marketplace.visualstudio.com/items?itemName=carbon-lang.carbon-vscode).
|
||||
3. Configure the installed path to `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.
|
||||
2. Install the
|
||||
[Carbon Language extension](https://marketplace.visualstudio.com/items?itemName=carbon-lang.carbon-vscode).
|
||||
3. Configure the installed path to `carbon`.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
+19
-19
@@ -36,28 +36,28 @@ This installs `vsce` and `ovsx` to `/usr/local/bin`. Ensure that
|
||||
|
||||
- Using the UI:
|
||||
|
||||
1. `npm install && vsce package -o carbon.vsix && realpath carbon.vsix`
|
||||
- This installs dependencies, builds the VSIX file, and prints the
|
||||
path.
|
||||
2. Open the
|
||||
[command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette)
|
||||
and select "Extensions: Install from VSIX...".
|
||||
3. Enter the path printed by the above command.
|
||||
1. `npm install && vsce package -o carbon.vsix && realpath carbon.vsix`
|
||||
- This installs dependencies, builds the VSIX file, and prints the
|
||||
path.
|
||||
2. Open the
|
||||
[command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette)
|
||||
and select "Extensions: Install from VSIX...".
|
||||
3. Enter the path printed by the above command.
|
||||
|
||||
- Publish a new release:
|
||||
|
||||
1. Increase the version number in `package.json`.
|
||||
2. Build and publish to the VSCode Marketplace using the website:
|
||||
1. `npm install && vsce package -o carbon.vsix && realpath carbon.vsix`
|
||||
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.
|
||||
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
|
||||
[Open VSX documentation for publishing extensions](https://github.com/EclipseFdn/open-vsx.org/wiki/Publishing-Extensions).
|
||||
1. Increase the version number in `package.json`.
|
||||
2. Build and publish to the VSCode Marketplace using the website:
|
||||
1. `npm install && vsce package -o carbon.vsix && realpath carbon.vsix`
|
||||
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.
|
||||
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
|
||||
[Open VSX documentation for publishing extensions](https://github.com/EclipseFdn/open-vsx.org/wiki/Publishing-Extensions).
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ title: 404
|
||||
nav_exclude: true
|
||||
---
|
||||
|
||||
# 404: File not found
|
||||
## 404: File not found
|
||||
|
||||
<!--
|
||||
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
|
||||
Reference in New Issue
Block a user