mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:20:10 +01:00
Compare commits
305
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
733b76efea | ||
|
|
69d745c6d7 | ||
|
|
d6a741f208 | ||
|
|
1e3906177c | ||
|
|
5e2f693db1 | ||
|
|
1cc699ddda | ||
|
|
ad0a4ea8a4 | ||
|
|
f91990aa87 | ||
|
|
e7626f46cc | ||
|
|
af04d08965 | ||
|
|
a6061d975c | ||
|
|
896338d281 | ||
|
|
d8fe95cccb | ||
|
|
df33276f6b | ||
|
|
327cb2396a | ||
|
|
1d5113649b | ||
|
|
cdfa57f230 | ||
|
|
46f46a538d | ||
|
|
114cf401c2 | ||
|
|
7c94878c10 | ||
|
|
82fad29028 | ||
|
|
26ddada3ae | ||
|
|
bab35c114e | ||
|
|
96529e16bd | ||
|
|
43867a678b | ||
|
|
5b1de7633c | ||
|
|
f31e1685fd | ||
|
|
3cdb159067 | ||
|
|
12d7574636 | ||
|
|
cc5a42691e | ||
|
|
19efec93be | ||
|
|
3db691ecef | ||
|
|
6cc08ae6e6 | ||
|
|
ab977ee04d | ||
|
|
be0c07dc7e | ||
|
|
b79d9adeca | ||
|
|
b74e0d1260 | ||
|
|
9f1a0c816c | ||
|
|
6f02354d62 | ||
|
|
0635f4628f | ||
|
|
d1dc8e820d | ||
|
|
e1f30669af | ||
|
|
f483a28f2f | ||
|
|
cc4fd39238 | ||
|
|
013a417ea5 | ||
|
|
8fd4156616 | ||
|
|
05ba1d7356 | ||
|
|
8e0d856725 | ||
|
|
ea409f7cbf | ||
|
|
fed9e8c878 | ||
|
|
451b50a3ad | ||
|
|
912825feaf | ||
|
|
81ed4d829d | ||
|
|
9266ced4e3 | ||
|
|
1fa7a64cd4 | ||
|
|
562b423830 | ||
|
|
6f0ec37a8b | ||
|
|
0851d657c8 | ||
|
|
07afa07127 | ||
|
|
f7a767a77b | ||
|
|
be283a0744 | ||
|
|
cd6ab7ce8e | ||
|
|
0075d530b9 | ||
|
|
5b7c908e8b | ||
|
|
2bbcfa5e1a | ||
|
|
dfac728571 | ||
|
|
8f3b057179 | ||
|
|
17180558e5 | ||
|
|
39eac6f277 | ||
|
|
2787089247 | ||
|
|
3578dd6b91 | ||
|
|
8b59e85b16 | ||
|
|
47e9d62fd5 | ||
|
|
f4260feee4 | ||
|
|
aec2534e9d | ||
|
|
2e0d9dc709 | ||
|
|
396756c151 | ||
|
|
bf6a14ac39 | ||
|
|
9ed045ec25 | ||
|
|
2318294eb5 | ||
|
|
d9b901394b | ||
|
|
181a592b8c | ||
|
|
1ef35e8299 | ||
|
|
aa8e96ac72 | ||
|
|
5503f643c6 | ||
|
|
899e54de36 | ||
|
|
a2ba7f1262 | ||
|
|
2b1fe7c292 | ||
|
|
a0416a1250 | ||
|
|
c68c4007ab | ||
|
|
1f7d8e4675 | ||
|
|
557039648b | ||
|
|
786e02cb3e | ||
|
|
262e24a2a0 | ||
|
|
18f87e4f79 | ||
|
|
85da6cae01 | ||
|
|
d6be20641c | ||
|
|
4a0c1ddd8e | ||
|
|
5ae3629e49 | ||
|
|
25b85a55ae | ||
|
|
15dabbfb0d | ||
|
|
25793358c3 | ||
|
|
37b238fa28 | ||
|
|
311670c84a | ||
|
|
965879a9a9 | ||
|
|
415cd6f8f0 | ||
|
|
7345f4e860 | ||
|
|
29a8b315d3 | ||
|
|
e0305684b0 | ||
|
|
2af5f971da | ||
|
|
f9e1806c4a | ||
|
|
e0c6800ab3 | ||
|
|
a345a74145 | ||
|
|
86d05b598b | ||
|
|
7b6e3dfbb0 | ||
|
|
17657d0586 | ||
|
|
3ef991466d | ||
|
|
44f2a68ee0 | ||
|
|
81215e873e | ||
|
|
bc38deb16c | ||
|
|
6d2387cb77 | ||
|
|
000b4f3fa5 | ||
|
|
e06eb8f532 | ||
|
|
8e824d02be | ||
|
|
8e5b358ec2 | ||
|
|
ce50f181f1 | ||
|
|
fd2d210c63 | ||
|
|
08148f3a3a | ||
|
|
10beae2c20 | ||
|
|
6d1130f657 | ||
|
|
14b72f16da | ||
|
|
7b3f120f97 | ||
|
|
0482b27c6b | ||
|
|
98e2567524 | ||
|
|
d47b6221ae | ||
|
|
87fc05750b | ||
|
|
2e32f309eb | ||
|
|
1d71e7a707 | ||
|
|
613a139bef | ||
|
|
c5761d2d16 | ||
|
|
943cd41924 | ||
|
|
c006013e0c | ||
|
|
aeed8f608b | ||
|
|
8b907b5a60 | ||
|
|
6f1f59a385 | ||
|
|
27cc14848a | ||
|
|
fbe917b949 | ||
|
|
bad9beddc7 | ||
|
|
6706162582 | ||
|
|
ffe8f8f67d | ||
|
|
5d1973ab93 | ||
|
|
610094ccfd | ||
|
|
4df2b6ea9d | ||
|
|
1e9708e2cc | ||
|
|
4c69a1baf0 | ||
|
|
c1fd771242 | ||
|
|
5d41529590 | ||
|
|
0a4fd2cb7e | ||
|
|
2e5b195813 | ||
|
|
6ac561afe9 | ||
|
|
70c401f85f | ||
|
|
39fd358059 | ||
|
|
ba6257891e | ||
|
|
6304df1db9 | ||
|
|
99bde2acb3 | ||
|
|
9e2d0a887f | ||
|
|
c297344937 | ||
|
|
18cfeb7476 | ||
|
|
5ad9b1a35d | ||
|
|
a1b6f1c4bd | ||
|
|
3e3a97593d | ||
|
|
4b076291c9 | ||
|
|
bee2633946 | ||
|
|
1a47c02e5d | ||
|
|
8a4888c3df | ||
|
|
744b1290cf | ||
|
|
6b2d55d289 | ||
|
|
cdcd3ab66c | ||
|
|
0dac40e793 | ||
|
|
f27f8838d0 | ||
|
|
6786edd6ff | ||
|
|
53c257d2e2 | ||
|
|
2e155567bd | ||
|
|
53729325a0 | ||
|
|
21291b4cc3 | ||
|
|
2327b62b5f | ||
|
|
97af347490 | ||
|
|
1257ef2fd0 | ||
|
|
c837c004bc | ||
|
|
6a650941d2 | ||
|
|
bf6f21b8e9 | ||
|
|
a9f1e17ecb | ||
|
|
e5957037fb | ||
|
|
002b7c74ea | ||
|
|
4d0003765d | ||
|
|
b28e899a8c | ||
|
|
1c7a4030ab | ||
|
|
15680ba101 | ||
|
|
6dba8ee111 | ||
|
|
9ff6b0a682 | ||
|
|
069c6f4447 | ||
|
|
6359e3f550 | ||
|
|
b14015602b | ||
|
|
2389590230 | ||
|
|
ef0bb898ac | ||
|
|
067378ba37 | ||
|
|
34764d0d0e | ||
|
|
3b49b51956 | ||
|
|
93faac45af | ||
|
|
cea52ad2d8 | ||
|
|
d5ec82e7ac | ||
|
|
a6a0e55167 | ||
|
|
41dd256d56 | ||
|
|
be88dfd744 | ||
|
|
b83dcd4348 | ||
|
|
bf9219d30e | ||
|
|
f9ab963bd6 | ||
|
|
96f163f114 | ||
|
|
d11ee4b2b1 | ||
|
|
34651f429f | ||
|
|
980ab7fab3 | ||
|
|
17897bb05d | ||
|
|
d9570b4d37 | ||
|
|
3163af2563 | ||
|
|
3df256cfa9 | ||
|
|
c5931a036d | ||
|
|
c6bc033af8 | ||
|
|
af368dbadd | ||
|
|
157de6e370 | ||
|
|
142596b49c | ||
|
|
fbc8d59d32 | ||
|
|
e2bdbe8507 | ||
|
|
c46cd65bd0 | ||
|
|
f210f4ab04 | ||
|
|
1a3f762dba | ||
|
|
8edd5eb9a1 | ||
|
|
9915e155a3 | ||
|
|
4a0cf6c1fb | ||
|
|
375a736c42 | ||
|
|
393e6e4f9a | ||
|
|
41f47c0e87 | ||
|
|
c3eb393c6a | ||
|
|
fdb188ccfd | ||
|
|
bea24a8bee | ||
|
|
e991657e1d | ||
|
|
6a3529f4b5 | ||
|
|
e00394ea92 | ||
|
|
46fb941b3c | ||
|
|
917a6ea971 | ||
|
|
e5b094fdad | ||
|
|
a5a4c756a7 | ||
|
|
82e4c3a8af | ||
|
|
108277c3f3 | ||
|
|
768582d8d3 | ||
|
|
de3147ce3e | ||
|
|
2cee87683e | ||
|
|
6df9d5ba32 | ||
|
|
8a8dd01302 | ||
|
|
f21e0e17ac | ||
|
|
f1b6e818d1 | ||
|
|
1aa1a2a373 | ||
|
|
0300d35cf6 | ||
|
|
773837e1bb | ||
|
|
f289592dfa | ||
|
|
64e3fab43a | ||
|
|
b3d57aff7a | ||
|
|
3c324e4877 | ||
|
|
611aba3cc2 | ||
|
|
1c885a629e | ||
|
|
9a90f19c60 | ||
|
|
74969cab04 | ||
|
|
2184663511 | ||
|
|
b267ec85cf | ||
|
|
7f29436d4e | ||
|
|
d39fdfcfad | ||
|
|
3719d200d6 | ||
|
|
320096da67 | ||
|
|
e2f451dc9c | ||
|
|
8b967943d3 | ||
|
|
628b6c8a73 | ||
|
|
45b3f47349 | ||
|
|
13d5fe9eed | ||
|
|
1b2ae912fc | ||
|
|
2d5e5e9692 | ||
|
|
09b9746251 | ||
|
|
f292972816 | ||
|
|
2c6d9c7f66 | ||
|
|
a465018fec | ||
|
|
7938d9a8d0 | ||
|
|
1382a8645a | ||
|
|
70614da67e | ||
|
|
c7a7688d21 | ||
|
|
68182ba37b | ||
|
|
1d0bf72508 | ||
|
|
f0e04c89c3 | ||
|
|
7d97389642 | ||
|
|
8efb4aa989 | ||
|
|
45e4c71703 | ||
|
|
c860c178d4 | ||
|
|
f63d0a6266 | ||
|
|
45ca3d28f5 | ||
|
|
e5b05a1fac | ||
|
|
2980e6bcbb | ||
|
|
917ce5bd6b | ||
|
|
fb05ed2447 |
@@ -0,0 +1,83 @@
|
||||
---
|
||||
name: Bazel usage
|
||||
description:
|
||||
Instructions for using Bazel or Bazelisk to build, test, and debug in the
|
||||
Carbon repository.
|
||||
---
|
||||
|
||||
# Bazel usage
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
This skill documents how best to use Bazel when building, testing, or
|
||||
manipulating the Carbon repository's Bazel in any way.
|
||||
|
||||
## Bazel wrappers
|
||||
|
||||
Carbon uses Bazel for its build system. To ensure consistent versions, the
|
||||
project uses Bazelisk.
|
||||
|
||||
> [!IMPORTANT] Always use `bazelisk` whenever you want to run Bazel. Never run
|
||||
> `bazel` directly in the Carbon project. Anything you want to do with `bazel`
|
||||
> can be done with the `bazelisk` command instead.
|
||||
|
||||
- **Bazelisk**: Try to use `bazelisk` in your existing `$PATH` if available.
|
||||
- **`run_bazelisk.py`**: If `bazelisk` isn't available, use
|
||||
`./scripts/run_bazelisk.py` to run bazelisk without it being installed.
|
||||
|
||||
## Essential commands
|
||||
|
||||
### Building
|
||||
|
||||
- **Build all**: `bazelisk build //...`
|
||||
- **Build toolchain**: `bazelisk build //toolchain/...`
|
||||
- **Build specific target**: `bazelisk build //toolchain:carbon`
|
||||
|
||||
### Testing
|
||||
|
||||
- **Test all**: `bazelisk test //...:all`
|
||||
- **Test toolchain**: `bazelisk test //toolchain/...`
|
||||
- **Test examples**: `bazelisk test //examples/...`
|
||||
|
||||
> [!TIP] Running all of the tests can be slow, so try to narrowly test the
|
||||
> immediately relevant parts of the project first, and only expand coverage as
|
||||
> necessary to be confident in the changes.
|
||||
|
||||
> [!TIP] For specialized instructions on testing and developing the Carbon
|
||||
> toolchain, consult these skills:
|
||||
>
|
||||
> - [Toolchain tests](/.agents/skills/toolchain_tests/SKILL.md): For
|
||||
> authoring, structuring, and running `file_test` tests.
|
||||
> - [Toolchain development](/.agents/skills/toolchain_development/SKILL.md):
|
||||
> For architecture, essential commands, and debugging the toolchain.
|
||||
|
||||
### Running binaries built by Bazel
|
||||
|
||||
> [!IMPORTANT] Always manually run binaries built by Bazel using the
|
||||
> `bazelisk run` command. Never run the binary directly from `bazel-bin/`.
|
||||
|
||||
You can run the Carbon driver or command line directly via Bazel:
|
||||
|
||||
- `bazelisk run //toolchain -- compile --phase=parse toolchain/parse/testdata/basics/empty.carbon`
|
||||
|
||||
## Advanced configurations
|
||||
|
||||
### AddressSanitizer (ASan)
|
||||
|
||||
To enable ASan for local testing:
|
||||
|
||||
- Pass `--config=asan`: `bazelisk test --config=asan //...`
|
||||
|
||||
## Common pitfalls and troubleshooting
|
||||
|
||||
### `bazel clean`
|
||||
|
||||
Changes to packages installed on your system (like changing LLVM versions or
|
||||
installing `libc++`) may not be noticed by Bazel.
|
||||
|
||||
- Run `bazelisk clean` to force cached state to be rebuilt when environment
|
||||
changes occur.
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
name: Code style
|
||||
description:
|
||||
Instructions for code formatting and style guidelines in the Carbon
|
||||
toolchain.
|
||||
---
|
||||
|
||||
# Code style
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
## License
|
||||
|
||||
- **Licenses**: All Carbon files outside of `third_party/` should have a
|
||||
license following
|
||||
[CONTRIBUTING license instructions](/CONTRIBUTING.md#license).
|
||||
|
||||
## Formatting
|
||||
|
||||
- **Bazel**: Use `pre-commit run buildifier --files <file.bzl>` to format
|
||||
Bazel files.
|
||||
- **C++**: Use `pre-commit run clang-format --files <file.cpp>` to format C++
|
||||
files.
|
||||
- **Carbon**: The toolchain's `format` command doesn't work well right now.
|
||||
Instead, try to format Carbon code based on other Carbon files and the C++
|
||||
style.
|
||||
- **Markdown**: Use `pre-commit run prettier --files <file.md>` to format
|
||||
markdown files.
|
||||
- **Python**: Use `pre-commit run black --files <file.py>` to format Python
|
||||
files.
|
||||
|
||||
## Style Guides
|
||||
|
||||
- **C++ style**: Follow the
|
||||
[Carbon C++ Project Style Guide](/docs/project/cpp_style_guide.md).
|
||||
- **Markdown style**: Follow the
|
||||
[Google developer documentation style guide](https://developers.google.com/style).
|
||||
- **Python style**: Follow the [PEP 8](https://peps.python.org/pep-0008/)
|
||||
style guide.
|
||||
- Wrap code and comments to 80 columns.
|
||||
- Run `pre-commit run flake8 --files <file.py>` to check Python style.
|
||||
@@ -0,0 +1,171 @@
|
||||
---
|
||||
name: GitHub CLI usage
|
||||
description:
|
||||
Instructions for using the `gh` command to query and inspect GitHub state
|
||||
safely.
|
||||
---
|
||||
|
||||
# GitHub CLI usage
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
This skill provides instructions for using the GitHub CLI (`gh`) to query,
|
||||
inspect, and search GitHub state (issues, pull requests, repositories) for the
|
||||
Carbon project.
|
||||
|
||||
## Safety First: Read-Only Usage
|
||||
|
||||
> [!IMPORTANT] AI assistants MUST NOT use the `gh` tool to modify any GitHub
|
||||
> project state. Do NOT run commands that create, edit, delete, label, comment
|
||||
> on, or merge issues, pull requests, releases, or any other resources.
|
||||
|
||||
### Allowed Verbs
|
||||
|
||||
- `list`
|
||||
- `view`
|
||||
- `search`
|
||||
- `status`
|
||||
- `api` (Only with `GET` requests)
|
||||
|
||||
### Prohibited Verbs
|
||||
|
||||
- `create`
|
||||
- `edit`
|
||||
- `delete`
|
||||
- `merge`
|
||||
- `reopen`
|
||||
- `close`
|
||||
- `comment`
|
||||
- `label`
|
||||
|
||||
## Repository Configuration
|
||||
|
||||
The `gh` tool interacts with a default repository when run within a local check
|
||||
out. For this project, the default repository is expected to be
|
||||
`carbon-language/carbon-lang`.
|
||||
|
||||
### Verifying Default Repository
|
||||
|
||||
To verify the current default repository configuration:
|
||||
|
||||
```bash
|
||||
gh repo view
|
||||
```
|
||||
|
||||
The output should indicate the repository is `carbon-language/carbon-lang`.
|
||||
|
||||
### Correcting Misconfigurations
|
||||
|
||||
If the default repository is misconfigured (for example, pointing to a personal
|
||||
fork or a different repository), the human operator must correct it.
|
||||
|
||||
> [!IMPORTANT] AI Assistants MUST NOT attempt to mutate `gh` configuration or
|
||||
> run commands that change the default repository (such as
|
||||
> `gh repository set-default`).
|
||||
|
||||
Instruct the human operator to run the following command to select the correct
|
||||
default repository:
|
||||
|
||||
```bash
|
||||
gh repo set-default
|
||||
```
|
||||
|
||||
The operator will be prompted to select the correct repository (e.g.,
|
||||
`carbon-language/carbon-lang`) from the available remotes.
|
||||
|
||||
## Common Query Commands
|
||||
|
||||
### Issues
|
||||
|
||||
- **List issues**: `gh issue list`
|
||||
- **View specific issue**: `gh issue view <number>`
|
||||
- **Search issues**: `gh issue search "<query>"`
|
||||
- Example: `gh issue search "crash" --state open`
|
||||
|
||||
### Pull Requests
|
||||
|
||||
- **List PRs**: `gh pr list`
|
||||
- **View specific PR**: `gh pr view <number>`
|
||||
- **View PR diff**: `gh pr diff <number>`
|
||||
- **Check PR status**: `gh pr status`
|
||||
|
||||
### Search
|
||||
|
||||
- **Search code**: `gh search code "<query>"`
|
||||
- **Search repositories**: `gh search repos "<query>"`
|
||||
|
||||
## Advanced Usage: GitHub API
|
||||
|
||||
For queries that are not supported by standard `gh` commands, you can use the
|
||||
`gh api` command to query the GitHub REST or GraphQL APIs.
|
||||
|
||||
### REST API
|
||||
|
||||
Query the REST API using paths relative to the API root.
|
||||
|
||||
- **List contributors**:
|
||||
|
||||
```bash
|
||||
gh api repos/carbon-language/carbon-lang/contributors
|
||||
```
|
||||
|
||||
- **List issue comments**:
|
||||
|
||||
```bash
|
||||
gh api repos/carbon-language/carbon-lang/issues/<issue_number>/comments
|
||||
```
|
||||
|
||||
### GraphQL API
|
||||
|
||||
For complex queries, use GraphQL to fetch exactly the data needed.
|
||||
|
||||
- **Get repository information**:
|
||||
|
||||
```bash
|
||||
gh api graphql -f query='
|
||||
query {
|
||||
repository(owner: "carbon-language", name: "carbon-lang") {
|
||||
description
|
||||
stargazerCount
|
||||
}
|
||||
}
|
||||
'
|
||||
```
|
||||
|
||||
### Pagination
|
||||
|
||||
Use the `--paginate` flag to automatically fetch all pages of results.
|
||||
|
||||
```bash
|
||||
gh api --paginate repos/carbon-language/carbon-lang/issues
|
||||
```
|
||||
|
||||
### Filtering and Formatting
|
||||
|
||||
Use `--json` to request JSON output, and `--jq` or `--template` to filter or
|
||||
format the results.
|
||||
|
||||
- **List PR titles and authors**:
|
||||
|
||||
```bash
|
||||
gh pr list --json title,author --jq '.[] | "\(.title) by \(.author.login)"'
|
||||
```
|
||||
|
||||
- **Format with Go templates**:
|
||||
|
||||
```bash
|
||||
gh issue list --template '{{range .}}{{.number}} - {{.title}}{{"\n"}}{{end}}'
|
||||
```
|
||||
|
||||
## Documentation References
|
||||
|
||||
- **GitHub CLI Manual**:
|
||||
[cli.github.com/manual](https://cli.github.com/manual/)
|
||||
- **GitHub REST API Documentation**:
|
||||
[docs.github.com/en/rest](https://docs.github.com/en/rest)
|
||||
- **GitHub GraphQL API Documentation**:
|
||||
[docs.github.com/en/graphql](https://docs.github.com/en/graphql)
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
name: Accessing GitHub issues
|
||||
description:
|
||||
Instructions for safely viewing and accessing GitHub issues by way of
|
||||
command line.
|
||||
---
|
||||
|
||||
# Accessing GitHub issues
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
This skill provides instructions for AI assistants on how to access and view
|
||||
GitHub issues. Agents should strongly prefer using the command line `gh` tool to
|
||||
access and view the contents of issues rather than viewing their contents by way
|
||||
of a web browser.
|
||||
|
||||
## Safety First
|
||||
|
||||
> [!IMPORTANT] AI assistants MUST NOT modify any GitHub issue state. Only use
|
||||
> read-only access commands like `view` or `list`. Do NOT comment, edit, create,
|
||||
> close, or delete issues.
|
||||
|
||||
## Accessing Issues
|
||||
|
||||
Agents must use this skill to access issues regardless of how they are mentioned
|
||||
(for example, by URL or by issue number).
|
||||
|
||||
### Basic View
|
||||
|
||||
To view an issue in the current default repository (expected to be Carbon):
|
||||
|
||||
```bash
|
||||
gh issue view <issue_number>
|
||||
```
|
||||
|
||||
### Including Full Context (All Comments)
|
||||
|
||||
To ensure the view includes the entire context of the issue, always include the
|
||||
`--comments` flag to dump all comments:
|
||||
|
||||
```bash
|
||||
gh issue view <issue_number> --comments
|
||||
```
|
||||
|
||||
> [!TIP] If the issue is extremely large and comments are truncated, or you need
|
||||
> to process comments programmatically, use the JSON output with `jq`:
|
||||
>
|
||||
> ```bash
|
||||
> gh issue view <issue_number> --json comments --jq '.comments[].body'
|
||||
> ```
|
||||
|
||||
### Accessing Issues in Other Repositories
|
||||
|
||||
To view an issue in another repository (for example, LLVM), use the `-R` or
|
||||
`--repo` flag to specify the repository:
|
||||
|
||||
```bash
|
||||
gh issue view <issue_number> -R <owner>/<repo> --comments
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
- **LLVM Issue**:
|
||||
|
||||
```bash
|
||||
gh issue view 5678 -R llvm/llvm-project --comments
|
||||
```
|
||||
|
||||
- **Carbon Issue (Explicit)**:
|
||||
|
||||
```bash
|
||||
gh issue view 1234 -R carbon-language/carbon-lang --comments
|
||||
```
|
||||
|
||||
## Mentions via URL
|
||||
|
||||
If an issue is mentioned via URL, parse the URL to extract the repository owner,
|
||||
repository name, and issue number.
|
||||
|
||||
- **URL pattern**: `https://github.com/<owner>/<repo>/issues/<number>`
|
||||
- **Extraction**:
|
||||
- Host: `github.com`
|
||||
- Owner: `<owner>`
|
||||
- Repo: `<repo>`
|
||||
- Number: `<number>`
|
||||
|
||||
Run the command specifying the repository:
|
||||
|
||||
```bash
|
||||
gh issue view <number> -R <owner>/<repo> --comments
|
||||
```
|
||||
@@ -0,0 +1,203 @@
|
||||
---
|
||||
name: Summarize testdata changes
|
||||
description:
|
||||
Instructions for summarizing changes to Carbon testdata files
|
||||
(`toolchain/*/testdata`).
|
||||
---
|
||||
|
||||
# Summarize testdata changes
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
This skill provides instructions for creating a comprehensive report summarizing
|
||||
changes to Carbon testdata files (`toolchain/*/testdata`) and associating them
|
||||
with related code changes.
|
||||
|
||||
## Goals
|
||||
|
||||
Produce a report that:
|
||||
|
||||
1. Summarizes code changes outside of testdata.
|
||||
2. Groups similar testdata changes together, listing all affected files for
|
||||
each group. **Every change to testdata must be represented by at least one
|
||||
group. This includes changes to CHECK lines.**
|
||||
3. Provides detailed breakdowns of test input changes and diagnostic output
|
||||
changes in the corresponding group. **Every single change to inputs or to
|
||||
STDERR checks must be explicitly mentioned in the group, with either an
|
||||
inline diff or a link to the file.**
|
||||
|
||||
## Process
|
||||
|
||||
### 1. Identify Changes
|
||||
|
||||
Use your VCS (Git or Jujutsu) or query Github to identify changes. For large
|
||||
changes, it is recommended to use the included helper script to extract test
|
||||
input changes.
|
||||
|
||||
#### For Git Users:
|
||||
|
||||
- **Summarize code changes**: `git diff --stat -- ':!toolchain/*/testdata'`
|
||||
- To see content of non-testdata changes:
|
||||
`git diff -- ':!toolchain/*/testdata'`
|
||||
- **Identify testdata changes**: `git diff --name-only 'toolchain/*/testdata'`
|
||||
|
||||
#### For Jujutsu (jj) Users:
|
||||
|
||||
- **Summarize code changes**:
|
||||
`jj --no-pager diff --stat '~toolchain/*/testdata'`
|
||||
- Note: Quoting the fileset `'~toolchain/*/testdata'` is critical if it
|
||||
contains wildcards.
|
||||
- To see content of non-testdata changes, use `--git` to get standard
|
||||
unified diff format: `jj --no-pager diff --git '~toolchain/*/testdata'`
|
||||
- **Identify testdata changes**:
|
||||
`jj --no-pager diff --name-only 'toolchain/*/testdata'`
|
||||
|
||||
#### For Github Pull Requests:
|
||||
|
||||
- **Summarize code changes**: `gh pr diff`
|
||||
- **Identify testdata changes**:
|
||||
`gh pr diff --name-only | grep '^toolchain/.*/testdata'`
|
||||
|
||||
#### Handling Specific Revisions:
|
||||
|
||||
If you are summarizing changes in a specific revision (for example, `@-`) or
|
||||
pull request (for example, #1234), add `-r <rev>` or `<pr_number>` to the
|
||||
commands:
|
||||
|
||||
- `git diff <rev>^ <rev> ...` (or use `git show <rev>`)
|
||||
- `jj --no-pager diff -r <rev> ...`
|
||||
- `gh pr diff <pr_number>`
|
||||
|
||||
### 2. Extract Test Input Changes (Recommended)
|
||||
|
||||
To easily identify changes, use the included Python helper script to extract all
|
||||
text additions and removals from the diff, categorized by Input, STDERR, and
|
||||
STDOUT changes. This script reads a unified diff from stdin.
|
||||
|
||||
```bash
|
||||
# For Git:
|
||||
git diff -- 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py
|
||||
|
||||
# For Jujutsu (jj):
|
||||
jj diff --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py
|
||||
|
||||
# For a specific revision with jj:
|
||||
jj diff -r @- --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py
|
||||
|
||||
# For a specific PR with Github:
|
||||
gh pr diff 1234 | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py
|
||||
```
|
||||
|
||||
### 3. Identify Patterns and Produce a List of Groups
|
||||
|
||||
- Read the diff and produce a list of groups of changes that share a common
|
||||
theme or cause (for example, "Updated expected output for integer literals",
|
||||
"Added tests for new keyword").
|
||||
- **CRITICAL**: _Every single change_ in the testdata diff must be represented
|
||||
by at least one group. Do not ignore changes to `CHECK` lines.
|
||||
- If it's not clear what group a change belongs to, create a new group for
|
||||
it.
|
||||
- For each group:
|
||||
- Provide a brief description of the group.
|
||||
- (Optional) Briefly note if the group appears to be an intended or
|
||||
unintended consequence of the code changes.
|
||||
- Divide the groups into sections:
|
||||
- Test Changes: Changes to test inputs (lines not prefixed with
|
||||
`// CHECK`), along with diagnostic output changes where relevant
|
||||
- Diagnostic Changes: Changes to diagnostic output (lines prefixed with
|
||||
`// CHECK:STDERR`) with no corresponding changes to test inputs
|
||||
- [Output Type] Changes: Changes to STDOUT (lines prefixed with `// CHECK:STDOUT`)
|
||||
- Create one section for each relevant kind of test. For example,
|
||||
parser tests should typically be in a "Parse Tree Changes" section,
|
||||
check tests should typically be in a "SemIR Changes" section, and
|
||||
lower tests should typically be in an "LLVM IR Changes" section.
|
||||
|
||||
### 4. Improve Grouping
|
||||
|
||||
- Read the list of groups and check to see if any of them should be combined
|
||||
or split apart. If needed, do so.
|
||||
|
||||
### 5. Assign Changes to Groups
|
||||
|
||||
- Read the diff again, and then for _each_ change in the diff:
|
||||
- Add the change to the appropriate group (or, rarely, groups).
|
||||
- **CRITICAL**: _Every single change_ in the testdata diff must be
|
||||
represented by at least one group. Do not ignore changes to `CHECK`
|
||||
lines.
|
||||
- If the change affects _test inputs_ (lines not prefixed with `// CHECK`)
|
||||
or _diagnostic output_ (lines prefixed with `// CHECK:STDERR`):
|
||||
- List the file within the group. Don't just give one or a few
|
||||
examples. Include every file.
|
||||
- Provide an inline diff if the change is small.
|
||||
- Provide a link to the file if the change is large.
|
||||
- Otherwise, if the change only affects _STDOUT_ (lines prefixed with
|
||||
`// CHECK:STDOUT`):
|
||||
- Ensure the group contains a representative example that matches the
|
||||
current change.
|
||||
- The representative example should be an inline diff of the change.
|
||||
- **CRITICAL**: _Every single change_ to test inputs and diagnostic
|
||||
outputs in the files being summarized must be explicitly listed in at
|
||||
least one group. Do not skip changes, even if they are similar to
|
||||
changes you've already seen, and do not just give examples.
|
||||
|
||||
### 6. Validation
|
||||
|
||||
As a final validation step:
|
||||
|
||||
- Read through the testdata diff again.
|
||||
- Ensure that every change in the diff is reflected by at least one group in
|
||||
the report.
|
||||
|
||||
## Report Template
|
||||
|
||||
Use the following template for the generated report:
|
||||
|
||||
```markdown
|
||||
# `testdata` Change Summary
|
||||
|
||||
## Code Changes
|
||||
|
||||
[One paragraph summarizing changes outside of testdata.]
|
||||
|
||||
## Test Changes
|
||||
|
||||
### [Group Name]
|
||||
|
||||
[Description of the group.]
|
||||
|
||||
[Change 1: diff context OR link]
|
||||
|
||||
[Change 2: diff context OR link]
|
||||
|
||||
...
|
||||
|
||||
## Diagnostic Changes
|
||||
|
||||
### [Group Name]
|
||||
|
||||
[Description of the group.]
|
||||
|
||||
[Change 1: diff context OR link]
|
||||
|
||||
[Change 2: diff context OR link]
|
||||
|
||||
...
|
||||
|
||||
## [Output Type] Changes
|
||||
|
||||
### [File Path]
|
||||
|
||||
[Description of the group.]
|
||||
|
||||
[Example diff context]
|
||||
|
||||
Changes of this kind were found in [Number] files. Examples: [List of files]
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
Skip sections that would be empty.
|
||||
@@ -0,0 +1,65 @@
|
||||
__copyright__ = """
|
||||
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
|
||||
"""
|
||||
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from typing import TextIO, Dict, List
|
||||
|
||||
|
||||
def parse_diff(stream: TextIO) -> None:
|
||||
current_file: str = ""
|
||||
file_changes: Dict[str, Dict[str, List[str]]] = defaultdict(
|
||||
lambda: {"input": [], "stderr": [], "stdout": []}
|
||||
)
|
||||
|
||||
for line in stream:
|
||||
if line.startswith("diff --git"):
|
||||
parts = line.split()
|
||||
if len(parts) >= 4:
|
||||
current_file = (
|
||||
parts[3][2:] if parts[3].startswith("b/") else parts[3]
|
||||
)
|
||||
elif line.startswith("+") or line.startswith("-"):
|
||||
if not line.startswith("+++") and not line.startswith("---"):
|
||||
stripped = line[1:].strip()
|
||||
if stripped.startswith("// CHECK:STDERR"):
|
||||
file_changes[current_file]["stderr"].append(
|
||||
line.rstrip("\n")
|
||||
)
|
||||
elif stripped.startswith("// CHECK:STDOUT"):
|
||||
file_changes[current_file]["stdout"].append(
|
||||
line.rstrip("\n")
|
||||
)
|
||||
elif stripped.startswith("// CHECK"):
|
||||
file_changes[current_file]["stdout"].append(
|
||||
line.rstrip("\n")
|
||||
)
|
||||
else:
|
||||
file_changes[current_file]["input"].append(
|
||||
line.rstrip("\n")
|
||||
)
|
||||
|
||||
for f, c in file_changes.items():
|
||||
if not c["input"] and not c["stderr"] and not c["stdout"]:
|
||||
continue
|
||||
print(f"File: {f}")
|
||||
if c["input"]:
|
||||
print(" --- Input Changes ---")
|
||||
for change in c["input"]:
|
||||
print(f" {change}")
|
||||
if c["stderr"]:
|
||||
print(" --- STDERR Changes ---")
|
||||
for change in c["stderr"]:
|
||||
print(f" {change}")
|
||||
if c["stdout"]:
|
||||
print(" --- STDOUT Changes ---")
|
||||
for change in c["stdout"]:
|
||||
print(f" {change}")
|
||||
print("-" * 40)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parse_diff(sys.stdin)
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: Tool usage
|
||||
description:
|
||||
Instructions for AI assistants on what tools to use in the carbon-lang
|
||||
project.
|
||||
---
|
||||
|
||||
# Tool usage
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
## Bazelisk and Bazel
|
||||
|
||||
We use `bazelisk` for build and test.
|
||||
|
||||
**IMPORTANT**: AI assistants use `bazelisk` instead of `bazel`.
|
||||
|
||||
## Pre-commit
|
||||
|
||||
Running `pre-commit` is mandatory. To run it on all files:
|
||||
|
||||
```bash
|
||||
pre-commit run -a
|
||||
```
|
||||
|
||||
To validate a specific list of files:
|
||||
|
||||
```bash
|
||||
pre-commit run --files <files>
|
||||
```
|
||||
@@ -0,0 +1,115 @@
|
||||
---
|
||||
name: Toolchain development
|
||||
description:
|
||||
Instructions for checking, building, debugging, and understanding the Carbon
|
||||
toolchain.
|
||||
---
|
||||
|
||||
# Toolchain development
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
## Toolchain structure
|
||||
|
||||
- Under [`toolchain/`](/toolchain/):
|
||||
- [`base/`](/toolchain/base/): Base infrastructure and common utilities.
|
||||
- [`check/`](/toolchain/check/): Semantic analysis (SemIR generation).
|
||||
- [`lex/`](/toolchain/lex/): Lexing (Source -> Tokens).
|
||||
- [`lower/`](/toolchain/lower/): Lowering to LLVM IR.
|
||||
- [`parse/`](/toolchain/parse/): Parsing (Token -> Parse Tree).
|
||||
- [`sem_ir/`](/toolchain/sem_ir/): Semantic Intermediate Representation
|
||||
(SemIR) definitions.
|
||||
|
||||
## Toolchain architecture
|
||||
|
||||
- **Documentation**: Refer to [`toolchain/docs`](/toolchain/docs) for detailed
|
||||
architecture design and patterns.
|
||||
- Refer to [Toolchain Idioms](/toolchain/docs/idioms.md) for a
|
||||
comprehensive list of patterns (for example, `ValueStore`, formatting
|
||||
`.def` files, struct reflection) used throughout the implementation.
|
||||
- **Phases**: Lex -> Parse -> Check -> Lower.
|
||||
- **Definitions**: Many kinds (tokens, parse nodes, SemIR instructions) are
|
||||
defined in `.def` files and expanded by way of macros.
|
||||
- **Handlers**:
|
||||
- Parser: `Handle<StateName>` in `parse/handle_*.cpp`.
|
||||
- Checker: `HandleParseNode` in `check/handle_*.cpp`.
|
||||
- Lowering: `HandleInst` in `lower/handle_*.cpp`.
|
||||
- **Iteration**: Prefer iterative algorithms over recursive ones to prevent
|
||||
stack exhaustion on complex codebases.
|
||||
|
||||
### Essential commands
|
||||
|
||||
- **Test everything**: `bazelisk test //...`
|
||||
- **Test specific target**: `bazelisk test //toolchain/testing:file_test`
|
||||
- **Test specific file**:
|
||||
`bazelisk test //toolchain/testing:file_test --test_arg=--file_tests=<path_to_carbon_file>`
|
||||
- **Build toolchain**: `bazelisk build //toolchain/...`
|
||||
|
||||
### Updating test data
|
||||
|
||||
Carbon tests often use `file_test` (for example,
|
||||
`//toolchain/testing/file_test`). For detailed guidelines on authoring tests,
|
||||
including file splits, naming conventions (`fail_`, `todo_`), and generating
|
||||
minimal output with SemIR dumps, please refer to the **Toolchain tests** skill.
|
||||
|
||||
If you change compiler behavior, you likely need to update expected test
|
||||
outputs. **Do not manually edit thousands of lines of expected output.** Use the
|
||||
script:
|
||||
|
||||
```bash
|
||||
./toolchain/autoupdate_testdata.py
|
||||
# Or for a specific file:
|
||||
./toolchain/autoupdate_testdata.py toolchain/check/testdata/my_test.carbon
|
||||
```
|
||||
|
||||
## Debugging and diagnostics
|
||||
|
||||
- **Printing to stderr**: Use `llvm::errs() << "debug info\n";`.
|
||||
- Avoid `std::cout` (it may interfere with tool output).
|
||||
- **SemIR Stringification**:
|
||||
- SemIR objects often have a `Print` method or `operator<<`.
|
||||
- `inst.Print(llvm::errs())`
|
||||
- **Debugging Crashes**:
|
||||
- Bazel sandboxing can hide artifacts. Use `--sandbox_debug` if needed,
|
||||
but often running the binary directly from `bazel-bin/` is easier for
|
||||
debugging.
|
||||
|
||||
## Error handling
|
||||
|
||||
- **No exceptions**: Do not use C++ exceptions.
|
||||
- **`ErrorOr<T>`**: Return `ErrorOr<T>` for fallible operations.
|
||||
- Check with `if (auto result = Function(); result) { Use(*result); }`
|
||||
- **`llvm::Expected<T>`**: Similar to `ErrorOr`, used when interfacing with
|
||||
LLVM.
|
||||
|
||||
### Casting (LLVM style)
|
||||
|
||||
- Use `llvm::cast<T>(obj)` (checked, asserts on failure).
|
||||
- Use `llvm::dyn_cast<T>(obj)` (returns null on failure).
|
||||
- Use `llvm::isa<T>(obj)` (boolean check).
|
||||
- **Avoid** `dynamic_cast` and standard RTTI.
|
||||
|
||||
### Data structures
|
||||
|
||||
- Prefer APIs in `common/` and `toolchain/base/` over LLVM ADTs. For example,
|
||||
use `Map` instead of `llvm::DenseMap`.
|
||||
- If no Carbon API exists, prefer LLVM ADTs over standard library ones (for
|
||||
example `llvm::SmallVector`, `llvm::StringRef`).
|
||||
- `StringRef` is a view; be careful with lifetimes.
|
||||
|
||||
## Common pitfalls
|
||||
|
||||
1. **Legacy `explorer` references**: The `explorer` prototype has been moved.
|
||||
Ignore references to it in proposals or old docs; focus on `toolchain`.
|
||||
2. **Manually updating test files**: Always check if `autoupdate_testdata.py`
|
||||
can do it for you.
|
||||
3. **Using `std::string` unnecessarily**: Prefer `llvm::StringRef` for
|
||||
arguments.
|
||||
4. **Header includes**: Use specific include orders (often enforced by
|
||||
`clang-format`).
|
||||
5. **Parse node order**: Semantics processes parse nodes in post-order; ensure
|
||||
your parser transitions support this.
|
||||
@@ -0,0 +1,136 @@
|
||||
---
|
||||
name: Toolchain tests
|
||||
description:
|
||||
Instructions for authoring, structuring, and running toolchain tests using
|
||||
the file_test infrastructure.
|
||||
---
|
||||
|
||||
# Toolchain tests
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
## Introduction
|
||||
|
||||
This skill provides guidelines and patterns for creating and updating tests for
|
||||
the Carbon toolchain, especially file tests in `toolchain/*/testdata/` (for
|
||||
example, `toolchain/check/testdata/`).
|
||||
|
||||
Toolchain tests evaluate Carbon source files through Lexing, Parsing, Checking,
|
||||
and optionally Lowering. Output (for example SemIR dumps, Clang errors) is
|
||||
captured and validated using inline CHECK records.
|
||||
|
||||
## Structure and Authoring
|
||||
|
||||
### File Layout and Headers
|
||||
|
||||
Test files must start with the standard Carbon license, followed by
|
||||
configuration comments. Separate sections with blank comment lines (`//`).
|
||||
|
||||
```carbon
|
||||
// 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
|
||||
//
|
||||
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/...
|
||||
//
|
||||
// AUTOUPDATE
|
||||
```
|
||||
|
||||
- `// AUTOUPDATE` is mandatory for files using CHECK markers.
|
||||
- `// TIP:` lines are automatically generated by the autoupdater. You do not
|
||||
need to hand-write them. It is harmless to add them, but the script will
|
||||
handle it.
|
||||
|
||||
### Minimized Preludes
|
||||
|
||||
When writing tests entirely unrelated to the Core package, specify a minimal
|
||||
prelude file using `// INCLUDE-FILE`. Usually, include
|
||||
`toolchain/testing/testdata/min_prelude/` scripts, such as `int.carbon` or
|
||||
`primitives.carbon`. This significantly speeds up execution and minimizes STDOUT
|
||||
noise.
|
||||
|
||||
### Split Tests and `[[@TEST_NAME]]`
|
||||
|
||||
A single physical file can test multiple scenarios using split constraints:
|
||||
|
||||
```carbon
|
||||
// --- passing_case.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
// ...
|
||||
|
||||
// --- fail_bad_case.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
// ...
|
||||
```
|
||||
|
||||
- Use `library "[[@TEST_NAME]]";` in each split when necessary to prevent name
|
||||
conflicts or redefining the default library.
|
||||
- Exactly `[[@TEST_NAME]]` (including the brackets) should be used. The test
|
||||
infrastructure automatically replaces it with the split's filename minus
|
||||
`todo_` and `fail_` prefixes.
|
||||
- **Do not put code that is expected to pass and code that is expected to fail
|
||||
into the same split.** Validation relies on non-failing splits producing
|
||||
absolutely no errors and failing splits producing the correct compiler
|
||||
errors independently.
|
||||
|
||||
### File Prefixing: `fail_` and `todo_`
|
||||
|
||||
Expected failures must be differentiated from unexpected failures (and from
|
||||
bugs). Include prefixes to name individual split files or the main test:
|
||||
|
||||
- `fail_...`: The test should and does produce compiler errors.
|
||||
- `todo_fail_...`: The test should produce errors but currently does not.
|
||||
- `fail_todo_...`: The test does produce errors or crashes, but it shouldn't
|
||||
(or produces the wrong errors or otherwise misbehaves with errors).
|
||||
- `todo_...`: The test has some incorrect behavior, but doesn't produce errors
|
||||
currently, and shouldn't.
|
||||
|
||||
**Main File Naming**: The main test file (and any split-files) must have a
|
||||
`fail_` prefix if they have an associated error. **Exception**: The main file
|
||||
may omit `fail_` if it contains a least one split that has a `fail_` prefix.
|
||||
|
||||
Both the `fail_` and `todo_` prefixes are stripped from filename properties like
|
||||
`[[@TEST_NAME]]`.
|
||||
|
||||
### Test Code Comments
|
||||
|
||||
- **No agent thinking:** Do not include comments describing your reasoning or
|
||||
"train of thought" (for example, "Wait, but...") inside the test files. Any
|
||||
comments left in tests should be concise and describe what the test _itself_
|
||||
is validating for human readers.
|
||||
|
||||
## SemIR Dumps and Minimizing Output
|
||||
|
||||
Limit STDOUT checks to the logic under test. Always use `//@dump-sem-ir-begin`
|
||||
and `//@dump-sem-ir-end` around the specific declarations/blocks where SemIR
|
||||
output is desired. Only use these markers and **not**
|
||||
`--dump-sem-ir-ranges=if-present` or similar extra args—new tests use
|
||||
`//@dump-sem-ir...` to naturally filter output to the highlighted segments based
|
||||
on the default behavior.
|
||||
|
||||
```carbon
|
||||
//@dump-sem-ir-begin
|
||||
fn F(x:? form(ref i32));
|
||||
//@dump-sem-ir-end
|
||||
```
|
||||
|
||||
## Creating/Updating the Output
|
||||
|
||||
AI tools should **never** hand-write or manually touch `// CHECK:STDOUT:` or
|
||||
`// CHECK:STDERR:` comments.
|
||||
|
||||
Write your Carbon test code, headers, and `// AUTOUPDATE` then run the test
|
||||
updater:
|
||||
|
||||
```bash
|
||||
./toolchain/autoupdate_testdata.py toolchain/PATH/TO/YOUR/TEST.carbon
|
||||
```
|
||||
|
||||
Review the updated test outputs (for example, by way of `git diff`). Ensure
|
||||
logic paths are correctly tested rather than producing massive boilerplate
|
||||
blocks.
|
||||
@@ -8,8 +8,5 @@ bazel-carbon-lang
|
||||
# See github_tools/MODULE.bazel.
|
||||
github_tools
|
||||
|
||||
# Used as part of repo patching.
|
||||
third_party/boost_unordered
|
||||
|
||||
# Example Bazel project.
|
||||
examples/bazel
|
||||
|
||||
@@ -38,11 +38,9 @@ common:non-fatal-checks --per_file_copt=common/check_internal.cpp@-DCARBON_NON_F
|
||||
# enable use of the target config here to make our build and tests more
|
||||
# efficient, see the documentation in //bazel/carbon_rules/BUILD for details.
|
||||
common --flag_alias=use_target_config_carbon_rules=//bazel/carbon_rules:use_target_config_carbon_rules
|
||||
common --flag_alias=use_target_config_runtimes_builder=//toolchain/driver:use_target_config_runtimes_builder
|
||||
# Bazel doesn't track what commands the flag_alias is valid for, so we can't use
|
||||
# common here.
|
||||
build --use_target_config_carbon_rules
|
||||
build --use_target_config_runtimes_builder
|
||||
|
||||
# Default to using a disk cache to minimize re-building LLVM and Clang which we
|
||||
# try to avoid updating too frequently to minimize rebuild cost. The location
|
||||
@@ -87,12 +85,12 @@ common --define=absl=1
|
||||
# Enable TCMalloc on Linux in optimized builds.
|
||||
common --custom_malloc=//bazel/malloc:tcmalloc_if_linux_opt
|
||||
|
||||
# Configuration for enabling Address Sanitizer. Note that this is enabled by
|
||||
# default for fastbuild. The config is provided to enable ASan even in
|
||||
# optimized or other build configurations. Note that ASan and TCMalloc are
|
||||
# Configuration for enabling Address Sanitizer. Note that ASan and TCMalloc are
|
||||
# incompatible so this explicitly forces the system malloc.
|
||||
common:asan --features=asan
|
||||
common:asan --custom_malloc=@bazel_tools//tools/cpp:malloc
|
||||
# Also double the test timeouts for ASan to improve their consistency.
|
||||
test:asan --test_timeout=120,600,1800,-1
|
||||
|
||||
# Configuration for enabling LibFuzzer (along with ASan).
|
||||
common:fuzzer --features=fuzzer
|
||||
@@ -123,6 +121,11 @@ common:linux --define=pfm=1
|
||||
# Disables `actions.declare_symlink`. Done for cross-environment support.
|
||||
common --allow_unresolved_symlinks=false
|
||||
|
||||
# Removes the leading `/proc/self/cwd/` from file paths in the debug info. Some
|
||||
# tools like VS Code don't understand `/proc/self/cwd` in places like terminal
|
||||
# stack dumps, but do understand paths relative to the workspace root.
|
||||
common --copt=-fdebug-prefix-map=/proc/self/cwd=
|
||||
|
||||
# Allow users to override any of the flags desired by importing a user-specific
|
||||
# RC file here if present.
|
||||
try-import %workspace%/user.bazelrc
|
||||
|
||||
@@ -11,6 +11,7 @@ DerivePointerAlignment: 'false'
|
||||
ExperimentalAutoDetectBinPacking: 'false'
|
||||
FixNamespaceComments: 'true'
|
||||
InsertBraces: 'true'
|
||||
InsertTrailingCommas: None
|
||||
PointerAlignment: Left
|
||||
# We abuse control macros for formatting other kinds of macros.
|
||||
SpaceBeforeParens: ControlStatementsExceptControlMacros
|
||||
@@ -23,3 +24,11 @@ IfMacros:
|
||||
'CARBON_KIND_SWITCH',
|
||||
]
|
||||
StatementMacros: ['ABSTRACT']
|
||||
QualifierAlignment: Custom
|
||||
QualifierOrder:
|
||||
[inline, static, friend, constexpr, const, volatile, restrict, type]
|
||||
Macros:
|
||||
# These macros can contain variable declarations, so clang-format needs to
|
||||
# "see through" them in order to format them correctly.
|
||||
- CARBON_ASSIGN_OR_RETURN(x)=x
|
||||
- CARBON_KIND(x)=x
|
||||
|
||||
@@ -19,3 +19,12 @@ Diagnostics:
|
||||
Suppress:
|
||||
# The `#error` requiring a macro definition.
|
||||
- pp_hash_error
|
||||
|
||||
---
|
||||
|
||||
# Suppress diagnostics for template source files.
|
||||
If:
|
||||
PathMatch: .*\.tpl\.h
|
||||
Diagnostics:
|
||||
Suppress:
|
||||
- undeclared_var_use
|
||||
|
||||
@@ -12,12 +12,12 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
# Setup Python and related tools.
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
# Match the min version listed in docs/project/contribution_tools.md
|
||||
# or the oldest version available on the OS.
|
||||
python-version:
|
||||
${{ inputs.matrix_runner == 'macos-14' && '3.11' || '3.9' }}
|
||||
${{ inputs.matrix_runner == 'macos-14' && '3.11' || '3.10' }}
|
||||
|
||||
- uses: ./.github/actions/build-setup-macos
|
||||
if: startsWith(inputs.matrix_runner, 'macos')
|
||||
@@ -70,6 +70,13 @@ runs:
|
||||
build --remote_cache=https://storage.googleapis.com/carbon-builds-github-v${CACHE_VERSION}
|
||||
build --remote_download_outputs=minimal
|
||||
|
||||
# Allow passing targets that are incompatible so that our explicit
|
||||
# target lists work more like //... wild card patterns in CI. In CI,
|
||||
# we're using explicit target lists to prune to a minimal set of
|
||||
# dependencies, and so skipping incompatible targets is the expected
|
||||
# behavior.
|
||||
build --skip_incompatible_explicit_targets
|
||||
|
||||
# We import a special key into every action in order to key the Bazel
|
||||
# remote cache in a way that avoids collisions between different
|
||||
# runners. Anything that might change the system external to Bazel but
|
||||
|
||||
@@ -28,7 +28,7 @@ runs:
|
||||
# minimum supported LLVM version.
|
||||
- name: Cache Homebrew
|
||||
id: cache-homebrew-macos
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||
with:
|
||||
# Cover all the critical parts of Homebrew here. Homebrew on Arm macOS
|
||||
# uses its own prefix making this easy to cover, but we need a few
|
||||
|
||||
@@ -27,7 +27,7 @@ runs:
|
||||
# reliability.
|
||||
- name: Cache LLVM and Clang installation
|
||||
id: cache-llvm-ubuntu
|
||||
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
|
||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||
with:
|
||||
path: ~/llvm
|
||||
key: LLVM-19.1.7-Cache-ubuntu-${{ runner.arch }}
|
||||
|
||||
@@ -18,6 +18,7 @@ the "Harden Runner" steps are
|
||||
Most jobs only have a few endpoints, but due to tools which do downloads, a few
|
||||
have significantly more. These are:
|
||||
|
||||
- clangd_tidy.yaml (Bazel)
|
||||
- pre_commit.yaml (Bazel, pre-commit)
|
||||
- nightly_release.yaml (Bazel)
|
||||
- tests.yaml (Bazel)
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# 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
|
||||
|
||||
name: Check Dependent Label
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, labeled, unlabeled]
|
||||
|
||||
# This workflow runs as `pull_request_target` so that the check can't be
|
||||
# disabled or bypassed by a the PR, but it doesn't need any permissions.
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
check_label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
# prettier-ignore
|
||||
allowed-endpoints: >
|
||||
api.github.com:443
|
||||
|
||||
- name: Check for 'dependent' label
|
||||
run: |
|
||||
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'dependent') }}" == "true" ]]; then
|
||||
echo "PR has 'dependent' label. Blocking merge."
|
||||
exit 1
|
||||
fi
|
||||
echo "PR does not have 'dependent' label."
|
||||
@@ -26,27 +26,36 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
egress-policy: block
|
||||
# When adding endpoints, see README.md.
|
||||
# prettier-ignore
|
||||
allowed-endpoints: >
|
||||
*.dl.sourceforge.net:443
|
||||
*.blob.storage.azure.net:443
|
||||
*.githubapp.com:443
|
||||
*.sourceforge.net:443
|
||||
api.github.com:443
|
||||
api.ipify.org:443
|
||||
bcr.bazel.build:443
|
||||
downloads.sourceforge.net:443
|
||||
files.pythonhosted.org:443
|
||||
github.com:443
|
||||
go.dev:443
|
||||
mirror.bazel.build:443
|
||||
mirrors.kernel.org:443
|
||||
nodejs.org:443
|
||||
oauth2.googleapis.com:443
|
||||
objects.githubusercontent.com:443
|
||||
pypi.org:443
|
||||
registry.npmjs.org:443
|
||||
release-assets.githubusercontent.com:443
|
||||
releases.bazel.build:443
|
||||
sourceforge.net:443
|
||||
storage.googleapis.com:443
|
||||
uploads.github.com:443
|
||||
www.googleapis.com:443
|
||||
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- id: filter
|
||||
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
@@ -66,10 +75,6 @@ jobs:
|
||||
if: steps.filter.outputs.has_cpp == 'true'
|
||||
run: ./scripts/create_compdb.py
|
||||
|
||||
- name: Build deps for clangd-tidy
|
||||
if: steps.filter.outputs.has_cpp == 'true'
|
||||
run: ./scripts/run_bazel.py build //scripts:deps_for_clangd_tidy
|
||||
|
||||
- name: Install clangd-tidy
|
||||
if: steps.filter.outputs.has_cpp == 'true'
|
||||
run: pip install clangd-tidy==1.1.0.post2
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -22,16 +22,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Prebuild actions
|
||||
run: ./website/prebuild.py
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0
|
||||
uses: ruby/setup-ruby@6ca151fd1bfcfd6fe0c4eb6837eb0584d0134a0c # v1.290.0
|
||||
with:
|
||||
# Runs 'bundle install' and caches installed gems automatically.
|
||||
bundler-cache: true
|
||||
|
||||
@@ -29,18 +29,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Prebuild actions
|
||||
run: ./website/prebuild.py
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0
|
||||
uses: ruby/setup-ruby@6ca151fd1bfcfd6fe0c4eb6837eb0584d0134a0c # v1.290.0
|
||||
with:
|
||||
# Runs 'bundle install' and caches installed gems automatically.
|
||||
bundler-cache: true
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
- name: Upload artifact
|
||||
# Automatically uploads an artifact from the './_site' directory by
|
||||
# default.
|
||||
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
|
||||
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
|
||||
|
||||
deploy:
|
||||
environment:
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
needs: build
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -37,26 +37,37 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
egress-policy: block
|
||||
# When adding endpoints, see README.md.
|
||||
# prettier-ignore
|
||||
allowed-endpoints: >
|
||||
*.dl.sourceforge.net:443
|
||||
*.blob.storage.azure.net:443
|
||||
*.githubapp.com:443
|
||||
*.sourceforge.net:443
|
||||
api.github.com:443
|
||||
api.ipify.org:443
|
||||
bcr.bazel.build:443
|
||||
downloads.sourceforge.net:443
|
||||
files.pythonhosted.org:443
|
||||
github.com:443
|
||||
go.dev:443
|
||||
mirror.bazel.build:443
|
||||
mirrors.kernel.org:443
|
||||
nodejs.org:443
|
||||
oauth2.googleapis.com:443
|
||||
objects.githubusercontent.com:443
|
||||
pypi.org:443
|
||||
registry.npmjs.org:443
|
||||
release-assets.githubusercontent.com:443
|
||||
releases.bazel.build:443
|
||||
sourceforge.net:443
|
||||
storage.googleapis.com:443
|
||||
uploads.github.com:443
|
||||
www.googleapis.com:443
|
||||
|
||||
- name: Checkout branch
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Set up remote cache access
|
||||
env:
|
||||
@@ -82,7 +93,7 @@ jobs:
|
||||
test -c opt --stamp --remote_download_toplevel \
|
||||
--pre_release=nightly --nightly_date=${{ env.nightly_date }} \
|
||||
//toolchain \
|
||||
//toolchain/install:carbon_toolchain_tar_gz_rule \
|
||||
//toolchain/install:carbon_toolchain_tar_gz \
|
||||
//toolchain/install:carbon_toolchain_tar_gz_test
|
||||
|
||||
- name: Extract the release version
|
||||
|
||||
@@ -18,30 +18,37 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
disable-sudo-and-containers: true
|
||||
egress-policy: block
|
||||
# When adding endpoints, see README.md.
|
||||
# prettier-ignore
|
||||
allowed-endpoints: >
|
||||
*.dl.sourceforge.net:443
|
||||
*.blob.storage.azure.net:443
|
||||
*.githubapp.com:443
|
||||
*.sourceforge.net:443
|
||||
api.github.com:443
|
||||
api.ipify.org:443
|
||||
bcr.bazel.build:443
|
||||
downloads.sourceforge.net:443
|
||||
files.pythonhosted.org:443
|
||||
github.com:443
|
||||
go.dev:443
|
||||
mirror.bazel.build:443
|
||||
mirrors.kernel.org:443
|
||||
nodejs.org:443
|
||||
oauth2.googleapis.com:443
|
||||
objects.githubusercontent.com:443
|
||||
pypi.org:443
|
||||
registry.npmjs.org:443
|
||||
release-assets.githubusercontent.com:443
|
||||
releases.bazel.build:443
|
||||
storage.googleapis.com:443
|
||||
sourceforge.net:443
|
||||
uploads.github.com:443
|
||||
www.googleapis.com:443
|
||||
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
|
||||
# Ensure LLVM is set up consistently.
|
||||
- uses: ./.github/actions/build-setup-common
|
||||
@@ -63,7 +70,7 @@ jobs:
|
||||
mkdir -p pre-commit-output
|
||||
git diff > pre-commit-output/diff
|
||||
cp $GITHUB_EVENT_PATH pre-commit-output/event
|
||||
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
if: failure()
|
||||
with:
|
||||
name: pre-commit output
|
||||
|
||||
@@ -28,12 +28,11 @@ jobs:
|
||||
# Only generate suggestions if pre-commit for a PR failed.
|
||||
if: |
|
||||
github.event.workflow_run.conclusion == 'failure' &&
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.actor != 'jonmeow'
|
||||
github.event.workflow_run.event == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
@@ -48,10 +47,10 @@ jobs:
|
||||
with:
|
||||
reviewdog_version: latest
|
||||
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Download pre-commit output
|
||||
uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
with:
|
||||
name: pre-commit output
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
@@ -25,13 +25,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
# Checkout our main repository.
|
||||
- name: Checkout the main repository
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
# Run the sync script.
|
||||
- name: Sync to other repositories
|
||||
|
||||
@@ -22,36 +22,62 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name:
|
||||
Testing ${{ matrix.config.name != 'Default' && format('({0})',
|
||||
matrix.config.name) || '' }} (${{ matrix.runner }})
|
||||
strategy:
|
||||
matrix:
|
||||
# Test a recent version of each supported OS.
|
||||
runner: ['ubuntu-22.04', 'macos-14']
|
||||
build_mode: [fastbuild, opt]
|
||||
# Create a synthetic matrix dimension with the event name for filtering.
|
||||
event: ['${{ github.event_name }}']
|
||||
config:
|
||||
- name: 'Default'
|
||||
flags: ''
|
||||
- name: 'Opt'
|
||||
flags: '-c opt'
|
||||
- name: 'ASan'
|
||||
flags: '--config=asan'
|
||||
exclude:
|
||||
- runner: 'macos-14'
|
||||
config: { name: 'ASan', flags: '--config=asan' }
|
||||
- event: 'pull_request'
|
||||
config: { name: 'ASan', flags: '--config=asan' }
|
||||
- event: 'merge_group'
|
||||
config: { name: 'ASan', flags: '--config=asan' }
|
||||
runs-on: ${{ matrix.runner }}
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
egress-policy: block
|
||||
# When adding endpoints, see README.md.
|
||||
# prettier-ignore
|
||||
allowed-endpoints: >
|
||||
*.dl.sourceforge.net:443
|
||||
*.blob.storage.azure.net:443
|
||||
*.githubapp.com:443
|
||||
*.sourceforge.net:443
|
||||
api.github.com:443
|
||||
api.ipify.org:443
|
||||
bcr.bazel.build:443
|
||||
downloads.sourceforge.net:443
|
||||
files.pythonhosted.org:443
|
||||
github.com:443
|
||||
go.dev:443
|
||||
mirror.bazel.build:443
|
||||
mirrors.kernel.org:443
|
||||
nodejs.org:443
|
||||
oauth2.googleapis.com:443
|
||||
objects.githubusercontent.com:443
|
||||
pypi.org:443
|
||||
registry.npmjs.org:443
|
||||
release-assets.githubusercontent.com:443
|
||||
releases.bazel.build:443
|
||||
sourceforge.net:443
|
||||
storage.googleapis.com:443
|
||||
uploads.github.com:443
|
||||
www.googleapis.com:443
|
||||
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- id: test-setup
|
||||
uses: ./.github/actions/test-setup
|
||||
@@ -65,7 +91,7 @@ jobs:
|
||||
targets_file: ${{ runner.temp }}/targets
|
||||
|
||||
# Build and run just the tests impacted by the PR or merge group.
|
||||
- name: Test (${{ matrix.build_mode }})
|
||||
- name: Test (${{ matrix.config.name }})
|
||||
if: steps.test-setup.outputs.has_code == 'true'
|
||||
shell: bash
|
||||
env:
|
||||
@@ -76,10 +102,11 @@ jobs:
|
||||
run: |
|
||||
# Decrease the jobs sharply if we see repeated failures to try to
|
||||
# work around transient network errors even if it makes things
|
||||
# slower.
|
||||
# slower. Note that we allow passing targets that are incompatible and
|
||||
# skip thim as-if we were using `//...` style wild card patterns.
|
||||
./scripts/run_bazel.py \
|
||||
--attempts=5 --jobs-on-last-attempt=4 \
|
||||
test -c ${{ matrix.build_mode }} \
|
||||
test ${{ matrix.config.flags }} \
|
||||
--target_pattern_file=$TARGETS_FILE
|
||||
|
||||
# See "Disk space before build" in `test-setup`.
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
|
||||
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
# vim temporary files
|
||||
.*.sw[a-p]
|
||||
.swp
|
||||
|
||||
# generated by utils/tree_sitter/helix.sh
|
||||
/.helix/
|
||||
|
||||
@@ -33,6 +33,11 @@ repos:
|
||||
rev: efaea7c61c774c0b1a9805fd999e754a2d19dbd1 # frozen: v1.2.5
|
||||
hooks:
|
||||
- id: check-google-doc-style
|
||||
exclude: |
|
||||
(?x)^(
|
||||
.*\.agents/.*|
|
||||
.*AGENTS.md
|
||||
)$
|
||||
- id: markdown-toc
|
||||
- repo: local
|
||||
hooks:
|
||||
@@ -45,7 +50,7 @@ repos:
|
||||
|
||||
# Formatters should be run late so that they can re-format any prior changes.
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 8a737e727ac5ab2f1d4cf5876720ed276dc8dc4b # frozen: 25.1.0
|
||||
rev: 35ea67920b7f6ac8e09be1c47278752b1e827f76 # frozen: 26.3.0
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: local
|
||||
@@ -159,7 +164,7 @@ repos:
|
||||
.*_test\.py
|
||||
)$
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: 63c8f8312b7559622c0d82815639671ae42132ac # frozen: v2.4.1
|
||||
rev: 2ccb47ff45ad361a21071a7eedda4c37e6ae8c5a # frozen: v2.4.2
|
||||
hooks:
|
||||
- id: codespell
|
||||
args: ['-I', '.codespell_ignore', '--uri-ignore-words-list', '*']
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# Gemini & AI assistant guide for Carbon
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
This document provides high-density technical context for AI assistants (and
|
||||
humans!) contributing to the Carbon Language project. If you are an AI
|
||||
assistant, **read this first** to avoid common pitfalls.
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [General instructions](#general-instructions)
|
||||
- [Project structure](#project-structure)
|
||||
- [Bazel usage](#bazel-usage)
|
||||
- [Toolchain development](#toolchain-development)
|
||||
|
||||
## General instructions
|
||||
|
||||
- **Communication**: Be concise, professional, and technical. Use GitHub-style
|
||||
markdown.
|
||||
- **Verification**: Always run relevant tests.
|
||||
- **Tool usage**: Use web search for any research outside the immediate
|
||||
codebase or KIs.
|
||||
|
||||
## Project structure
|
||||
|
||||
- **[`common/`](common/)**: Common C++ utilities used across the project.
|
||||
- **[`core/`](core/)**: The Carbon standard library (Core).
|
||||
- **[`docs/`](docs/)**: Project documentation, design, and style guides.
|
||||
- **[`examples/`](examples/)**: Example Carbon programs and code snippets.
|
||||
- **[`proposals/`](proposals/)**: Evolution proposals.
|
||||
- **[`testing/`](testing/)**: Testing utilities and infrastructure.
|
||||
- **[`toolchain/`](toolchain/)**: The C++ implementation of the compiler
|
||||
(Toolchain).
|
||||
|
||||
## Tool usage
|
||||
|
||||
See the "Tool usage" skill for instructions on what tools to use in the
|
||||
carbon-lang project.
|
||||
|
||||
## Bazel usage
|
||||
|
||||
> [!IMPORTANT] Always use `bazelisk` instead of `bazel` for all commands in the
|
||||
> Carbon project. Refer to the
|
||||
> [Bazel usage skill](/.agents/skills/bazel/SKILL.md) for detailed instructions.
|
||||
|
||||
## Code style
|
||||
|
||||
See the "Code style" skill for instructions on formatting, style guides, and
|
||||
code conventions to follow.
|
||||
|
||||
## Toolchain development
|
||||
|
||||
See the "Toolchain Development" skill for instructions on architecture,
|
||||
building, testing, debugging, C++ patterns, and common pitfalls.
|
||||
@@ -2,8 +2,51 @@
|
||||
# Exceptions. See /LICENSE for license information.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "bool_setting", "int_flag")
|
||||
|
||||
filegroup(
|
||||
name = "clang_tidy_config",
|
||||
srcs = [".clang-tidy"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
# `bazel run //:generate_compile_commands` to produce `compile_commands.json`.
|
||||
alias(
|
||||
name = "generate_compile_commands",
|
||||
actual = "@wolfd_bazel_compile_commands//:generate_compile_commands",
|
||||
)
|
||||
|
||||
bool_setting(
|
||||
name = "runtimes_build",
|
||||
build_setting_default = False,
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
int_flag(
|
||||
name = "bootstrap_stage",
|
||||
build_setting_default = 0,
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
# A setting that causes bootstrapping to occur using the `exec` config rather
|
||||
# than the target config.
|
||||
#
|
||||
# The exec config is the more technically correct way of doing bootstrapping
|
||||
# than the target config. For example it allows bootstrapping with a target that
|
||||
# isn't compatible with the current execution host. However, in development
|
||||
# builds, it is likely to force building the entire toolchain twice -- once in
|
||||
# the target config for running test, and a second time in the exec config for
|
||||
# the bootstrap. As a consequence, this is disabled by default.
|
||||
#
|
||||
# TODO: Add documentation for using the bootstrap flags once stabilized.
|
||||
bool_flag(
|
||||
name = "bootstrap_exec_config",
|
||||
build_setting_default = False,
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "bootstrap_with_exec_config",
|
||||
flag_values = {"//:bootstrap_exec_config": "True"},
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
+14
-2
@@ -33,6 +33,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Style](#style)
|
||||
- [Google Docs and Markdown](#google-docs-and-markdown)
|
||||
- [Other files](#other-files)
|
||||
- [Testing](#testing)
|
||||
- [License](#license)
|
||||
- [Google Docs](#google-docs)
|
||||
- [Markdown](#markdown)
|
||||
@@ -98,7 +99,7 @@ early, before even writing a proposal, and the process explains how to do that.
|
||||
|
||||
Helping with
|
||||
[pull requests](https://github.com/carbon-language/carbon-lang/pulls) review is
|
||||
a good way to provide feedback, while getting a acquainted with the code base.
|
||||
a good way to provide feedback, while getting acquainted with the code base.
|
||||
|
||||
#### Implement Carbon's design
|
||||
|
||||
@@ -231,6 +232,10 @@ as well as helpful tooling that will ease the contribution process. For example,
|
||||
|
||||
#### Using AI-based contribution tools
|
||||
|
||||
If you are using an AI assistant to help you contribute, or if you are an AI
|
||||
assistant yourself, please consult [AGENTS.md](/AGENTS.md) for high-density
|
||||
technical context and tips.
|
||||
|
||||
All submissions to Carbon need to follow our
|
||||
[Contributor License Agreement (CLA)](#contributor-license-agreements-clas),
|
||||
which covers any original work of authorship included in the submission. This
|
||||
@@ -304,7 +309,6 @@ follow the Carbon documentation and coding styles.
|
||||
request.
|
||||
|
||||
- For code:
|
||||
|
||||
- New features should have a documented design that has been approved
|
||||
through the [evolution process](docs/project/evolution.md). This
|
||||
includes modifications to preexisting designs.
|
||||
@@ -423,6 +427,14 @@ Other style points to be aware of are:
|
||||
|
||||
If you're not sure what style to use, please ask on Discord or GitHub.
|
||||
|
||||
## Testing
|
||||
|
||||
Most development in the Carbon project is on the [toolchain](toolchain/). The
|
||||
toolchain contains some unit tests, but the majority of testing is done through
|
||||
`file_test` tests, which test the output of the different phases of the
|
||||
toolchain. The toolchain docs include instructions for
|
||||
[building and running tests](toolchain/docs/adding_features.md#tests-and-debugging).
|
||||
|
||||
## License
|
||||
|
||||
A license is required at the top of all documents and files.
|
||||
|
||||
+34
-61
@@ -19,43 +19,33 @@ of:
|
||||
- Running `bazel mod deps` provides a canonical update to
|
||||
`MODULE.bazel.lock`; create a PR with those changes in order to include
|
||||
the host platform.
|
||||
|
||||
For updates, run `scripts/query_module_versions.py` to list the latest package
|
||||
versions.
|
||||
"""
|
||||
|
||||
module(name = "carbon")
|
||||
|
||||
http_archive = use_repo_rule(
|
||||
"@bazel_tools//tools/build_defs/repo:http.bzl",
|
||||
"http_archive",
|
||||
)
|
||||
|
||||
bazel_dep(name = "abseil-cpp", version = "20260107.0")
|
||||
bazel_dep(name = "abseil-cpp", version = "20260107.1")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.9.0")
|
||||
bazel_dep(name = "boost.unordered", version = "1.90.0.bcr.1")
|
||||
bazel_dep(name = "google_benchmark", version = "1.9.5")
|
||||
bazel_dep(name = "googletest", version = "1.17.0.bcr.2")
|
||||
bazel_dep(name = "libpfm", version = "4.13.0")
|
||||
bazel_dep(name = "re2", version = "2025-11-05.bcr.1")
|
||||
bazel_dep(name = "rules_cc", version = "0.2.16")
|
||||
bazel_dep(name = "rules_cc", version = "0.2.17")
|
||||
bazel_dep(name = "rules_pkg", version = "1.2.0")
|
||||
bazel_dep(name = "rules_shell", version = "0.6.1")
|
||||
bazel_dep(name = "tcmalloc", version = "0.0.0-20250927-12f2552")
|
||||
bazel_dep(name = "tree-sitter-bazel", version = "0.26.3.bcr.1")
|
||||
bazel_dep(name = "tree-sitter-bazel", version = "0.26.5")
|
||||
|
||||
# The registry only has an old version. We use that here to avoid a miss but
|
||||
# override it with a newer version.
|
||||
bazel_dep(name = "libpfm", version = "4.11.0")
|
||||
|
||||
libpfm_version = "4.13.0"
|
||||
|
||||
# The official site is https://perfmon2.sourceforge.net/, but SourceForge makes
|
||||
# it difficult to download from bazel. On GitHub action runners,
|
||||
# https://git.code.sf.net/p/perfmon2/libpfm4 seems to be blocked. As a
|
||||
# consequence, use a mirror.
|
||||
archive_override(
|
||||
module_name = "libpfm",
|
||||
integrity = "sha256-sGBx1+UoQCplBCc+pwA1Tr/PS2L/4jnLZHH82wSuPz0=",
|
||||
patch_strip = 1,
|
||||
patches = ["@//bazel/libpfm:0001-Introduce-a-simple-native-Bazel-build.patch"],
|
||||
strip_prefix = "libpfm4-{0}".format(libpfm_version),
|
||||
urls = ["https://github.com/wcohen/libpfm4/archive/v{0}.tar.gz".format(libpfm_version)],
|
||||
bazel_dep(name = "wolfd_bazel_compile_commands", version = "0.5.2", dev_dependency = True)
|
||||
git_override(
|
||||
module_name = "wolfd_bazel_compile_commands",
|
||||
# This is https://github.com/wolfd/bazel-compile-commands/pull/3 which is
|
||||
# needed to correctly select target configurations in our compile commands.
|
||||
commit = "7c673ac868cd237f262bb37a7819b1a279566a66",
|
||||
remote = "https://github.com/chandlerc/bazel-compile-commands.git",
|
||||
)
|
||||
|
||||
bazel_dep(name = "bazel_clang_tidy", dev_dependency = True)
|
||||
@@ -74,27 +64,11 @@ use_repo(bazel_cc_toolchain, "bazel_cc_toolchain")
|
||||
|
||||
register_toolchains("@bazel_cc_toolchain//:all")
|
||||
|
||||
bazel_dep(name = "hedron_compile_commands", dev_dependency = True)
|
||||
git_override(
|
||||
module_name = "hedron_compile_commands",
|
||||
# HEAD as of 2026-01-28.
|
||||
commit = "abb61a688167623088f8768cc9264798df6a9d10",
|
||||
remote = "https://github.com/hedronvision/bazel-compile-commands-extractor.git",
|
||||
)
|
||||
|
||||
boost_unordered_version = "1.88.0"
|
||||
|
||||
http_archive(
|
||||
name = "boost_unordered",
|
||||
build_file = "@//:third_party/boost_unordered/BUILD.bazel",
|
||||
integrity = "sha256-a5ydXEQCspPhFmCD9vNa3JUIVeitbodEYaJhfOSO8no=",
|
||||
strip_prefix = "boost_unordered-{0}".format(boost_unordered_version),
|
||||
urls = ["https://github.com/MikePopoloski/boost_unordered/archive/v{0}.tar.gz".format(boost_unordered_version)],
|
||||
)
|
||||
register_toolchains("//toolchain/install:all")
|
||||
|
||||
# Required for llvm-project.
|
||||
bazel_dep(name = "platforms", version = "1.0.0")
|
||||
bazel_dep(name = "protobuf", version = "34.0-rc1", repo_name = "com_google_protobuf")
|
||||
bazel_dep(name = "protobuf", version = "34.0.bcr.1", repo_name = "com_google_protobuf")
|
||||
bazel_dep(name = "zlib-ng", version = "2.0.7", repo_name = "llvm_zlib")
|
||||
bazel_dep(name = "zstd", version = "1.5.7.bcr.1", repo_name = "llvm_zstd")
|
||||
|
||||
@@ -102,26 +76,25 @@ bazel_dep(name = "zstd", version = "1.5.7.bcr.1", repo_name = "llvm_zstd")
|
||||
# llvm-project
|
||||
###############################################################################
|
||||
|
||||
# We pin to specific upstream commits and try to track top-of-tree reasonably
|
||||
# closely rather than pinning to a specific release.
|
||||
# HEAD as of 2026-01-08.
|
||||
llvm_project_version = "21a1e6e6a70d70635c68b9aaa54f816ae36a6416"
|
||||
|
||||
# Load a repository for the raw llvm-project, pre-overlay.
|
||||
http_archive(
|
||||
name = "llvm-raw",
|
||||
bazel_dep(name = "llvm-raw")
|
||||
git_override(
|
||||
module_name = "llvm-raw",
|
||||
build_file_content = "# empty",
|
||||
integrity = "sha256-ouWG2d4Cob9P6+dxCLZnV4RldSOqZp7mtwd6vd+ZK3Q=",
|
||||
patch_args = ["-p1"],
|
||||
# We pin to specific upstream commits and try to track top-of-tree
|
||||
# reasonably closely rather than pinning to a specific release.
|
||||
# HEAD as of 2026-04-01.
|
||||
commit = "b71eacea7687f68c11299e3bda5654fbbaa1e20e",
|
||||
patch_cmds = ["echo \"module(name='llvm-raw')\" > MODULE.bazel"],
|
||||
patch_strip = 1,
|
||||
patches = [
|
||||
"@carbon//bazel/llvm_project:0001_Patch_for_mallinfo2_when_using_Bazel_build_system.patch",
|
||||
"@carbon//bazel/llvm_project:0002_Added_Bazel_build_for_compiler_rt_fuzzer.patch",
|
||||
"@carbon//bazel/llvm_project:0004_Introduce_basic_sources_exporting_for_libunwind.patch",
|
||||
"@carbon//bazel/llvm_project:0005_Introduce_basic_sources_exporting_for_libcxx_and_libcxxabi.patch",
|
||||
"@carbon//bazel/llvm_project:0008_Add_filegroups_for_installed_compiler-rt_headers.patch",
|
||||
"//bazel/llvm_project:0001_Patch_for_mallinfo2_when_using_Bazel_build_system.patch",
|
||||
"//bazel/llvm_project:0002_Added_Bazel_build_for_compiler_rt_fuzzer.patch",
|
||||
"//bazel/llvm_project:0004_Introduce_basic_sources_exporting_for_libunwind.patch",
|
||||
"//bazel/llvm_project:0005_Introduce_basic_sources_exporting_for_libcxx_and_libcxxabi.patch",
|
||||
"//bazel/llvm_project:0009_Introduce_starlark_exporting_compiler-rt_build_information.patch",
|
||||
],
|
||||
strip_prefix = "llvm-project-{0}".format(llvm_project_version),
|
||||
urls = ["https://github.com/llvm/llvm-project/archive/{0}.tar.gz".format(llvm_project_version)],
|
||||
remote = "https://github.com/llvm/llvm-project.git",
|
||||
)
|
||||
|
||||
# Apply the overlay to produce llvm-project.
|
||||
@@ -135,7 +108,7 @@ use_repo(llvm_project, "llvm-project")
|
||||
# Python
|
||||
###############################################################################
|
||||
|
||||
bazel_dep(name = "rules_python", version = "1.8.3")
|
||||
bazel_dep(name = "rules_python", version = "1.9.0")
|
||||
|
||||
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
|
||||
python.toolchain(
|
||||
@@ -149,7 +122,7 @@ use_repo(python, "python_versions")
|
||||
|
||||
bazel_dep(
|
||||
name = "rules_bazel_integration_test",
|
||||
version = "0.36.0",
|
||||
version = "0.37.1",
|
||||
dev_dependency = True,
|
||||
)
|
||||
|
||||
|
||||
Generated
+57
-718
@@ -11,12 +11,13 @@
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20240116.0/MODULE.bazel": "98dc378d64c12a4e4741ad3362f87fb737ee6a0886b2d90c3cdbb4d93ea3e0bf",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20250127.0/MODULE.bazel": "d1086e248cda6576862b4b3fe9ad76a214e08c189af5b42557a6e1888812c5d5",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20250814.0/MODULE.bazel": "c43c16ca2c432566cdb78913964497259903ebe8fb7d9b57b38e9f1425b427b8",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20260107.0/MODULE.bazel": "94bdc259eccc59d880d3ae55e35ff1f27a289618a023cb1ed87182e17887b7c3",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20260107.0/source.json": "cd3c69eebe331264c87283774631f39006cd25caf159f4e1dab74322ef5c4bb9",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20260107.1/MODULE.bazel": "e33b3801443f5fd64465262084534115db76363df13d2168a42bbfacc747be81",
|
||||
"https://bcr.bazel.build/modules/abseil-cpp/20260107.1/source.json": "7a9a88969b1e79268cf613728ca8ff8fa4bc4b1a9abee9ec1fb5f113ca751971",
|
||||
"https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896",
|
||||
"https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85",
|
||||
"https://bcr.bazel.build/modules/apple_support/1.22.1/MODULE.bazel": "90bd1a660590f3ceffbdf524e37483094b29352d85317060b2327fff8f3f4458",
|
||||
@@ -65,8 +66,29 @@
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.9.0/MODULE.bazel": "72997b29dfd95c3fa0d0c48322d05590418edef451f8db8db5509c57875fb4b7",
|
||||
"https://bcr.bazel.build/modules/bazel_skylib/1.9.0/source.json": "7ad77c1e8c1b84222d9b3f3cae016a76639435744c19330b0b37c0a3c9da7dc0",
|
||||
"https://bcr.bazel.build/modules/boost.assert/1.90.0.bcr.1/MODULE.bazel": "82fa42de969959b0eb59b03b528b6ed6fdc130429766f980f0bda20a7efd09bb",
|
||||
"https://bcr.bazel.build/modules/boost.assert/1.90.0.bcr.1/source.json": "276a47c8c07761df24435e276ec6ed0ac859839ae9d62259787d222e022d23e2",
|
||||
"https://bcr.bazel.build/modules/boost.config/1.90.0.bcr.1/MODULE.bazel": "c14d7f8f9d6ba5d13383df5dabe296dcfef3925b398158b71c1c4080e2a14365",
|
||||
"https://bcr.bazel.build/modules/boost.config/1.90.0.bcr.1/source.json": "44b2941a2e656fd2c3747576ddd1e44e4d55c5d3ef5a22f0231f35c8dded3051",
|
||||
"https://bcr.bazel.build/modules/boost.container_hash/1.90.0.bcr.1/MODULE.bazel": "99905e56c4de3090bd802393e9a683fcf885f9ef9a7add79c05333de1c41ccf7",
|
||||
"https://bcr.bazel.build/modules/boost.container_hash/1.90.0.bcr.1/source.json": "9403da9bcc0f1600e569d7921aede5505a4f8407541597b00dcfd116ffb30580",
|
||||
"https://bcr.bazel.build/modules/boost.core/1.90.0.bcr.1/MODULE.bazel": "c94d17f2da1e7557046730a5647e06943e4e0fc10d6537e3656dbd23f8a0a573",
|
||||
"https://bcr.bazel.build/modules/boost.core/1.90.0.bcr.1/source.json": "5b3b6b9c6ea8e38e63d3b1a92370902a9ba78a4efd6c23df3c538d719a200cbe",
|
||||
"https://bcr.bazel.build/modules/boost.describe/1.90.0.bcr.1/MODULE.bazel": "ee5316a4d469c5a272e90b6a1c6f8185fb842a2a6401e970da159b08b4bdcc6a",
|
||||
"https://bcr.bazel.build/modules/boost.describe/1.90.0.bcr.1/source.json": "5ca72db73619c8915d030d88f7bcff970211daee4d7fa49a99ac3a510b507355",
|
||||
"https://bcr.bazel.build/modules/boost.mp11/1.90.0.bcr.1/MODULE.bazel": "9180b001b76e786d764f40b9cf9f3cffc92fd58b36fe7680b1f481e8e9991d2a",
|
||||
"https://bcr.bazel.build/modules/boost.mp11/1.90.0.bcr.1/source.json": "5720af0062e685970e3adcc72e925445171ba2ff192cde0b68c53031d25fa7f4",
|
||||
"https://bcr.bazel.build/modules/boost.predef/1.90.0.bcr.1/MODULE.bazel": "0c92fea5e1d63e301f7bb81763a5bfbb5f27204d6b6127e09ae23ae7d1bb3eaa",
|
||||
"https://bcr.bazel.build/modules/boost.predef/1.90.0.bcr.1/source.json": "f32e27769816c6de69925c5995733adf8e176e5a281d23c079c64aafae532e2f",
|
||||
"https://bcr.bazel.build/modules/boost.throw_exception/1.90.0.bcr.1/MODULE.bazel": "57242f92eecc485f09b07a8a1c8e2c7a6bf211808abb4599eec6fdbe875bb33f",
|
||||
"https://bcr.bazel.build/modules/boost.throw_exception/1.90.0.bcr.1/source.json": "1889e091be52f80ebb436305663c64bc631527445edb153e622f6e22010e6c9e",
|
||||
"https://bcr.bazel.build/modules/boost.unordered/1.90.0.bcr.1/MODULE.bazel": "4f7e455c70e9b3c57b840307aa77224011c10045082b45c0e46a1f96fce141ef",
|
||||
"https://bcr.bazel.build/modules/boost.unordered/1.90.0.bcr.1/source.json": "61fb5bd89e2f70131f4afb459e61f14faa5f0b6d5cbbfc0a5cc1e0bee6e6fece",
|
||||
"https://bcr.bazel.build/modules/boost/1.90.0.bcr.1/MODULE.bazel": "2f0a26d9a55a46017cf1f8a7895e49250f11306486419b002355f85ab595390f",
|
||||
"https://bcr.bazel.build/modules/boost/1.90.0.bcr.1/source.json": "3ba95d0dcf35d52e907cc82d460a27024270cd684641912e550bfb4102da1a9e",
|
||||
"https://bcr.bazel.build/modules/buildifier_prebuilt/7.3.1/MODULE.bazel": "537faf0ad9f5892910074b8e43b4c91c96f1d5d86b6ed04bdbe40cf68aa48b68",
|
||||
"https://bcr.bazel.build/modules/buildifier_prebuilt/7.3.1/source.json": "55153a5e6ca9c8a7e266c4b46b951e8a010d25ec6062bc35d5d4f89925796bad",
|
||||
"https://bcr.bazel.build/modules/buildifier_prebuilt/8.2.1.1/MODULE.bazel": "2e2e306add04b7c7cd21e73c9293dcbd7528a08a84338e919036f402eb6b1e2e",
|
||||
"https://bcr.bazel.build/modules/buildifier_prebuilt/8.2.1.1/source.json": "4c86fd3a384a09613c2213fb1f71562d6d70471977e6e81173e6625fd6ce53bc",
|
||||
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
|
||||
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
|
||||
"https://bcr.bazel.build/modules/cgrindel_bazel_starlib/0.28.0/MODULE.bazel": "85c2dba5f968cbf8aa0fc735cab450f16cd36eed58b941ff7e3587ad442d5627",
|
||||
@@ -94,8 +116,11 @@
|
||||
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
|
||||
"https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0",
|
||||
"https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000",
|
||||
"https://bcr.bazel.build/modules/libpfm/4.11.0.bcr.1/MODULE.bazel": "e5362dadc90aab6724c83a2cc1e67cbed9c89a05d97fb1f90053c8deb1e445c8",
|
||||
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
|
||||
"https://bcr.bazel.build/modules/libpfm/4.13.0/MODULE.bazel": "6f2fcac49a2ebd660573aa8075654d84a4904d3a8a7d416f3bde3678573a7244",
|
||||
"https://bcr.bazel.build/modules/libpfm/4.13.0/source.json": "d77a2fd45f92dcebdd864a3c2a05f28506a4f2f71ce15f85333d9ce5b9e29742",
|
||||
"https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74",
|
||||
"https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9",
|
||||
"https://bcr.bazel.build/modules/package_metadata/0.0.2/MODULE.bazel": "fb8d25550742674d63d7b250063d4580ca530499f045d70748b1b142081ebb92",
|
||||
"https://bcr.bazel.build/modules/package_metadata/0.0.2/source.json": "e53a759a72488d2c0576f57491ef2da0cf4aab05ac0997314012495935531b73",
|
||||
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
|
||||
@@ -121,9 +146,10 @@
|
||||
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
|
||||
"https://bcr.bazel.build/modules/protobuf/3.19.2/MODULE.bazel": "532ffe5f2186b69fdde039efe6df13ba726ff338c6bc82275ad433013fa10573",
|
||||
"https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858",
|
||||
"https://bcr.bazel.build/modules/protobuf/31.0/MODULE.bazel": "cce0f305064713b382211c4c5af1d4fc1466e1fbc9059aa0941801970f6add5c",
|
||||
"https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d",
|
||||
"https://bcr.bazel.build/modules/protobuf/34.0-rc1/MODULE.bazel": "3625d0d1e4032b624d093c1064cf4d7544caec48e66766f32b6407d4e15822f3",
|
||||
"https://bcr.bazel.build/modules/protobuf/34.0-rc1/source.json": "aab642d6812f4aaf3f2f1097f23182702c465aff1a79c86a8e6f32db1600934a",
|
||||
"https://bcr.bazel.build/modules/protobuf/34.0.bcr.1/MODULE.bazel": "74e541b0ba877813da786a11707d4e394433c157841d5111a36be0d44b907931",
|
||||
"https://bcr.bazel.build/modules/protobuf/34.0.bcr.1/source.json": "fc174b3d6215aa14197d1bd779f98bb72d9fd666ee5ec0d6bba6ae986baa4535",
|
||||
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1.bzl.1/MODULE.bazel": "1ef2994c097ee88f8f7ae8fbf991aaefb0603b2540fe575eca14943bc9f220a6",
|
||||
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
|
||||
"https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34",
|
||||
@@ -140,9 +166,8 @@
|
||||
"https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
|
||||
"https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
|
||||
"https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a",
|
||||
"https://bcr.bazel.build/modules/rules_apple/3.16.0/source.json": "d8b5fe461272018cc07cfafce11fe369c7525330804c37eec5a82f84cd475366",
|
||||
"https://bcr.bazel.build/modules/rules_bazel_integration_test/0.36.0/MODULE.bazel": "80e7595ab3a92ecd32f3cb00a60df6018e9eb1b2a2a3d5aa68d908514d0c6c69",
|
||||
"https://bcr.bazel.build/modules/rules_bazel_integration_test/0.36.0/source.json": "928bead08b5cf296bc0abd11f86989b13758891cfb7925885dde9c006a0c5b2f",
|
||||
"https://bcr.bazel.build/modules/rules_bazel_integration_test/0.37.1/MODULE.bazel": "f0ae81ced7a917eb59f865ebd2307af9e142763783990ac1207140ad6275505e",
|
||||
"https://bcr.bazel.build/modules/rules_bazel_integration_test/0.37.1/source.json": "9123f56b53be8d7dbe6b90a753bb2443e286605e70e485cd4f649d8ab7fe2564",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
|
||||
@@ -160,7 +185,8 @@
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.16/MODULE.bazel": "9242fa89f950c6ef7702801ab53922e99c69b02310c39fb6e62b2bd30df2a1d4",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.16/source.json": "d03d5cde49376d87e14ec14b666c56075e5e3926930327fd5d0484a1ff2ac1cc",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642",
|
||||
"https://bcr.bazel.build/modules/rules_cc/0.2.9/MODULE.bazel": "34263f1dca62ea664265438cef714d7db124c03e1ed55ebb4f1dc860164308d1",
|
||||
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
|
||||
@@ -233,8 +259,8 @@
|
||||
"https://bcr.bazel.build/modules/rules_python/1.5.1/MODULE.bazel": "acfe65880942d44a69129d4c5c3122d57baaf3edf58ae5a6bd4edea114906bf5",
|
||||
"https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8",
|
||||
"https://bcr.bazel.build/modules/rules_python/1.6.3/MODULE.bazel": "a7b80c42cb3de5ee2a5fa1abc119684593704fcd2fec83165ebe615dec76574f",
|
||||
"https://bcr.bazel.build/modules/rules_python/1.8.3/MODULE.bazel": "f343e159b59701334be3914416b9f1b72845801ba47920fcb288af4ce8c5cce3",
|
||||
"https://bcr.bazel.build/modules/rules_python/1.8.3/source.json": "e5439f308e3c6f79f318a0f87108db46fc575be89370c3dfb3f7e0eaa571a3f8",
|
||||
"https://bcr.bazel.build/modules/rules_python/1.9.0/MODULE.bazel": "afc3a05f29f09f2d3ee95ad99a145250dab41a2b2d8d6f82cc91936b3213282c",
|
||||
"https://bcr.bazel.build/modules/rules_python/1.9.0/source.json": "3921ea0b65298d51aead5b9e4a82203d7be9b5918619b58b53f1c259f4e63169",
|
||||
"https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
|
||||
"https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b",
|
||||
"https://bcr.bazel.build/modules/rules_shell/0.4.1/MODULE.bazel": "00e501db01bbf4e3e1dd1595959092c2fadf2087b2852d3f553b5370f5633592",
|
||||
@@ -242,7 +268,6 @@
|
||||
"https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c",
|
||||
"https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca",
|
||||
"https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046",
|
||||
"https://bcr.bazel.build/modules/rules_swift/2.1.1/source.json": "40fc69dfaac64deddbb75bd99cdac55f4427d9ca0afbe408576a65428427a186",
|
||||
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
|
||||
"https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
|
||||
"https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef",
|
||||
@@ -253,14 +278,13 @@
|
||||
"https://bcr.bazel.build/modules/stardoc/0.8.0/MODULE.bazel": "bbad4298d7ba185684f5fcd71b049c95b0575d1248891fd80b8d7077d647c9d8",
|
||||
"https://bcr.bazel.build/modules/stardoc/0.8.0/source.json": "7321db37080ee8a445dc60e8516a98ab3a27884d1457b892485d73759ccb7f4d",
|
||||
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91",
|
||||
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/source.json": "32bd87e5f4d7acc57c5b2ff7c325ae3061d5e242c0c4c214ae87e0f1c13e54cb",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.2.1/MODULE.bazel": "52d1c00a80a8cc67acbd01649e83d8dd6a9dc426a6c0b754a04fe8c219c76468",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.5.1/MODULE.bazel": "7c2eb3dcfc53b0f3d6f9acdfd911ca803eaf92aadf54f8ca6e4c1f3aee288351",
|
||||
"https://bcr.bazel.build/modules/tar.bzl/0.5.1/source.json": "deed3094f7cc779ed1d37a68403847b0e38d9dd9d931e03cb90825f3368b515f",
|
||||
"https://bcr.bazel.build/modules/tcmalloc/0.0.0-20250927-12f2552/MODULE.bazel": "b702a6b6806b1041d84918c5098b765b204261647f8cb3e75e0f439106b65ddd",
|
||||
"https://bcr.bazel.build/modules/tcmalloc/0.0.0-20250927-12f2552/source.json": "a6f5da61dd65e3f2f7380b4f52dd4b0f771a5b6ba9db7b46be7c28c52bc7af58",
|
||||
"https://bcr.bazel.build/modules/tree-sitter-bazel/0.26.3.bcr.1/MODULE.bazel": "f1a345fed7a67d7638580bad407f34d06eee2ca61816e3e7e75c80a1c0a2e610",
|
||||
"https://bcr.bazel.build/modules/tree-sitter-bazel/0.26.3.bcr.1/source.json": "4e468b20cd538648e5a9ac3581ff459e68509bd5b7ce467f6faf0382a469b0c1",
|
||||
"https://bcr.bazel.build/modules/tree-sitter-bazel/0.26.5/MODULE.bazel": "89490910fa107d8ef22cc8c3be7acbce733c2352739c7a61297336454a539a65",
|
||||
"https://bcr.bazel.build/modules/tree-sitter-bazel/0.26.5/source.json": "cd6d21ca1b159961230ac6c33e0c7f638d7c40daa6746b4097d896441fd89074",
|
||||
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
|
||||
"https://bcr.bazel.build/modules/upb/0.0.0-20230516-61a97ef/MODULE.bazel": "c0df5e35ad55e264160417fd0875932ee3c9dda63d9fccace35ac62f45e1b6f9",
|
||||
"https://bcr.bazel.build/modules/yq.bzl/0.1.1/MODULE.bazel": "9039681f9bcb8958ee2c87ffc74bdafba9f4369096a2b5634b88abc0eaefa072",
|
||||
@@ -279,7 +303,7 @@
|
||||
"moduleExtensions": {
|
||||
"//bazel/cc_toolchains:clang_configuration.bzl%clang_toolchain_extension": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "44/bjnoCpU6JrWf798MGhACH/QjSv0OkcCi/jF+EGg0=",
|
||||
"bzlTransitiveDigest": "H3RsK0MbgutDMSlPWTwZq4Vk1U5sjDtgJ5MXQxg7GLU=",
|
||||
"usagesDigest": "lTxkeAFhR0iBEa3dg5hWvtd2HFCr5zCJx/fl27A+IKA=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
@@ -302,7 +326,7 @@
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"llvm-project": {
|
||||
"repoRuleId": "@@+_repo_rules+llvm-raw//utils/bazel:configure.bzl%llvm_configure",
|
||||
"repoRuleId": "@@llvm-raw+//utils/bazel:configure.bzl%llvm_configure",
|
||||
"attributes": {
|
||||
"targets": [
|
||||
"AArch64",
|
||||
@@ -315,146 +339,7 @@
|
||||
[
|
||||
"",
|
||||
"llvm-raw",
|
||||
"+_repo_rules+llvm-raw"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"@@buildifier_prebuilt+//:defs.bzl%buildifier_prebuilt_deps_extension": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "o1WPvgvSISMJsXVrFW1v+M17eIj9AJjkcTAucRVb3vI=",
|
||||
"usagesDigest": "eWMDBEn8E8CrwAPXrlrjIap2pseSMhxDyDdrntHBOOE=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"buildifier_darwin_amd64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-darwin-amd64"
|
||||
],
|
||||
"downloaded_file_path": "buildifier",
|
||||
"executable": true,
|
||||
"sha256": "375f823103d01620aaec20a0c29c6cbca99f4fd0725ae30b93655c6704f44d71"
|
||||
}
|
||||
},
|
||||
"buildifier_darwin_arm64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-darwin-arm64"
|
||||
],
|
||||
"downloaded_file_path": "buildifier",
|
||||
"executable": true,
|
||||
"sha256": "5a6afc6ac7a09f5455ba0b89bd99d5ae23b4174dc5dc9d6c0ed5ce8caac3f813"
|
||||
}
|
||||
},
|
||||
"buildifier_linux_amd64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-linux-amd64"
|
||||
],
|
||||
"downloaded_file_path": "buildifier",
|
||||
"executable": true,
|
||||
"sha256": "5474cc5128a74e806783d54081f581662c4be8ae65022f557e9281ed5dc88009"
|
||||
}
|
||||
},
|
||||
"buildifier_linux_arm64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-linux-arm64"
|
||||
],
|
||||
"downloaded_file_path": "buildifier",
|
||||
"executable": true,
|
||||
"sha256": "0bf86c4bfffaf4f08eed77bde5b2082e4ae5039a11e2e8b03984c173c34a561c"
|
||||
}
|
||||
},
|
||||
"buildifier_windows_amd64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildifier-windows-amd64.exe"
|
||||
],
|
||||
"downloaded_file_path": "buildifier.exe",
|
||||
"executable": true,
|
||||
"sha256": "370cd576075ad29930a82f5de132f1a1de4084c784a82514bd4da80c85acf4a8"
|
||||
}
|
||||
},
|
||||
"buildozer_darwin_amd64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-darwin-amd64"
|
||||
],
|
||||
"downloaded_file_path": "buildozer",
|
||||
"executable": true,
|
||||
"sha256": "854c9583efc166602276802658cef3f224d60898cfaa60630b33d328db3b0de2"
|
||||
}
|
||||
},
|
||||
"buildozer_darwin_arm64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-darwin-arm64"
|
||||
],
|
||||
"downloaded_file_path": "buildozer",
|
||||
"executable": true,
|
||||
"sha256": "31b1bfe20d7d5444be217af78f94c5c43799cdf847c6ce69794b7bf3319c5364"
|
||||
}
|
||||
},
|
||||
"buildozer_linux_amd64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-linux-amd64"
|
||||
],
|
||||
"downloaded_file_path": "buildozer",
|
||||
"executable": true,
|
||||
"sha256": "3305e287b3fcc68b9a35fd8515ee617452cd4e018f9e6886b6c7cdbcba8710d4"
|
||||
}
|
||||
},
|
||||
"buildozer_linux_arm64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-linux-arm64"
|
||||
],
|
||||
"downloaded_file_path": "buildozer",
|
||||
"executable": true,
|
||||
"sha256": "0b5a2a717ac4fc911e1fec8d92af71dbb4fe95b10e5213da0cc3d56cea64a328"
|
||||
}
|
||||
},
|
||||
"buildozer_windows_amd64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/bazelbuild/buildtools/releases/download/v7.3.1/buildozer-windows-amd64.exe"
|
||||
],
|
||||
"downloaded_file_path": "buildozer.exe",
|
||||
"executable": true,
|
||||
"sha256": "58d41ce53257c5594c9bc86d769f580909269f68de114297f46284fbb9023dcf"
|
||||
}
|
||||
},
|
||||
"buildifier_prebuilt_toolchains": {
|
||||
"repoRuleId": "@@buildifier_prebuilt+//:defs.bzl%_buildifier_toolchain_setup",
|
||||
"attributes": {
|
||||
"assets_json": "[{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"darwin\",\"sha256\":\"375f823103d01620aaec20a0c29c6cbca99f4fd0725ae30b93655c6704f44d71\",\"version\":\"v7.3.1\"},{\"arch\":\"arm64\",\"name\":\"buildifier\",\"platform\":\"darwin\",\"sha256\":\"5a6afc6ac7a09f5455ba0b89bd99d5ae23b4174dc5dc9d6c0ed5ce8caac3f813\",\"version\":\"v7.3.1\"},{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"linux\",\"sha256\":\"5474cc5128a74e806783d54081f581662c4be8ae65022f557e9281ed5dc88009\",\"version\":\"v7.3.1\"},{\"arch\":\"arm64\",\"name\":\"buildifier\",\"platform\":\"linux\",\"sha256\":\"0bf86c4bfffaf4f08eed77bde5b2082e4ae5039a11e2e8b03984c173c34a561c\",\"version\":\"v7.3.1\"},{\"arch\":\"amd64\",\"name\":\"buildifier\",\"platform\":\"windows\",\"sha256\":\"370cd576075ad29930a82f5de132f1a1de4084c784a82514bd4da80c85acf4a8\",\"version\":\"v7.3.1\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"darwin\",\"sha256\":\"854c9583efc166602276802658cef3f224d60898cfaa60630b33d328db3b0de2\",\"version\":\"v7.3.1\"},{\"arch\":\"arm64\",\"name\":\"buildozer\",\"platform\":\"darwin\",\"sha256\":\"31b1bfe20d7d5444be217af78f94c5c43799cdf847c6ce69794b7bf3319c5364\",\"version\":\"v7.3.1\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"linux\",\"sha256\":\"3305e287b3fcc68b9a35fd8515ee617452cd4e018f9e6886b6c7cdbcba8710d4\",\"version\":\"v7.3.1\"},{\"arch\":\"arm64\",\"name\":\"buildozer\",\"platform\":\"linux\",\"sha256\":\"0b5a2a717ac4fc911e1fec8d92af71dbb4fe95b10e5213da0cc3d56cea64a328\",\"version\":\"v7.3.1\"},{\"arch\":\"amd64\",\"name\":\"buildozer\",\"platform\":\"windows\",\"sha256\":\"58d41ce53257c5594c9bc86d769f580909269f68de114297f46284fbb9023dcf\",\"version\":\"v7.3.1\"}]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": [
|
||||
[
|
||||
"buildifier_prebuilt+",
|
||||
"bazel_skylib",
|
||||
"bazel_skylib+"
|
||||
],
|
||||
[
|
||||
"buildifier_prebuilt+",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
"llvm-raw+"
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -475,174 +360,22 @@
|
||||
"recordedRepoMappingEntries": []
|
||||
}
|
||||
},
|
||||
"@@hedron_compile_commands+//:workspace_setup.bzl%hedron_compile_commands_extension": {
|
||||
"@@protobuf+//python/dist:system_python.bzl%system_python_extension": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "GTNjt7oW5GiUBfcBtXAq5etqAZ6ue6PRd5nPaxeMoYM=",
|
||||
"usagesDigest": "CbJ2MjubH36j9xaONhhASfhodhpi5fzvuyg/IW2f7Ds=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {},
|
||||
"recordedRepoMappingEntries": [
|
||||
[
|
||||
"hedron_compile_commands+",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"@@hedron_compile_commands+//:workspace_setup_transitive.bzl%hedron_compile_commands_extension": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "IfDf0vEa2jjQ11RNpUM0u4xftPXIs+pyM8IMVkRqVMk=",
|
||||
"usagesDigest": "yxZQbFglJyjpn7JZ9mhIc3EhLzZivlbs6wiHWOKJ/UA=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {},
|
||||
"recordedRepoMappingEntries": []
|
||||
}
|
||||
},
|
||||
"@@hedron_compile_commands+//:workspace_setup_transitive_transitive.bzl%hedron_compile_commands_extension": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "1p58k3o2Jgjt/pBE7cb8WmmkplrSguIKma/h32x7X10=",
|
||||
"usagesDigest": "GkOuy/k8wz0dbKMeEJFKEJB3CWkMZt3DYcPgj4lALkI=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {},
|
||||
"recordedRepoMappingEntries": []
|
||||
}
|
||||
},
|
||||
"@@hedron_compile_commands+//:workspace_setup_transitive_transitive_transitive.bzl%hedron_compile_commands_extension": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "arNWX4EleUjJxqkM5nCRTj+ce05Zz1gSdGH1DCKOoLs=",
|
||||
"usagesDigest": "WZExKK/BI4lqpUZfPpv4YARDE1Y7igQB+wYGKvNoCKs=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {},
|
||||
"recordedRepoMappingEntries": []
|
||||
}
|
||||
},
|
||||
"@@rules_apple+//apple:apple.bzl%provisioning_profile_repository_extension": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "pdRt+Wm+XQmS427nAIg9z7qfm56CnZChO+HJ4zu3Xa8=",
|
||||
"usagesDigest": "vsJl8Rw5NL+5Ag2wdUDoTeRF/5klkXO8545Iy7U1Q08=",
|
||||
"bzlTransitiveDigest": "pmsA+awieucfllLc2n7k8xEoPp0i5LF9Hw6mGX0cqSQ=",
|
||||
"usagesDigest": "A+RWmbKdBBwZcBbNGNvfPbqG2vYZRjVrFp6x1iRUrAk=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"local_provisioning_profiles": {
|
||||
"repoRuleId": "@@rules_apple+//apple/internal:local_provisioning_profiles.bzl%provisioning_profile_repository",
|
||||
"attributes": {}
|
||||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": [
|
||||
[
|
||||
"apple_support+",
|
||||
"bazel_skylib",
|
||||
"bazel_skylib+"
|
||||
],
|
||||
[
|
||||
"bazel_tools",
|
||||
"rules_cc",
|
||||
"rules_cc+"
|
||||
],
|
||||
[
|
||||
"rules_apple+",
|
||||
"bazel_skylib",
|
||||
"bazel_skylib+"
|
||||
],
|
||||
[
|
||||
"rules_apple+",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
],
|
||||
[
|
||||
"rules_apple+",
|
||||
"build_bazel_apple_support",
|
||||
"apple_support+"
|
||||
],
|
||||
[
|
||||
"rules_apple+",
|
||||
"build_bazel_rules_swift",
|
||||
"rules_swift+"
|
||||
],
|
||||
[
|
||||
"rules_cc+",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
],
|
||||
[
|
||||
"rules_cc+",
|
||||
"cc_compatibility_proxy",
|
||||
"rules_cc++compatibility_proxy+cc_compatibility_proxy"
|
||||
],
|
||||
[
|
||||
"rules_cc+",
|
||||
"rules_cc",
|
||||
"rules_cc+"
|
||||
],
|
||||
[
|
||||
"rules_cc++compatibility_proxy+cc_compatibility_proxy",
|
||||
"rules_cc",
|
||||
"rules_cc+"
|
||||
],
|
||||
[
|
||||
"rules_swift+",
|
||||
"bazel_skylib",
|
||||
"bazel_skylib+"
|
||||
],
|
||||
[
|
||||
"rules_swift+",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
],
|
||||
[
|
||||
"rules_swift+",
|
||||
"build_bazel_apple_support",
|
||||
"apple_support+"
|
||||
],
|
||||
[
|
||||
"rules_swift+",
|
||||
"build_bazel_rules_swift",
|
||||
"rules_swift+"
|
||||
],
|
||||
[
|
||||
"rules_swift+",
|
||||
"build_bazel_rules_swift_local_config",
|
||||
"rules_swift++non_module_deps+build_bazel_rules_swift_local_config"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"@@rules_apple+//apple:extensions.bzl%non_module_deps": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "UsflLeiazyu2v5pvibcvOeIdDV95S25rT96h4XU1nhY=",
|
||||
"usagesDigest": "M3VqFpeTCo4qmrNKGZw0dxBHvTYDrfV3cscGzlSAhQ4=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"xctestrunner": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"system_python": {
|
||||
"repoRuleId": "@@protobuf+//python/dist:system_python.bzl%system_python",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/google/xctestrunner/archive/b7698df3d435b6491b4b4c0f9fc7a63fbed5e3a6.tar.gz"
|
||||
],
|
||||
"strip_prefix": "xctestrunner-b7698df3d435b6491b4b4c0f9fc7a63fbed5e3a6",
|
||||
"sha256": "ae3a063c985a8633cb7eb566db21656f8db8eb9a0edb8c182312c7f0db53730d"
|
||||
"minimum_python_version": "3.9"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": [
|
||||
[
|
||||
"rules_apple+",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
]
|
||||
]
|
||||
"recordedRepoMappingEntries": []
|
||||
}
|
||||
},
|
||||
"@@rules_bazel_integration_test+//:extensions.bzl%bazel_binaries": {
|
||||
@@ -782,245 +515,10 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"@@rules_python+//python/extensions:config.bzl%config": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "uo49IDITNsksO4x76pZ7eYlLKomkU77mK8VTrbCHXZM=",
|
||||
"usagesDigest": "HZ99ezJBkgjKcxXQ3OBxGgesUIMF6eg7E0TUNOait2I=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"rules_python_internal": {
|
||||
"repoRuleId": "@@rules_python+//python/private:internal_config_repo.bzl%internal_config_repo",
|
||||
"attributes": {
|
||||
"transition_setting_generators": {},
|
||||
"transition_settings": []
|
||||
}
|
||||
},
|
||||
"pypi__build": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/e2/03/f3c8ba0a6b6e30d7d18c40faab90807c9bb5e9a1e3b2fe2008af624a9c97/build-1.2.1-py3-none-any.whl",
|
||||
"sha256": "75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__click": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl",
|
||||
"sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__colorama": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl",
|
||||
"sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__importlib_metadata": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl",
|
||||
"sha256": "30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__installer": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl",
|
||||
"sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__more_itertools": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/50/e2/8e10e465ee3987bb7c9ab69efb91d867d93959095f4807db102d07995d94/more_itertools-10.2.0-py3-none-any.whl",
|
||||
"sha256": "686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__packaging": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl",
|
||||
"sha256": "2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__pep517": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/25/6e/ca4a5434eb0e502210f591b97537d322546e4833dcb4d470a48c375c5540/pep517-0.13.1-py3-none-any.whl",
|
||||
"sha256": "31b206f67165b3536dd577c5c3f1518e8fbaf38cbc57efff8369a392feff1721",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__pip": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl",
|
||||
"sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__pip_tools": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/0d/dc/38f4ce065e92c66f058ea7a368a9c5de4e702272b479c0992059f7693941/pip_tools-7.4.1-py3-none-any.whl",
|
||||
"sha256": "4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__pyproject_hooks": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/ae/f3/431b9d5fe7d14af7a32340792ef43b8a714e7726f1d7b69cc4e8e7a3f1d7/pyproject_hooks-1.1.0-py3-none-any.whl",
|
||||
"sha256": "7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__setuptools": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/90/99/158ad0609729111163fc1f674a5a42f2605371a4cf036d0441070e2f7455/setuptools-78.1.1-py3-none-any.whl",
|
||||
"sha256": "c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__tomli": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl",
|
||||
"sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__wheel": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl",
|
||||
"sha256": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"pypi__zipp": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"url": "https://files.pythonhosted.org/packages/da/55/a03fd7240714916507e1fcf7ae355bd9d9ed2e6db492595f1a67f61681be/zipp-3.18.2-py3-none-any.whl",
|
||||
"sha256": "dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e",
|
||||
"type": "zip",
|
||||
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": [
|
||||
[
|
||||
"rules_python+",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__build",
|
||||
"rules_python++config+pypi__build"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__click",
|
||||
"rules_python++config+pypi__click"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__colorama",
|
||||
"rules_python++config+pypi__colorama"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__importlib_metadata",
|
||||
"rules_python++config+pypi__importlib_metadata"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__installer",
|
||||
"rules_python++config+pypi__installer"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__more_itertools",
|
||||
"rules_python++config+pypi__more_itertools"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__packaging",
|
||||
"rules_python++config+pypi__packaging"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__pep517",
|
||||
"rules_python++config+pypi__pep517"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__pip",
|
||||
"rules_python++config+pypi__pip"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__pip_tools",
|
||||
"rules_python++config+pypi__pip_tools"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__pyproject_hooks",
|
||||
"rules_python++config+pypi__pyproject_hooks"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__setuptools",
|
||||
"rules_python++config+pypi__setuptools"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__tomli",
|
||||
"rules_python++config+pypi__tomli"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__wheel",
|
||||
"rules_python++config+pypi__wheel"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"pypi__zipp",
|
||||
"rules_python++config+pypi__zipp"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"@@rules_python+//python/uv:uv.bzl%uv": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "zyNsrbgVKwpA0B3zI84imAfuC424VSzYNPgjr/HJy5M=",
|
||||
"usagesDigest": "XRYYokHTb3p1WwpZj2sncZ1bh8zJfO4YrKJ2PkapnO8=",
|
||||
"bzlTransitiveDigest": "xMgnVVV6SeyGCaYQT+4rYddx63q6+JXtyCrlLeA8OLM=",
|
||||
"usagesDigest": "6MjoD3H+netDdhklgMWks3NARpHVXxy8kfsMe9XXPa8=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
@@ -1058,165 +556,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"@@rules_swift+//swift:extensions.bzl%non_module_deps": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "WQxCEBSXJEaQYe860JXZvAQug2B6+/VbBtRIDMF0pOc=",
|
||||
"usagesDigest": "mhACFnrdMv9Wi0Mt67bxocJqviRkDSV+Ee5Mqdj5akA=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"com_github_apple_swift_protobuf": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/apple/swift-protobuf/archive/1.20.2.tar.gz"
|
||||
],
|
||||
"sha256": "3fb50bd4d293337f202d917b6ada22f9548a0a0aed9d9a4d791e6fbd8a246ebb",
|
||||
"strip_prefix": "swift-protobuf-1.20.2/",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_protobuf/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"com_github_grpc_grpc_swift": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/grpc/grpc-swift/archive/1.16.0.tar.gz"
|
||||
],
|
||||
"sha256": "58b60431d0064969f9679411264b82e40a217ae6bd34e17096d92cc4e47556a5",
|
||||
"strip_prefix": "grpc-swift-1.16.0/",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_grpc_grpc_swift/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_docc_symbolkit": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/apple/swift-docc-symbolkit/archive/refs/tags/swift-5.10-RELEASE.tar.gz"
|
||||
],
|
||||
"sha256": "de1d4b6940468ddb53b89df7aa1a81323b9712775b0e33e8254fa0f6f7469a97",
|
||||
"strip_prefix": "swift-docc-symbolkit-swift-5.10-RELEASE",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_docc_symbolkit/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_nio": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/apple/swift-nio/archive/2.42.0.tar.gz"
|
||||
],
|
||||
"sha256": "e3304bc3fb53aea74a3e54bd005ede11f6dc357117d9b1db642d03aea87194a0",
|
||||
"strip_prefix": "swift-nio-2.42.0/",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_nio/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_nio_http2": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/apple/swift-nio-http2/archive/1.26.0.tar.gz"
|
||||
],
|
||||
"sha256": "f0edfc9d6a7be1d587e5b403f2d04264bdfae59aac1d74f7d974a9022c6d2b25",
|
||||
"strip_prefix": "swift-nio-http2-1.26.0/",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_nio_http2/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_nio_transport_services": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/apple/swift-nio-transport-services/archive/1.15.0.tar.gz"
|
||||
],
|
||||
"sha256": "f3498dafa633751a52b9b7f741f7ac30c42bcbeb3b9edca6d447e0da8e693262",
|
||||
"strip_prefix": "swift-nio-transport-services-1.15.0/",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_nio_transport_services/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_nio_extras": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/apple/swift-nio-extras/archive/1.4.0.tar.gz"
|
||||
],
|
||||
"sha256": "4684b52951d9d9937bb3e8ccd6b5daedd777021ef2519ea2f18c4c922843b52b",
|
||||
"strip_prefix": "swift-nio-extras-1.4.0/",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_nio_extras/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_log": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/apple/swift-log/archive/1.4.4.tar.gz"
|
||||
],
|
||||
"sha256": "48fe66426c784c0c20031f15dc17faf9f4c9037c192bfac2f643f65cb2321ba0",
|
||||
"strip_prefix": "swift-log-1.4.4/",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_log/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_nio_ssl": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/apple/swift-nio-ssl/archive/2.23.0.tar.gz"
|
||||
],
|
||||
"sha256": "4787c63f61dd04d99e498adc3d1a628193387e41efddf8de19b8db04544d016d",
|
||||
"strip_prefix": "swift-nio-ssl-2.23.0/",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_nio_ssl/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_collections": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/apple/swift-collections/archive/1.0.4.tar.gz"
|
||||
],
|
||||
"sha256": "d9e4c8a91c60fb9c92a04caccbb10ded42f4cb47b26a212bc6b39cc390a4b096",
|
||||
"strip_prefix": "swift-collections-1.0.4/",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_collections/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_atomics": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/apple/swift-atomics/archive/1.1.0.tar.gz"
|
||||
],
|
||||
"sha256": "1bee7f469f7e8dc49f11cfa4da07182fbc79eab000ec2c17bfdce468c5d276fb",
|
||||
"strip_prefix": "swift-atomics-1.1.0/",
|
||||
"build_file": "@@rules_swift+//third_party:com_github_apple_swift_atomics/BUILD.overlay"
|
||||
}
|
||||
},
|
||||
"build_bazel_rules_swift_index_import": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"build_file": "@@rules_swift+//third_party:build_bazel_rules_swift_index_import/BUILD.overlay",
|
||||
"canonical_id": "index-import-5.8",
|
||||
"urls": [
|
||||
"https://github.com/MobileNativeFoundation/index-import/releases/download/5.8.0.1/index-import.tar.gz"
|
||||
],
|
||||
"sha256": "28c1ffa39d99e74ed70623899b207b41f79214c498c603915aef55972a851a15"
|
||||
}
|
||||
},
|
||||
"build_bazel_rules_swift_local_config": {
|
||||
"repoRuleId": "@@rules_swift+//swift/internal:swift_autoconfiguration.bzl%swift_autoconfiguration",
|
||||
"attributes": {}
|
||||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": [
|
||||
[
|
||||
"rules_swift+",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
],
|
||||
[
|
||||
"rules_swift+",
|
||||
"build_bazel_rules_swift",
|
||||
"rules_swift+"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"@@tar.bzl+//tar:extensions.bzl%toolchains": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "/2afh6fPjq/rcyE/jztQDK3ierehmFFngfvmqyRv72M=",
|
||||
@@ -1273,8 +612,8 @@
|
||||
},
|
||||
"@@tree-sitter-bazel+//:extensions.bzl%tree_sitter_source_code": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "KYhQoHhKhCJWpa7kdOCSJHfvoRI6uarN4w0fyeq4iR4=",
|
||||
"usagesDigest": "hkrVfsiyTLSTF7N2MmeQQHb6pousjxoec1z1ssf1ves=",
|
||||
"bzlTransitiveDigest": "+u7gt12DDE2IggDr5YYMDsyBWdTH2+a+CzDt4N2GLEA=",
|
||||
"usagesDigest": "SDugPL30QE62Ha2gZXbI9INYOeOxsPevizX6CCLFoto=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
@@ -1283,11 +622,11 @@
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/tree-sitter/tree-sitter/archive/refs/tags/v0.26.3.tar.gz"
|
||||
"https://github.com/tree-sitter/tree-sitter/archive/refs/tags/v0.26.5.tar.gz"
|
||||
],
|
||||
"sha256": "",
|
||||
"integrity": "sha384-hjXxOdrMwTow3ji5CeIL5UchJHXQYTIU/MOZ4cG+TPqS0kQaEF9HsGianilGFIY+",
|
||||
"strip_prefix": "tree-sitter-0.26.3",
|
||||
"integrity": "sha384-UFn59au2/IMpAb2LqYOhZsHOhoFOttBAnZ5wPPPL4woryAnZyW/c1xEiiBobALr/",
|
||||
"strip_prefix": "tree-sitter-0.26.5",
|
||||
"build_file_content": "exports_files(glob([\"lib/**\"]))"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,6 +365,19 @@ Learn more about the Carbon project:
|
||||
|
||||
Carbon focused talks from the community:
|
||||
|
||||
### 2026
|
||||
|
||||
- Benchmarking and optimizing the Carbon compiler, NDC {Toronto} (May 5-8)
|
||||
- Carbon: graduating from the experiment, NDC {Toronto} (May 5-8)
|
||||
|
||||
### 2025
|
||||
|
||||
- Carbon: from C++ to Memory Safety, REBASE - ICFP/SPLASH
|
||||
([slides](https://chandlerc.blog/slides/2025-rebase-carbon))
|
||||
- Memory safety everywhere with both Carbon and Rust, RustConf
|
||||
([video](https://youtu.be/FYLuom6gg_s),
|
||||
[slides](https://chandlerc.blog/slides/2025-rustconf-memory-safety-everywhere))
|
||||
|
||||
### 2024
|
||||
|
||||
- Generic implementation strategies in Carbon and Clang, LLVM Developers'
|
||||
|
||||
@@ -27,7 +27,6 @@ If you haven't received a response, a couple steps to take are (in order):
|
||||
1. Contact individuals directly:
|
||||
- [Chandler Carruth](mailto:chandlerc@gmail.com)
|
||||
- [Richard Smith](mailto:richard@metafoo.co.uk)
|
||||
- [Jon Ross-Perkins](mailto:jperkins@google.com)
|
||||
2. Reach out on
|
||||
[#infra](https://discord.com/channels/655572317891461132/707150492370862090)
|
||||
on Discord ([invite](https://discord.gg/ZjVdShJDAs))
|
||||
|
||||
+45
-23
@@ -4,20 +4,10 @@
|
||||
|
||||
"""Provides rules for building Carbon files using the toolchain."""
|
||||
|
||||
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
|
||||
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
|
||||
load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
|
||||
|
||||
def _runtimes_path(runtimes_target):
|
||||
path = None
|
||||
for f in runtimes_target:
|
||||
if f.short_path.endswith("clang_resource_dir/lib"):
|
||||
path = f.path
|
||||
break
|
||||
|
||||
if not path:
|
||||
fail("Could not find the `clang_resource_dir` in target {}".format(runtimes_target.label))
|
||||
|
||||
return path[:-len("/clang_resource_dir/lib")]
|
||||
|
||||
def _carbon_binary_impl(ctx):
|
||||
toolchain_driver = ctx.executable.internal_exec_toolchain_driver
|
||||
toolchain_data = ctx.files.internal_exec_toolchain_data
|
||||
@@ -30,10 +20,12 @@ def _carbon_binary_impl(ctx):
|
||||
toolchain_data = ctx.files.internal_target_toolchain_data
|
||||
prebuilt_runtimes = ctx.files.internal_target_prebuilt_runtimes
|
||||
|
||||
# The extra link flags needed.
|
||||
link_flags = []
|
||||
|
||||
# Pass any C++ flags from our dependencies onto Carbon.
|
||||
dep_flags = []
|
||||
dep_hdrs = []
|
||||
dep_link_flags = []
|
||||
dep_link_inputs = []
|
||||
for dep in ctx.attr.deps:
|
||||
if CcInfo in dep:
|
||||
@@ -47,15 +39,16 @@ def _carbon_binary_impl(ctx):
|
||||
dep_flags += ["--clang-arg=-isystem{0}".format(path) for path in cc_info.compilation_context.system_includes.to_list()]
|
||||
dep_hdrs.append(cc_info.compilation_context.headers)
|
||||
for link_input in cc_info.linking_context.linker_inputs.to_list():
|
||||
# TODO: `carbon link` doesn't support linker flags yet.
|
||||
# dep_link_flags += link_input.user_link_flags
|
||||
link_flags += link_input.user_link_flags
|
||||
dep_link_inputs += link_input.additional_inputs
|
||||
for lib in link_input.libraries:
|
||||
dep_link_inputs += [dep for dep in [lib.dynamic_library, lib.static_library] if dep]
|
||||
dep_link_inputs += lib.objects
|
||||
if DefaultInfo in dep:
|
||||
dep_link_inputs += dep[DefaultInfo].files.to_list()
|
||||
dep_link_flags += [dep.path for dep in dep_link_inputs]
|
||||
|
||||
# Add the dependencies' link flags and inputs to the link flags.
|
||||
link_flags += [dep.path for dep in dep_link_inputs]
|
||||
|
||||
# Build object files for the prelude and for the binary itself.
|
||||
# TODO: Eventually the prelude should be build as a separate `carbon_library`.
|
||||
@@ -89,19 +82,47 @@ def _carbon_binary_impl(ctx):
|
||||
inputs = depset(direct = srcs_reordered, transitive = dep_hdrs),
|
||||
executable = toolchain_driver,
|
||||
tools = depset(toolchain_data),
|
||||
arguments = ["compile", "--output=" + out.path] +
|
||||
arguments = ["compile", "--output=" + out.path, "--output-last-input-only"] +
|
||||
[s.path for s in srcs_reordered] + extra_flags + ctx.attr.flags,
|
||||
mnemonic = "CarbonCompile",
|
||||
progress_message = "Compiling " + src.short_path,
|
||||
)
|
||||
|
||||
# Add the Carbon object files to the link flags.
|
||||
link_flags += [o.path for o in objs]
|
||||
|
||||
bin = ctx.actions.declare_file(ctx.label.name)
|
||||
|
||||
# Get all link options from the toolchain and dependencies using standard pattern.
|
||||
cc_toolchain = ctx.attr._cc_toolchain[cc_common.CcToolchainInfo]
|
||||
feature_configuration = cc_common.configure_features(
|
||||
ctx = ctx,
|
||||
cc_toolchain = cc_toolchain,
|
||||
requested_features = ctx.features,
|
||||
unsupported_features = ctx.disabled_features,
|
||||
)
|
||||
variables = cc_common.create_link_variables(
|
||||
feature_configuration = feature_configuration,
|
||||
cc_toolchain = cc_toolchain,
|
||||
is_using_linker = True,
|
||||
user_link_flags = link_flags + [
|
||||
# TODO: Remove once the sanitizer runtimes are available.
|
||||
"-fno-sanitize=all",
|
||||
],
|
||||
output_file = bin.path,
|
||||
)
|
||||
full_link_flags = cc_common.get_memory_inefficient_command_line(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = ACTION_NAMES.cpp_link_executable,
|
||||
variables = variables,
|
||||
)
|
||||
|
||||
ctx.actions.run(
|
||||
outputs = [bin],
|
||||
inputs = objs + dep_link_inputs,
|
||||
executable = toolchain_driver,
|
||||
tools = depset(toolchain_data + prebuilt_runtimes),
|
||||
arguments = ["--prebuilt-runtimes=" + _runtimes_path(prebuilt_runtimes), "link", "--output=" + bin.path] + ["--"] + dep_link_flags + [o.path for o in objs],
|
||||
arguments = full_link_flags,
|
||||
mnemonic = "CarbonLink",
|
||||
progress_message = "Linking " + bin.short_path,
|
||||
)
|
||||
@@ -148,9 +169,10 @@ _carbon_binary_internal = rule(
|
||||
),
|
||||
"prelude_srcs": attr.label_list(allow_files = [".carbon"]),
|
||||
"srcs": attr.label_list(allow_files = [".carbon"]),
|
||||
"_cc_toolchain": attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain"),
|
||||
"_cc_toolchain": attr.label(default = "//toolchain/install:carbon_stage1_cc_toolchain"),
|
||||
},
|
||||
executable = True,
|
||||
fragments = ["cpp"],
|
||||
)
|
||||
|
||||
def carbon_binary(name, srcs, deps = [], flags = [], tags = []):
|
||||
@@ -177,7 +199,7 @@ def carbon_binary(name, srcs, deps = [], flags = [], tags = []):
|
||||
# `select` which one we use.
|
||||
internal_exec_toolchain_driver = select({
|
||||
"//bazel/carbon_rules:use_target_config_carbon_rules_config": None,
|
||||
"//conditions:default": "//toolchain/install:prefix/bin/carbon",
|
||||
"//conditions:default": "//toolchain/install:carbon-busybox",
|
||||
}),
|
||||
internal_exec_toolchain_data = select({
|
||||
"//bazel/carbon_rules:use_target_config_carbon_rules_config": None,
|
||||
@@ -185,10 +207,10 @@ def carbon_binary(name, srcs, deps = [], flags = [], tags = []):
|
||||
}),
|
||||
internal_exec_prebuilt_runtimes = select({
|
||||
"//bazel/carbon_rules:use_target_config_carbon_rules_config": None,
|
||||
"//conditions:default": "//toolchain/driver:prebuilt_runtimes",
|
||||
"//conditions:default": "//toolchain/install:built_runtimes",
|
||||
}),
|
||||
internal_target_toolchain_driver = select({
|
||||
"//bazel/carbon_rules:use_target_config_carbon_rules_config": "//toolchain/install:prefix/bin/carbon",
|
||||
"//bazel/carbon_rules:use_target_config_carbon_rules_config": "//toolchain/install:carbon-busybox",
|
||||
"//conditions:default": None,
|
||||
}),
|
||||
internal_target_toolchain_data = select({
|
||||
@@ -196,7 +218,7 @@ def carbon_binary(name, srcs, deps = [], flags = [], tags = []):
|
||||
"//conditions:default": None,
|
||||
}),
|
||||
internal_target_prebuilt_runtimes = select({
|
||||
"//bazel/carbon_rules:use_target_config_carbon_rules_config": "//toolchain/driver:prebuilt_runtimes",
|
||||
"//bazel/carbon_rules:use_target_config_carbon_rules_config": "//toolchain/install:built_runtimes",
|
||||
"//conditions:default": None,
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -3,9 +3,13 @@
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
load("@bazel_skylib//lib:selects.bzl", "selects")
|
||||
load("@rules_python//python:defs.bzl", "py_library", "py_test")
|
||||
load(":carbon_cc_toolchain_config.bzl", "gen_cc_toolchain_paths_with_stage")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(["carbon_cc_toolchain_config.bzl"])
|
||||
|
||||
# For use by defs.bzl.
|
||||
# Matches when asan is enabled on a macOS platform.
|
||||
selects.config_setting_group(
|
||||
@@ -61,5 +65,31 @@ filegroup(
|
||||
"cc_toolchain_optimization.bzl",
|
||||
"cc_toolchain_sanitizer_features.bzl",
|
||||
"cc_toolchain_tools.bzl",
|
||||
|
||||
# TODO: Remove this once we can remove the use of it from Carbon
|
||||
# toolchain rules.
|
||||
"cc_toolchain_carbon_project_features.bzl",
|
||||
],
|
||||
)
|
||||
|
||||
gen_cc_toolchain_paths_with_stage(
|
||||
name = "gen_cc_tools_paths",
|
||||
stage = 0,
|
||||
)
|
||||
|
||||
# Test that the default toolchain's Make variables expand correctly.
|
||||
py_test(
|
||||
name = "cc_tools_test",
|
||||
srcs = ["cc_tools_test.py"],
|
||||
args = ["$(location :gen_cc_tools_paths)"],
|
||||
data = [":gen_cc_tools_paths"],
|
||||
deps = [":cc_tools_test_lib"],
|
||||
)
|
||||
|
||||
# Library containing the test logic, used by tests in other packages.
|
||||
py_library(
|
||||
name = "cc_tools_test_lib",
|
||||
srcs = ["cc_tools_test.py"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@bazel_tools//tools/python/runfiles"],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,547 @@
|
||||
# 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
|
||||
|
||||
"""Starlark cc_toolchain configuration rules for using the Carbon toolchain"""
|
||||
|
||||
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
|
||||
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
|
||||
load(
|
||||
"@rules_cc//cc:cc_toolchain_config_lib.bzl",
|
||||
"action_config",
|
||||
"flag_group",
|
||||
"flag_set",
|
||||
"tool",
|
||||
)
|
||||
load(
|
||||
"@rules_cc//cc:defs.bzl",
|
||||
"CcToolchainConfigInfo",
|
||||
"cc_toolchain",
|
||||
)
|
||||
load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
|
||||
load("//toolchain/runtimes:carbon_runtimes.bzl", "carbon_runtimes_build")
|
||||
load(
|
||||
"carbon_clang_variables.bzl",
|
||||
"clang_include_dirs",
|
||||
"clang_resource_dir",
|
||||
"clang_sysroot",
|
||||
)
|
||||
load(
|
||||
"cc_toolchain_actions.bzl",
|
||||
"all_c_compile_actions",
|
||||
"all_cpp_compile_actions",
|
||||
"all_link_actions",
|
||||
)
|
||||
load("cc_toolchain_carbon_project_features.bzl", "carbon_project_features")
|
||||
load("cc_toolchain_features.bzl", "clang_cc_toolchain_features")
|
||||
load(
|
||||
":cc_toolchain_tools.bzl",
|
||||
"llvm_tool_paths",
|
||||
)
|
||||
|
||||
def _make_action_configs(tools, runtimes_path = None):
|
||||
runtimes_flag = "--no-build-runtimes"
|
||||
if runtimes_path:
|
||||
runtimes_flag = "--prebuilt-runtimes={0}".format(runtimes_path)
|
||||
|
||||
return [
|
||||
action_config(
|
||||
action_name = name,
|
||||
enabled = True,
|
||||
tools = [tools.clang],
|
||||
)
|
||||
for name in all_c_compile_actions
|
||||
] + [
|
||||
action_config(
|
||||
action_name = name,
|
||||
enabled = True,
|
||||
tools = [tools.clangpp],
|
||||
)
|
||||
for name in all_cpp_compile_actions
|
||||
] + [
|
||||
action_config(
|
||||
action_name = name,
|
||||
enabled = True,
|
||||
tools = [tools.carbon_busybox],
|
||||
flag_sets = [flag_set(flag_groups = [flag_group(flags = [
|
||||
runtimes_flag,
|
||||
"link",
|
||||
# We want to allow Bazel to intermingle linked object files and
|
||||
# Clang-spelled link flags. The first `--` starts the list of
|
||||
# initial object files by ending flags to the `link` subcommand,
|
||||
# and the second `--` switches to Clang-spelled flags.
|
||||
"--",
|
||||
"--",
|
||||
])])],
|
||||
)
|
||||
for name in all_link_actions
|
||||
] + [
|
||||
action_config(
|
||||
action_name = name,
|
||||
enabled = True,
|
||||
tools = [tools.llvm_ar],
|
||||
)
|
||||
for name in [ACTION_NAMES.cpp_link_static_library]
|
||||
] + [
|
||||
action_config(
|
||||
action_name = name,
|
||||
enabled = True,
|
||||
tools = [tools.llvm_strip],
|
||||
)
|
||||
for name in [ACTION_NAMES.strip]
|
||||
]
|
||||
|
||||
def _compute_clang_system_include_dirs():
|
||||
system_include_dirs_start_index = None
|
||||
for index, dir in enumerate(clang_include_dirs):
|
||||
# Skip over the include search directories until we find the resource
|
||||
# directory. The system include directories are everything after that.
|
||||
if dir.startswith(clang_resource_dir):
|
||||
system_include_dirs_start_index = index + 1
|
||||
break
|
||||
if not system_include_dirs_start_index:
|
||||
fail("Could not find the resource directory in the clang include " +
|
||||
"directories: {}".format(clang_include_dirs))
|
||||
return clang_include_dirs[system_include_dirs_start_index:]
|
||||
|
||||
def _carbon_cc_toolchain_config_impl(ctx):
|
||||
llvm_bindir = "llvm/bin"
|
||||
clang_bindir = llvm_bindir
|
||||
tools = struct(
|
||||
carbon_busybox = tool(path = "carbon-busybox"),
|
||||
clang = tool(path = clang_bindir + "/clang"),
|
||||
clangpp = tool(path = clang_bindir + "/clang++"),
|
||||
llvm_ar = tool(path = llvm_bindir + "/llvm-ar"),
|
||||
llvm_strip = tool(path = llvm_bindir + "/llvm-strip"),
|
||||
)
|
||||
if ctx.attr.bins:
|
||||
carbon_busybox = None
|
||||
clang = None
|
||||
clangpp = None
|
||||
llvm_ar = None
|
||||
llvm_strip = None
|
||||
for f in ctx.files.bins:
|
||||
if f.basename == "carbon-busybox":
|
||||
carbon_busybox = f
|
||||
elif f.basename == "clang":
|
||||
clang = f
|
||||
elif f.basename == "clang++":
|
||||
clangpp = f
|
||||
elif f.basename == "llvm-ar":
|
||||
llvm_ar = f
|
||||
elif f.basename == "llvm-strip":
|
||||
llvm_strip = f
|
||||
if not all([carbon_busybox, clang, clangpp, llvm_ar, llvm_strip]):
|
||||
fail("Missing required tool in bins: {0}".format(ctx.attr.bins))
|
||||
llvm_bindir = llvm_ar.dirname
|
||||
clang_bindir = clang.dirname
|
||||
tools = struct(
|
||||
carbon_busybox = tool(tool = carbon_busybox),
|
||||
clang = tool(tool = clang),
|
||||
clangpp = tool(tool = clangpp),
|
||||
llvm_ar = tool(tool = llvm_ar),
|
||||
llvm_strip = tool(tool = llvm_strip),
|
||||
)
|
||||
|
||||
# Only use a sysroot if a non-trivial one is set in Carbon's config.
|
||||
builtin_sysroot = None
|
||||
sysroot_include_search = []
|
||||
if clang_sysroot != "None" and clang_sysroot != "/":
|
||||
builtin_sysroot = clang_sysroot
|
||||
sysroot_include_search = ["%sysroot%/usr/include"]
|
||||
|
||||
runtimes_path = None
|
||||
if ctx.attr.runtimes:
|
||||
for f in ctx.files.runtimes:
|
||||
if f.basename == "runtimes_root":
|
||||
runtimes_path = f.dirname
|
||||
break
|
||||
if not runtimes_path:
|
||||
fail("Unable to compute the runtimes path for: {0}".format(
|
||||
ctx.attr.runtimes,
|
||||
))
|
||||
|
||||
identifier = "{0}_toolchain_{1}_{2}".format(
|
||||
ctx.attr.identifier_prefix,
|
||||
ctx.attr.target_cpu,
|
||||
ctx.attr.target_os,
|
||||
)
|
||||
return cc_common.create_cc_toolchain_config_info(
|
||||
ctx = ctx,
|
||||
features = clang_cc_toolchain_features(
|
||||
target_os = ctx.attr.target_os,
|
||||
target_cpu = ctx.attr.target_cpu,
|
||||
|
||||
# TODO: This should be configured externally rather than here so
|
||||
# that the install Carbon toolchain doesn't automatically include
|
||||
# Carbon-project-specific flags. However, that is especially awkward
|
||||
# to do until we fully migrate to a rules-based toolchain, and the
|
||||
# project-specific flags are largely harmless at the moment. We also
|
||||
# omit a meaningful cache key as when using the Carbon toolchain we
|
||||
# don't need it as it is a hermetic part of Bazel.
|
||||
project_features = carbon_project_features(cache_key = ""),
|
||||
),
|
||||
action_configs = _make_action_configs(tools, runtimes_path),
|
||||
cxx_builtin_include_directories = [
|
||||
"runtimes/libunwind/include",
|
||||
"runtimes/libcxx/include",
|
||||
"runtimes/libcxxabi/include",
|
||||
"{}/include".format(clang_resource_dir),
|
||||
"runtimes/clang_resource_dir/include",
|
||||
] + _compute_clang_system_include_dirs() + sysroot_include_search,
|
||||
builtin_sysroot = builtin_sysroot,
|
||||
|
||||
# This configuration only supports local non-cross builds so derive
|
||||
# everything from the target CPU selected.
|
||||
toolchain_identifier = identifier,
|
||||
|
||||
# This is used to expose a "flag" that `config_setting` rules can use to
|
||||
# determine if the compiler is Clang.
|
||||
compiler = "clang",
|
||||
|
||||
# Pass in our tool paths to expose Make variables like $(NM) and
|
||||
# $(OBJCOPY).
|
||||
tool_paths = llvm_tool_paths(llvm_bindir, clang_bindir),
|
||||
)
|
||||
|
||||
carbon_cc_toolchain_config = rule(
|
||||
implementation = _carbon_cc_toolchain_config_impl,
|
||||
attrs = {
|
||||
"bins": attr.label(mandatory = False),
|
||||
"identifier_prefix": attr.string(mandatory = True),
|
||||
"runtimes": attr.label(mandatory = False),
|
||||
"target_cpu": attr.string(mandatory = True),
|
||||
"target_os": attr.string(mandatory = True),
|
||||
},
|
||||
provides = [CcToolchainConfigInfo],
|
||||
)
|
||||
|
||||
def _transition_with_stage_impl(_, attr):
|
||||
return {
|
||||
"//:bootstrap_stage": attr.stage,
|
||||
"//:runtimes_build": attr.enable_runtimes_build,
|
||||
}
|
||||
|
||||
_transition_with_stage = transition(
|
||||
inputs = [],
|
||||
outputs = [
|
||||
"//:bootstrap_stage",
|
||||
"//:runtimes_build",
|
||||
],
|
||||
implementation = _transition_with_stage_impl,
|
||||
)
|
||||
|
||||
def _filegroup_with_stage_impl(ctx):
|
||||
return [DefaultInfo(files = depset(ctx.files.srcs))]
|
||||
|
||||
filegroup_with_stage = rule(
|
||||
implementation = _filegroup_with_stage_impl,
|
||||
attrs = {
|
||||
# Whether to enable runtimes building for the sources of this filegroup.
|
||||
"enable_runtimes_build": attr.bool(default = False),
|
||||
|
||||
# Mark that our dependencies are built through a transition.
|
||||
"srcs": attr.label_list(mandatory = True, cfg = _transition_with_stage),
|
||||
|
||||
# The bootstrap stage that the sources of this filegroup should be built
|
||||
# with.
|
||||
"stage": attr.int(mandatory = True),
|
||||
|
||||
# Enable transitions in this rule.
|
||||
"_allowlist_function_transition": attr.label(
|
||||
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
|
||||
),
|
||||
},
|
||||
doc = """
|
||||
A filegroup whose sources are built using a specific toolchain stage, and
|
||||
which provides an interface to build those sources with or without enabling
|
||||
runtimes building.
|
||||
""",
|
||||
)
|
||||
|
||||
def _exec_filegroup_impl(ctx):
|
||||
return [DefaultInfo(files = depset(ctx.files.srcs))]
|
||||
|
||||
_exec_filegroup = rule(
|
||||
implementation = _exec_filegroup_impl,
|
||||
attrs = {
|
||||
"srcs": attr.label_list(cfg = "exec"),
|
||||
},
|
||||
)
|
||||
|
||||
def filegroup_with_stage_and_exec(name, srcs, stage, tags = []):
|
||||
"""Wraps `filegroup_with_stage` with a conditional `exec` config transition.
|
||||
|
||||
When `//:bootstrap_exec_config` is disabled, this works exactly like
|
||||
`filegroup_with_stage`. But when it is _enabled_, it also adds an `exec`
|
||||
config transition. This allows bootstrapping for a target that is not exec
|
||||
compatible with the host, and in general makes bootstrapping more robust at
|
||||
the expense of a likely duplicate build of the entire toolchain.
|
||||
"""
|
||||
filegroup_with_stage(
|
||||
name = name + "_stage_only",
|
||||
srcs = srcs,
|
||||
stage = stage,
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
_exec_filegroup(
|
||||
name = name + "_with_exec",
|
||||
srcs = [":" + name + "_stage_only"],
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
native.alias(
|
||||
name = name,
|
||||
actual = select({
|
||||
"//:bootstrap_with_exec_config": ":" + name + "_with_exec",
|
||||
"//conditions:default": ":" + name + "_stage_only",
|
||||
}),
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
def _gen_cc_toolchain_paths_impl(ctx):
|
||||
cc_toolchain = find_cpp_toolchain(ctx)
|
||||
|
||||
expanded_vars = [
|
||||
ctx.expand_make_variables("vars", v, {})
|
||||
for v in ctx.attr.vars
|
||||
]
|
||||
|
||||
out = ctx.actions.declare_file(ctx.attr.name + ".txt")
|
||||
ctx.actions.write(out, "\n".join(expanded_vars) + "\n")
|
||||
|
||||
# Include all toolchain files in runfiles.
|
||||
runfiles = ctx.runfiles(files = [out]).merge(
|
||||
ctx.runfiles(transitive_files = cc_toolchain.all_files),
|
||||
)
|
||||
|
||||
return [DefaultInfo(files = depset([out]), runfiles = runfiles)]
|
||||
|
||||
gen_cc_toolchain_paths_with_stage = rule(
|
||||
implementation = _gen_cc_toolchain_paths_impl,
|
||||
attrs = {
|
||||
"enable_runtimes_build": attr.bool(default = False),
|
||||
"stage": attr.int(mandatory = True),
|
||||
"vars": attr.string_list(
|
||||
default = ["$(CC)", "$(AR)", "$(NM)", "$(OBJCOPY)", "$(STRIP)"],
|
||||
),
|
||||
"_allowlist_function_transition": attr.label(
|
||||
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
|
||||
),
|
||||
"_cc_toolchain": attr.label(
|
||||
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
|
||||
),
|
||||
},
|
||||
toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
|
||||
cfg = _transition_with_stage,
|
||||
)
|
||||
|
||||
def carbon_cc_toolchain_suite(
|
||||
name,
|
||||
all_hdrs,
|
||||
base_files,
|
||||
clang_hdrs,
|
||||
platforms,
|
||||
runtimes_cfg,
|
||||
build_stage = 1,
|
||||
base_stage = 0,
|
||||
tags = []):
|
||||
"""Create a Carbon `cc_toolchain` for the current target platform.
|
||||
|
||||
This provides the final toolchain for Carbon, but also all of the
|
||||
infrastructure for supporting on-demand built runtimes in this toolchain.
|
||||
|
||||
There is also support for bootstrapping, where one `build_stage` toolchain
|
||||
builds on top of another `base_stage`.
|
||||
|
||||
Args:
|
||||
name:
|
||||
The name of the toolchain suite to produce, used as the base of the
|
||||
names of each component of the toolchain suite.
|
||||
all_hdrs: A list of header files to include in the toolchain.
|
||||
base_files: A list of files to include in the toolchain.
|
||||
build_stage: The stage to use for the build files.
|
||||
base_stage: The stage to use for the base files.
|
||||
clang_hdrs: A list of header files to include in the toolchain.
|
||||
platforms: An array of (os, cpu) pairs to support in the toolchain.
|
||||
runtimes_cfg: The runtimes configuration to use in the toolchain.
|
||||
tags: Tags to apply to the toolchain.
|
||||
"""
|
||||
|
||||
# First, declare file groups that are explicitly built using the base stage,
|
||||
# and not in the runtimes build. These allow us to form the inputs to both
|
||||
# the runtimes toolchain and the main toolchain of this stage that are built
|
||||
# entirely by the base stage toolchain.
|
||||
filegroup_with_stage_and_exec(
|
||||
name = "{}_clang_hdrs".format(name),
|
||||
srcs = clang_hdrs,
|
||||
stage = base_stage,
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
filegroup_with_stage_and_exec(
|
||||
name = "{}_base_files".format(name),
|
||||
srcs = base_files,
|
||||
stage = base_stage,
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
filegroup_with_stage_and_exec(
|
||||
name = "{}_runtimes_compile_files".format(name),
|
||||
srcs = [
|
||||
":{}_base_files".format(name),
|
||||
":{}_clang_hdrs".format(name),
|
||||
],
|
||||
stage = base_stage,
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
filegroup_with_stage_and_exec(
|
||||
name = "{}_compile_files".format(name),
|
||||
srcs = [":{}_base_files".format(name)] + all_hdrs,
|
||||
stage = base_stage,
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
# Now build a configuration and toolchain that is configured to work
|
||||
# _without_ runtimes, and be used to _build_ the runtimes on-demand.
|
||||
carbon_cc_toolchain_config(
|
||||
name = "{}_runtimes_toolchain_config".format(name),
|
||||
identifier_prefix = "{}_runtimes".format(name),
|
||||
target_cpu = select({
|
||||
# Note that we need to select on both OS and CPU so that we end up
|
||||
# spelling the CPU in the correct OS-specific ways.
|
||||
":is_{}_{}".format(os, cpu): cpu
|
||||
for os, cpus in platforms.items()
|
||||
for cpu in cpus
|
||||
}),
|
||||
target_os = select({
|
||||
"@platforms//os:{}".format(os): os
|
||||
for os in platforms.keys()
|
||||
}),
|
||||
bins = ":{}_base_files".format(name),
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
cc_toolchain(
|
||||
name = "{}_runtimes_cc_toolchain".format(name),
|
||||
all_files = ":{}_runtimes_compile_files".format(name),
|
||||
ar_files = ":{}_base_files".format(name),
|
||||
as_files = ":{}_runtimes_compile_files".format(name),
|
||||
compiler_files = ":{}_runtimes_compile_files".format(name),
|
||||
dwp_files = ":{}_base_files".format(name),
|
||||
linker_files = ":{}_base_files".format(name),
|
||||
objcopy_files = ":{}_base_files".format(name),
|
||||
strip_files = ":{}_base_files".format(name),
|
||||
toolchain_config = ":{}_runtimes_toolchain_config".format(name),
|
||||
toolchain_identifier = select({
|
||||
":is_{}_{}".format(os, cpu): "{}_{}_{}_runtimes_toolchain".format(name, os, cpu)
|
||||
for os, cpus in platforms.items()
|
||||
for cpu in cpus
|
||||
}),
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
native.toolchain(
|
||||
name = "{}_runtimes_toolchain".format(name),
|
||||
target_settings = [
|
||||
":is_bootstrap_stage_{}".format(build_stage),
|
||||
":is_runtimes_build",
|
||||
],
|
||||
use_target_platform_constraints = True,
|
||||
toolchain = ":{}_runtimes_cc_toolchain".format(name),
|
||||
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
# Now that we have a toolchain for building runtimes, actually do the build
|
||||
# here using the runtimes config provided to us. This is important to do
|
||||
# here because we need each runtimes build for a particular bootstrapping
|
||||
# stage of the toolchain to be distinct.
|
||||
carbon_runtimes_build(
|
||||
name = "{}_runtimes_build".format(name),
|
||||
config = runtimes_cfg,
|
||||
clang_hdrs = [":{}_clang_hdrs".format(name)],
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
# Wrap the built runtimes for this stage in a filegroup that ensures they
|
||||
# are built at this stage, but with the runtimes build enabled. This will
|
||||
# select the runtimes build toolchain above that doesn't yet provide any
|
||||
# runtimes, avoiding a cycle when the main toolchain below depends on these
|
||||
# runtimes.
|
||||
filegroup_with_stage(
|
||||
name = "{}_runtimes".format(name),
|
||||
enable_runtimes_build = True,
|
||||
srcs = ["{}_runtimes_build".format(name)],
|
||||
stage = build_stage,
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
# Now we can build the main toolchain configuration, filegroups including
|
||||
# the on-demand built runtimes, and the final tolochain itself.
|
||||
carbon_cc_toolchain_config(
|
||||
name = "{}_toolchain_config".format(name),
|
||||
identifier_prefix = name,
|
||||
target_cpu = select({
|
||||
# Note that we need to select on both OS and CPU so that we end up
|
||||
# spelling the CPU in the correct OS-specific ways.
|
||||
":is_{}_{}".format(os, cpu): cpu
|
||||
for os, cpus in platforms.items()
|
||||
for cpu in cpus
|
||||
}),
|
||||
target_os = select({
|
||||
"@platforms//os:{}".format(os): os
|
||||
for os in platforms.keys()
|
||||
}),
|
||||
runtimes = ":{}_runtimes".format(name),
|
||||
bins = ":{}_base_files".format(name),
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
native.filegroup(
|
||||
name = "{}_linker_files".format(name),
|
||||
srcs = [
|
||||
":{}_base_files".format(name),
|
||||
":{}_runtimes".format(name),
|
||||
],
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
native.filegroup(
|
||||
name = "{}_all_files".format(name),
|
||||
srcs = [
|
||||
":{}_compile_files".format(name),
|
||||
":{}_linker_files".format(name),
|
||||
],
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
cc_toolchain(
|
||||
name = "{}_cc_toolchain".format(name),
|
||||
all_files = ":{}_all_files".format(name),
|
||||
ar_files = ":" + name + "_base_files",
|
||||
as_files = ":" + name + "_compile_files",
|
||||
compiler_files = ":" + name + "_compile_files",
|
||||
dwp_files = ":" + name + "_linker_files",
|
||||
linker_files = ":" + name + "_linker_files",
|
||||
objcopy_files = ":" + name + "_base_files",
|
||||
strip_files = ":" + name + "_base_files",
|
||||
toolchain_config = ":" + name + "_toolchain_config",
|
||||
toolchain_identifier = select({
|
||||
":is_{}_{}".format(os, cpu): "{}_{}_{}_toolchain".format(name, os, cpu)
|
||||
for os, cpus in platforms.items()
|
||||
for cpu in cpus
|
||||
}),
|
||||
tags = tags,
|
||||
)
|
||||
|
||||
native.toolchain(
|
||||
name = name + "_toolchain",
|
||||
target_settings = [":is_bootstrap_stage_{}".format(build_stage), ":not_runtimes_build"],
|
||||
use_target_platform_constraints = True,
|
||||
toolchain = ":" + name + "_cc_toolchain",
|
||||
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
|
||||
tags = tags,
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
# 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
|
||||
|
||||
"""A Starlark file exporting detected Carbon toolchain configuration variables.
|
||||
|
||||
This file gets processed by a repository rule, substituting the `VARIABLE`s with
|
||||
values, for example using an invocation of `carbon config`.
|
||||
"""
|
||||
|
||||
load(
|
||||
"@bazel_cc_toolchain//:clang_detected_variables.bzl",
|
||||
_clang_include_dirs = "clang_include_dirs",
|
||||
_clang_resource_dir = "clang_resource_dir",
|
||||
_sysroot_dir = "sysroot_dir",
|
||||
)
|
||||
|
||||
clang_include_dirs = _clang_include_dirs
|
||||
clang_resource_dir = _clang_resource_dir
|
||||
clang_sysroot = _sysroot_dir
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
"""Definitions used for the base features of a `cc_toolchain_config`."""
|
||||
|
||||
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
|
||||
load(
|
||||
"@rules_cc//cc:cc_toolchain_config_lib.bzl",
|
||||
"feature",
|
||||
@@ -92,12 +93,41 @@ output_flags_feature = feature(
|
||||
],
|
||||
)
|
||||
|
||||
strip_feature = feature(
|
||||
name = "strip_flags",
|
||||
enabled = True,
|
||||
flag_sets = [flag_set(
|
||||
actions = [ACTION_NAMES.strip],
|
||||
flag_groups = [
|
||||
flag_group(
|
||||
flags = ["-S"],
|
||||
),
|
||||
flag_group(
|
||||
flags = ["-p"],
|
||||
),
|
||||
flag_group(
|
||||
expand_if_available = "output_file",
|
||||
flags = ["-o", "%{output_file}"],
|
||||
),
|
||||
flag_group(
|
||||
iterate_over = "stripopts",
|
||||
flags = ["%{stripopts}"],
|
||||
),
|
||||
flag_group(
|
||||
expand_if_available = "input_file",
|
||||
flags = ["%{input_file}"],
|
||||
),
|
||||
],
|
||||
)],
|
||||
)
|
||||
|
||||
base_features = [
|
||||
dbg_feature,
|
||||
fastbuild_feature,
|
||||
host_feature,
|
||||
no_legacy_features_feature,
|
||||
opt_feature,
|
||||
strip_feature,
|
||||
supports_pic_feature,
|
||||
supports_dynamic_linker_feature,
|
||||
supports_start_end_lib_feature,
|
||||
|
||||
@@ -27,10 +27,9 @@ carbon_project_fastbuild_feature = feature(
|
||||
enabled = True,
|
||||
requires = [feature_set(["fastbuild"])],
|
||||
implies = [
|
||||
"asan",
|
||||
"asan_min_size",
|
||||
"minimal_optimization_flags",
|
||||
"minimal_debug_info_flags",
|
||||
"preserve_call_stacks",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ minimal_optimization_flags = feature(
|
||||
name = "minimal_optimization_flags",
|
||||
flag_sets = [flag_set(
|
||||
actions = codegen_compile_actions,
|
||||
flag_groups = [flag_group(flags = ["-O1"])],
|
||||
flag_groups = [flag_group(flags = ["-Og"])],
|
||||
)],
|
||||
)
|
||||
default_optimization_flags = feature(
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
"""Tests that the C++ toolchain tools can be executed.
|
||||
|
||||
This script reads a file containing paths to C++ tools (like clang++, llvm-ar)
|
||||
and attempts to run each with `--version` to verify they are functional.
|
||||
"""
|
||||
|
||||
__copyright__ = """
|
||||
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
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from bazel_tools.tools.python.runfiles import runfiles
|
||||
|
||||
|
||||
def test_tools() -> None:
|
||||
"""Reads paths from file and runs each tool with --version."""
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: cc_tools_test.py <paths_file>")
|
||||
sys.exit(1)
|
||||
|
||||
paths_file = sys.argv[1]
|
||||
print(f"Reading tools from: {paths_file}")
|
||||
with open(paths_file, "r") as f:
|
||||
tools = [line.strip() for line in f if line.strip()]
|
||||
|
||||
print(f"Testing tools: {tools}")
|
||||
r = runfiles.Create()
|
||||
repo_name = os.environ.get("TEST_WORKSPACE") or "_main"
|
||||
|
||||
for tool in tools:
|
||||
if "bazel-out/" in tool:
|
||||
_, _, rest = tool.partition("bazel-out/")
|
||||
_, sep, after = rest.partition("bin/")
|
||||
if sep:
|
||||
tool = after
|
||||
|
||||
rlocation_path = os.path.join(repo_name, tool)
|
||||
tool = r.Rlocation(rlocation_path)
|
||||
|
||||
print(f"Running {tool} --version")
|
||||
try:
|
||||
res = subprocess.run(
|
||||
[tool, "--version"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
print(res.stdout)
|
||||
except Exception as e:
|
||||
print(f"Failed to run {tool}: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_tools()
|
||||
@@ -17,7 +17,7 @@ load(
|
||||
load(
|
||||
":clang_detected_variables.bzl",
|
||||
"clang_bindir",
|
||||
"clang_include_dirs_list",
|
||||
"clang_include_dirs",
|
||||
"clang_resource_dir",
|
||||
"clang_version_for_cache",
|
||||
"llvm_bindir",
|
||||
@@ -40,7 +40,7 @@ def _impl(ctx):
|
||||
extra_cpp_features = [libcxx_feature(llvm_bindir, clang_bindir)],
|
||||
),
|
||||
action_configs = llvm_action_configs(llvm_bindir, clang_bindir),
|
||||
cxx_builtin_include_directories = clang_include_dirs_list + [
|
||||
cxx_builtin_include_directories = clang_include_dirs + [
|
||||
# Add Clang's resource directory to the end of the builtin include
|
||||
# directories to cover the use of sanitizer resource files by the
|
||||
# driver.
|
||||
@@ -92,7 +92,7 @@ def cc_local_toolchain_suite(name, configs):
|
||||
target_cpu = cpu,
|
||||
)
|
||||
cc_toolchain(
|
||||
name = config_name + "_tools",
|
||||
name = config_name + "_toolchain",
|
||||
all_files = ":" + name + "_empty",
|
||||
ar_files = ":" + name + "_empty",
|
||||
as_files = ":" + name + "_empty",
|
||||
@@ -109,7 +109,11 @@ def cc_local_toolchain_suite(name, configs):
|
||||
native.toolchain(
|
||||
name = config_name,
|
||||
exec_compatible_with = compatible_with,
|
||||
target_settings = [
|
||||
"@carbon//toolchain/install:is_bootstrap_stage_0",
|
||||
"@carbon//toolchain/install:not_runtimes_build",
|
||||
],
|
||||
target_compatible_with = compatible_with,
|
||||
toolchain = config_name + "_tools",
|
||||
toolchain = config_name + "_toolchain",
|
||||
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
|
||||
)
|
||||
|
||||
@@ -226,7 +226,7 @@ def _configure_clang_toolchain_impl(repository_ctx):
|
||||
repository_ctx.attr._clang_detected_variables_template,
|
||||
substitutions = {
|
||||
"{CLANG_BINDIR}": str(clang.dirname),
|
||||
"{CLANG_INCLUDE_DIRS_LIST}": str(
|
||||
"{CLANG_INCLUDE_DIRS}": str(
|
||||
[str(path) for path in include_dirs],
|
||||
),
|
||||
"{CLANG_RESOURCE_DIR}": resource_dir,
|
||||
|
||||
@@ -14,5 +14,5 @@ clang_bindir = "{CLANG_BINDIR}"
|
||||
clang_version = {CLANG_VERSION}
|
||||
clang_version_for_cache = "{CLANG_VERSION_FOR_CACHE}"
|
||||
clang_resource_dir = "{CLANG_RESOURCE_DIR}"
|
||||
clang_include_dirs_list = {CLANG_INCLUDE_DIRS_LIST}
|
||||
clang_include_dirs = {CLANG_INCLUDE_DIRS}
|
||||
sysroot_dir = "{SYSROOT}"
|
||||
|
||||
@@ -13,8 +13,8 @@ load("@rules_python//python:defs.bzl", "py_test")
|
||||
filegroup(
|
||||
name = "non_test_cc_rules",
|
||||
data = [
|
||||
"//toolchain/install:carbon_toolchain_tar_gz_rule",
|
||||
"//toolchain/install:carbon_toolchain_tar_rule",
|
||||
"//toolchain/install:carbon_toolchain_tar",
|
||||
"//toolchain/install:carbon_toolchain_tar_gz",
|
||||
],
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
From 04fb28b5673d29a8c38519845c87f4c00c76e9cf Mon Sep 17 00:00:00 2001
|
||||
From: Chandler Carruth <chandlerc@gmail.com>
|
||||
Date: Sat, 13 Jan 2024 02:15:19 -0800
|
||||
Subject: [PATCH] Introduce a simple native Bazel build.
|
||||
|
||||
---
|
||||
BUILD.bazel | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
MODULE.bazel | 10 ++++++
|
||||
WORKSPACE.bazel | 5 +++
|
||||
3 files changed, 99 insertions(+)
|
||||
create mode 100644 BUILD.bazel
|
||||
create mode 100644 MODULE.bazel
|
||||
create mode 100644 WORKSPACE.bazel
|
||||
|
||||
diff --git a/BUILD.bazel b/BUILD.bazel
|
||||
new file mode 100644
|
||||
index 0000000..427c854
|
||||
--- /dev/null
|
||||
+++ b/BUILD.bazel
|
||||
@@ -0,0 +1,84 @@
|
||||
+# 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
|
||||
+
|
||||
+load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
+
|
||||
+package(default_visibility = ["//visibility:public"])
|
||||
+
|
||||
+aarch64_srcs = [
|
||||
+ "lib/pfmlib_arm_perf_event.c",
|
||||
+ "lib/pfmlib_arm.c",
|
||||
+ "lib/pfmlib_arm_armv8.c",
|
||||
+ "lib/pfmlib_arm_armv9.c",
|
||||
+ "lib/pfmlib_tx2_unc_perf_event.c",
|
||||
+ "lib/pfmlib_kunpeng_unc_perf_event.c",
|
||||
+ "lib/pfmlib_arm_priv.h",
|
||||
+ "lib/events/arm_cortex_a57_events.h",
|
||||
+ "lib/events/arm_cortex_a53_events.h",
|
||||
+ "lib/events/arm_xgene_events.h",
|
||||
+ "lib/events/arm_cavium_tx2_events.h",
|
||||
+ "lib/events/arm_marvell_tx2_unc_events.h",
|
||||
+ "lib/events/arm_fujitsu_a64fx_events.h",
|
||||
+ "lib/events/arm_neoverse_n1_events.h",
|
||||
+ "lib/events/arm_neoverse_n2_events.h",
|
||||
+ "lib/events/arm_neoverse_v1_events.h",
|
||||
+ "lib/events/arm_neoverse_v2_events.h",
|
||||
+ "lib/events/arm_hisilicon_kunpeng_events.h",
|
||||
+ "lib/events/arm_hisilicon_kunpeng_unc_events.h",
|
||||
+]
|
||||
+
|
||||
+x86_64_srcs = [
|
||||
+ "lib/pfmlib_amd64_priv.h",
|
||||
+] + glob(
|
||||
+ [
|
||||
+ "lib/pfmlib_amd64*.c",
|
||||
+ "lib/pfmlib_intel*.c",
|
||||
+ "lib/pfmlib_intel*_priv.h",
|
||||
+ "lib/events/amd64_events_*.h",
|
||||
+ "lib/events/intel_*_events.h",
|
||||
+ ],
|
||||
+ exclude = [
|
||||
+ # 32-bit CPUs
|
||||
+ "lib/pfmlib_intel_coreduo.c",
|
||||
+ "lib/pfmlib_intel_p6.c",
|
||||
+ ],
|
||||
+)
|
||||
+
|
||||
+cc_library(
|
||||
+ name = "libpfm",
|
||||
+ srcs = [
|
||||
+ "lib/events/perf_events.h",
|
||||
+ "lib/pfmlib_common.c",
|
||||
+ "lib/pfmlib_perf_event.c",
|
||||
+ "lib/pfmlib_perf_event_pmu.c",
|
||||
+ "lib/pfmlib_perf_event_priv.h",
|
||||
+ "lib/pfmlib_perf_event_raw.c",
|
||||
+ "lib/pfmlib_priv.h",
|
||||
+ ] + select({
|
||||
+ "@platforms//cpu:aarch64": aarch64_srcs,
|
||||
+ "@platforms//cpu:x86_64": x86_64_srcs,
|
||||
+ }),
|
||||
+ hdrs = glob(["include/perfmon/*.h"]),
|
||||
+ copts = [
|
||||
+ "-DHAS_OPENAT",
|
||||
+ "-D_REENTRANT",
|
||||
+ "-I.",
|
||||
+ "-fvisibility=hidden",
|
||||
+ ] + select({
|
||||
+ "@platforms//cpu:x86_64": [
|
||||
+ "-DCONFIG_PFMLIB_ARCH_X86",
|
||||
+ "-DCONFIG_PFMLIB_ARCH_X86_64",
|
||||
+ ],
|
||||
+ "//conditions:default": [],
|
||||
+ }),
|
||||
+ strip_include_prefix = "include",
|
||||
+ target_compatible_with = select({
|
||||
+ # This library only makes sense on Linux, and we only include support
|
||||
+ # for building on AArch64 and x86-64. Other CPUs can be added to this
|
||||
+ # list if build support is added for them.
|
||||
+ "@platforms//cpu:aarch64": ["@platforms//os:linux"],
|
||||
+ "@platforms//cpu:x86_64": ["@platforms//os:linux"],
|
||||
+ "//conditions:default": ["@platforms//:incompatible"],
|
||||
+ }),
|
||||
+)
|
||||
diff --git a/MODULE.bazel b/MODULE.bazel
|
||||
new file mode 100644
|
||||
index 0000000..c901cbe
|
||||
--- /dev/null
|
||||
+++ b/MODULE.bazel
|
||||
@@ -0,0 +1,10 @@
|
||||
+# 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
|
||||
+
|
||||
+"""Bazel modules."""
|
||||
+
|
||||
+module(name = "libpfm")
|
||||
+
|
||||
+bazel_dep(name = "rules_cc", version = "0.0.9")
|
||||
+bazel_dep(name = "platforms", version = "0.0.8")
|
||||
diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel
|
||||
new file mode 100644
|
||||
index 0000000..9aad57c
|
||||
--- /dev/null
|
||||
+++ b/WORKSPACE.bazel
|
||||
@@ -0,0 +1,5 @@
|
||||
+# 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
|
||||
+
|
||||
+# See `MODULE.bazel` for details.
|
||||
--
|
||||
2.43.0
|
||||
@@ -1,9 +0,0 @@
|
||||
# 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
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(glob([
|
||||
"*.patch",
|
||||
]))
|
||||
@@ -1,7 +1,7 @@
|
||||
Commit ID: a79f1facf56cc5772557cdb09d811aa11a22e43b
|
||||
Commit ID: 354e38c89f28e2cc284e655a9cde707f457dc02c
|
||||
Change ID: sxspxmonsuvqzuvxvrvorlumwpwromsv
|
||||
Author : Chandler Carruth <chandlerc@gmail.com> (2025-09-25 22:55:26)
|
||||
Committer: Chandler Carruth <chandlerc@gmail.com> (2025-11-17 09:59:25)
|
||||
Committer: Chandler Carruth <chandlerc@gmail.com> (2026-02-14 03:46:06)
|
||||
|
||||
Introduce basic sources exporting for libunwind
|
||||
|
||||
@@ -32,3 +32,33 @@ index c9fdc819c0..7d734c5a06 100644
|
||||
+ "src/*.S",
|
||||
+ ]),
|
||||
+)
|
||||
diff --git a/utils/bazel/llvm-project-overlay/libunwind/libunwind_library.bzl b/utils/bazel/llvm-project-overlay/libunwind/libunwind_library.bzl
|
||||
new file mode 100644
|
||||
index 0000000000..25675d3070
|
||||
--- /dev/null
|
||||
+++ b/utils/bazel/llvm-project-overlay/libunwind/libunwind_library.bzl
|
||||
@@ -0,0 +1,24 @@
|
||||
+# This file is licensed under the Apache License v2.0 with LLVM Exceptions.
|
||||
+# See https://llvm.org/LICENSE.txt for license information.
|
||||
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
+
|
||||
+"""Starlark variables and macros for building libunwind.
|
||||
+
|
||||
+Variables provide base line information for how to build libunwind source files.
|
||||
+These can be used to generate non-Bazel builds of the library.
|
||||
+
|
||||
+Macros provide a convenient way to construct Bazel `cc_library` rules for
|
||||
+libunwind.
|
||||
+"""
|
||||
+
|
||||
+# TODO: Should libunwind use `-fvisibility-inlines-hidden` and
|
||||
+# `-fvisibility=hidden`, similar to libc++?
|
||||
+libunwind_copts = [
|
||||
+ "-D_LIBUNWIND_IS_NATIVE_ONLY",
|
||||
+ "-O3",
|
||||
+ "-fPIC",
|
||||
+ "-fno-exceptions",
|
||||
+ "-fno-rtti",
|
||||
+ "-funwind-tables",
|
||||
+ "-nostdinc++",
|
||||
+]
|
||||
|
||||
+154
-14
@@ -1,20 +1,21 @@
|
||||
Commit ID: e4ff7299fe7e35e70ba79f5d8e2c58658cfba678
|
||||
Commit ID: 1fd710ed69a0f47f454c386d39302ddb756a88b3
|
||||
Change ID: mstnwoqruyypnoouksnyqssllrsozpos
|
||||
Bookmarks: bz-libcxx bz-libcxx@git bz-libcxx@origin
|
||||
Bookmarks: bz-libcxx* bz-libcxx@git
|
||||
Author : Chandler Carruth <chandlerc@gmail.com> (2025-09-25 22:55:26)
|
||||
Committer: Chandler Carruth <chandlerc@gmail.com> (2025-11-22 09:23:52)
|
||||
Committer: Chandler Carruth <chandlerc@gmail.com> (2026-03-08 07:41:54)
|
||||
|
||||
Introduce basic sources exporting for libcxx and libcxxabi
|
||||
|
||||
This exports the source files directly so that they can be used to build
|
||||
a libcxx runtime library on demand.
|
||||
a libcxx runtime library on demand. It also differentiates between
|
||||
normal sources and textual sources.
|
||||
|
||||
diff --git a/utils/bazel/llvm-project-overlay/libcxx/BUILD.bazel b/utils/bazel/llvm-project-overlay/libcxx/BUILD.bazel
|
||||
new file mode 100644
|
||||
index 0000000000..a81a64c649
|
||||
index 0000000000..c8b517ab56
|
||||
--- /dev/null
|
||||
+++ b/utils/bazel/llvm-project-overlay/libcxx/BUILD.bazel
|
||||
@@ -0,0 +1,49 @@
|
||||
@@ -0,0 +1,139 @@
|
||||
+# This file is licensed under the Apache License v2.0 with LLVM Exceptions.
|
||||
+# See https://llvm.org/LICENSE.txt for license information.
|
||||
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
@@ -25,9 +26,11 @@ index 0000000000..a81a64c649
|
||||
+ default_visibility = ["//visibility:public"],
|
||||
+)
|
||||
+
|
||||
+exports_files(["include/__config_site.in"])
|
||||
+
|
||||
+exports_files(["vendor/llvm/default_assertion_handler.in"])
|
||||
+exports_files([
|
||||
+ "include/__config_site.in",
|
||||
+ "include/module.modulemap.in",
|
||||
+ "vendor/llvm/default_assertion_handler.in",
|
||||
+])
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxx_hdrs",
|
||||
@@ -54,22 +57,153 @@ index 0000000000..a81a64c649
|
||||
+ ),
|
||||
+)
|
||||
+
|
||||
+LIBCXX_SRCS_PSTL_LIBDISPATCH = [
|
||||
+ "src/pstl/libdispatch.cpp",
|
||||
+]
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxx_srcs",
|
||||
+ name = "libcxx_srcs_pstl_libdispatch",
|
||||
+ srcs = LIBCXX_SRCS_PSTL_LIBDISPATCH,
|
||||
+)
|
||||
+
|
||||
+LIBCXX_SRCS_SUPPORT_IBM_PATTERNS = [
|
||||
+ "src/support/ibm/**/*.cpp",
|
||||
+]
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxx_srcs_support_ibm",
|
||||
+ srcs = glob(LIBCXX_SRCS_SUPPORT_IBM_PATTERNS),
|
||||
+)
|
||||
+
|
||||
+LIBCXX_SRCS_SUPPORT_WIN32_PATTERNS = [
|
||||
+ "src/support/win32/**/*.cpp",
|
||||
+]
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxx_srcs_support_win32",
|
||||
+ srcs = glob(LIBCXX_SRCS_SUPPORT_WIN32_PATTERNS),
|
||||
+)
|
||||
+
|
||||
+LIBCXX_SRCS_TZDB = [
|
||||
+ "src/experimental/chrono_exception.cpp",
|
||||
+ "src/experimental/time_zone.cpp",
|
||||
+ "src/experimental/tzdb.cpp",
|
||||
+ "src/experimental/tzdb_list.cpp",
|
||||
+]
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxx_srcs_tzdb",
|
||||
+ srcs = LIBCXX_SRCS_TZDB,
|
||||
+)
|
||||
+
|
||||
+# Exclude platform-dependent patterns that are provided by per-target filegroups
|
||||
+# above.
|
||||
+LIBCXX_SRCS_TARGET_EXCLUDES = (
|
||||
+ LIBCXX_SRCS_PSTL_LIBDISPATCH +
|
||||
+ LIBCXX_SRCS_SUPPORT_IBM_PATTERNS +
|
||||
+ LIBCXX_SRCS_SUPPORT_WIN32_PATTERNS +
|
||||
+ LIBCXX_SRCS_TZDB
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxx_srcs_generic",
|
||||
+ srcs = glob(
|
||||
+ [
|
||||
+ "src/**/*.cpp",
|
||||
+ "src/**/*.h",
|
||||
+ "src/**/*.ipp",
|
||||
+ ],
|
||||
+ exclude = [
|
||||
+ # Build is for use with libc++abi and so don't need 'new.cpp'.
|
||||
+ "src/new.cpp",
|
||||
+
|
||||
+ # Build is for compiler-rt platforms so we have its int128 support.
|
||||
+ "src/filesystem/int128_builtins.cpp",
|
||||
+ ] + LIBCXX_SRCS_TARGET_EXCLUDES,
|
||||
+ ),
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxx_linux_srcs",
|
||||
+ srcs = [
|
||||
+ ":libcxx_srcs_generic",
|
||||
+ ":libcxx_srcs_tzdb",
|
||||
+ ],
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxx_macos_srcs",
|
||||
+ srcs = [
|
||||
+ ":libcxx_srcs_generic",
|
||||
+ # TODO: Include libdispatch sources here to enable that pstl backend.
|
||||
+ ],
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxx_win32_srcs",
|
||||
+ srcs = [
|
||||
+ ":libcxx_srcs_generic",
|
||||
+ ":libcxx_srcs_support_win32",
|
||||
+ ],
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxx_all_srcs",
|
||||
+ srcs = [
|
||||
+ ":libcxx_linux_srcs",
|
||||
+ ":libcxx_macos_srcs",
|
||||
+ ":libcxx_win32_srcs",
|
||||
+ ],
|
||||
+)
|
||||
diff --git a/utils/bazel/llvm-project-overlay/libcxx/libcxx_library.bzl b/utils/bazel/llvm-project-overlay/libcxx/libcxx_library.bzl
|
||||
new file mode 100644
|
||||
index 0000000000..66f64f3610
|
||||
--- /dev/null
|
||||
+++ b/utils/bazel/llvm-project-overlay/libcxx/libcxx_library.bzl
|
||||
@@ -0,0 +1,37 @@
|
||||
+# This file is licensed under the Apache License v2.0 with LLVM Exceptions.
|
||||
+# See https://llvm.org/LICENSE.txt for license information.
|
||||
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
+
|
||||
+"""Starlark variables and macros for building libc++ and libc++abi.
|
||||
+
|
||||
+Variables provide base line information for how to build libc++ and libc++abi
|
||||
+source files. These can be used to generate non-Bazel builds of the library.
|
||||
+
|
||||
+TODO: Add macros that provide a convenient way to construct Bazel `cc_library`
|
||||
+rules for libc++ and libc++abi.
|
||||
+
|
||||
+TODO: Add either sufficient usage in the macros, or add a how-to example here in
|
||||
+the documentation so the use of these variables is more clear.
|
||||
+"""
|
||||
+
|
||||
+_libcxx_base_copts = [
|
||||
+ "-std=c++26",
|
||||
+ "-O3",
|
||||
+ "-fPIC",
|
||||
+ "-fvisibility-inlines-hidden",
|
||||
+ "-fvisibility=hidden",
|
||||
+ "-nostdinc++",
|
||||
+]
|
||||
+
|
||||
+_libcxx_defines = [
|
||||
+ "-D_LIBCPP_BUILDING_LIBRARY",
|
||||
+ "-D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES",
|
||||
+]
|
||||
+
|
||||
+_libcxxabi_defines = [
|
||||
+ "-DLIBCXX_BUILDING_LIBCXXABI",
|
||||
+]
|
||||
+
|
||||
+libcxx_copts = _libcxx_base_copts + _libcxx_defines
|
||||
+libcxxabi_copts = _libcxx_base_copts + _libcxxabi_defines
|
||||
+libcxx_and_abi_copts = _libcxx_base_copts + _libcxx_defines + _libcxxabi_defines
|
||||
diff --git a/utils/bazel/llvm-project-overlay/libcxxabi/BUILD.bazel b/utils/bazel/llvm-project-overlay/libcxxabi/BUILD.bazel
|
||||
new file mode 100644
|
||||
index 0000000000..cf491e4e46
|
||||
index 0000000000..2db70b54e2
|
||||
--- /dev/null
|
||||
+++ b/utils/bazel/llvm-project-overlay/libcxxabi/BUILD.bazel
|
||||
@@ -0,0 +1,24 @@
|
||||
@@ -0,0 +1,30 @@
|
||||
+# This file is licensed under the Apache License v2.0 with LLVM Exceptions.
|
||||
+# See https://llvm.org/LICENSE.txt for license information.
|
||||
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
@@ -89,8 +223,14 @@ index 0000000000..cf491e4e46
|
||||
+ name = "libcxxabi_srcs",
|
||||
+ srcs = glob([
|
||||
+ "src/**/*.cpp",
|
||||
+ "src/**/*.def",
|
||||
+ "src/**/*.inc",
|
||||
+ "src/**/*.h",
|
||||
+ ]),
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "libcxxabi_textual_srcs",
|
||||
+ srcs = glob([
|
||||
+ "src/**/*.def",
|
||||
+ "src/**/*.inc",
|
||||
+ ]),
|
||||
+)
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
Commit ID: e92461dc72d53b737ac14fe2c4c9c539946a4318
|
||||
Change ID: xyswklonuwpozzpkzwowszwnrzvkonxu
|
||||
Author : Chandler Carruth <chandlerc@gmail.com> (2025-12-30 10:19:01)
|
||||
Committer: Chandler Carruth <chandlerc@gmail.com> (2025-12-30 21:28:56)
|
||||
|
||||
Add filegroups for installed compiler-rt headers
|
||||
|
||||
These are installed along-side the builtin Clang headers.
|
||||
|
||||
diff --git a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel
|
||||
index 115da4cb77..ebe376fcaa 100644
|
||||
--- a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel
|
||||
+++ b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel
|
||||
@@ -131,6 +131,21 @@
|
||||
],
|
||||
)
|
||||
|
||||
+filegroup(
|
||||
+ name = "fuzzer_installed_hdrs",
|
||||
+ srcs = glob(["include/fuzzer/*.h"]),
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "profile_installed_hdrs",
|
||||
+ srcs = glob(["include/profile/*.h"]),
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "sanitizer_installed_hdrs",
|
||||
+ srcs = glob(["include/sanitizer/*.h"]),
|
||||
+)
|
||||
+
|
||||
BUILTINS_CRTBEGIN_SRCS = ["lib/builtins/crtbegin.c"]
|
||||
|
||||
filegroup(
|
||||
+521
@@ -0,0 +1,521 @@
|
||||
Commit ID: d3b82534c2546a892a27856672ed95a7db97dba3
|
||||
Change ID: zyxuvzwmzsnorloyuupuurxkppkoplnw
|
||||
Author : Chandler Carruth <chandlerc@gmail.com> (2026-02-16 23:17:06)
|
||||
Committer: Chandler Carruth <chandlerc@gmail.com> (2026-03-11 07:54:02)
|
||||
|
||||
Improve compiler-rt build structure and export compilation info
|
||||
|
||||
This first improves the structure of the compiler-rt BUILD.bazel, fixing
|
||||
bugs and exposing more carefully arranged source files.
|
||||
|
||||
It also exposes compilation info for builtins and CRT files for use in
|
||||
compiling these source files.
|
||||
|
||||
diff --git a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel
|
||||
index 4ded226174..3b5b8fc787 100644
|
||||
--- a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel
|
||||
+++ b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel
|
||||
@@ -3,6 +3,7 @@
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
+load("compiler-rt.bzl", "make_filtered_builtins_srcs_groups")
|
||||
|
||||
package(
|
||||
default_visibility = ["//visibility:public"],
|
||||
@@ -160,9 +161,15 @@
|
||||
srcs = BUILTINS_CRTEND_SRCS,
|
||||
)
|
||||
|
||||
+BUILTINS_EMUTLS_SRCS = ["lib/builtins/emutls.c"]
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "builtins_emutls_srcs",
|
||||
+ srcs = BUILTINS_EMUTLS_SRCS,
|
||||
+)
|
||||
+
|
||||
BUILTINS_HOSTED_SRCS = [
|
||||
"lib/builtins/clear_cache.c",
|
||||
- "lib/builtins/emutls.c",
|
||||
"lib/builtins/enable_execute_stack.c",
|
||||
"lib/builtins/eprintf.c",
|
||||
]
|
||||
@@ -224,11 +231,11 @@
|
||||
),
|
||||
)
|
||||
|
||||
-BUILTNS_ATOMICS_SRCS = ["lib/builtins/atomic.c"]
|
||||
+BUILTINS_ATOMICS_SRCS = ["lib/builtins/atomic.c"]
|
||||
|
||||
filegroup(
|
||||
name = "builtins_atomics_srcs",
|
||||
- srcs = BUILTNS_ATOMICS_SRCS + ["lib/builtins/assembly.h"],
|
||||
+ srcs = BUILTINS_ATOMICS_SRCS + ["lib/builtins/assembly.h"],
|
||||
)
|
||||
|
||||
BUILTINS_MACOS_ATOMIC_SRCS_PATTERNS = [
|
||||
@@ -241,6 +248,28 @@
|
||||
srcs = glob(BUILTINS_MACOS_ATOMIC_SRCS_PATTERNS),
|
||||
)
|
||||
|
||||
+# Source files for portable components of the compiler builtins library.
|
||||
+filegroup(
|
||||
+ name = "builtins_generic_srcs",
|
||||
+ srcs = ["lib/builtins/cpu_model/cpu_model.h"] + glob(
|
||||
+ [
|
||||
+ "lib/builtins/*.c",
|
||||
+ "lib/builtins/*.cpp",
|
||||
+ "lib/builtins/*.h",
|
||||
+ "lib/builtins/*.inc",
|
||||
+ ],
|
||||
+ allow_empty = True,
|
||||
+ exclude = (
|
||||
+ BUILTINS_CRTBEGIN_SRCS +
|
||||
+ BUILTINS_CRTEND_SRCS +
|
||||
+ BUILTINS_TF_EXCLUDES +
|
||||
+ BUILTINS_TF_SRCS_PATTERNS +
|
||||
+ BUILTINS_ATOMICS_SRCS +
|
||||
+ BUILTINS_MACOS_ATOMIC_SRCS_PATTERNS
|
||||
+ ),
|
||||
+ ),
|
||||
+)
|
||||
+
|
||||
# Apple-platform specific SME source file.
|
||||
filegroup(
|
||||
name = "builtins_aarch64_apple_sme_srcs",
|
||||
@@ -305,10 +334,13 @@
|
||||
|
||||
# Source files for the AArch64 architecture-specific builtins.
|
||||
filegroup(
|
||||
- name = "builtins_aarch64_srcs",
|
||||
+ name = "builtins_unfiltered_aarch64_srcs",
|
||||
srcs = [
|
||||
"lib/builtins/cpu_model/aarch64.c",
|
||||
"lib/builtins/cpu_model/aarch64.h",
|
||||
+ ":builtins_bf16_srcs",
|
||||
+ ":builtins_generic_srcs",
|
||||
+ ":builtins_tf_srcs",
|
||||
] + [
|
||||
AARCH64_OUTLINE_ATOMICS_FMT.format(pat, size, model)
|
||||
for (pat, size, model) in AARCH64_OUTLINE_ATOMICS
|
||||
@@ -328,10 +360,20 @@
|
||||
"lib/builtins/aarch64/lse.S",
|
||||
# These files are provided by SME-specific file groups above.
|
||||
"lib/builtins/aarch64/*sme*",
|
||||
+ # This is only used with MinGW.
|
||||
+ "lib/builtins/aarch64/chkstk.S",
|
||||
+ # TODO: Remove this once we have a way of accessing `SipHash.h`.
|
||||
+ "lib/builtins/aarch64/emupac.cpp",
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
+make_filtered_builtins_srcs_groups(
|
||||
+ name = "builtins_aarch64_srcs",
|
||||
+ srcs = [":builtins_unfiltered_aarch64_srcs"],
|
||||
+ textual_name = "builtins_aarch64_textual_srcs",
|
||||
+)
|
||||
+
|
||||
BUILTINS_ARM_VFP_SRCS_PATTERNS = [
|
||||
"lib/builtins/arm/*vfp*.S",
|
||||
"lib/builtins/arm/*vfp*.c",
|
||||
@@ -348,9 +390,19 @@
|
||||
),
|
||||
)
|
||||
|
||||
+BUILTINS_ARM_IMPLICIT_IT_SRCS = [
|
||||
+ "lib/builtins/arm/mulsf3.S",
|
||||
+ "lib/builtins/arm/divsf3.S",
|
||||
+]
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "builtins_arm_implicit_it_srcs",
|
||||
+ srcs = BUILTINS_ARM_IMPLICIT_IT_SRCS,
|
||||
+)
|
||||
+
|
||||
# Source files for the ARM architecture-specific builtins.
|
||||
filegroup(
|
||||
- name = "builtins_arm_srcs",
|
||||
+ name = "builtins_arm_arch_srcs",
|
||||
srcs = glob(
|
||||
[
|
||||
"lib/builtins/arm/*.S",
|
||||
@@ -359,14 +411,52 @@
|
||||
"lib/builtins/arm/*.h",
|
||||
],
|
||||
allow_empty = True,
|
||||
- exclude = BUILTINS_ARM_VFP_SRCS_PATTERNS,
|
||||
+ exclude = (BUILTINS_ARM_VFP_SRCS_PATTERNS +
|
||||
+ BUILTINS_ARM_IMPLICIT_IT_SRCS) + [
|
||||
+ # This is only used with MinGW.
|
||||
+ "lib/builtins/arm/chkstk.S",
|
||||
+ ],
|
||||
),
|
||||
)
|
||||
|
||||
-# Source files for the PPC architecture-specific builtins.
|
||||
-filegroup(
|
||||
- name = "builtins_ppc_srcs",
|
||||
- srcs = glob(
|
||||
+filegroup(
|
||||
+ name = "builtins_unfiltered_armv7_srcs",
|
||||
+ srcs = [
|
||||
+ ":builtins_arm_arch_srcs",
|
||||
+ ":builtins_arm_vfp_srcs",
|
||||
+ ":builtins_bf16_srcs",
|
||||
+ ":builtins_generic_srcs",
|
||||
+ ],
|
||||
+)
|
||||
+
|
||||
+make_filtered_builtins_srcs_groups(
|
||||
+ name = "builtins_armv7_srcs",
|
||||
+ srcs = [":builtins_unfiltered_armv7_srcs"],
|
||||
+ textual_name = "builtins_armv7_textual_srcs",
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "builtins_unfiltered_aarch32_srcs",
|
||||
+ srcs = [
|
||||
+ ":builtins_arm_arch_srcs",
|
||||
+ ":builtins_arm_vfp_srcs",
|
||||
+ ":builtins_bf16_srcs",
|
||||
+ ":builtins_generic_srcs",
|
||||
+ ],
|
||||
+)
|
||||
+
|
||||
+make_filtered_builtins_srcs_groups(
|
||||
+ name = "builtins_aarch32_srcs",
|
||||
+ srcs = [":builtins_unfiltered_aarch32_srcs"],
|
||||
+ textual_name = "builtins_aarch32_textual_srcs",
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "builtins_unfiltered_ppc64_srcs",
|
||||
+ srcs = [
|
||||
+ ":builtins_generic_srcs",
|
||||
+ ":builtins_tf_srcs",
|
||||
+ ] + glob(
|
||||
[
|
||||
"lib/builtins/ppc/*.S",
|
||||
"lib/builtins/ppc/*.c",
|
||||
@@ -377,17 +467,64 @@
|
||||
),
|
||||
)
|
||||
|
||||
-# Source files for the RISC-V architecture-specific builtins.
|
||||
-filegroup(
|
||||
- name = "builtins_riscv_srcs",
|
||||
- srcs = glob(
|
||||
- [
|
||||
- "lib/builtins/riscv/*.S",
|
||||
- "lib/builtins/riscv/*.c",
|
||||
- "lib/builtins/riscv/*.cpp",
|
||||
- ],
|
||||
- allow_empty = True,
|
||||
- ),
|
||||
+make_filtered_builtins_srcs_groups(
|
||||
+ name = "builtins_ppc64_srcs",
|
||||
+ srcs = [":builtins_unfiltered_ppc64_srcs"],
|
||||
+ textual_name = "builtins_ppc64_textual_srcs",
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "builtins_unfiltered_ppc32_srcs",
|
||||
+ srcs = [":builtins_generic_srcs"],
|
||||
+)
|
||||
+
|
||||
+make_filtered_builtins_srcs_groups(
|
||||
+ name = "builtins_ppc32_srcs",
|
||||
+ srcs = [":builtins_unfiltered_ppc32_srcs"],
|
||||
+ textual_name = "builtins_ppc32_textual_srcs",
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "builtins_unfiltered_riscv64_srcs",
|
||||
+ srcs = [
|
||||
+ ":builtins_generic_srcs",
|
||||
+ ":builtins_tf_srcs",
|
||||
+ ] + glob(
|
||||
+ [
|
||||
+ "lib/builtins/riscv/*.S",
|
||||
+ "lib/builtins/riscv/*.c",
|
||||
+ "lib/builtins/riscv/*.cpp",
|
||||
+ "lib/builtins/riscv/*.h",
|
||||
+ ],
|
||||
+ allow_empty = True,
|
||||
+ ),
|
||||
+)
|
||||
+
|
||||
+make_filtered_builtins_srcs_groups(
|
||||
+ name = "builtins_riscv64_srcs",
|
||||
+ srcs = [":builtins_unfiltered_riscv64_srcs"],
|
||||
+ textual_name = "builtins_riscv64_textual_srcs",
|
||||
+)
|
||||
+
|
||||
+filegroup(
|
||||
+ name = "builtins_unfiltered_riscv32_srcs",
|
||||
+ srcs = [
|
||||
+ ":builtins_generic_srcs",
|
||||
+ ] + glob(
|
||||
+ [
|
||||
+ "lib/builtins/riscv/*.S",
|
||||
+ "lib/builtins/riscv/*.c",
|
||||
+ "lib/builtins/riscv/*.cpp",
|
||||
+ "lib/builtins/riscv/*.h",
|
||||
+ ],
|
||||
+ allow_empty = True,
|
||||
+ ),
|
||||
+)
|
||||
+
|
||||
+make_filtered_builtins_srcs_groups(
|
||||
+ name = "builtins_riscv32_srcs",
|
||||
+ srcs = [":builtins_unfiltered_riscv32_srcs"],
|
||||
+ textual_name = "builtins_riscv32_textual_srcs",
|
||||
)
|
||||
|
||||
# Source files for the x86 architecture specific builtins (both 32-bit and
|
||||
@@ -402,8 +539,14 @@
|
||||
|
||||
# Source files for the x86-64 architecture specific builtins.
|
||||
filegroup(
|
||||
- name = "builtins_x86_64_srcs",
|
||||
- srcs = glob(
|
||||
+ name = "builtins_unfiltered_x86_64_srcs",
|
||||
+ srcs = [
|
||||
+ ":builtins_bf16_srcs",
|
||||
+ ":builtins_generic_srcs",
|
||||
+ ":builtins_tf_srcs",
|
||||
+ ":builtins_x86_arch_srcs",
|
||||
+ ":builtins_x86_fp80_srcs",
|
||||
+ ] + glob(
|
||||
[
|
||||
"lib/builtins/x86_64/*.S",
|
||||
"lib/builtins/x86_64/*.c",
|
||||
@@ -411,13 +554,29 @@
|
||||
"lib/builtins/x86_64/*.h",
|
||||
],
|
||||
allow_empty = True,
|
||||
+ exclude = [
|
||||
+ # This is a Windows-specific routine.
|
||||
+ # TODO: We should expose this as a Windows source at some point.
|
||||
+ "lib/builtins/x86_64/chkstk.S",
|
||||
+ ],
|
||||
),
|
||||
)
|
||||
|
||||
+make_filtered_builtins_srcs_groups(
|
||||
+ name = "builtins_x86_64_srcs",
|
||||
+ srcs = [":builtins_unfiltered_x86_64_srcs"],
|
||||
+ textual_name = "builtins_x86_64_textual_srcs",
|
||||
+)
|
||||
+
|
||||
# Source files for the 32-bit-specific x86 architecture specific builtins.
|
||||
filegroup(
|
||||
- name = "builtins_i386_srcs",
|
||||
- srcs = glob(
|
||||
+ name = "builtins_unfiltered_i386_srcs",
|
||||
+ srcs = [
|
||||
+ ":builtins_bf16_srcs",
|
||||
+ ":builtins_generic_srcs",
|
||||
+ ":builtins_x86_arch_srcs",
|
||||
+ ":builtins_x86_fp80_srcs",
|
||||
+ ] + glob(
|
||||
[
|
||||
"lib/builtins/i386/*.S",
|
||||
"lib/builtins/i386/*.c",
|
||||
@@ -429,28 +588,16 @@
|
||||
# This file is used for both i386 and x86_64 and so included in the
|
||||
# broader x86 sources.
|
||||
"lib/builtins/i386/fp_mode.c",
|
||||
+ # These are Windows-specific routines.
|
||||
+ # TODO: We should expose these as Windows source at some point.
|
||||
+ "lib/builtins/i386/chkstk.S",
|
||||
+ "lib/builtins/i386/chkstk2.S",
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
-# Source files for portable components of the compiler builtins library.
|
||||
-filegroup(
|
||||
- name = "builtins_generic_srcs",
|
||||
- srcs = ["lib/builtins/cpu_model/cpu_model.h"] + glob(
|
||||
- [
|
||||
- "lib/builtins/*.c",
|
||||
- "lib/builtins/*.cpp",
|
||||
- "lib/builtins/*.h",
|
||||
- "lib/builtins/*.inc",
|
||||
- ],
|
||||
- allow_empty = True,
|
||||
- exclude = (
|
||||
- BUILTINS_CRTBEGIN_SRCS +
|
||||
- BUILTINS_CRTEND_SRCS +
|
||||
- BUILTINS_TF_EXCLUDES +
|
||||
- BUILTINS_TF_SRCS_PATTERNS +
|
||||
- BUILTNS_ATOMICS_SRCS +
|
||||
- BUILTINS_MACOS_ATOMIC_SRCS_PATTERNS
|
||||
- ),
|
||||
- ),
|
||||
+make_filtered_builtins_srcs_groups(
|
||||
+ name = "builtins_i386_srcs",
|
||||
+ srcs = [":builtins_unfiltered_i386_srcs"],
|
||||
+ textual_name = "builtins_i386_textual_srcs",
|
||||
)
|
||||
diff --git a/utils/bazel/llvm-project-overlay/compiler-rt/compiler-rt.bzl b/utils/bazel/llvm-project-overlay/compiler-rt/compiler-rt.bzl
|
||||
new file mode 100644
|
||||
index 0000000000..e33ceb6a89
|
||||
--- /dev/null
|
||||
+++ b/utils/bazel/llvm-project-overlay/compiler-rt/compiler-rt.bzl
|
||||
@@ -0,0 +1,153 @@
|
||||
+# This file is licensed under the Apache License v2.0 with LLVM Exceptions.
|
||||
+# See https://llvm.org/LICENSE.txt for license information.
|
||||
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
+
|
||||
+"""Starlark for building parts of compiler-rt.
|
||||
+
|
||||
+Variables provide baseline information for how to build various parts of
|
||||
+compiler-rt. These can be used to generate non-Bazel builds of the library.
|
||||
+
|
||||
+Rules and macros support building the relevant filegroups of source files.
|
||||
+
|
||||
+TODO: Add macros that provide a convenient way to construct a Bazel target for
|
||||
+the Clang resource directory with builtins and crt files.
|
||||
+"""
|
||||
+
|
||||
+_common_copts = [
|
||||
+ "-O3",
|
||||
+ "-fPIC",
|
||||
+ "-ffreestanding",
|
||||
+ "-std=c11",
|
||||
+]
|
||||
+
|
||||
+crt_copts = _common_copts + [
|
||||
+ "-DCRT_HAS_INITFINI_ARRAY",
|
||||
+ "-DEH_USE_FRAME_REGISTRY",
|
||||
+ "-fno-lto",
|
||||
+]
|
||||
+
|
||||
+builtins_copts = _common_copts + [
|
||||
+ "-fno-builtin",
|
||||
+ "-fomit-frame-pointer",
|
||||
+ "-fvisibility=hidden",
|
||||
+ "-Wno-missing-prototypes",
|
||||
+ "-Wno-unused-parameter",
|
||||
+]
|
||||
+
|
||||
+def _get_rel_path(path_str):
|
||||
+ rel_path = path_str.rpartition("/lib/builtins/")[2]
|
||||
+ if rel_path == path_str:
|
||||
+ fail("Expected '/lib/builtins/' in path " + path_str)
|
||||
+ return rel_path
|
||||
+
|
||||
+def _filtered_builtins_srcs_impl(ctx):
|
||||
+ """Implementation of filter_builtins_srcs rule."""
|
||||
+
|
||||
+ # Build a map from generic file basename to list of overriding files.
|
||||
+ overrides = {}
|
||||
+ for f in ctx.files.srcs:
|
||||
+ rel_path = _get_rel_path(f.short_path)
|
||||
+ if "/" in rel_path:
|
||||
+ base_file = rel_path.rpartition("/")[2]
|
||||
+ if base_file.endswith(".S"):
|
||||
+ base_file = base_file.removesuffix(".S") + ".c"
|
||||
+ overrides[base_file] = True
|
||||
+
|
||||
+ filtered_files = []
|
||||
+ for f in ctx.files.srcs:
|
||||
+ rel_path = _get_rel_path(f.short_path)
|
||||
+ if "/" not in rel_path:
|
||||
+ # This is a generic file. Check if it's overridden.
|
||||
+ if rel_path not in overrides:
|
||||
+ filtered_files.append(f)
|
||||
+ else:
|
||||
+ # This is an arch-specific file, include it.
|
||||
+ filtered_files.append(f)
|
||||
+
|
||||
+ # Remove any textual sources from this list.
|
||||
+ filtered_files = [
|
||||
+ f
|
||||
+ for f in filtered_files
|
||||
+ if f.extension not in ["inc", "def"]
|
||||
+ ]
|
||||
+
|
||||
+ return [DefaultInfo(files = depset(filtered_files))]
|
||||
+
|
||||
+filtered_builtins_srcs = rule(
|
||||
+ implementation = _filtered_builtins_srcs_impl,
|
||||
+ attrs = {
|
||||
+ "srcs": attr.label_list(
|
||||
+ mandatory = True,
|
||||
+ allow_files = True,
|
||||
+ doc = "Input files.",
|
||||
+ ),
|
||||
+ },
|
||||
+ doc = """Build a filtered filegroup of non-textual srcs for builtins.
|
||||
+
|
||||
+ Accepts a filegroup whose files are in lib/builtins/, and produces a target
|
||||
+ behaving like a filegroup containing filtered files.
|
||||
+
|
||||
+ This removes any textual source files (`.inc` or `.def`) from the input.
|
||||
+
|
||||
+ It also replaces generic srcs that are overridden by architecture-specific
|
||||
+ sources. For example, given a list of sources from filegroup of the form:
|
||||
+
|
||||
+ - `.../lib/builtins/file_0.c`
|
||||
+ - `.../lib/builtins/file_1.c`
|
||||
+ - `.../lib/builtins/file_2.c`
|
||||
+ - `.../lib/builtins/arch/file_0.c`
|
||||
+ - `.../lib/builtins/arch/file_1.S`
|
||||
+
|
||||
+ It removes any source-file at the top level of lib/builtins/ (e.g.
|
||||
+ lib/builtins/file_0.c) that has a corresponding source-file in an arch
|
||||
+ directory (e.g. lib/builtins/arch/file_0.c or lib/builtins/arch/file_1.S),
|
||||
+ producing a list like:
|
||||
+
|
||||
+ - `.../lib/builtins/file_2.c`
|
||||
+ - `.../lib/builtins/arch/file_0.c`
|
||||
+ - `.../lib/builtins/arch/file_1.S`
|
||||
+
|
||||
+ This allows a target architecture to simply add a specialized file to the
|
||||
+ list of sources with the architecture prefix and have the specialized
|
||||
+ version override the generic version.
|
||||
+ """,
|
||||
+)
|
||||
+
|
||||
+def _filtered_builtins_textual_srcs_impl(ctx):
|
||||
+ """Implementation of filter_builtins_textual_srcs rule."""
|
||||
+
|
||||
+ filtered_files = [
|
||||
+ f
|
||||
+ for f in ctx.files.srcs
|
||||
+ if f.extension in ["inc", "def"]
|
||||
+ ]
|
||||
+
|
||||
+ return [DefaultInfo(files = depset(filtered_files))]
|
||||
+
|
||||
+filtered_builtins_textual_srcs = rule(
|
||||
+ implementation = _filtered_builtins_textual_srcs_impl,
|
||||
+ attrs = {
|
||||
+ "srcs": attr.label_list(
|
||||
+ mandatory = True,
|
||||
+ allow_files = True,
|
||||
+ doc = "Input files.",
|
||||
+ ),
|
||||
+ },
|
||||
+ doc = """Build a filegroup of the textual srcs for builtins.
|
||||
+
|
||||
+ Textual sources are those that can't be compiled directly and aren't
|
||||
+ recognized as header files by Bazel. The extensions recognized here are
|
||||
+ `.inc` and `.def`.
|
||||
+ """,
|
||||
+)
|
||||
+
|
||||
+def make_filtered_builtins_srcs_groups(name, textual_name, srcs):
|
||||
+ """Macro to expand both the non-textual and textual filtered srcs groups."""
|
||||
+ filtered_builtins_srcs(
|
||||
+ name = name,
|
||||
+ srcs = srcs,
|
||||
+ )
|
||||
+ filtered_builtins_textual_srcs(
|
||||
+ name = textual_name,
|
||||
+ srcs = srcs,
|
||||
+ )
|
||||
@@ -8,10 +8,6 @@ def _get_files(ctx):
|
||||
files = []
|
||||
for src in ctx.attr.srcs:
|
||||
files.extend([f.path for f in src[DefaultInfo].files.to_list()])
|
||||
files.extend([
|
||||
f.path
|
||||
for f in src[DefaultInfo].default_runfiles.files.to_list()
|
||||
])
|
||||
|
||||
if ctx.attr.strip_package_dir:
|
||||
# Files may or may not be prefixed with the bin directory, and then
|
||||
|
||||
@@ -88,7 +88,7 @@ def main() -> None:
|
||||
# Remove line endings.
|
||||
line = line.rstrip("\r\n")
|
||||
# Exactly matches our pattern
|
||||
(key, value) = line.split(" ", 1)
|
||||
key, value = line.split(" ", 1)
|
||||
key = key.removeprefix("STABLE_")
|
||||
if key in substitutions:
|
||||
if args.verbose:
|
||||
|
||||
@@ -134,7 +134,7 @@ expand_version_build_info_internal = rule(
|
||||
def expand_version_build_info(name, **kwargs):
|
||||
expand_version_build_info_internal(
|
||||
name = name,
|
||||
internal_stamp_flag_detect = select({
|
||||
internal_stamp_flag_detect = False if kwargs.get("stamp") == 0 else select({
|
||||
"//bazel/version:internal_stamp_flag_detect": True,
|
||||
"//conditions:default": False,
|
||||
}),
|
||||
|
||||
+2
-2
@@ -473,7 +473,7 @@ cc_binary(
|
||||
"//testing/base:benchmark_main",
|
||||
"@abseil-cpp//absl/container:flat_hash_map",
|
||||
"@abseil-cpp//absl/random",
|
||||
"@boost_unordered",
|
||||
"@boost.unordered",
|
||||
"@google_benchmark//:benchmark",
|
||||
"@llvm-project//llvm:Support",
|
||||
],
|
||||
@@ -577,7 +577,7 @@ cc_library(
|
||||
"@abseil-cpp//absl/base:no_destructor",
|
||||
"@abseil-cpp//absl/hash",
|
||||
"@abseil-cpp//absl/random",
|
||||
"@boost_unordered",
|
||||
"@boost.unordered",
|
||||
"@google_benchmark//:benchmark",
|
||||
"@llvm-project//llvm:Support",
|
||||
],
|
||||
|
||||
@@ -643,7 +643,7 @@ auto DirRef::ReadlinkSlow(const std::filesystem::path& path)
|
||||
if (buffer_size == 0) {
|
||||
buffer_size = MinBufferSize;
|
||||
}
|
||||
large_buffer.resize(status.size());
|
||||
large_buffer.resize(buffer_size);
|
||||
ssize_t result =
|
||||
readlinkat(dfd_, path.c_str(), large_buffer.data(), large_buffer.size());
|
||||
if (result == -1) {
|
||||
|
||||
@@ -18,17 +18,18 @@ namespace Carbon {
|
||||
//
|
||||
// This provides a hashtable-specific extension point to implement equality
|
||||
// comparison within a hashtable key context. By default, it will use
|
||||
// `operator==` on the LHS and RHS operands. However, types can provide a
|
||||
// dedicated customization point by implementing a free function that can be
|
||||
// found by ADL for your type called `CarbonHashtableEq` with the following
|
||||
// signature:
|
||||
// `operator==` on the LHS and RHS operands if they are of the identical type.
|
||||
// However, types can provide a dedicated customization point by implementing a
|
||||
// free function that can be found by ADL for your type called
|
||||
// `CarbonHashtableEq` with the following signature:
|
||||
//
|
||||
// ```cpp
|
||||
// auto CarbonHashtableEq(const YourType& lhs, const YourType& rhs) -> bool;
|
||||
// ```
|
||||
//
|
||||
// Any such overload will be able to override the default we provide for types
|
||||
// that can compare with `==`.
|
||||
// that can compare with `==`. This overload may only compare two objects equal
|
||||
// if the hash of those two objects are identical.
|
||||
//
|
||||
// This library also provides any customization points for LLVM or standard
|
||||
// library types either lacking `operator==` or where that operator is not
|
||||
@@ -161,8 +162,37 @@ inline auto CarbonHashtableEq(const llvm::APFloat& lhs,
|
||||
return lhs.bitwiseIsEqual(rhs);
|
||||
}
|
||||
|
||||
template <typename LeftT, typename RightT>
|
||||
inline auto CarbonHashtableEq(const LeftT& lhs, const RightT& rhs) -> bool
|
||||
inline auto CarbonHashtableEq(llvm::StringRef lhs, const std::string& rhs)
|
||||
-> bool {
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline auto CarbonHashtableEq(llvm::MutableArrayRef<T> lhs,
|
||||
llvm::ArrayRef<T> rhs) -> bool {
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
template <typename LHS, typename RHS>
|
||||
inline auto CarbonHashtableEq(const LHS& lhs, const RHS& rhs) -> bool
|
||||
requires(requires {
|
||||
{ CarbonHashtableEq(rhs, lhs) } -> std::convertible_to<bool>;
|
||||
})
|
||||
{
|
||||
return CarbonHashtableEq(rhs, lhs);
|
||||
}
|
||||
|
||||
// Provides symmetric equality so the `CarbonHashtableEq` operands aren't
|
||||
// ordered.
|
||||
//
|
||||
// If this template proves problematic in any way, we can revisit it - the
|
||||
// `CarbonHashtableEq` functions don't really need to be symmetric, since they
|
||||
// generally represent an implicit conversion which is often only one-way (eg:
|
||||
// MutableArrayRef converts to ArrayRef, but not the other way around) - but
|
||||
// documenting/describing that asymmetry felt a little awkward too - so maybe
|
||||
// this template is an OK solution for now.
|
||||
template <typename T>
|
||||
inline auto CarbonHashtableEq(const T& lhs, const T& rhs) -> bool
|
||||
requires(requires {
|
||||
{ lhs == rhs } -> std::convertible_to<bool>;
|
||||
})
|
||||
|
||||
@@ -45,6 +45,10 @@ struct TestData : Printable<TestData> {
|
||||
|
||||
static_assert(std::is_copy_constructible_v<TestData>);
|
||||
|
||||
inline auto CarbonHashtableEq(int lhs, TestData rhs) -> bool {
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
// Non-trivial type for testing.
|
||||
struct MoveOnlyTestData : Printable<TestData> {
|
||||
int value;
|
||||
@@ -85,6 +89,10 @@ struct MoveOnlyTestData : Printable<TestData> {
|
||||
static_assert(!std::is_copy_constructible_v<MoveOnlyTestData>);
|
||||
static_assert(std::is_move_constructible_v<MoveOnlyTestData>);
|
||||
|
||||
inline auto CarbonHashtableEq(int lhs, const MoveOnlyTestData& rhs) -> bool {
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
// Test stateless key context that produces different hashes from normal.
|
||||
// Changing the hash values should result in test failures if the context ever
|
||||
// fails to be used.
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
package Core library "prelude";
|
||||
|
||||
export import library "prelude/copy";
|
||||
export import library "prelude/default";
|
||||
export import library "prelude/destroy";
|
||||
export import library "prelude/iterate";
|
||||
export import library "prelude/operators";
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// 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
|
||||
|
||||
package Core library "prelude/default";
|
||||
|
||||
import library "prelude/types/bool";
|
||||
import library "prelude/types/int_literal";
|
||||
|
||||
// Provides the default value of an object. If implemented for a type `T`, this
|
||||
// is used to initialize declarations without an explicit initializer, such as
|
||||
// `var x: T;`, and leaves them in a fully-formed state.
|
||||
interface Default { fn Op() -> Self; }
|
||||
|
||||
// Indicates that a type permits unformed initialization, which leaves the
|
||||
// object in a state where calling the destructor is valid but optional, and no
|
||||
// other operations on the object except for reinitialization are permitted.
|
||||
interface UnformedInit {
|
||||
// TODO: This should probably be:
|
||||
// let StructT:! type;
|
||||
// fn Op() -> StructT;
|
||||
// and should be able to initialize a subset of the fields. For now we always
|
||||
// leave the object uninitialized when it is in an unformed state.
|
||||
// See https://github.com/carbon-language/carbon-lang/pull/5913
|
||||
}
|
||||
|
||||
// Implementations for some builtin types. These need to be here to satisfy the
|
||||
// orphan rule because these builtin types have no associated library of their
|
||||
// own.
|
||||
impl bool as UnformedInit {}
|
||||
impl forall [T:! type] T* as UnformedInit {}
|
||||
impl forall [T:! UnformedInit, N:! IntLiteral()] array(T, N) as UnformedInit {}
|
||||
// TODO: Generalize these to apply to tuples and structs containing only
|
||||
// `UnformedInit` types.
|
||||
impl () as UnformedInit {}
|
||||
impl {} as UnformedInit {}
|
||||
|
||||
// Provides a default, possibly unformed, value of an object. This should not be
|
||||
// implemented directly. Instead, implement `Default` to provide a fully-formed
|
||||
// state or (eventually) `UnformedInit` to provide an unformed state.
|
||||
interface DefaultOrUnformed {
|
||||
// TODO: This should return `MaybeUnformed(Self)` once that is supported.
|
||||
fn Op() -> Self;
|
||||
}
|
||||
|
||||
final impl forall [T:! Default] T as DefaultOrUnformed {
|
||||
fn Op() -> Self {
|
||||
return T.(Default.Op)();
|
||||
}
|
||||
}
|
||||
|
||||
impl forall [T:! UnformedInit] T as DefaultOrUnformed {
|
||||
fn Op() -> Self = "make_uninitialized";
|
||||
}
|
||||
@@ -20,7 +20,7 @@ interface Iterate {
|
||||
impl forall [T:! Copy & Destroy, N:! IntLiteral()]
|
||||
array(T, N) as Iterate
|
||||
where .ElementType = T and .CursorType = i32 {
|
||||
fn NewCursor[self: Self]() -> i32 { return 0; }
|
||||
fn NewCursor[unused self: Self]() -> i32 { return 0; }
|
||||
fn Next[self: Self](cursor: i32*) -> Optional(T) {
|
||||
if (*cursor < N) {
|
||||
++*cursor;
|
||||
|
||||
@@ -9,3 +9,4 @@ export import library "prelude/operators/as";
|
||||
export import library "prelude/operators/bitwise";
|
||||
export import library "prelude/operators/comparison";
|
||||
export import library "prelude/operators/index";
|
||||
export import library "prelude/operators/deref";
|
||||
|
||||
@@ -44,8 +44,21 @@ impl forall [T:! type, U:! ImplicitAs(T)] const U as ImplicitAs(T) {
|
||||
fn Convert[self: const U]() -> T { return (self as U).Convert(); }
|
||||
}
|
||||
|
||||
// `const` can be added to a pointer.
|
||||
// TODO: This is also provided as a builtin conversion. We provide it here so
|
||||
// that Optional(T*) can implicitly convert to Optional(const T*). See #5750.
|
||||
impl forall [T:! type] T* as ImplicitAs(const T*) {
|
||||
fn Convert[self: T*]() -> const T* = "pointer.unsafe_convert";
|
||||
}
|
||||
|
||||
impl forall [T:! type] T* as As(const T*) {
|
||||
fn Convert[self: T*]() -> const T* = "pointer.unsafe_convert";
|
||||
}
|
||||
|
||||
// Pointer types can be unsafely cast to other pointer types.
|
||||
// TODO: Should `unsafe as` be able to remove `const`?
|
||||
impl forall [T:! type, U:! type] T* as UnsafeAs(U*) {
|
||||
fn Convert[self: T*]() -> U* = "pointer.unsafe_convert";
|
||||
}
|
||||
|
||||
interface IntFitsIn(Dest:! type) {}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// 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
|
||||
|
||||
package Core library "prelude/operators/deref";
|
||||
|
||||
// TODO: Align with https://docs.carbon-lang.dev/docs/design/values.html#dereferencing-customization.
|
||||
interface CppUnsafeDeref {
|
||||
let Result:! type;
|
||||
fn Op[ref self: Self]() -> ref Result;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
package Core library "prelude/types/char";
|
||||
|
||||
import library "prelude/copy";
|
||||
import library "prelude/default";
|
||||
import library "prelude/destroy";
|
||||
import library "prelude/operators";
|
||||
import library "prelude/types/uint";
|
||||
@@ -17,6 +18,8 @@ class Char {
|
||||
adapt u8;
|
||||
}
|
||||
|
||||
impl Char as UnformedInit {}
|
||||
|
||||
impl Char as Copy {
|
||||
fn Op[self: Self]() -> Self = "primitive_copy";
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package Core library "prelude/types/cpp/int";
|
||||
|
||||
import library "prelude/copy";
|
||||
import library "prelude/default";
|
||||
import library "prelude/operators";
|
||||
import library "prelude/types/int";
|
||||
import library "prelude/types/int_literal";
|
||||
@@ -28,6 +29,11 @@ class CppCompat.ULongLong64 {
|
||||
adapt u64;
|
||||
}
|
||||
|
||||
impl CppCompat.Long32 as UnformedInit {}
|
||||
impl CppCompat.ULong32 as UnformedInit {}
|
||||
impl CppCompat.LongLong64 as UnformedInit {}
|
||||
impl CppCompat.ULongLong64 as UnformedInit {}
|
||||
|
||||
// Copy
|
||||
|
||||
impl CppCompat.Long32 as Copy {
|
||||
@@ -93,12 +99,12 @@ final impl CppCompat.ULong32 as ImplicitAs(IntLiteral()) {
|
||||
|
||||
// TODO: ImplicitAs from UInt(N) to ULong32 if N < 32.
|
||||
impl u32 as ImplicitAs(CppCompat.ULong32) {
|
||||
fn Convert[self: Self]() -> CppCompat.ULong32 = "int.convert_checked";
|
||||
fn Convert[self: Self]() -> CppCompat.ULong32 = "int.convert";
|
||||
}
|
||||
|
||||
// TODO: ImplicitAs from ULong32 to UInt(N) if N > 32.
|
||||
final impl CppCompat.ULong32 as ImplicitAs(u32) {
|
||||
fn Convert[self: Self]() -> u32 = "int.convert";
|
||||
final impl CppCompat.ULong32 as ImplicitAs(u64) {
|
||||
fn Convert[self: Self]() -> u64 = "int.convert";
|
||||
}
|
||||
|
||||
impl IntLiteral() as ImplicitAs(CppCompat.LongLong64) {
|
||||
@@ -142,12 +148,12 @@ final impl CppCompat.ULongLong64 as ImplicitAs(IntLiteral()) {
|
||||
|
||||
// TODO: ImplicitAs from UInt(N) to ULongLong64 if N < 64.
|
||||
impl u64 as ImplicitAs(CppCompat.ULongLong64) {
|
||||
fn Convert[self: Self]() -> CppCompat.ULongLong64 = "int.convert_checked";
|
||||
fn Convert[self: Self]() -> CppCompat.ULongLong64 = "int.convert";
|
||||
}
|
||||
|
||||
// TODO: ImplicitAs from ULongLong64 to UInt(N) if N > 64.
|
||||
final impl CppCompat.ULongLong64 as ImplicitAs(u64) {
|
||||
fn Convert[self: Self]() -> u64 = "int.convert";
|
||||
final impl CppCompat.ULongLong64 as ImplicitAs(u128) {
|
||||
fn Convert[self: Self]() -> u128 = "int.convert";
|
||||
}
|
||||
|
||||
// TODO: As from Long32 to Int(N) if N < 32.
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package Core library "prelude/types/cpp/nullptr";
|
||||
|
||||
import library "prelude/copy";
|
||||
import library "prelude/default";
|
||||
import library "prelude/destroy";
|
||||
import library "prelude/operators/as";
|
||||
import library "prelude/types/cpp/void";
|
||||
@@ -29,13 +30,17 @@ class CppCompat.NullptrT {
|
||||
// TODO: Give this type a custom empty value representation.
|
||||
adapt MaybeUnformed(VoidBase*);
|
||||
|
||||
// TODO: This should be just
|
||||
// fn Make() -> Self = "make_uninitialized";
|
||||
// but we don't yet delay processing builtin function definitions until the
|
||||
// end of the enclosing class.
|
||||
fn Make() -> Self {
|
||||
returned var s: Self;
|
||||
return var;
|
||||
fn MakeImpl() -> Self = "make_uninitialized";
|
||||
return MakeImpl();
|
||||
}
|
||||
|
||||
impl as Copy {
|
||||
fn Op[self: Self]() -> Self {
|
||||
fn Op[unused self: Self]() -> Self {
|
||||
return Make();
|
||||
}
|
||||
}
|
||||
@@ -43,8 +48,10 @@ class CppCompat.NullptrT {
|
||||
// TODO: impl as EqWith(Self)
|
||||
|
||||
impl forall [T:! type] as ImplicitAs(Optional(T*)) {
|
||||
fn Convert[self: Self]() -> Optional(T*) {
|
||||
fn Convert[unused self: Self]() -> Optional(T*) {
|
||||
return Optional(T*).None();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CppCompat.NullptrT as UnformedInit {}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package Core library "prelude/types/float";
|
||||
|
||||
import library "prelude/copy";
|
||||
import library "prelude/default";
|
||||
import library "prelude/destroy";
|
||||
import library "prelude/operators";
|
||||
import library "prelude/types/float_literal";
|
||||
@@ -16,6 +17,8 @@ class Float(N:! IntLiteral()) {
|
||||
adapt MakeFloat(N);
|
||||
}
|
||||
|
||||
impl forall [N:! IntLiteral()] Float(N) as UnformedInit {}
|
||||
|
||||
// Copy.
|
||||
|
||||
impl forall [N:! IntLiteral()] Float(N) as Copy {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// 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
|
||||
|
||||
package Core library "prelude/types/form";
|
||||
|
||||
// TODO: this should be a concrete constant, not a function.
|
||||
fn Form() -> type = "form.make_type";
|
||||
@@ -5,6 +5,7 @@
|
||||
package Core library "prelude/types/int";
|
||||
|
||||
import library "prelude/copy";
|
||||
import library "prelude/default";
|
||||
import library "prelude/destroy";
|
||||
import library "prelude/operators";
|
||||
import library "prelude/types/int_literal";
|
||||
@@ -15,6 +16,8 @@ class Int(N:! IntLiteral()) {
|
||||
adapt MakeInt(N);
|
||||
}
|
||||
|
||||
impl forall [N:! IntLiteral()] Int(N) as UnformedInit {}
|
||||
|
||||
// Copy.
|
||||
|
||||
impl forall [N:! IntLiteral()] Int(N) as Copy {
|
||||
@@ -42,7 +45,26 @@ final impl forall [From:! IntLiteral()] Int(From) as As(IntLiteral()) {
|
||||
fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
|
||||
}
|
||||
|
||||
// TODO: Allow as an implicit conversion if N > M.
|
||||
// Work around the inability to put a `where` clause on a generic parameter of
|
||||
// type `IntLiteral`.
|
||||
// TODO: Remove this once possible.
|
||||
private interface AnyInt {
|
||||
let Width:! IntLiteral();
|
||||
fn AsInt[self: Self]() -> Int(Width);
|
||||
}
|
||||
|
||||
impl forall [N:! IntLiteral()] Int(N) as AnyInt where .Width = N {
|
||||
fn AsInt[self: Self]() -> Self { return self; }
|
||||
}
|
||||
|
||||
impl forall [To:! IntLiteral(), From:! AnyInt & IntFitsIn(Int(To))]
|
||||
From as ImplicitAs(Int(To)) {
|
||||
fn Convert[self: Self]() -> Int(To) {
|
||||
fn Impl(src: Int(From.Width)) -> Int(To) = "int.convert";
|
||||
return Impl(self.AsInt());
|
||||
}
|
||||
}
|
||||
|
||||
final impl forall [From:! IntLiteral(), To:! IntLiteral()] Int(From) as As(Int(To)) {
|
||||
fn Convert[self: Self]() -> Int(To) = "int.convert";
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
package Core library "prelude/types/maybe_unformed";
|
||||
|
||||
import library "prelude/default";
|
||||
import library "prelude/destroy";
|
||||
|
||||
private fn MakeMaybeUnformed(t: type) -> type = "maybe_unformed.make_type";
|
||||
@@ -12,3 +13,5 @@ private fn MakeMaybeUnformed(t: type) -> type = "maybe_unformed.make_type";
|
||||
class MaybeUnformed(T:! Destroy) {
|
||||
adapt MakeMaybeUnformed(T);
|
||||
}
|
||||
|
||||
impl forall [T:! Destroy] MaybeUnformed(T) as UnformedInit {}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package Core library "prelude/types/optional";
|
||||
|
||||
import library "prelude/copy";
|
||||
import library "prelude/default";
|
||||
import library "prelude/destroy";
|
||||
import library "prelude/operators/as";
|
||||
import library "prelude/operators/bitwise";
|
||||
@@ -40,6 +41,8 @@ class Optional(T:! OptionalStorage) {
|
||||
adapt T.Type;
|
||||
}
|
||||
|
||||
impl forall [T:! OptionalStorage & UnformedInit] Optional(T) as UnformedInit {}
|
||||
|
||||
// Support for converting a `T` to an `Optional(U)` if `T` converts to `U`.
|
||||
// Once we have match_first, this can be rewritten more simply as:
|
||||
//
|
||||
@@ -105,17 +108,23 @@ private class DefaultOptionalStorage(T:! Copy & Destroy) {
|
||||
var has_value: bool;
|
||||
}
|
||||
|
||||
private fn MakeUninitializedOptionalStorage(T:! Copy & Destroy)
|
||||
-> DefaultOptionalStorage(T) = "make_uninitialized";
|
||||
|
||||
impl forall [T:! Copy & Destroy] T as OptionalStorage
|
||||
where .Type = DefaultOptionalStorage(T) {
|
||||
fn None() -> DefaultOptionalStorage(T) {
|
||||
returned var me: DefaultOptionalStorage(T);
|
||||
returned var me: DefaultOptionalStorage(T) =
|
||||
MakeUninitializedOptionalStorage(T);
|
||||
me.has_value = false;
|
||||
return var;
|
||||
}
|
||||
fn Some[self: Self]() -> DefaultOptionalStorage(T) {
|
||||
returned var me: DefaultOptionalStorage(T);
|
||||
// TODO: Should be:
|
||||
// me.value = self as MaybeUnformed(T);
|
||||
// TODO: This whole function should be just
|
||||
// return {.value = self, .has_value = true};
|
||||
// but that requires that `T` implements `ImplicitAs(MaybeUnformed(T))`.
|
||||
returned var me: DefaultOptionalStorage(T) =
|
||||
MakeUninitializedOptionalStorage(T);
|
||||
me.value unsafe as T = self;
|
||||
me.has_value = true;
|
||||
return var;
|
||||
@@ -130,13 +139,17 @@ impl forall [T:! Copy & Destroy] T as OptionalStorage
|
||||
|
||||
private fn PointerIsNull[T:! type](value: MaybeUnformed(T*)) -> bool = "pointer.is_null";
|
||||
|
||||
private fn MakeUninitializedOptionalPointer(T:! type)
|
||||
-> MaybeUnformed(T*) = "make_uninitialized";
|
||||
|
||||
// For pointers, we use a null pointer value as the "None" value. This allows
|
||||
// `Optional(T*)` to be ABI-compatible with a C++ nullable pointer.
|
||||
final impl forall [T:! type] T* as OptionalStorage
|
||||
where .Type = MaybeUnformed(T*) {
|
||||
fn None() -> MaybeUnformed(T*) = "pointer.make_null";
|
||||
fn Some[self: Self]() -> MaybeUnformed(T*) {
|
||||
returned var result: MaybeUnformed(T*);
|
||||
returned var result: MaybeUnformed(T*) =
|
||||
MakeUninitializedOptionalPointer(T);
|
||||
result unsafe as T* = self;
|
||||
return var;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package Core library "prelude/types/string";
|
||||
|
||||
import library "prelude/copy";
|
||||
import library "prelude/default";
|
||||
import library "prelude/destroy";
|
||||
import library "prelude/types/char";
|
||||
import library "prelude/types/uint";
|
||||
@@ -24,6 +25,8 @@ class String {
|
||||
private var size: u64;
|
||||
}
|
||||
|
||||
impl String as UnformedInit {}
|
||||
|
||||
impl forall [T:! ImplicitAs(i64)] String as IndexWith(T) where .ElementType = Char {
|
||||
fn At[self: Self](subscript: T) -> Char = "string.at";
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package Core library "prelude/types/uint";
|
||||
|
||||
import library "prelude/copy";
|
||||
import library "prelude/default";
|
||||
import library "prelude/destroy";
|
||||
import library "prelude/operators";
|
||||
import library "prelude/types/int";
|
||||
@@ -16,6 +17,8 @@ class UInt(N:! IntLiteral()) {
|
||||
adapt MakeUInt(N);
|
||||
}
|
||||
|
||||
impl forall [N:! IntLiteral()] UInt(N) as UnformedInit {}
|
||||
|
||||
// Copy.
|
||||
|
||||
impl forall [N:! IntLiteral()] UInt(N) as Copy {
|
||||
@@ -43,12 +46,52 @@ final impl forall [From:! IntLiteral()] UInt(From) as As(IntLiteral()) {
|
||||
fn Convert[self: Self]() -> IntLiteral() = "int.convert_checked";
|
||||
}
|
||||
|
||||
// TODO: Allow as an implicit conversion if To > From.
|
||||
// Work around the inability to put a `where` clause on a generic parameter of
|
||||
// type `IntLiteral`.
|
||||
// TODO: Remove this once possible.
|
||||
private interface AnyUInt {
|
||||
let Width:! IntLiteral();
|
||||
fn AsUInt[self: Self]() -> UInt(Width);
|
||||
}
|
||||
|
||||
impl forall [N:! IntLiteral()] UInt(N) as AnyUInt where .Width = N {
|
||||
fn AsUInt[self: Self]() -> Self { return self; }
|
||||
}
|
||||
|
||||
// Work around the inability to constrain types other than `.Self` by reversing
|
||||
// the Self and argument type of `ImplicitAs`.
|
||||
// TODO: Remove this once possible.
|
||||
private interface FromUInt(From:! type) {
|
||||
fn Convert(from: From) -> Self;
|
||||
}
|
||||
|
||||
impl forall [To:! IntLiteral(), From:! AnyUInt & IntFitsIn(UInt(To))]
|
||||
UInt(To) as FromUInt(From) {
|
||||
fn Convert(from: From) -> Self {
|
||||
fn Impl(src: UInt(From.Width)) -> Self = "int.convert";
|
||||
return Impl(from.AsUInt());
|
||||
}
|
||||
}
|
||||
|
||||
impl forall [To:! IntLiteral(), From:! AnyUInt & IntFitsIn(Int(To))]
|
||||
Int(To) as FromUInt(From) {
|
||||
fn Convert(from: From) -> Self {
|
||||
fn Impl(src: UInt(From.Width)) -> Self = "int.convert";
|
||||
return Impl(from.AsUInt());
|
||||
}
|
||||
}
|
||||
|
||||
impl forall [From:! IntLiteral(), To:! FromUInt(UInt(From))]
|
||||
UInt(From) as ImplicitAs(To) {
|
||||
fn Convert[self: Self]() -> To {
|
||||
return To.Convert(self);
|
||||
}
|
||||
}
|
||||
|
||||
final impl forall [From:! IntLiteral(), To:! IntLiteral()] UInt(From) as As(UInt(To)) {
|
||||
fn Convert[self: Self]() -> UInt(To) = "int.convert";
|
||||
}
|
||||
|
||||
// TODO: Allow as an implicit conversion if To > From.
|
||||
final impl forall [From:! IntLiteral(), To:! IntLiteral()] UInt(From) as As(Int(To)) {
|
||||
fn Convert[self: Self]() -> Int(To) = "int.convert";
|
||||
}
|
||||
|
||||
@@ -515,15 +515,16 @@ may be limited to integers of at most 128 bits due to LLVM limitations.
|
||||
|
||||
#### Integer literals
|
||||
|
||||
Integers may be written in decimal, hexadecimal, or binary:
|
||||
Integers may be written in decimal, hexadecimal, octal, or binary:
|
||||
|
||||
- `12345` (decimal)
|
||||
- `0x1FE` (hexadecimal)
|
||||
- `0o755` (octal)
|
||||
- `0b1010` (binary)
|
||||
|
||||
Underscores (`_`) may be used as digit separators. Numeric literals are
|
||||
case-sensitive: `0x`, `0b` must be lowercase, whereas hexadecimal digits must be
|
||||
uppercase. Integer literals never contain a `.`.
|
||||
case-sensitive: `0x`, `0o`, `0b` must be lowercase, whereas hexadecimal digits
|
||||
must be uppercase. Integer literals never contain a `.`.
|
||||
|
||||
Unlike in C++, literals do not have a suffix to indicate their type. Instead,
|
||||
numeric literals have a type derived from their value, and can be
|
||||
|
||||
+13
-11
@@ -601,19 +601,21 @@ Assert(different_order.y == 2);
|
||||
```
|
||||
|
||||
Initialization and assignment occur field-by-field. The order of fields is
|
||||
determined from the target on the left side of the `=`. This rule matches what
|
||||
we expect for classes with encapsulation more generally.
|
||||
determined by the source on the right side of the `=`, and individual operations
|
||||
are generally interleaved field-by-field. See [here](values.md#type-conversions)
|
||||
for details about the semantics, and
|
||||
[here](pattern_matching.md#evaluation-order) for details about the order of
|
||||
operations.
|
||||
|
||||
**Open question:** What operations and in what order happen for assignment and
|
||||
initialization?
|
||||
> **Open question:** Do we need a way for a class to require the source order to
|
||||
> match? Should that be the default, with an opt out?
|
||||
|
||||
- Is assignment just destruction followed by initialization? Is that
|
||||
destruction completed for the whole object before initializing, or is it
|
||||
interleaved field-by-field?
|
||||
- When initializing to a literal value, is a temporary containing the literal
|
||||
value constructed first or are the fields initialized directly? The latter
|
||||
approach supports types that can't be moved or copied, such as mutex.
|
||||
- Perhaps some operations are _not_ ordered with respect to each other?
|
||||
> **Open question:** What operations and in what order happen for assignment?
|
||||
>
|
||||
> - Is assignment just destruction followed by initialization? Is that
|
||||
> destruction completed for the whole object before initializing, or is it
|
||||
> interleaved field-by-field?
|
||||
> - Perhaps some operations are _not_ ordered with respect to each other?
|
||||
|
||||
### Operations performed field-wise
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Same type](#same-type)
|
||||
- [Pointer conversions](#pointer-conversions)
|
||||
- [Facet types](#facet-types)
|
||||
- [Struct, tuple, and array types](#struct-tuple-and-array-types)
|
||||
- [Consistency with `as`](#consistency-with-as)
|
||||
- [Extensibility](#extensibility)
|
||||
- [Alternatives considered](#alternatives-considered)
|
||||
@@ -189,6 +190,10 @@ implicitly converted to the facet type `TT2` if `T`
|
||||
[satisfies the requirements](../generics/details.md#subtyping-between-facet-types)
|
||||
of `TT2`.
|
||||
|
||||
### Struct, tuple, and array types
|
||||
|
||||
See [here](/docs/design/values.md#type-conversions).
|
||||
|
||||
## Consistency with `as`
|
||||
|
||||
An implicit conversion of an expression `E` of type `T` to type `U`, when
|
||||
|
||||
@@ -13,7 +13,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Overview](#overview)
|
||||
- [Member resolution](#member-resolution)
|
||||
- [Package and namespace members](#package-and-namespace-members)
|
||||
- [Types and facets](#types-and-facets)
|
||||
- [Types, forms, and facets](#types-forms-and-facets)
|
||||
- [Tuple indexing](#tuple-indexing)
|
||||
- [Values](#values)
|
||||
- [Facet binding](#facet-binding)
|
||||
@@ -127,13 +127,18 @@ A member access expression is processed using the following steps:
|
||||
The process of _member resolution_ determines which member `M` a member access
|
||||
expression is referring to.
|
||||
|
||||
For a simple member access, if the first operand is a type, facet, package, or
|
||||
namespace, a search for the member name is performed in the first operand.
|
||||
Otherwise, a search for the member name is performed in the type of the first
|
||||
operand. In either case, the search must succeed. In the latter case, if the
|
||||
result is an instance member, then [instance binding](#instance-binding) is
|
||||
For a simple member access, if the first operand is a type, form, facet,
|
||||
package, or namespace, a search for the member name is performed in the first
|
||||
operand. Otherwise, a search for the member name is performed in the type of the
|
||||
first operand. In either case, the search must succeed. In the latter case, if
|
||||
the result is an instance member, then [instance binding](#instance-binding) is
|
||||
performed on the first operand.
|
||||
|
||||
A search for a name within a form searches for the name in its
|
||||
[type component](/docs/design/values.md#expression-forms). Note that this means
|
||||
that the form of an expression never affects simple member access into that
|
||||
expression, except through its type component.
|
||||
|
||||
For a compound member access, the second operand is evaluated as a compile-time
|
||||
constant to determine the member being accessed. The evaluation is required to
|
||||
succeed and to result in a member of a type, interface, or non-type facet, or a
|
||||
@@ -189,11 +194,12 @@ class Bar {
|
||||
}
|
||||
```
|
||||
|
||||
### Types and facets
|
||||
### Types, forms, and facets
|
||||
|
||||
If the first operand is a type or facet, it must be a compile-time constant.
|
||||
This disallows member access into a type except during compile-time, see leads
|
||||
issue [#1293](https://github.com/carbon-language/carbon-lang/issues/1293).
|
||||
If the first operand is a type, form, or facet, it must be a compile-time
|
||||
constant. This disallows member access into a type except during compile-time,
|
||||
see leads issue
|
||||
[#1293](https://github.com/carbon-language/carbon-lang/issues/1293).
|
||||
|
||||
Like the previous case, types (including
|
||||
[facet types](/docs/design/generics/terminology.md#facet-type)) have member
|
||||
@@ -228,6 +234,9 @@ class Avatar {
|
||||
Simple member access `(Avatar as Cowboy).Draw` finds the `Cowboy.Draw`
|
||||
implementation for `Avatar`, ignoring `Renderable.Draw`.
|
||||
|
||||
Similarly, a form has members, specifically the members of the form's type
|
||||
component.
|
||||
|
||||
### Tuple indexing
|
||||
|
||||
Tuple types have member names that are *integer-literal*s, not *word*s.
|
||||
@@ -273,9 +282,9 @@ let n: i32 = p->(e);
|
||||
|
||||
### Values
|
||||
|
||||
If the first operand is not a type, package, namespace, or facet, it does not
|
||||
have member names, and a search is performed into the type of the first operand
|
||||
instead.
|
||||
If the first operand is not a type, form, package, namespace, or facet, it does
|
||||
not have member names, and a search is performed into the type of the first
|
||||
operand instead.
|
||||
|
||||
```carbon
|
||||
interface Printable {
|
||||
@@ -723,16 +732,22 @@ fn SumIntegers(v: Vector(Integer)) -> Integer {
|
||||
## Instance binding
|
||||
|
||||
Next, _instance binding_ may be performed. This associates an expression with a
|
||||
particular object instance. For example, this is the value bound to `self` when
|
||||
calling a method.
|
||||
particular object or value instance. For example, this is the value bound to
|
||||
`self` when calling a method.
|
||||
|
||||
For the simple member access syntax `x.y`, if `x` is an entity that has member
|
||||
names, such as a namespace or a type, then `y` is looked up within `x`, and
|
||||
instance binding is not performed. Otherwise, `y` is looked up within the type
|
||||
of `x` and instance binding is performed if an instance member is found.
|
||||
|
||||
If instance binding is performed:
|
||||
If instance binding is to be performed, the result of instance binding depends
|
||||
on what instance member `M` was found:
|
||||
|
||||
- For a field member of a struct type or tuple type, `x` is converted to a
|
||||
struct or tuple form by
|
||||
[form decomposition](/docs/design/values.md#category-conversions), and the
|
||||
`.f` element of the result of that conversion becomes the result of `x.f`.
|
||||
All other elements are [discarded](/docs/design/values.md#form-conversions).
|
||||
- For a field member in class `C`, `x` is required to be of type `C` or of a
|
||||
type derived from `C`. The result is the corresponding subobject within `x`.
|
||||
If `x` is an
|
||||
|
||||
@@ -97,6 +97,9 @@ possible syntaxes:
|
||||
`fn Sleep(seconds: i64) -> ();`.
|
||||
- `()` is similar to a `void` return type in C++.
|
||||
|
||||
> **TODO:** Update this section to cover return forms, as discussed
|
||||
> [here](values.md#function-calls-and-returns).
|
||||
|
||||
### `return` statements
|
||||
|
||||
The [`return` statement](control_flow/return.md) is essential to function
|
||||
@@ -111,6 +114,9 @@ When the return clause is provided, including when it is `-> ()`, the `return`
|
||||
statement must have an expression that is convertible to the return type, and a
|
||||
`return` statement must be used to end control flow of the function.
|
||||
|
||||
> **TODO:** Update this section to cover the requirements on the form of the
|
||||
> expression.
|
||||
|
||||
## Function declarations
|
||||
|
||||
Functions may be declared separate from the definition by providing only a
|
||||
|
||||
@@ -27,6 +27,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Return type](#return-type)
|
||||
- [Interfaces recap](#interfaces-recap)
|
||||
- [Facet types](#facet-types)
|
||||
- [Identified facet types](#identified-facet-types)
|
||||
- [Named constraints](#named-constraints)
|
||||
- [Subtyping between facet types](#subtyping-between-facet-types)
|
||||
- [Combining interfaces by anding facet types](#combining-interfaces-by-anding-facet-types)
|
||||
@@ -894,6 +895,25 @@ names of the facet type.
|
||||
This general structure of facet types holds not just for interfaces, but others
|
||||
described in the rest of this document.
|
||||
|
||||
### Identified facet types
|
||||
|
||||
A facet type is _identified_ if all the interfaces it references are declared
|
||||
and all of its named constraints are complete. An identified facet type is
|
||||
associated with a known set of interfaces.
|
||||
|
||||
A facet type is _partially identified_ if any of its named constraints are in
|
||||
the process of being defined. The interfaces associated with a partially
|
||||
identified facet type change as the named constraint is fully defined.
|
||||
|
||||
Types can implicitly convert to facet types when the requirements of the facet
|
||||
type are satisfied, but only if the facet type is identified. Attempting to
|
||||
convert to a facet type that is not identified is an error, since the
|
||||
requirements of the target facet type are not yet fully determined.
|
||||
|
||||
A facet with an unidentified or partially identified facet type may be converted
|
||||
_to_ other facet types. While its set of requirements are not fully determined,
|
||||
the requirements that are known at that time may be used.
|
||||
|
||||
## Named constraints
|
||||
|
||||
If the interfaces discussed above are the building blocks for facet types,
|
||||
@@ -933,6 +953,54 @@ constraint DrawVectorLegoFish {
|
||||
}
|
||||
```
|
||||
|
||||
However a named constraint may not refer to itself as a requirement, as that
|
||||
produces a cycle. In general, any use of named constraint inside its own
|
||||
definition is disallowed, except through the use of `Self`.
|
||||
|
||||
```carbon
|
||||
constraint SelfReferential {
|
||||
// ❌ Error: Can not refer to `SelfReferential` inside its own definition.
|
||||
require impls SelfReferential;
|
||||
}
|
||||
```
|
||||
|
||||
The facet type of `Self` is partially identified inside the definition of a
|
||||
named constraint. This allows `Self` to be converted to other facet types based
|
||||
on the known requirements of the partially identified facet type. Those
|
||||
requirements include any `require` ... `impls` statements written before the use
|
||||
of `Self`.
|
||||
|
||||
```carbon
|
||||
interface Z {}
|
||||
class UsesZ(T:! Z) {}
|
||||
|
||||
interface Y(T:! type) {}
|
||||
interface X {}
|
||||
|
||||
constraint Constraint {
|
||||
// The partially identified facet type of `Self` includes `Z` after this
|
||||
// statement.
|
||||
require impls Z;
|
||||
|
||||
// OK, the partially identified facet type of `Self` can convert to facet
|
||||
// type `Z` to match the parameter of `UsesZ`.
|
||||
require impls Y(UsesZ(Self));
|
||||
|
||||
// Also OK, as `Self` converts to `Z` again.
|
||||
require UsesZ(Self) impls X;
|
||||
}
|
||||
|
||||
constraint UseOfFutureRequirement {
|
||||
// ❌ Error: The partially identified facet type of `Self` does not yet
|
||||
// include `Z` since the requirement for `Z` comes later in the definition.
|
||||
require impls Y(UsesZ(Self));
|
||||
|
||||
// The partially identified facet type of `Self` includes `Z` after this
|
||||
// statement.
|
||||
require impls Z;
|
||||
}
|
||||
```
|
||||
|
||||
In general, Carbon makes no syntactic distinction between the uses of named
|
||||
constraints and interfaces, so one may be replaced with the other without
|
||||
affecting users. To accomplish this, Carbon allows a named constraint to be used
|
||||
@@ -1229,6 +1297,27 @@ var x: Iota;
|
||||
DoAdvanceAndEquals(x);
|
||||
```
|
||||
|
||||
The facet type at the end of a `require` ... `impls` statement must be
|
||||
identified.
|
||||
|
||||
```carbon
|
||||
constraint N;
|
||||
|
||||
interface I {
|
||||
// ❌ Error: Facet type `N` is not identified since the constraint `N` is not
|
||||
// complete.
|
||||
require impls N;
|
||||
}
|
||||
|
||||
interface J;
|
||||
|
||||
interface K {
|
||||
// OK, the facet type `J` is identified because the interface `J` is
|
||||
// declared.
|
||||
require impls J;
|
||||
}
|
||||
```
|
||||
|
||||
Like with named constraints, an interface implementation requirement doesn't by
|
||||
itself add any names to the interface, but again those can be added with `alias`
|
||||
declarations:
|
||||
@@ -3189,7 +3278,7 @@ fn G[T:! Transitive](t: T) {
|
||||
|
||||
// ❌ Illegal: only the current type is
|
||||
// searched for interface implementations.
|
||||
a.(Q.InQ());
|
||||
a.(Q.InQ)();
|
||||
|
||||
// ✅ Allowed: values of type `T.A` may be cast
|
||||
// to `T.B`, which extends and implements `Q`.
|
||||
@@ -3197,7 +3286,7 @@ fn G[T:! Transitive](t: T) {
|
||||
|
||||
// ✅ Allowed: `T.A` == `T.B` that implements `Q`.
|
||||
observe T.A == T.B impls Q;
|
||||
a.(Q.InQ());
|
||||
a.(Q.InQ)();
|
||||
|
||||
// ❌ Illegal: `T.A` still does not extend `Q`.
|
||||
a.InQ();
|
||||
@@ -5913,10 +6002,10 @@ impl forall [T:! A] T as B { }
|
||||
impl forall [T:! B] T as C { }
|
||||
impl forall [T:! C] T as D { }
|
||||
|
||||
fn RequiresD(T:! D)(x: T);
|
||||
fn RequiresB(T:! B)(x: T);
|
||||
fn RequiresD[T:! D](x: T);
|
||||
fn RequiresB[T:! B](x: T);
|
||||
|
||||
fn RequiresA(T:! A)(x: T) {
|
||||
fn RequiresA[T:! A](x: T) {
|
||||
// ✅ Allowed: There is a blanket implementation
|
||||
// of `B` for types implementing `A`.
|
||||
RequiresB(x);
|
||||
|
||||
@@ -12,6 +12,26 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
- [Philosophy and goals](#philosophy-and-goals)
|
||||
- [Overview](#overview)
|
||||
- [C++ interoperability model: introduction and principles](#c-interoperability-model-introduction-and-principles)
|
||||
- [The successor language mandate](#the-successor-language-mandate)
|
||||
- [The C++ interop type](#the-c-interop-type)
|
||||
- [Importing C++ APIs into Carbon](#importing-c-apis-into-carbon)
|
||||
- [Importing C++ libraries (header-based)](#importing-c-libraries-header-based)
|
||||
- [TODO: Importing C++ code (inline)](#todo-importing-c-code-inline)
|
||||
- [Accessing built-in C++ entities (file-less)](#accessing-built-in-c-entities-file-less)
|
||||
- [The `Cpp` package](#the-cpp-package)
|
||||
- [TODO: Importing C++ macros](#todo-importing-c-macros)
|
||||
- [Calling C++ code from Carbon](#calling-c-code-from-carbon)
|
||||
- [Function call syntax and semantics](#function-call-syntax-and-semantics)
|
||||
- [TODO: Overload resolution](#todo-overload-resolution)
|
||||
- [TODO: Constructors](#todo-constructors)
|
||||
- [TODO: Struct literals](#todo-struct-literals)
|
||||
- [TODO: Accessing C++ classes, structs, and members](#todo-accessing-c-classes-structs-and-members)
|
||||
- [TODO: Accessing global variables](#todo-accessing-global-variables)
|
||||
- [TODO: Bi-directional type mapping: primitives and core types](#todo-bi-directional-type-mapping-primitives-and-core-types)
|
||||
- [TODO: Advanced type mapping: pointers, references, and `const`](#todo-advanced-type-mapping-pointers-references-and-const)
|
||||
- [TODO: Bi-directional type mapping: standard library types](#todo-bi-directional-type-mapping-standard-library-types)
|
||||
- [TODO: The operator interoperability model](#todo-the-operator-interoperability-model)
|
||||
|
||||
<!-- tocstop -->
|
||||
|
||||
@@ -29,4 +49,167 @@ more detail.
|
||||
|
||||
## Overview
|
||||
|
||||
TODO
|
||||
Carbon's bidirectional interoperability with C++ is
|
||||
[a cornerstone of its design](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code),
|
||||
enabling a gradual transition from existing C++ codebases. The goal is not just
|
||||
a foreign function interface (FFI), but a seamless, high-fidelity integration
|
||||
that supports advanced C++ features, from templates to class hierarchies.
|
||||
|
||||
C++ APIs are imported into Carbon using an `import Cpp` directive, which makes
|
||||
C++ declarations available within a dedicated `Cpp` package in Carbon. This
|
||||
prevents name collisions and makes the origin of symbols explicit. Carbon code
|
||||
can then call C++ functions, instantiate C++ classes, and use C++ types, while
|
||||
respecting C++'s semantics, including its complex overload resolution rules and
|
||||
preserving the nominal distinctions between C++ types like `long` and
|
||||
`long long`, or `T*` and `T&`, which is critical for correct overload resolution
|
||||
and template instantiation.
|
||||
|
||||
Similarly, Carbon APIs can be designed to be callable from C++. The
|
||||
interoperability layer is designed to be zero-cost, avoiding unnecessary
|
||||
allocations or copies when calling between the two languages.
|
||||
|
||||
## C++ interoperability model: introduction and principles
|
||||
|
||||
### The successor language mandate
|
||||
|
||||
The design of Carbon's C++ interoperability is governed by its foundational
|
||||
goal: [to be a successor language](/README.md), not merely a language with a
|
||||
foreign function interface (FFI). This mandate dictates a design that moves
|
||||
beyond the C-style FFI adopted by most modern languages and instead provides
|
||||
seamless, bidirectional interoperability. The objective is to support deep
|
||||
integration with existing C++ code, encompassing its most complex features, from
|
||||
inheritance to templates.
|
||||
|
||||
This goal has profound implications for the Carbon compiler and language
|
||||
semantics. It requires that C++ is not treated as a foreign entity. Instead,
|
||||
Carbon's semantic model must be _co-designed_ to understand, map, and interact
|
||||
with C++'s semantic constructs—including templates, class hierarchies, and
|
||||
complex overload resolution—with high fidelity. The interoperability layer must,
|
||||
therefore, operate at the semantic analysis level, not just at the linking (ABI)
|
||||
level. This document specifies the design of this semantic contract.
|
||||
|
||||
### The C++ interop type
|
||||
|
||||
A core mechanism in this design is the C++ interop type. This concept defines
|
||||
the "trigger" that activates C++-specific semantic rules within the Carbon
|
||||
compiler. Any operation involving a type that is designated as a C++ interop
|
||||
type could invoke the specialized interoperability logic, such as C++ overload
|
||||
resolution or operator overload resolution that involves both Carbon and C++
|
||||
operator overloads.
|
||||
|
||||
A type is considered a C++ interop type if its definition involves an imported
|
||||
C++ type in any of the following ways:
|
||||
|
||||
1. A C++ imported type (for example, `Cpp.Widget`).
|
||||
2. A pointer to a C++ interop type (for example, `Cpp.Widget*`).
|
||||
3. A Carbon generic type parameterized with a C++ interop type (for example,
|
||||
`MyCarbonVector(Cpp.Widget)`).
|
||||
|
||||
More generally, a C++ interop type is any type for which Carbon's
|
||||
[orphan rule](https://docs.carbon-lang.dev/docs/design/generics/details.html#orphan-rule)
|
||||
would allow an impl to be provided by a library in `package Cpp`.
|
||||
|
||||
This "pervasive" model of C++-awareness is a fundamental design choice. The C++
|
||||
semantics are not confined to a specific `unsafe` or `extern "C++"` block; they
|
||||
affect any Carbon type that composes them. For example, when the Carbon compiler
|
||||
instantiates a _Carbon_ generic type like `MyCarbonVector(Cpp.Widget)`, its type
|
||||
system must be aware that the `Cpp.Widget` parameter carries C++-specific rules.
|
||||
This mandates that Carbon's own generic system, struct layout logic, overload
|
||||
resolution and operator lookup must query the type system for the presence of a
|
||||
C++ interop type. If present, Carbon must consider C++ rules when operating over
|
||||
C++ interop types. This design prioritizes the goal of a seamless and intuitive
|
||||
user experience.
|
||||
|
||||
## Importing C++ APIs into Carbon
|
||||
|
||||
### Importing C++ libraries (header-based)
|
||||
|
||||
The primary mechanism for importing existing, user-defined C++ code is through
|
||||
header file inclusion. Carbon must be able to parse and analyze C++ header files
|
||||
to make their declarations available within Carbon.
|
||||
|
||||
**Syntax:** The syntax for this operation is `import Cpp library "header_name"`.
|
||||
This syntax is used for both standard library headers and user-defined headers:
|
||||
|
||||
- **Standard Library:**
|
||||
|
||||
```carbon
|
||||
import Cpp library "<cstdio>";
|
||||
```
|
||||
|
||||
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)
|
||||
|
||||
### Accessing built-in C++ entities (file-less)
|
||||
|
||||
Some C++ entities, particularly built-in primitive types, are not defined in any
|
||||
header file. They are "intrinsic" to the C++ language. These entities are
|
||||
available in Carbon without an explicit `import` declaration.
|
||||
|
||||
### The `Cpp` package
|
||||
|
||||
A critical design choice for managing C++ imports is the mandatory use of a
|
||||
containing package, `Cpp`. All imported C++ named entities (functions, types,
|
||||
namespaces) are contained in the `Cpp` package.
|
||||
|
||||
- **Functions:** `Cpp.putchar(...)`
|
||||
- **Classes/Types:** `Cpp.Circle`, `Cpp.Point`
|
||||
- **Constructors:** `Cpp.Circle.Circle()`
|
||||
|
||||
The `Cpp.` prefix makes the _origin_ of every symbol explicit and unambiguous.
|
||||
It ensures that C++ entities cannot collide with Carbon code.
|
||||
|
||||
### TODO: Importing C++ macros
|
||||
|
||||
## Calling C++ code from Carbon
|
||||
|
||||
### Function call syntax and semantics
|
||||
|
||||
Once imported, C++ functions are invoked using standard Carbon function call
|
||||
syntax, prefixed with the `Cpp` name. The Carbon compiler is responsible for
|
||||
mapping the Carbon arguments to the types expected by the C++ function's
|
||||
signature.
|
||||
|
||||
This often requires explicit casting on the Carbon side, using the `as` keyword,
|
||||
to satisfy the C++ function's parameter types.
|
||||
|
||||
**Example:** The following example imports `cstdio` and calls the C function
|
||||
`putchar`. The Carbon `Core.Char` variable `n` must be cast first to `u8` and
|
||||
then to `i32` to match the `int` parameter expected by `putchar`.
|
||||
|
||||
```carbon
|
||||
import Cpp library "<cstdio>";
|
||||
|
||||
fn Run() {
|
||||
let hello: array(Core.Char, 6) = ('H', 'e', 'l', 'l', 'o', '!');
|
||||
for (n: Core.Char in hello) {
|
||||
// Carbon 'as' casting is used to match the C++ signature
|
||||
Cpp.putchar((n as u8) as i32);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### TODO: Overload resolution
|
||||
|
||||
### TODO: Constructors
|
||||
|
||||
### TODO: Struct literals
|
||||
|
||||
## TODO: Accessing C++ classes, structs, and members
|
||||
|
||||
## TODO: Accessing global variables
|
||||
|
||||
## TODO: Bi-directional type mapping: primitives and core types
|
||||
|
||||
## TODO: Advanced type mapping: pointers, references, and `const`
|
||||
|
||||
## TODO: Bi-directional type mapping: standard library types
|
||||
|
||||
## TODO: The operator interoperability model
|
||||
|
||||
@@ -28,6 +28,7 @@ The following syntaxes are supported:
|
||||
- [Integer literals](#integer-literals)
|
||||
- `12345` (decimal)
|
||||
- `0x1FE` (hexadecimal)
|
||||
- `0o755` (octal)
|
||||
- `0b1010` (binary)
|
||||
- [Real-number literals](#real-number-literals)
|
||||
- `123.456` (digits on both sides of the `.`)
|
||||
@@ -55,15 +56,16 @@ base. The available base specifiers and corresponding bases are:
|
||||
| Base specifier | Base | Digits |
|
||||
| -------------- | ---- | ------------------------ |
|
||||
| `b` | 2 | `0` and `1` |
|
||||
| `o` | 8 | `0` ... `7` |
|
||||
| `x` | 16 | `0` ... `9`, `A` ... `F` |
|
||||
|
||||
The above table is case-sensitive. For example, `0b1` and `0x1A` are valid, and
|
||||
`0B1`, `0X1A`, and `0x1a` are invalid.
|
||||
The above table is case-sensitive. For example, `0b1`, `0o7`, and `0x1A` are
|
||||
valid, and `0B1`, `0O7`, `0X1A`, and `0x1a` are invalid.
|
||||
|
||||
A zero at the start of a literal can never be followed by another digit: either
|
||||
the literal is `0`, the `0` begins a base specifier, or the next character is a
|
||||
decimal point (see below). No support is provided for octal literals, and any C
|
||||
or C++ octal literal (other than `0`) is invalid in Carbon.
|
||||
decimal point (see below). The `0o` prefix is used for octal literals; a C-style
|
||||
`0755` octal is invalid in Carbon.
|
||||
|
||||
### Real-number literals
|
||||
|
||||
@@ -111,8 +113,9 @@ example:
|
||||
|
||||
- Decimal integers: `1_23_456_7890`
|
||||
- Hexadecimal integers: `0x7_F_FF_FFFF`
|
||||
- Real-number literals: `2_147.48_3648e12_345` or `0x1_00CA.FE_F00Dp+2_4`
|
||||
- Octal literals: `0o7_55`
|
||||
- Binary literals: `0b1_000_101_11`
|
||||
- Real-number literals: `2_147.48_3648e12_345` or `0x1_00CA.FE_F00Dp+2_4`
|
||||
|
||||
## Divergence from other languages
|
||||
|
||||
@@ -129,7 +132,7 @@ provides benefits directly in line with the goal that Carbon code should be
|
||||
That said, it still provides sufficient variations to address important use
|
||||
cases for the goal of not leaving room for a lower level language:
|
||||
|
||||
- Hexadecimal and binary integer literals.
|
||||
- Hexadecimal, octal, and binary integer literals.
|
||||
- Scientific notation floating point literals.
|
||||
- Hexadecimal (scientific) floating point literals.
|
||||
|
||||
@@ -145,6 +148,7 @@ cases for the goal of not leaving room for a lower level language:
|
||||
- [3-digit decimal groupings](/proposals/p1983.md#3-digit-decimal-groupings)
|
||||
- [2-digit or 4-digit hexadecimal digit groupings](/proposals/p1983.md#2-digit-or-4-digit-hexadecimal-digit-groupings)
|
||||
- [Disallow digit separators in fractions](/proposals/p1983.md#disallow-digit-separators-in-fractions)
|
||||
- [No octal literals](/proposals/p6910.md#no-octal-literals)
|
||||
|
||||
## References
|
||||
|
||||
@@ -154,3 +158,5 @@ cases for the goal of not leaving room for a lower level language:
|
||||
[#866: Allow ties in floating literals](https://github.com/carbon-language/carbon-lang/pull/866)
|
||||
- Proposal
|
||||
[#1983: Weaken digit separator placement rules](https://github.com/carbon-language/carbon-lang/pull/1983)
|
||||
- Proposal
|
||||
[#6910: Support octal literals](https://github.com/carbon-language/carbon-lang/pull/6910)
|
||||
|
||||
+258
-143
@@ -18,7 +18,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Name binding patterns](#name-binding-patterns)
|
||||
- [Anonymous bindings](#anonymous-bindings)
|
||||
- [Alternatives considered](#alternatives-considered-1)
|
||||
- [Compile-time bindings](#compile-time-bindings)
|
||||
- [`auto` and type deduction](#auto-and-type-deduction)
|
||||
- [Alternatives considered](#alternatives-considered-2)
|
||||
- [`var`](#var)
|
||||
@@ -36,10 +35,12 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Alternatives considered](#alternatives-considered-6)
|
||||
- [Guards](#guards)
|
||||
- [Pattern matching in local variables](#pattern-matching-in-local-variables)
|
||||
- [Evaluation order](#evaluation-order)
|
||||
- [Alternatives considered](#alternatives-considered-7)
|
||||
- [Open questions](#open-questions)
|
||||
- [Slice or array nested value pattern matching](#slice-or-array-nested-value-pattern-matching)
|
||||
- [Pattern matching as function overload resolution](#pattern-matching-as-function-overload-resolution)
|
||||
- [Alternatives considered](#alternatives-considered-7)
|
||||
- [Alternatives considered](#alternatives-considered-8)
|
||||
- [References](#references)
|
||||
|
||||
<!-- tocstop -->
|
||||
@@ -60,14 +61,13 @@ of the full pattern as well.
|
||||
|
||||
## Pattern Syntax and Semantics
|
||||
|
||||
Expressions are patterns, as described below. A pattern that is not an
|
||||
All expressions are patterns, but they may be either tuple patterns, struct
|
||||
patterns, or expression patterns, as described below. A pattern that is not an
|
||||
expression, because it contains pattern-specific syntax such as a binding
|
||||
pattern, is a _proper pattern_. Many expression forms, such as arbitrary
|
||||
function calls, are not permitted as proper patterns, so cannot contain binding
|
||||
patterns.
|
||||
|
||||
- _pattern_ ::= _proper-pattern_
|
||||
|
||||
```carbon
|
||||
fn F(n: i32) -> i32 { return n; }
|
||||
|
||||
@@ -81,10 +81,11 @@ match (F(42)) {
|
||||
|
||||
An expression is a pattern.
|
||||
|
||||
- _pattern_ ::= _expression_
|
||||
- _expression-pattern_ ::= _expression_
|
||||
- _pattern_ ::= _expression-pattern_
|
||||
|
||||
The pattern is compared with the expression using the `==` operator: _pattern_
|
||||
`==` _scrutinee_.
|
||||
The scrutinee is compared with the expression using the `==` operator:
|
||||
_expression_ `==` _scrutinee_.
|
||||
|
||||
```carbon
|
||||
fn F(n: i32) {
|
||||
@@ -96,31 +97,30 @@ fn F(n: i32) {
|
||||
}
|
||||
```
|
||||
|
||||
Any `==` operations performed by a pattern match occur in lexical order, but for
|
||||
repeated matches against the same _pattern_, later comparisons may be skipped by
|
||||
reusing the result from an earlier comparison:
|
||||
As depicted here, _expression-pattern_ is ambiguous with _tuple-pattern_,
|
||||
_struct-pattern_, and _alternative-pattern_. In the case of _tuple-pattern_ and
|
||||
_struct-pattern_, the ambiguity is resolved in their favor, meaning that a tuple
|
||||
or struct literal in a pattern context is not interpreted as an expression
|
||||
pattern, but as a tuple or struct pattern whose elements are expression
|
||||
patterns. For example:
|
||||
|
||||
```carbon
|
||||
class ChattyIntMatcher {
|
||||
impl as EqWith(i32) {
|
||||
fn Eq[self: ChattyIntMatcher](other: i32) {
|
||||
Print("Matching {0}", other);
|
||||
return other == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn F() {
|
||||
// Prints `Matching 1` then `Matching 2`,
|
||||
// may or may not then print `Matching 1` again.
|
||||
match ((1, 2)) {
|
||||
case ({} as ChattyIntMatcher, 0) => {}
|
||||
case (1, {} as ChattyIntMatcher) => {}
|
||||
case ({} as ChattyIntMatcher, 2) => {}
|
||||
}
|
||||
match (0, 1, 2) {
|
||||
case (F(), 0, G()) => ...
|
||||
}
|
||||
```
|
||||
|
||||
Here `(F(), 0, G())` is not an expression, but three separate expressions in a
|
||||
tuple pattern. As a result, this code will call `F()` but not `G()`, because the
|
||||
mismatch between the middle tuple elements will cause pattern matching to fail
|
||||
before reaching `G()`. Other than this short-circuiting behavior, a tuple
|
||||
pattern of expression patterns behaves the same as if it were a single
|
||||
expression pattern.
|
||||
|
||||
The resolution of the _alternative-pattern_ ambiguity is not specified, because
|
||||
_alternative-pattern_ is specified to behave the same way an expression pattern
|
||||
would, in the cases where they overlap.
|
||||
|
||||
#### Alternatives considered
|
||||
|
||||
- [Introducer syntax for expression patterns](/proposals/p2188.md#introducer-syntax-for-expression-patterns)
|
||||
@@ -131,14 +131,16 @@ fn F() {
|
||||
|
||||
A name binding pattern is a pattern.
|
||||
|
||||
- _binding-pattern_ ::= _identifier_ `:` _expression_
|
||||
- _proper-pattern_ ::= _binding-pattern_
|
||||
- _binding-pattern_ ::= `ref`? (_identifier_ | `self`) `:` _expression_
|
||||
- _binding-pattern_ ::= `template`? _identifier_ `:!` _expression_
|
||||
- _pattern_ ::= _binding-pattern_
|
||||
|
||||
A name binding pattern declares a _binding_ with a name specified by the
|
||||
_identifier_, which can be used as an expression. If the binding pattern is
|
||||
enclosed by a `var` pattern, it is a _reference binding pattern_, and the
|
||||
binding is a durable reference expression. Otherwise, it is a _value binding
|
||||
pattern_, and the binding is a value expression.
|
||||
prefixed with `ref` or enclosed by a `var` pattern, it is a _reference binding
|
||||
pattern_, and otherwise it is a _value binding pattern_. A binding pattern
|
||||
enclosed by a `var` pattern cannot have a `ref` prefix, because it would be
|
||||
redundant.
|
||||
|
||||
A _variable binding pattern_ is a special kind of reference binding pattern,
|
||||
which is the immediate subpattern of its enclosing `var` pattern.
|
||||
@@ -147,15 +149,36 @@ which is the immediate subpattern of its enclosing `var` pattern.
|
||||
> expected to be the only difference between variable binding patterns and other
|
||||
> reference binding patterns.
|
||||
|
||||
The type of the binding is specified by the _expression_. If the pattern is a
|
||||
value binding pattern, the scrutinee is implicitly converted to a value
|
||||
expression of that type if necessary, and the binding is _bound_ to the
|
||||
converted value. If the pattern is a reference binding pattern, the enclosing
|
||||
`var` pattern will ensure that the scrutinee is already a durable reference
|
||||
expression with the specified type, and the binding is bound directly to it.
|
||||
If the pattern syntax uses `:` it is a _runtime binding pattern_. If it uses
|
||||
`:!`, it is a _compile-time binding pattern_, and it cannot appear inside a
|
||||
`var` pattern. A compile-time binding pattern is either a _symbolic binding
|
||||
pattern_ or a _template binding pattern_, depending on whether it is prefixed
|
||||
with `template`.
|
||||
|
||||
A use of a value binding is a value expression of the declared type, and a use
|
||||
of a reference binding is a durable reference expression of the declared type.
|
||||
The binding declared by a binding pattern has a
|
||||
[primitive form](values.md#expression-forms) with the following components:
|
||||
|
||||
- The type is _expression_.
|
||||
- The category is "value" if the pattern is a value binding pattern, "durable
|
||||
entire reference" if it's a variable binding pattern, or "durable non-entire
|
||||
reference" if it's a non-variable reference binding pattern.
|
||||
- The phase is "runtime", "symbolic", or "template" depending on whether the
|
||||
pattern is a runtime, symbolic, or template binding pattern.
|
||||
|
||||
During pattern matching, the scrutinee is implicitly converted as needed to have
|
||||
the same form, and the binding is _bound_ to (and consumes) the result of these
|
||||
conversions. This makes a runtime or template binding a kind of reusable alias
|
||||
for the converted scrutinee expression, with the same form and value. Symbolic
|
||||
bindings are more complex: the binding will have the same type, category, and
|
||||
phase as the converted scrutinee expression, but its constant value is an opaque
|
||||
symbol introduced by the binding, which the type system knows to be equal to the
|
||||
converted scrutinee expression.
|
||||
|
||||
Note that there is no way to implicitly convert to a durable reference
|
||||
expression from any other category, so the scrutinee of a reference binding
|
||||
pattern must already be a durable reference. `var` pattern matching ensures that
|
||||
this is the case for the bindings nested inside it, but for `ref` binding
|
||||
patterns the user-provided scrutinee must meet this requirement itself.
|
||||
|
||||
```carbon
|
||||
fn F() -> i32 {
|
||||
@@ -170,41 +193,23 @@ fn F() -> i32 {
|
||||
}
|
||||
```
|
||||
|
||||
When a new object needs to be created for the binding, the lifetime of the bound
|
||||
value matches the scope of the binding.
|
||||
|
||||
```carbon
|
||||
class NoisyDestructor {
|
||||
fn Make() -> Self { return {}; }
|
||||
impl i32 as ImplicitAs(NoisyDestructor) {
|
||||
fn Convert[self: i32]() -> Self { return Make(); }
|
||||
}
|
||||
destructor {
|
||||
Print("Destroyed!");
|
||||
}
|
||||
}
|
||||
|
||||
fn G() {
|
||||
// Does not print "Destroyed!".
|
||||
let n: NoisyDestructor = NoisyDestructor.Make();
|
||||
Print("Body of G");
|
||||
// Prints "Destroyed!" here.
|
||||
}
|
||||
|
||||
fn H(n: i32) {
|
||||
// Does not print "Destroyed!".
|
||||
let (v: NoisyDestructor, w: i32) = (n, n);
|
||||
Print("Body of H");
|
||||
// Prints "Destroyed!" here.
|
||||
}
|
||||
```
|
||||
When `self` is used instead of an identifier, the pattern must appear in the
|
||||
implicit parameter list of a method (as discussed [here](classes.md#methods)).
|
||||
During pattern matching in a method call, the parameter pattern containing
|
||||
`self` is matched with the object that the method was invoked on. In all other
|
||||
respects, the `self` pattern behaves just like an ordinary binding pattern,
|
||||
introducing a binding named `self` into scope, just as if `self` were an
|
||||
identifier rather than a keyword.
|
||||
|
||||
#### Anonymous bindings
|
||||
|
||||
A syntax like a binding but with `_` in place of an identifier can be used to
|
||||
ignore part of a value.
|
||||
A syntax like a binding but with `_` in place of an identifier is an anonymous
|
||||
binding. It does not participate in name lookup (so there can be multiple such
|
||||
patterns in the same scope), and in all other respects it behaves as if it were
|
||||
wrapped in an [`unused` pattern](#unused).
|
||||
|
||||
- _binding-pattern_ ::= `_` `:` _expression_
|
||||
- _binding-pattern_ ::= `template`? `_` `:!` _expression_
|
||||
|
||||
```carbon
|
||||
fn F(n: i32) {
|
||||
@@ -239,27 +244,6 @@ fn H(m: i32) {}
|
||||
- [Anonymous, named identifiers](/proposals/p2022.md#anonymous-named-identifiers)
|
||||
- [Attributes](/proposals/p2022.md#attributes)
|
||||
|
||||
#### Compile-time bindings
|
||||
|
||||
A `:!` can be used in place of `:` for a binding that is usable at compile time.
|
||||
|
||||
- _compile-time-pattern_ ::= `template`? _identifier_ `:!` _expression_
|
||||
- _compile-time-pattern_ ::= `template`? `_` `:!` _expression_
|
||||
- _compile-time-pattern_ ::= `unused` `template`? _identifier_ `:!`
|
||||
_expression_
|
||||
- _proper-pattern_ ::= _compile-time-pattern_
|
||||
|
||||
```carbon
|
||||
// ✅ `F` takes a symbolic facet parameter `T` and a parameter `x` of type `T`.
|
||||
fn F(T:! type, x: T) {
|
||||
var v: T = x;
|
||||
}
|
||||
```
|
||||
|
||||
The `template` keyword indicates the binding pattern is introducing a template
|
||||
binding, so name lookups into the binding will not be fully resolved until its
|
||||
value is known.
|
||||
|
||||
#### `auto` and type deduction
|
||||
|
||||
The `auto` keyword is a placeholder for a unique deduced type.
|
||||
@@ -310,12 +294,18 @@ specified.
|
||||
A `var` prefix indicates that a pattern provides mutable storage for the
|
||||
scrutinee.
|
||||
|
||||
- _proper-pattern_ ::= `var` _proper-pattern_
|
||||
- _pattern_ ::= `var` _pattern_
|
||||
|
||||
A `var` pattern matches when its nested pattern matches. The type of the storage
|
||||
is the resolved type of the nested _pattern_. Any binding patterns within the
|
||||
nested pattern are reference binding patterns, and their bindings refer to
|
||||
portions of the corresponding storage rather than to the scrutinee.
|
||||
The scrutinee is expected to have the same type as the resolved type of the
|
||||
nested _pattern_, and it is expected to be a runtime-phase ephemeral entire
|
||||
reference expression, which therefore refers to a newly-allocated temporary
|
||||
object. The scrutinee expression is converted as needed to satisfy those
|
||||
expectations, and the `var` pattern takes ownership of the referenced object,
|
||||
promotes it to a _durable_ entire reference expression, and matches the nested
|
||||
_pattern_ with it.
|
||||
|
||||
The lifetime of the allocated object extends to the end of scope of the `var`
|
||||
pattern (that is the scope that any bindings declared within it would have).
|
||||
|
||||
```carbon
|
||||
fn F(p: i32*);
|
||||
@@ -382,56 +372,48 @@ fn G() {
|
||||
|
||||
A tuple of patterns can be used as a pattern.
|
||||
|
||||
- _tuple-pattern_ ::= `(` [_expression_ `,`]\* _proper-pattern_ [`,`
|
||||
_pattern_]\*
|
||||
`,`? `)`
|
||||
- _proper-pattern_ ::= _tuple-pattern_
|
||||
- _tuple-pattern_ ::= `(` [_pattern_ `,` [_pattern_ [`,` _pattern_]\* `,`? ] ]
|
||||
`)`
|
||||
- _pattern_ ::= _tuple-pattern_
|
||||
|
||||
A _tuple-pattern_ containing no commas is treated as grouping parens: the
|
||||
contained _proper-pattern_ is matched directly against the scrutinee. Otherwise,
|
||||
the behavior is as follows.
|
||||
|
||||
A tuple pattern is matched left-to-right. The scrutinee is required to be of
|
||||
tuple type.
|
||||
|
||||
Note that a tuple pattern must contain at least one _proper-pattern_. Otherwise,
|
||||
it is a tuple-valued expression. However, a tuple pattern and a corresponding
|
||||
tuple-valued expression are matched in the same way because `==` for a tuple
|
||||
compares fields left-to-right.
|
||||
The scrutinee is required to be of tuple type, with the same arity as the number
|
||||
of nested _patterns_. It is converted to a tuple form by
|
||||
[form decomposition](values.md#form-conversions), and then each nested _pattern_
|
||||
is matched against the corresponding element of the converted scrutinee's
|
||||
[result](values.md#expression-forms). The tuple pattern matches if all of these
|
||||
sub-matches succeed.
|
||||
|
||||
### Struct patterns
|
||||
|
||||
A struct can be matched with a struct pattern.
|
||||
|
||||
- _proper-pattern_ ::= `{` [_field-init_ `,`]\* _proper-field-pattern_ [`,`
|
||||
_field-pattern_]\*
|
||||
`}`
|
||||
- _proper-pattern_ ::= `{` [_field-pattern_ `,`]+ `_` `}`
|
||||
- _field-init_ ::= _designator_ `=` _expression_
|
||||
- _proper-field-pattern_ ::= _designator_ `=` _proper-pattern_
|
||||
- _proper-field-pattern_ ::= _binding-pattern_
|
||||
- _field-pattern_ ::= _field-init_
|
||||
- _field-pattern_ ::= _proper-field-pattern_
|
||||
- _struct-pattern_ ::= `{` [_field-pattern_ [`,` _field-pattern_ ]\* ] `}`
|
||||
- _struct-pattern_ ::= `{` [_field-pattern_ `,`]+ `_` `}`
|
||||
- _field-pattern_ ::= _designator_ `=` _pattern_
|
||||
- _field-pattern_ ::= _binding-pattern_
|
||||
- _pattern_ ::= _struct-pattern_
|
||||
|
||||
A struct pattern resembles a struct literal, with at least one field initialized
|
||||
with a proper pattern:
|
||||
A struct pattern resembles a struct literal, except that the initializers can be
|
||||
patterns.
|
||||
|
||||
```carbon
|
||||
match ({.a = 1, .b = 2}) {
|
||||
// Struct literal as an expression pattern.
|
||||
// Struct literal as a pattern.
|
||||
case {.b = 2, .a = 1} => {}
|
||||
// Struct pattern.
|
||||
// Proper struct pattern.
|
||||
case {.b = n: i32, .a = m: i32} => {}
|
||||
}
|
||||
```
|
||||
|
||||
The scrutinee is required to be of struct type, and to have the same set of
|
||||
field names as the pattern. The pattern is matched left-to-right, meaning that
|
||||
matching is performed in the field order specified in the pattern, not in the
|
||||
field order of the scrutinee. This is consistent with the behavior of matching
|
||||
against a struct-valued expression, where the expression pattern becomes the
|
||||
left operand of the `==` and so determines the order in which `==` comparisons
|
||||
for fields are performed.
|
||||
The scrutinee is required to be of struct type, and every field name in the
|
||||
pattern must be a field name in the scrutinee. It is converted to a struct form
|
||||
by [form decomposition](values.md#form-conversions) and then each
|
||||
_field-pattern_ is matched with the same-named element of the converted
|
||||
scrutinee's [result](values.md#expression-forms). If the scrutinee result has
|
||||
any field names not present in the pattern, those sub-results are
|
||||
[discarded](values.md#form-conversions) in lexical order if the pattern has a
|
||||
trailing `_` (as in `{.a = 1, _}`), or diagnosed as an error if it does not. The
|
||||
struct pattern matches if all of these sub-matches succeed.
|
||||
|
||||
In the case where a field will be bound to an identifier with the same name, a
|
||||
shorthand syntax is available: `a: T` is synonymous with `.a = a: T`.
|
||||
@@ -442,6 +424,9 @@ match ({.a = 1, .b = 2}) {
|
||||
}
|
||||
```
|
||||
|
||||
Likewise, `ref a: T` is synonymous with `.a = ref a: T`, and `var a: T` is
|
||||
synonymous with `.a = var a: T`.
|
||||
|
||||
If some fields should be ignored when matching, a trailing `, _` can be added to
|
||||
specify this:
|
||||
|
||||
@@ -462,19 +447,22 @@ This is valid even if all fields are actually named in the pattern.
|
||||
|
||||
An alternative pattern is used to match one alternative of a choice type.
|
||||
|
||||
- _proper-pattern_ ::= _callee-expression_ _tuple-pattern_
|
||||
- _proper-pattern_ ::= _designator_ _tuple-pattern_?
|
||||
- _alternative-pattern_ ::= _callee-expression_ _tuple-pattern_?
|
||||
- _alternative-pattern_ ::= _designator_ _tuple-pattern_? \_ _pattern_ ::=
|
||||
_alternative-pattern_
|
||||
|
||||
Here, _callee-expression_ is syntactically an expression that is valid as the
|
||||
callee in a function call expression, and an alternative pattern is
|
||||
syntactically a function call expression whose argument list contains at least
|
||||
one _proper-pattern_.
|
||||
syntactically a function call expression whose argument list may contain proper
|
||||
patterns.
|
||||
|
||||
If a _callee-expression_ is provided, it is required to name a choice type
|
||||
alternative that has a parameter list, and the scrutinee is implicitly converted
|
||||
to that choice type. Otherwise, the scrutinee is required to be of some choice
|
||||
type, and the designator is looked up in that type and is required to name an
|
||||
alternative with a parameter list if and only if a _tuple-pattern_ is specified.
|
||||
Semantically, if the argument list contains no proper patterns, it behaves like
|
||||
an expression pattern. Otherwise, if a _callee-expression_ is provided, it is
|
||||
required to name a choice type alternative that has a parameter list, and the
|
||||
scrutinee is implicitly converted to that choice type. Otherwise, the scrutinee
|
||||
is required to be of some choice type, and the designator is looked up in that
|
||||
type and is required to name an alternative with a parameter list if and only if
|
||||
a _tuple-pattern_ is specified.
|
||||
|
||||
The pattern matches if the active alternative in the scrutinee is the specified
|
||||
alternative, and the arguments of the alternative match the given tuple pattern
|
||||
@@ -750,8 +738,10 @@ In order to match a value, whatever is specified in the pattern must match.
|
||||
Using `auto` for a type will always match, making `_: auto` the wildcard
|
||||
pattern.
|
||||
|
||||
Any initializing expressions in the scrutinee of a `match` statement are
|
||||
[materialized](values.md#temporary-materialization) before pattern matching
|
||||
If the scrutinee expression's [form](values.md#expression-forms) contains any
|
||||
primitive forms with category "initializing", they are converted to ephemeral
|
||||
non-entire reference expressions by
|
||||
[materialization](values.md#temporary-materialization) before pattern matching
|
||||
begins, so that the result can be reused by multiple `case`s. However, the
|
||||
objects created by `var` patterns are not reused by multiple `case`s:
|
||||
|
||||
@@ -813,6 +803,131 @@ fn Foo() -> i32 {
|
||||
This extracts the first value from the result of calling `Bar()` and binds it to
|
||||
a local variable named `p` which is then returned.
|
||||
|
||||
## Evaluation order
|
||||
|
||||
A pattern matching operation's potentially-observable side effects are a series
|
||||
of calls to functions that might be user-defined. This includes function calls
|
||||
and operators in the scrutinee and in expression patterns, and also type
|
||||
conversions and category conversions. Note that category conversions on tuple
|
||||
and struct types, and type conversions between tuple and struct types, are not
|
||||
modeled as function calls, but are broken down into function calls on their
|
||||
elements. Note also that for function and operator calls in expressions, we are
|
||||
only considering top-level calls, that is calls that aren't inputs to other
|
||||
calls within the expression, because the entire sub-expression of a top-level
|
||||
call acts as a single unit for purposes of evaluation ordering.
|
||||
|
||||
For example, suppose `A` is implicitly convertible to a `C` and `B` is
|
||||
implicitly convertible to `D`, but both conversions are value expressions
|
||||
(rather than initializing expressions), and consider the following code:
|
||||
|
||||
```
|
||||
fn MakeA() -> A;
|
||||
fn MakeB() -> B;
|
||||
|
||||
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`.
|
||||
|
||||
> **Note:** These `Core` interfaces haven't been specified yet, and their
|
||||
> details may change.
|
||||
|
||||
To define the evaluation order of these calls, we have to consider the
|
||||
dependencies between them, which we'll model as a DAG, with function calls as
|
||||
nodes, and edges representing data dependencies. It will also be useful to
|
||||
include leaf patterns (that is, patterns that have no subpatterns) as nodes in
|
||||
the graph; they don't have side effects as such, so they aren't part of the
|
||||
evaluation order, but they do constrain the evaluation order.
|
||||
|
||||
```mermaid
|
||||
%%{init: {'themeVariables': {'fontFamily': 'monospace'}}}%%
|
||||
flowchart BT
|
||||
2["A.(Core.ImplicitAsPrimitive(C))"]-->1[/"MakeA"\]
|
||||
3["A.(Core.Copy)"]-->2
|
||||
5["B.(Core.ImplicitAsPrimitive(D))"]-->4[/"MakeB"\]
|
||||
6["B.(Core.Copy)"]-->5
|
||||
7[\"cd: (C, D)"/]-->3
|
||||
7-->6
|
||||
```
|
||||
|
||||
This DAG will always have a few key properties:
|
||||
|
||||
- The sources are the primitive patterns. Only the sources can have multiple
|
||||
out-edges.
|
||||
- The sinks are function calls in the scrutinee expression, and in expression
|
||||
patterns. Only scrutinee expression sinks can have multiple in-edges.
|
||||
- The interior nodes always have one edge in and one edge out, forming a set
|
||||
of paths that connect a source to a sink.
|
||||
- The paths to calls in expression patterns are trivial: they consist of a
|
||||
single edge from an expression pattern source to a function call sink.
|
||||
Furthermore, a given source or sink has at most one such edge.
|
||||
- Each path to the scrutinee connects a type in the pattern to a type in the
|
||||
scrutinee, and together the paths uniquely cover the entire pattern and
|
||||
scrutinee types. Furthermore, they are minimal, in the sense that unless the
|
||||
path is a single edge, its source and sink types won't both be tuple or
|
||||
struct types.
|
||||
|
||||
> **Future work:** this design needs to be reconciled with the design for
|
||||
> [user-defined sum types](sum_types.md#user-defined-sum-types), because
|
||||
> `Match.Op` can violate this topology. This should probably be folded into a
|
||||
> broader redesign of sum type customization, which we expect to be necessary
|
||||
> for other reasons.
|
||||
|
||||
The order of evaluation is determined by a depth-first postorder traversal of
|
||||
the this DAG: while visiting a node, we recursively visit all its children, and
|
||||
a call occurs when we finish visiting the corresponding node (revisiting a node
|
||||
is a no-op). By eagerly consuming the result of each function call as soon as
|
||||
possible, this minimizes the number of simultaneously-live temporaries, which
|
||||
enables more efficient code generation.
|
||||
|
||||
When visiting a pattern, we visit its out-paths in the scrutinee type's
|
||||
left-to-right source code order (recall that each path is associated with a
|
||||
unique part of the scrutinee type). An edge to an expression pattern call, if
|
||||
any, is visited last. The patterns themselves are visited in their own
|
||||
left-to-right source code order. So, returning to our earlier example, the 6
|
||||
function calls will be evaluated in the order we listed them.
|
||||
|
||||
In some cases, visiting the patterns in their own order may lead to visiting the
|
||||
types within a scrutinee call out of order, but if it would lead to visiting the
|
||||
scrutinee calls themselves out of order, the program is ill-formed. For example:
|
||||
|
||||
```carbon
|
||||
// ❌ Error: visiting `.c: C` first leads to evaluating `MakeA()` before
|
||||
// `MakeB()`
|
||||
var {c: C, d: D} = {.d = MakeB(), .c = MakeA()};
|
||||
|
||||
// ✅ OK: only one pattern, and we use scrutinee order to visit its children.
|
||||
var cd: {.c: C, .d: D} = {.d = MakeB(), .c = MakeA()};
|
||||
|
||||
// ✅ OK: only one scrutinee call, so it can't be out of order.
|
||||
fn MakeAB() -> {.d: B, .c: A};
|
||||
var {c: C, d: D} = MakeAB();
|
||||
```
|
||||
|
||||
As a result, the overall evaluation order is always consistent with the written
|
||||
order of the patterns, and with the written order of the scrutinee expressions.
|
||||
Within those constraints, the order of the scrutinee types acts as a
|
||||
tie-breaker. Note in particular that this means the fields of a struct-type
|
||||
binding are not necessarily initialized in declaration order.
|
||||
|
||||
Note that generally speaking, pattern-match evaluation stops as soon as it's
|
||||
known that the match will fail, in which case only a prefix of the full
|
||||
evaluation order will be evaluated.
|
||||
|
||||
### Alternatives considered
|
||||
|
||||
- [Breadth-first evaluation order](/proposals/p5545.md#breadth-first-evaluation-order)
|
||||
- [Depth-first evaluation with a different "horizontal" order](/proposals/p5545.md#depth-first-evaluation-with-a-different-horizontal-order)
|
||||
|
||||
## Open questions
|
||||
|
||||
### Slice or array nested value pattern matching
|
||||
|
||||
@@ -12,6 +12,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Element access](#element-access)
|
||||
- [Conversion](#conversion)
|
||||
- [Empty tuples](#empty-tuples)
|
||||
- [Trailing commas and single-element tuples](#trailing-commas-and-single-element-tuples)
|
||||
- [Tuple of types and tuple types](#tuple-of-types-and-tuple-types)
|
||||
@@ -64,6 +65,14 @@ fn Choose(template N:! i32) -> i32 {
|
||||
}
|
||||
```
|
||||
|
||||
## Conversion
|
||||
|
||||
A tuple type `Source` can be converted to a tuple type `Dest` if they have the
|
||||
same number of elements, and each element type of `Source` is convertible to the
|
||||
corresponding element type of `Dest`, and the conversion is implicit if all of
|
||||
the element type conversions are implicit. See
|
||||
[here](values.md#type-conversions) for full details.
|
||||
|
||||
### Empty tuples
|
||||
|
||||
`()` is the empty tuple. This is used in other parts of the design, such as
|
||||
|
||||
+541
-79
@@ -20,6 +20,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Local variables](#local-variables)
|
||||
- [Consuming function parameters](#consuming-function-parameters)
|
||||
- [Reference expressions](#reference-expressions)
|
||||
- [Entire reference expressions](#entire-reference-expressions)
|
||||
- [Durable reference expressions](#durable-reference-expressions)
|
||||
- [Ephemeral reference expressions](#ephemeral-reference-expressions)
|
||||
- [Value expressions](#value-expressions)
|
||||
@@ -31,6 +32,11 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Function calls and returns](#function-calls-and-returns)
|
||||
- [Deferred initialization from values and references](#deferred-initialization-from-values-and-references)
|
||||
- [Declared `returned` variable](#declared-returned-variable)
|
||||
- [Expression forms](#expression-forms)
|
||||
- [Initializing results](#initializing-results)
|
||||
- [Form conversions](#form-conversions)
|
||||
- [Type conversions](#type-conversions)
|
||||
- [Category conversions](#category-conversions)
|
||||
- [Pointers](#pointers)
|
||||
- [Reference types](#reference-types)
|
||||
- [Pointer syntax](#pointer-syntax)
|
||||
@@ -64,21 +70,21 @@ itself.
|
||||
|
||||
### Expression categories
|
||||
|
||||
There are three expression categories in Carbon:
|
||||
There are three primary expression categories in Carbon:
|
||||
|
||||
- [_Value expressions_](#value-expressions) produce abstract, read-only
|
||||
_values_ that cannot be modified or have their address taken.
|
||||
- [_Reference expressions_](#reference-expressions) refer to _objects_ with
|
||||
_storage_ where a value may be read or written and the object's address can
|
||||
be taken.
|
||||
- [_Initializing expressions_](#initializing-expressions) require storage to
|
||||
be provided implicitly when evaluating the expression. The expression then
|
||||
initializes an object in that storage. These are used to model function
|
||||
returns, which can construct the returned value directly in the caller's
|
||||
storage.
|
||||
- [_Initializing expressions_](#initializing-expressions) require a result
|
||||
location to be provided implicitly when evaluating the expression. The
|
||||
expression then initializes an object in that location. These are used to
|
||||
model function returns, which can construct the returned value directly in
|
||||
the caller's storage.
|
||||
|
||||
Expressions in one category can be converted to any other category when needed.
|
||||
The primitive conversion steps used are:
|
||||
Expressions in one category can be implicitly converted to any other primary
|
||||
category when needed. The primitive conversion steps used are:
|
||||
|
||||
- [_Value acquisition_](#value-acquisition) forms a value expression from the
|
||||
current value of the object referenced by a reference expression.
|
||||
@@ -97,13 +103,36 @@ These conversion steps combine to provide the transitive conversion table:
|
||||
| to **reference** | direct init + materialize | == | materialize |
|
||||
| to **initializing** | direct init | copy init | == |
|
||||
|
||||
Reference expressions formed through temporary materialization are called
|
||||
[_ephemeral reference expressions_](#ephemeral-reference-expressions) and have
|
||||
restrictions on how they are used. In contrast, reference expressions that refer
|
||||
to declared storage are called
|
||||
[_durable reference expressions_](#durable-reference-expressions). Beyond the
|
||||
restrictions on what is valid, there is no distinction in their behavior or
|
||||
semantics.
|
||||
Reference expressions are divided into 2x2 sub-categories: they can be either
|
||||
[_ephemeral_](#ephemeral-reference-expressions) or
|
||||
[_durable_](#durable-reference-expressions), and either _entire_ or
|
||||
_non-entire_.
|
||||
|
||||
Ephemeral reference expressions are formed through temporary materialization,
|
||||
and have restrictions on how they are used. In contrast, durable reference
|
||||
expressions refer to storage that outlives the expression, and typically has a
|
||||
declared name. Entire reference expressions can only refer to complete objects,
|
||||
whereas non-entire reference expressions can refer to both complete objects and
|
||||
sub-objects (such as class fields and base class sub-objects). As a consequence,
|
||||
only entire reference expressions can be destructively moved.
|
||||
|
||||
> **Future work:** This means that pointer-dereference expressions are
|
||||
> non-entire, but we will presumably want to be able to destructively move from
|
||||
> them. We need to figure out how to support that without violating the
|
||||
> invariant that a live object has live fields.
|
||||
|
||||
Value acquisition and copy initialization can be applied to any reference
|
||||
expression, but materialization only produces ephemeral entire reference
|
||||
expressions. An entire reference expression can be implicitly converted to
|
||||
non-entire; this has no run-time effect because it merely discards static
|
||||
object-completeness information. Non-entire reference expressions can only be
|
||||
converted to entire reference expressions by round-tripping through
|
||||
copy-initialization and materialization. Non-durable-reference expressions
|
||||
cannot be implicitly converted to durable reference expressions at all.
|
||||
|
||||
> **TODO:** Determine how these reference sub-categories relate to memory-safety
|
||||
> properties like uniqueness, and make sure their names are aligned with
|
||||
> memory-safety terminology.
|
||||
|
||||
#### Value acquisition
|
||||
|
||||
@@ -157,9 +186,20 @@ fn Sum(x: i32, y: i32) -> i32 {
|
||||
Value bindings require the matched expression to be a _value expression_,
|
||||
converting it into one as necessary.
|
||||
|
||||
A _variable pattern_ is introduced with the `var` keyword. It declares storage
|
||||
for a new object, and initializes it from the matched expression, which must be
|
||||
an initializing expression.
|
||||
A _variable pattern_ is introduced with the `var` keyword. The matched
|
||||
expression must be an ephemeral entire reference expression (which typically
|
||||
requires the matched expression to be materialized); the `var` pattern takes
|
||||
ownership of the newly-allocated temporary storage it refers to, which extends
|
||||
its lifetime to the end of the enclosing scope. The subpattern is then matched
|
||||
against a _durable_ entire reference expression to the object in that storage.
|
||||
|
||||
> **Open question:** This implies that `var field: T = F().field;` doesn't
|
||||
> perform any copies or moves on `T`. This, in turn, implies that the storage
|
||||
> for `field` must be laid out as part of a complete `typeof(F())` object
|
||||
> layout, which is initialized by the call to `F()`. All other members of that
|
||||
> layout are immediately destroyed, and their storage is theoretically reusable
|
||||
> after that point, but it's unclear if this is the right default, or how to
|
||||
> enable user code to override that default when it's the wrong tradeoff.
|
||||
|
||||
A _reference binding pattern_ is a binding pattern that is nested under a `var`
|
||||
pattern. It introduces a name called a _reference binding_ that is a
|
||||
@@ -174,8 +214,10 @@ fn Example() {
|
||||
let x: i64 = 1;
|
||||
|
||||
// `2` also starts as a value expression, but the variable pattern requires it
|
||||
// to be converted to an initializing expression by using the value `2` to
|
||||
// initialize the provided variable storage that `y` will refer to.
|
||||
// to be converted to an ephemeral entire reference expression by using the
|
||||
// value `2` to initialize temporary storage, which the variable pattern
|
||||
// takes ownership of. The reference binding pattern is then bound to a
|
||||
// durable reference to the newly-initialized object.
|
||||
var y: i64 = 2;
|
||||
|
||||
// Allowed to take the address and mutate `y` as it is a durable reference
|
||||
@@ -214,8 +256,10 @@ inner `var` pattern here:
|
||||
fn DestructuringExample() {
|
||||
// Both `1` and `2` start as value expressions. The `x` binding directly
|
||||
// matches `1`. For `2`, the variable pattern requires it to be converted to
|
||||
// an initializing expression by using the value `2` to initialize the
|
||||
// provided variable storage that `y` will refer to.
|
||||
// an ephemeral entire reference expression by using the value `2` to
|
||||
// initialize temporary storage, which the variable pattern takes ownership
|
||||
// of. The reference binding `y` is then bound to a durable reference to the
|
||||
// newly-initialized object.
|
||||
let (x: i64, var y: i64) = (1, 2);
|
||||
|
||||
// Just like above, we can take the address and mutate `y`:
|
||||
@@ -250,9 +294,9 @@ This allows us to model an important special case of function inputs -- those
|
||||
that are _consumed_ by the function, either through local processing or being
|
||||
moved into some persistent storage. Marking these in the pattern and thus
|
||||
signature of the function changes the expression category required for arguments
|
||||
in the caller. These arguments are required to be _initializing expressions_,
|
||||
potentially being converted into such an expression if necessary, that directly
|
||||
initialize storage dedicated-to and owned-by the function parameter.
|
||||
in the caller. These arguments are required to be _ephemeral entire reference
|
||||
expressions_, potentially being converted into such an expression if necessary,
|
||||
whose storage will be dedicated-to and owned-by the function parameter.
|
||||
|
||||
This pattern serves the same purpose as C++'s pass-by-value when used with types
|
||||
that have non-trivial resources attached to pass ownership into the function and
|
||||
@@ -264,9 +308,60 @@ makes this a use case that requires a special marking on the declaration.
|
||||
_Reference expressions_ refer to _objects_ with _storage_ where a value may be
|
||||
read or written and the object's address can be taken.
|
||||
|
||||
There are two sub-categories of reference expressions: _durable_ and
|
||||
_ephemeral_. These refine the _lifetime_ of the underlying storage and provide
|
||||
safety restrictions reflecting that lifetime.
|
||||
Reference expressions can be either _durable_ or _ephemeral_. These refine the
|
||||
_lifetime_ of the underlying storage and provide safety restrictions reflecting
|
||||
that lifetime. Reference expressions can also be either _entire_ or
|
||||
_non-entire_, depending on whether the referenced object is known to be complete
|
||||
(rather than a sub-object of another object).
|
||||
|
||||
### Entire reference expressions
|
||||
|
||||
An _entire reference expression_ is one that is statically known to refer to a
|
||||
complete object. Other references are _non-entire_. Durable and ephemeral
|
||||
reference expressions can both be either entire or non-entire (although
|
||||
non-entire ephemeral references are rare). Unless otherwise specified, an
|
||||
expression or operation that produces a reference produces a non-entire
|
||||
reference.
|
||||
|
||||
Note that a non-entire reference expression still _might_ refer to a complete
|
||||
object; the language rules just don't _guarantee_ that is does. As a result, an
|
||||
entire reference can be implicitly converted to a non-entire reference (with the
|
||||
same durability), because this merely discards the knowledge that the object is
|
||||
complete. By the same token, there is no context that requires a non-entire
|
||||
reference; only contexts that accept both, that accept only entire references,
|
||||
or that don't accept references at all.
|
||||
|
||||
Currently, the only context that requires an entire reference is the scrutinee
|
||||
of a `var` pattern, which is required to be an entire ephemeral reference (and
|
||||
is [converted](#category-conversions) to that category if necessary).
|
||||
|
||||
> **Note:** This extends the lifetime of the reference, so it must be possible
|
||||
> to determine _which_ temporary an ephemeral entire reference refers to, so
|
||||
> that the implementation knows which lifetime to extend. Under the current
|
||||
> language rules, this can be done statically.
|
||||
|
||||
> **Open question:** Should we extend the language in ways that would force that
|
||||
> determination to be dynamic? For example, should we allow
|
||||
> `if c then r1 else r2` to be an entire ephemeral reference expression if `r1`
|
||||
> and `r2` are? As a more extreme example, should we support functions that take
|
||||
> and return entire ephemeral references?
|
||||
|
||||
There are several kinds of expressions that produce entire references. For
|
||||
example:
|
||||
|
||||
- The name of an object introduced with a
|
||||
[variable binding pattern](pattern_matching.md#name-binding-patterns) (in
|
||||
other words, a name that was declared with `var <name> : <type>`) is a
|
||||
durable entire reference.
|
||||
- a member access expression `x.member` or `x.(member)` is an entire reference
|
||||
if `x` is an initializing or entire ephemeral reference expression with a
|
||||
struct or tuple type.
|
||||
- The result of materialization is an entire ephemeral reference.
|
||||
- When a [tuple pattern](pattern_matching.md#tuple-patterns) or
|
||||
[struct pattern](pattern_matching.md#struct-patterns) is matched with an
|
||||
ephemeral entire reference scrutinee, that scrutinee is destructured into
|
||||
ephemeral entire references to its elements, which are then matched with the
|
||||
corresponding subpatterns.
|
||||
|
||||
### Durable reference expressions
|
||||
|
||||
@@ -274,7 +369,8 @@ _Durable reference expressions_ are those where the object's storage outlives
|
||||
the full expression and the address could be meaningfully propagated out of it
|
||||
as well.
|
||||
|
||||
There are two contexts that require a durable reference expression in Carbon:
|
||||
There are several contexts where durable reference expressions are required. For
|
||||
example:
|
||||
|
||||
- [Assignment statements](/docs/design/assignment.md) require the
|
||||
left-hand-side of the `=` to be a durable reference. This stronger
|
||||
@@ -282,9 +378,14 @@ There are two contexts that require a durable reference expression in Carbon:
|
||||
the `Carbon.Assign.Op` interface method.
|
||||
- [Address-of expressions](#pointer-syntax) require their operand to be a
|
||||
durable reference and compute the address of the referenced object.
|
||||
- [`ref` binding patterns](pattern_matching.md#name-binding-patterns) require
|
||||
their scrutinee to be a durable reference.
|
||||
- If a function's [return form](#function-calls-and-returns) contains `ref`
|
||||
tags, `return` statements require the corresponding parts of the operand to
|
||||
be durable reference expressions.
|
||||
|
||||
There are several kinds of expressions that produce durable references in
|
||||
Carbon:
|
||||
There are also several kinds of expressions that produce durable references. For
|
||||
example:
|
||||
|
||||
- Names of objects introduced with a
|
||||
[reference binding](#binding-patterns-and-local-variables-with-let-and-var):
|
||||
@@ -295,6 +396,8 @@ Carbon:
|
||||
- [Indexing](/docs/design/expressions/indexing.md) into a type similar to
|
||||
C++'s `std::span` that implements `IndirectIndexWith`, or indexing into any
|
||||
type with a durable reference expression such as `local_array[i]`.
|
||||
- Calls to functions whose [return forms](#function-calls-and-returns) contain
|
||||
`ref`.
|
||||
|
||||
Durable reference expressions can only be produced _directly_ by one of these
|
||||
expressions. They are never produced by converting one of the other expression
|
||||
@@ -305,22 +408,34 @@ categories into a reference expression.
|
||||
We call the reference expressions formed through
|
||||
[temporary materialization](#temporary-materialization) _ephemeral reference
|
||||
expressions_. They still refer to an object with storage, but it may be storage
|
||||
that will not outlive the full expression. Because the storage is only
|
||||
temporary, we impose restrictions on where these reference expressions can be
|
||||
used: their address can only be taken implicitly as part of a method call whose
|
||||
`self` parameter is marked with the `ref` specifier.
|
||||
that will not outlive the full expression, and so it can't be used where a
|
||||
durable reference is expected.
|
||||
|
||||
**Future work:** The current design allows directly requiring an ephemeral
|
||||
reference for `ref`-methods because this replicates the flexibility in C++ --
|
||||
very few C++ methods are L-value-ref-qualified which would have a similar effect
|
||||
to `ref`-methods requiring a durable reference expression. This is leveraged
|
||||
frequently in C++ for builder APIs and other patterns. However, Carbon provides
|
||||
more tools in this space than C++ already, and so it may be worth evaluating
|
||||
whether we can switch `ref`-methods to the same restrictions as assignment and
|
||||
`&`. Temporaries would never have their address escaped (in a safe way) in that
|
||||
world and there would be fewer different kinds of entities. But this is reserved
|
||||
for future work as we should be very careful about the expressivity hit being
|
||||
tolerable both for native-Carbon API design and for migrated C++ code.
|
||||
> **Future work:** The current design does not support mutating ephemeral
|
||||
> references (or initializing expressions): assigning to an ephemeral reference
|
||||
> is disallowed directly, and invoking mutating methods is disallowed because
|
||||
> the `ref self` parameter can only bind to a durable reference. In C++ it's
|
||||
> unusual but not rare to intentionally mutate a temporary, such as in a
|
||||
> builder-style method chain (for example `MakeFoo().SetBar().AddBaz()`), so
|
||||
> Carbon will need to provide some interop and migration target for that kind of
|
||||
> code.
|
||||
|
||||
There is one context that requires an ephemeral reference expression in Carbon:
|
||||
the scrutinee of a
|
||||
[`var` pattern](#binding-patterns-and-local-variables-with-let-and-var) (which
|
||||
also requires the reference to be entire).
|
||||
|
||||
There are only a few ways to produce an ephemeral reference expression. Most
|
||||
notably:
|
||||
|
||||
- The result of materialization is an entire ephemeral reference.
|
||||
- A member access expression `x.member` or `x.(member)` is an ephemeral
|
||||
reference if `x` is an initializing or ephemeral reference.
|
||||
- When a [tuple pattern](pattern_matching.md#tuple-patterns) or
|
||||
[struct pattern](pattern_matching.md#struct-patterns) is matched with an
|
||||
initializing or ephemeral reference scrutinee, that scrutinee is
|
||||
destructured into ephemeral references to its elements, which are then
|
||||
matched with the corresponding subpatterns.
|
||||
|
||||
## Value expressions
|
||||
|
||||
@@ -487,8 +602,9 @@ The specific tradeoff here is covered in a proposal
|
||||
## Initializing expressions
|
||||
|
||||
Storage in Carbon is initialized using _initializing expressions_. Their
|
||||
evaluation produces an initialized object in the storage, although that object
|
||||
may still be _unformed_.
|
||||
evaluation takes a _result location_ as an implicit input, and produces an
|
||||
initialized object at that location, although that object may still be
|
||||
_unformed_.
|
||||
|
||||
**Future work:** More details on initialization and unformed objects should be
|
||||
added to the design from the proposal
|
||||
@@ -506,29 +622,37 @@ the provided storage.
|
||||
**Future work:** The design should be expanded to fully cover how copying is
|
||||
managed and linked to from here.
|
||||
|
||||
The first place where an initializing expression is _required_ is to satisfy
|
||||
[_variable patterns_](#binding-patterns-and-local-variables-with-let-and-var).
|
||||
These require the expression they match to be an initializing expression for the
|
||||
storage they create. The simplest example is the expression after the `=` in a
|
||||
local `var` declaration.
|
||||
There are no syntactic contexts in Carbon that always require an initializing
|
||||
expression, and no expression syntax that always produces an initializing
|
||||
expression. By default, function call expressions are initializing expressions,
|
||||
and correspondingly the operand of `return` is required to be an initializing
|
||||
expression, but this default can be overridden by the
|
||||
[function signature](#function-calls-and-returns).
|
||||
|
||||
The next place where a Carbon expression requires an initializing expression is
|
||||
the expression operand to `return` statements. We expand more completely on how
|
||||
return statements interact with expressions, values, objects, and storage
|
||||
[below](#function-calls-and-returns).
|
||||
|
||||
The last path that requires forming an initializing expression in Carbon is when
|
||||
attempting to convert a non-reference expression into an ephemeral reference
|
||||
expression: the expression is first converted to an initializing expression if
|
||||
necessary, and then temporary storage is materialized to act as its output, and
|
||||
as the referent of the resulting ephemeral reference expression.
|
||||
Initializing expressions can also be created implicitly, when attempting to
|
||||
convert an expression into an ephemeral entire reference expression
|
||||
(particularly to match a `var` pattern): the expression is first converted to an
|
||||
initializing expression if necessary, and then temporary storage is materialized
|
||||
to act as its output, and as the referent of the resulting ephemeral reference
|
||||
expression.
|
||||
|
||||
### Function calls and returns
|
||||
|
||||
Function calls in Carbon are modeled directly as initializing expressions --
|
||||
they require storage as an input and when evaluated cause that storage to be
|
||||
initialized with an object. This means that when a function call is used to
|
||||
initialize some variable pattern as here:
|
||||
The [result](#expression-forms) of a function call can have an almost arbitrary
|
||||
form. The return clause of a function signature consists of `->` followed by a
|
||||
_return form_, an expression-like syntax that specifies not only the type but
|
||||
also the form of the function call's result. `return` expressions in the
|
||||
function body are expected to have that form, and are converted to it if
|
||||
necessary. When a function is declared without a return clause, it behaves from
|
||||
the caller's point of view as if the return clause were `-> ()`, but `return`
|
||||
statements in the function body don't take operands (and can be omitted at the
|
||||
end of the function).
|
||||
|
||||
In the common case, the return form is a type expression, in which case calls
|
||||
are modeled directly as initializing expressions -- they require storage as an
|
||||
input and when evaluated cause that storage to be initialized with an object.
|
||||
This means that when a function call is used to initialize some variable pattern
|
||||
as here:
|
||||
|
||||
```carbon
|
||||
fn CreateMyObject() -> MyType {
|
||||
@@ -541,18 +665,64 @@ var x: MyType = CreateMyObject();
|
||||
The `<return-expression>` in the `return` statement actually initializes the
|
||||
storage provided for `x`. There is no "copy" or other step.
|
||||
|
||||
> **Future work:** Extend this to also apply when a variable pattern is
|
||||
> initialized from a tuple/struct literal, or a tuple/struct pattern with
|
||||
> variable subpatterns is initialized from a single function call.
|
||||
In the body of such a function, all `return` statement expressions are required
|
||||
to be initializing expressions and in fact initialize the storage provided to
|
||||
the function's call expression. This in turn causes the property to hold
|
||||
_transitively_ across an arbitrary number of function calls and returns. The
|
||||
storage is forwarded at each stage and initialized exactly once.
|
||||
|
||||
All `return` statement expressions are required to be initializing expressions
|
||||
and in fact initialize the storage provided to the function's call expression.
|
||||
This in turn causes the property to hold _transitively_ across an arbitrary
|
||||
number of function calls and returns. The storage is forwarded at each stage and
|
||||
initialized exactly once.
|
||||
More generally, the syntax and semantics of a return form are as follows:
|
||||
|
||||
Note that functions without a specified return type work exactly the same as
|
||||
functions with a `()` return type for the purpose of expression categories.
|
||||
- _return-clause_ ::= `->` _return-form_
|
||||
- _return-form_ ::= _nesting-return-form_ | _auto-return-form_
|
||||
- _nesting-return-form_ ::= _expression-return-form_ | _proper-return-form_
|
||||
|
||||
Return forms can usually be nested, but syntaxes involving `auto` can only occur
|
||||
at top level. We further divide nesting return forms into expressions and
|
||||
"proper" return forms, but this is just a technical means of avoiding formal
|
||||
ambiguity in the grammar; it has no greater significance.
|
||||
|
||||
- _category-tag_ ::= `val` | `ref` | `var`
|
||||
|
||||
These tags are used to specify "value", "non-entire durable reference", or
|
||||
"initializing" expression category (respectively). Note that there is no way to
|
||||
express an entire or ephemeral reference category in a return form.
|
||||
|
||||
- _auto-return-form_ ::= _category-tag_? `auto`
|
||||
|
||||
This denotes a primitive form with runtime phase and deduced type. The category
|
||||
is determined by _category-tag_ if present, or "initializing" otherwise.
|
||||
|
||||
- _proper-return-form_ ::= _category-tag_ _expression_
|
||||
|
||||
This denotes a primitive form with runtime phase, category _category-tag_, and
|
||||
type "_expression_ `as type`".
|
||||
|
||||
- _expression-return-form_ ::= _expression_
|
||||
|
||||
An expression with no _category-tag_ is equivalent to "`var` _expression_".
|
||||
|
||||
- _proper-return-form_ ::= `(` [_expression-return-form_ `,`]\* _proper-return-form_
|
||||
[`,` _nesting-return-form_]\* `,`? `)`
|
||||
|
||||
A tuple literal of return forms denotes a tuple form whose sub-forms are
|
||||
specified by the comma-separated elements. To avoid formal ambiguity, this
|
||||
grammar rule requires at least one of the sub-forms to be proper.
|
||||
|
||||
- _expression-field-form_ ::= _designator_ `:` _expression-return-form_
|
||||
- _proper-field-form_ ::= _designator_ `:` _proper-return-form_
|
||||
- _field-form_ ::= _field-decl_
|
||||
- _field-form_ ::= _proper-field-form_
|
||||
- _proper-return-form_ ::= `{` [_expression-field-form_ `,`]\* _proper-field-form_
|
||||
[`,` _field-form_]\* `}`
|
||||
|
||||
A struct literal of return forms denotes a struct form whose field names and
|
||||
their forms are specified by the comma-separated field forms. To avoid formal
|
||||
ambiguity, this grammar rule requires at least one of the field forms to be
|
||||
proper.
|
||||
|
||||
> **Open question:** Should there be a way to specify symbolic or template phase
|
||||
> in return forms?
|
||||
|
||||
#### Deferred initialization from values and references
|
||||
|
||||
@@ -625,6 +795,295 @@ The model of initialization of returns also facilitates the use of
|
||||
[`returned var` declarations](control_flow/return.md#returned-var). These
|
||||
directly observe the storage provided for initialization of a function's return.
|
||||
|
||||
## Expression forms
|
||||
|
||||
We typically treat the category and type of an expression as independent
|
||||
properties. However, in some cases we need to deal with them as an integrated
|
||||
whole. The _form_ of an expression captures all of the information about it that
|
||||
is visible to the type system, while abstracting away all other information
|
||||
about it. Thus, forms are a generalization of types: what we conventionally call
|
||||
"types" are really the types of objects and values, whereas forms are the types
|
||||
of expressions and patterns.
|
||||
|
||||
A _primitive form_ currently consists of a type, an expression category, an
|
||||
expression phase, and optionally a constant value (which is present if and only
|
||||
if the expression phase is not "runtime"). When dealing with primitive forms,
|
||||
which is the common case, we can treat each of those properties as independent.
|
||||
For convenience, in this section we will use the notation `<T, C, P, V>` to
|
||||
represent a primitive form with type `T`, category `C`, phase `P` and value `V`,
|
||||
but this is not Carbon syntax.
|
||||
|
||||
Other forms are called _composite forms_, and there are two kinds:
|
||||
|
||||
A _tuple form_ can be thought of as a tuple of forms, just as a tuple type can
|
||||
be thought of as a tuple of types. The form of a tuple literal is a tuple form,
|
||||
whose elements are the forms of the literal elements.
|
||||
|
||||
> **TODO:** Extend this to support variadic forms.
|
||||
|
||||
A _struct form_ can be thought of as a struct whose fields are forms, just as a
|
||||
struct type can be thought of as a struct whose fields are types. The form of a
|
||||
struct literal is a struct form with the same field names, whose values are the
|
||||
forms of the corresponding fields of the struct literal.
|
||||
|
||||
The _type component_ of a form is defined as follows:
|
||||
|
||||
- The type component of a primitive form `<T, C, P, V>` is `T`.
|
||||
- The type component of a tuple form is a tuple of the type components of its
|
||||
elements.
|
||||
- The type component of a struct form is a struct whose field names are the
|
||||
field names of the struct form and whose field types are the type components
|
||||
of the corresponding elements.
|
||||
|
||||
The _category component_ and _phase component_ of a form are defined likewise.
|
||||
The category component of a struct form is called a _struct category_, and the
|
||||
category component of a tuple form is called a _tuple category_.
|
||||
|
||||
The type of an expression is the type component of the expression's form.
|
||||
|
||||
Evaluating an expression produces a _result_. It can be defined recursively in
|
||||
terms of the expression's form:
|
||||
|
||||
- The result of an initializing expression is an
|
||||
[initializing result](#initializing-results).
|
||||
- The result of a value expression is a value.
|
||||
- The result of a reference expression is a reference of the same kind.
|
||||
- The result of an expression with tuple form is a tuple of results.
|
||||
- The result of an expression with struct form is a struct of results.
|
||||
|
||||
An expression and its result always have the same form.
|
||||
|
||||
The code that accesses the result of an expression is said to _consume_ that
|
||||
result, and every primitive-form result is consumed exactly once (except in
|
||||
certain narrow contexts where the result is known not to be initializing). If a
|
||||
result isn't explicitly accessed, such as when the expression is used as a
|
||||
statement, it is said to be _discarded_, which consumes it in the absence of an
|
||||
explicit consumer. Discarding an initializing result materializes and then
|
||||
immediately destroys it. Discarding an entire ephemeral reference destroys the
|
||||
object it refers to. Discarding a value or any other kind of reference is a
|
||||
no-op.
|
||||
|
||||
### Initializing results
|
||||
|
||||
As discussed earlier, evaluation of an initializing expression takes as an input
|
||||
the result location that it initializes, which is implicitly provided by the
|
||||
context in which the evaluation takes place. In some cases, the context may
|
||||
obtain the location from its own context, and so on. For example:
|
||||
|
||||
```carbon
|
||||
class C {
|
||||
private var i: i32;
|
||||
|
||||
fn Make() -> C {
|
||||
return {.i = 0};
|
||||
}
|
||||
}
|
||||
|
||||
fn F() -> C {
|
||||
return C.Make();
|
||||
}
|
||||
|
||||
fn G() {
|
||||
var c: C = F();
|
||||
}
|
||||
```
|
||||
|
||||
By default, a function call is an initializing expression, and a `return`
|
||||
statement initializes the call's result location (which is passed as a hidden
|
||||
output parameter). So when the declaration of `c` is evaluated, its storage is
|
||||
implicitly passed into `F()` as an output parameter, which is initialized by the
|
||||
`return` statement inside `F`. When that `return` statement is evaluated to
|
||||
initialize the result location, it likewise implicitly passes the storage into
|
||||
`C.Make()` as an output parameter, which is initialized by the `return`
|
||||
statement inside `C.Make`. Finally, that `return` statement initializes the
|
||||
result location (which is still the location of `c`'s storage) by
|
||||
[direct initialization](#direct-initialization) from the value expression
|
||||
`{.i = 0}`.
|
||||
|
||||
Notice that the implicit storage parameter propagates "backwards", into an
|
||||
expression from the code that uses its result. In order to simplify the
|
||||
description of the language, we usually won't explicitly discuss the result
|
||||
locations of initializing expressions, or how they're propagated. Instead, this
|
||||
propagation is encapsulated inside the _initializing result_, which is the
|
||||
notional result of an initializing expression.
|
||||
|
||||
Whenever an initializing result is consumed, that implicitly means that the
|
||||
consumer passes a result location into the evaluation of the initializing
|
||||
expression. The source of that location depends on the consumer:
|
||||
|
||||
- If the consumer is a temporary materialization conversion, the result
|
||||
location is newly-allocated temporary storage (which the consumer may
|
||||
subsequently lifetime-extend to durable storage).
|
||||
- If the consumer is a `return` statement, and the initializing result
|
||||
corresponds to an initializing sub-form of the function's return form, the
|
||||
result location is the implicit output parameter corresponding to that
|
||||
initializing sub-form.
|
||||
|
||||
### Form conversions
|
||||
|
||||
A conversion between forms can be broken down into up to three steps: type
|
||||
conversion, category conversion, and phase conversion. These convert the form to
|
||||
a particular target type, category, and phase component (respectively). These
|
||||
steps aren't fully orthogonal: type conversions can change the category and
|
||||
phase components as a byproduct, and category conversions can change the phase
|
||||
component. However, category conversions can't change the type component, and
|
||||
phase conversions can't change either of the other two, so converting the type,
|
||||
then category, then phase, ensures that we converge on the desired result.
|
||||
|
||||
Any of these steps may be omitted, depending on whether the context imposes
|
||||
requirements on the corresponding component. Most commonly, an operand position
|
||||
requires its operand to have a primitive form with a particular category,
|
||||
usually with a particular type, and sometimes with a particular phase.
|
||||
|
||||
Phase conversions cannot change the form structure; they can only apply
|
||||
primitive phase conversions to primitive sub-forms. Type and category
|
||||
conversions are more complex, and are covered in the next two sections.
|
||||
|
||||
Note that these rules will implicitly convert between primitive and composite
|
||||
forms in both directions (except that a composite containing references cannot
|
||||
be converted to a primitive form). As a result, although the difference between
|
||||
primitive and composite forms is observable by way of overloading, it can't
|
||||
reliably carry any higher-level meaning, and should be used only as an
|
||||
optimization tool.
|
||||
|
||||
Note that this section describes the _logical structure_ of form conversions. As
|
||||
such, it primarily describes them "breadth-first", as a sequence of operations
|
||||
that each applies to the whole expression by recursively operating on its parts.
|
||||
However, the _physical execution_ of these conversions is actually depth-first,
|
||||
applying as many operations as possible to a minimal subexpression before moving
|
||||
on to the next one. The details of that process are described
|
||||
[here](pattern_matching.md#evaluation-order).
|
||||
|
||||
#### Type conversions
|
||||
|
||||
See [here](expressions/implicit_conversions.md) for overall information about
|
||||
type conversions. Conversions involving struct, tuple, and array types are
|
||||
described here because of their unique interactions with expression forms.
|
||||
|
||||
> **TODO:** A forthcoming proposal is expected to update the type conversion
|
||||
> interfaces to permit user-defined conversions to depend on the form of the
|
||||
> input, and customize the form of the output. Once that is done, these "built
|
||||
> in" conversions should be presented as implementations of those interfaces,
|
||||
> possibly with some "magic" for things like introspecting on struct field
|
||||
> names.
|
||||
|
||||
Each of the conversions described in this section is explicit if and only if it
|
||||
invokes another explicit type conversion. Otherwise, it is implicit.
|
||||
|
||||
A type conversion of a primitive-form expression to a
|
||||
[compatible type](generics/terminology.md#compatible-types) just re-interprets
|
||||
the expression's result with a new type, so it requires no run-time work, and
|
||||
has the same category as the input expression.
|
||||
|
||||
A result `source` that has a struct type can be converted to a struct type
|
||||
`Dest` if they have the same set of field names:
|
||||
|
||||
- If the type of `source` is `Dest`, return `source`.
|
||||
- If `source` is a struct result, for each field name `F` in `Dest`,
|
||||
type-convert `source.F` to `Dest.F`. Return a struct result where each field
|
||||
`F` is set to the result of the corresponding conversion.
|
||||
- If `source` is a primitive result, convert it to a struct result by
|
||||
[form decomposition](#category-conversions), and then type-convert the
|
||||
result to `Dest` and return the result.
|
||||
|
||||
Note that the sub-conversions invoked here are not necessarily defined; if so,
|
||||
the conversion itself is not defined.
|
||||
|
||||
There is a conversion to a class type `Dest` from a result `source` that has a
|
||||
struct type, if there is a conversion from `source` to a struct type that has
|
||||
the same field names as `Dest` (including a `.base` field if `Dest` is a derived
|
||||
class), with the same types, in the same order. The conversion type-converts
|
||||
`source` to that struct type, category-converts that to an initializing
|
||||
expression of the struct type, and then reinterprets it as an initializing
|
||||
expression of `Dest` (which is layout-compatible with the struct type by
|
||||
construction).
|
||||
|
||||
Note that some fields of an object may be initialized directly by the evaluation
|
||||
of the source expression, while others may be initialized by the conversions
|
||||
described here. The conversions initialize fields in their declaration order,
|
||||
but the evaluation of the source expression always happens before any of the
|
||||
conversions, and happens in the source expression's lexical order, so the fields
|
||||
of an object are not necessarily initialized in declaration order.
|
||||
|
||||
Conversions between tuple types are defined in the same way, treating tuples as
|
||||
structs that have fields named `.0`, `.1`, etc, in numerical order.
|
||||
|
||||
There is a conversion to `array(T, N)` from any expression with a tuple form of
|
||||
exactly `N` elements, whose type components are convertible to `T`. The
|
||||
conversion is an initializing expression, which type-converts each source
|
||||
element to `T`, and initializes the corresponding array element from the result
|
||||
of that conversion.
|
||||
|
||||
#### Category conversions
|
||||
|
||||
_Form composition_ converts an expression of composite form with consistent
|
||||
category to a primitive form as follows (where `min` as applied to phases uses
|
||||
the ordering "runtime" < "symbolic" < "template"):
|
||||
|
||||
- An expression of tuple form
|
||||
`(<T1, C, P1, V1>, <T2, C, P2, V2>, ... <TN, C, PN, VN>)` can be converted
|
||||
to a primitive form
|
||||
`<(T1, T2, ..., TN), C, min(P1, P2, ..., PN), (V1, V2, ... VN)>`.
|
||||
- An expression of struct form
|
||||
`{.a = <Ta, C, Pa, Va>, .b = <Tb, C, Pb, Vb>, ... .z = <Tz, C, Pz, Vz>}` can
|
||||
be converted to a primitive form
|
||||
`<{.a = Ta, .b = Tb, ... .z = Tz}, C, min(Pa, Pb, ... Pz), {.a = Va, .b = Vb, ... .z = Vz}>`.
|
||||
|
||||
When `C` is "value", composition forms a value representation of the aggregate
|
||||
from value representations of the elements. When `C` is "initializing", it
|
||||
transforms initializing expressions for each element into a single initializing
|
||||
expression that initializes the whole aggregate. `C` cannot be a reference
|
||||
category, because an aggregate of references to independent objects can't be
|
||||
replaced by a reference to a single aggregate object in a single step.
|
||||
|
||||
_Form decomposition_ is the inverse of form composition. It converts a
|
||||
primitive-form expression to a composite form as follows:
|
||||
|
||||
- An expression with primitive form `<(T0, T1, ..., TN), C, P, V>` can be
|
||||
converted to a tuple form
|
||||
`(<T0, CC, P, V.0>, <T1, CC, P, V.1>, ... <TN, CC, P, V.N>)`.
|
||||
- An expression with primitive form
|
||||
`<{.a = Ta, .b = Tb, ... .z = Tz}, C, P, V>` can be converted to a struct
|
||||
form
|
||||
`{.a = <Ta, CC, P, V.a>, .b = <Tb, CC, P, V.b>, ... .z = <Tz, CC, P, V.z>}`.
|
||||
|
||||
The category `CC` of the resulting sub-forms is the same as `C`, with two
|
||||
exceptions:
|
||||
|
||||
- If `C` is "durable entire reference", `CC` will be "durable non-entire
|
||||
reference", because the sub-forms don't refer to complete objects. This
|
||||
doesn't apply to ephemeral entire references, because in that case form
|
||||
decomposition implicitly ends the lifetime of the original aggregate,
|
||||
promoting its elements to complete objects with independent lifetimes.
|
||||
- If `C` is "initializing", the original expression is materialized before it
|
||||
is decomposed, so `CC` will be "ephemeral entire reference".
|
||||
|
||||
By convention, form decomposition is a no-op when applied to an expression with
|
||||
struct or tuple form.
|
||||
|
||||
_Category conversion_ converts an expression to have a given category component
|
||||
without changing its type. The conversion works by combining form composition
|
||||
and decomposition with primitive category conversions, and is defined
|
||||
recursively:
|
||||
|
||||
- If the target category component is a tuple, the source form must have a
|
||||
tuple type with the same arity. Convert the source to a tuple form by form
|
||||
decomposition, and then category-convert each source sub-form to the
|
||||
corresponding target sub-category.
|
||||
- If the target category component is a struct, the source form must have a
|
||||
struct type with the same set of field names in the same order. Convert the
|
||||
source to a struct form by form decomposition, and then category-convert
|
||||
each source sub-form to the corresponding target sub-category.
|
||||
- If the target category is a primitive category `C`:
|
||||
- If the source form is primitive, convert to `C` by applying primitive
|
||||
category conversions.
|
||||
- If the source form is composite and `C` is a reference category,
|
||||
category-convert the source form to "initializing", and then convert the
|
||||
result to `C` by applying primitive category conversions.
|
||||
- If the source form is composite and `C` is not a reference category,
|
||||
category-convert each source sub-form to `C`, and then convert the
|
||||
aggregate result of these conversions to `C` by form composition.
|
||||
|
||||
## Pointers
|
||||
|
||||
Pointers in Carbon are the primary mechanism for _indirect access_ to storage
|
||||
@@ -859,8 +1318,7 @@ functionality already proposed here or for [classes](/docs/design/classes.md):
|
||||
the most appealing as it _doesn't_ have the combinatorial explosion. But it
|
||||
is also very limited as it only applies to the implicit object parameter.
|
||||
- Allow overloading between `var` and non-`var` parameters.
|
||||
- Expand the `ref` technique from object parameters to all parameters, and
|
||||
allow overloading based on it.
|
||||
- Allow overloading between `ref` and non-`ref` parameters in general.
|
||||
|
||||
Perhaps more options will emerge as well. Again, the goal isn't to completely
|
||||
preclude pursuing this direction, but instead to try to ensure it is only
|
||||
@@ -1040,6 +1498,8 @@ itself.
|
||||
- [Exclusively using references](/proposals/p2006.md#exclusively-using-references)
|
||||
- [Alternative pointer syntaxes](/proposals/p2006.md#alternative-pointer-syntaxes)
|
||||
- [Alternative syntaxes for locals](/proposals/p2006.md#alternative-syntaxes-for-locals)
|
||||
- [Mixed expression categories](/proposals/p5545.md#mixed-expression-categories)
|
||||
- [Don't implicitly convert to less-primitive forms](/proposals/p5545.md#dont-implicitly-convert-to-less-primitive-forms)
|
||||
|
||||
## References
|
||||
|
||||
@@ -1048,9 +1508,11 @@ itself.
|
||||
- [Proposal #618: `var` ordering][p0618]
|
||||
- [Proposal #851: auto keyword for vars][p0851]
|
||||
- [Proposal #2006: Values, variables, and pointers][p2006]
|
||||
- [Proposal #5545: Expression form basics][p5545]
|
||||
|
||||
[p0257]: /proposals/p0257.md
|
||||
[p0339]: /proposals/p0339.md
|
||||
[p0618]: /proposals/p0618.md
|
||||
[p0851]: /proposals/p0851.md
|
||||
[p2006]: /proposals/p2006.md
|
||||
[p5545]: /proposals/p5545.md
|
||||
|
||||
@@ -23,6 +23,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
- [Responding to review comments](#responding-to-review-comments)
|
||||
- [Responding to questions or confusion](#responding-to-questions-or-confusion)
|
||||
- [Understand the feedback in the comments](#understand-the-feedback-in-the-comments)
|
||||
- [Fixing conflicts with trunk](#fixing-conflicts-with-trunk)
|
||||
- [Code reviewer guide](#code-reviewer-guide)
|
||||
- [How quickly should you respond to a review request?](#how-quickly-should-you-respond-to-a-review-request)
|
||||
- [What should be covered by a review?](#what-should-be-covered-by-a-review)
|
||||
@@ -325,6 +326,13 @@ long delays between these iterations. Consider discussing over Discord chat or
|
||||
scheduling a quick video chat on the specific issue. This can avoid multi-hour
|
||||
-- or multi-day -- round trips.
|
||||
|
||||
### Fixing conflicts with trunk
|
||||
|
||||
If a PR has conflicts with trunk, those conflicts must be resolved before the PR
|
||||
can be merged. If the PR is already in review, prefer to wait until review is
|
||||
mostly done before fixing the conflicts. Conflicts should be fixed by way of a
|
||||
merge commit rather than rebasing.
|
||||
|
||||
## Code reviewer guide
|
||||
|
||||
The specific goal for a particular review should always be to ensure that the
|
||||
|
||||
@@ -22,6 +22,9 @@ contributions.
|
||||
- [Main tools](#main-tools)
|
||||
- [Running pre-commit](#running-pre-commit)
|
||||
- [Optional tools](#optional-tools)
|
||||
- [Jujutsu (`jj`)](#jujutsu-jj)
|
||||
- [AI assistants](#ai-assistants)
|
||||
- [Running tests with AddressSanitizer (ASan)](#running-tests-with-addresssanitizer-asan)
|
||||
- [Manually building Clang and LLVM (not recommended)](#manually-building-clang-and-llvm-not-recommended)
|
||||
- [Troubleshooting build issues](#troubleshooting-build-issues)
|
||||
- [`bazel clean`](#bazel-clean)
|
||||
@@ -159,7 +162,7 @@ These tools are essential for work on Carbon.
|
||||
- To upgrade versions of `brew` packages, it will be necessary to
|
||||
periodically run `brew upgrade`.
|
||||
- [Python](https://python.org)
|
||||
- Carbon requires Python 3.9 or newer.
|
||||
- Carbon requires Python 3.10 or newer.
|
||||
- To upgrade versions of pip-installed packages, it will be necessary
|
||||
to periodically run `pipx list --outdated`, then
|
||||
`pipx install -U <package>` to upgrade desired packages.
|
||||
@@ -176,6 +179,10 @@ These tools are essential for work on Carbon.
|
||||
- [gh CLI](https://github.com/cli/cli): Helps with GitHub.
|
||||
- [pre-commit](https://pre-commit.com): Validates and cleans up git
|
||||
commits.
|
||||
- `autoupdate_testdata.py`: Updates expected output for tests.
|
||||
- Usage: `./toolchain/autoupdate_testdata.py [files...]`
|
||||
- This is essential when changes affect compiler output (diagnostics,
|
||||
SemIR, etc.).
|
||||
|
||||
#### Running pre-commit
|
||||
|
||||
@@ -226,18 +233,117 @@ considering if they fit your workflow.
|
||||
[GDB]((/toolchain/docs/debugging.md#debugging-with-gdb)
|
||||
- [clangd](https://clangd.llvm.org/installation): An LSP server implementation
|
||||
for C/C++.
|
||||
|
||||
- To ensure that `clangd` reports accurate diagnostics. It needs a
|
||||
generated file called `compile_commands.json`. This can be generated by
|
||||
invoking the command below:
|
||||
|
||||
```
|
||||
./scripts/create_compdb.py
|
||||
```
|
||||
|
||||
- **NOTE**: This assumes you have `python` 3 installed on your system.
|
||||
|
||||
- [`uv`](https://docs.astral.sh/uv/): A fast Python package manager.
|
||||
- Notably, `uv` supports automatic management of even complex Python
|
||||
dependencies for scripts: https://docs.astral.sh/uv/guides/scripts/
|
||||
- Installation: https://docs.astral.sh/uv/getting-started/installation/
|
||||
|
||||
#### Jujutsu (`jj`)
|
||||
|
||||
[Jujutsu](https://github.com/jj-vcs/jj) is a Git-compatible version control
|
||||
system that can be used instead of or alongside Git. See the
|
||||
[documentation for using Jujutsu with GitHub](https://jj-vcs.github.io/jj/latest/github/)
|
||||
for more information.
|
||||
|
||||
If you use `jj`, you may find the following configuration snippets (added to
|
||||
`jj config path --user`) helpful for your workflow:
|
||||
|
||||
```sh
|
||||
# Clean up untracked or abandoned commits.
|
||||
jj config set --user aliases.abandon-untagged '["abandon", "all() & ~ancestors(@ | bookmarks() | remote_bookmarks())"]'
|
||||
|
||||
# Use Git-style conflict markers, which VS Code can provide merge support for.
|
||||
jj config set --user ui.conflict-marker-style 'git'
|
||||
|
||||
# Produce Git-compatible diff format.
|
||||
jj config set --user ui.diff.format 'git'
|
||||
|
||||
# Automatically add a trailer to commits to indicate that they were AI-assisted.
|
||||
jj config set --user templates.commit_trailers "$(echo -e "'''\n\"Assisted-by: My AI Tool\"'''")"
|
||||
|
||||
# Make `jj bookmark advance` / `jj b a` only move bookmarks that point to
|
||||
# mutable commits, and move them to the most recent non-empty descendant.
|
||||
jj config set --user revsets.bookmark-advance-from 'heads(::to & bookmarks()) & ~immutable_heads()'
|
||||
jj config set --user revsets.bookmark-advance-to 'heads(::@ & ~(description("") & empty() & ~merges()))'
|
||||
```
|
||||
|
||||
<!-- google-doc-style-ignore -->
|
||||
|
||||
As well as this per-repository configuration (added to `jj config path --repo`)
|
||||
describing how your GitHub checkout is configured:
|
||||
|
||||
```sh
|
||||
# Automatically track all remote bookmarks.
|
||||
jj config set --repo remotes.origin.auto-track-bookmarks '*'
|
||||
|
||||
# `trunk()` is a jj builtin, but defaults to `main@upstream`.
|
||||
jj config set --repo 'revset-aliases."trunk()"' 'trunk@upstream'
|
||||
|
||||
# Treat github.com/carbon-language/carbon-lang as immutable, but treat your fork
|
||||
# as mutable.
|
||||
jj config set --repo 'revset-aliases."immutable_heads()"' 'remote_bookmarks(*, upstream)'
|
||||
```
|
||||
|
||||
<!-- google-doc-style-resume -->
|
||||
|
||||
The above assumes that you have configured the remote name `origin` to refer to
|
||||
your fork and `upstream` to refer to `github.com/carbon-language/carbon-lang`,
|
||||
and will need to be adjusted if you use different remote names.
|
||||
|
||||
#### AI assistants
|
||||
|
||||
When using AI assistants and reviewing terminal commands, some commands which
|
||||
may be helpful and reasonably safe to allowlist (assuming prefix-based
|
||||
allowlisting) are:
|
||||
|
||||
```
|
||||
# Carbon development commands.
|
||||
bazelisk build
|
||||
bazelisk test
|
||||
bazelisk run //toolchain/testing:file_test --
|
||||
clang-format
|
||||
pre-commit run
|
||||
./toolchain/autoupdate_testdata.py
|
||||
|
||||
# Shell commands. Note that these allow reading arbitrary files on your local
|
||||
# file system.
|
||||
cat
|
||||
grep
|
||||
head
|
||||
ls
|
||||
|
||||
# VCS commands.
|
||||
git diff
|
||||
git log
|
||||
git show
|
||||
git status
|
||||
```
|
||||
|
||||
### Running tests with AddressSanitizer (ASan)
|
||||
|
||||
By default, the Bazel build mode for the toolchain does not enable
|
||||
AddressSanitizer (ASan). If you wish to enable ASan for local testing, you must
|
||||
pass the `--config=asan` flag explicitly:
|
||||
|
||||
```shell
|
||||
bazelisk test --config=asan //...
|
||||
```
|
||||
|
||||
Note that our Continuous Integration (CI) infrastructure runs a separate
|
||||
configuration for ASan to ensure test coverage without slowing down the default
|
||||
test cycle.
|
||||
|
||||
### Manually building Clang and LLVM (not recommended)
|
||||
|
||||
We primarily test against [apt.llvm.org](https://apt.llvm.org) and Homebrew
|
||||
|
||||
@@ -11,6 +11,8 @@ import Core library "range";
|
||||
import library "io_utils";
|
||||
|
||||
class Terrain {
|
||||
impl as Core.UnformedInit {}
|
||||
|
||||
fn Read() -> Terrain {
|
||||
returned var me: Terrain;
|
||||
for (y: i32 in Core.Range(43)) {
|
||||
|
||||
@@ -24,6 +24,8 @@ fn PopCount(n: u256) -> i32 {
|
||||
}
|
||||
|
||||
class Reachable {
|
||||
impl as Core.UnformedInit {}
|
||||
|
||||
fn Make(terrain: Terrain) -> Reachable {
|
||||
returned var me: Reachable;
|
||||
var next: u256 = 1;
|
||||
|
||||
@@ -11,6 +11,8 @@ import library "day10_common";
|
||||
import library "io_utils";
|
||||
|
||||
class PathsToTop {
|
||||
impl as Core.UnformedInit {}
|
||||
|
||||
fn Make(terrain: Terrain) -> PathsToTop {
|
||||
returned var me: PathsToTop;
|
||||
for (y: i32 in Core.Range(43)) {
|
||||
|
||||
@@ -11,6 +11,8 @@ import library "day11_common";
|
||||
import library "io_utils";
|
||||
|
||||
class Digits {
|
||||
impl as Core.UnformedInit {}
|
||||
|
||||
fn Make() -> Digits {
|
||||
returned var me: Digits;
|
||||
for (digit: i32 in Core.Range(10)) {
|
||||
|
||||
@@ -11,6 +11,8 @@ import Core library "range";
|
||||
import library "io_utils";
|
||||
|
||||
class Map {
|
||||
impl as Core.UnformedInit {}
|
||||
|
||||
fn Read() -> Map {
|
||||
returned var me: Self;
|
||||
for (y: i32 in Core.Range(140)) {
|
||||
@@ -32,6 +34,8 @@ class Map {
|
||||
}
|
||||
|
||||
class DisjointSetForest {
|
||||
impl as Core.UnformedInit {}
|
||||
|
||||
fn Make() -> DisjointSetForest {
|
||||
returned var me: Self;
|
||||
for (i: i32 in Core.Range(140 * 140)) {
|
||||
|
||||
@@ -23,6 +23,8 @@ fn Euclid(a: i64, b: i64) -> {.m: i64, .n: i64, .gcd: i64} {
|
||||
}
|
||||
|
||||
class Machine {
|
||||
impl as Core.UnformedInit {}
|
||||
|
||||
fn Read() -> Machine {
|
||||
returned var me: Machine;
|
||||
// "Button A: X+"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user