Compare commits

...
Author SHA1 Message Date
Chandler Carruth 733b76efea Add a permissions restriction
Assisted-by: Antigravity with Gemini
2026-04-24 02:09:42 +00:00
Richard Smith 69d745c6d7 Don't allow merging PRs with the dependent label. 2026-04-22 20:15:37 +00:00
Chandler Carruth d6a741f208 Add bootstrapping flags to the build system (#7084)
This takes the bootstrap support that was added and makes it available
under convenient user-facing flags for while we're doing development.

For example, to build a bootstrap compiler and use it to build and run
the tests under `//common/...` you can now use:

```
bazel test --//:bootstrap_stage=1 --//:bootstrap_exec_config=true //common/...
```

This will use the stage1 bootstrap compiler, and it will build that
compiler in the exec config (so it is optimized and the above even works
when cross-building with Bazel).

Assisted-by: Antigravity with Gemini
2026-04-21 00:59:10 +00:00
Dana Jansens 1e3906177c Update the name of the bazel target to build the nightly tarball (#7080)
The target was renamed in `82fad290285baf9763132a13b1f73de1e7919074`
from `//toolchain/install:carbon_toolchain_tar_gz_rule` to
`//toolchain/install:carbon_toolchain_tar_gz`
2026-04-20 17:59:55 +00:00
Dana Jansens 5e2f693db1 Preserve ErrorInst in TryGetTypeIdForTypeConstantId (#7079)
An ErrorInst::ConstantId constant can be used as a type, and should
result in an ErrorInst::TypeId
2026-04-20 17:11:53 +00:00
David BlaikieandGeoff Romer 1cc699ddda Make heterogenous hash table lookup opt-in (#6950)
This still only works if the hash of the distinct types are identical
(so it still doesn't address the derived pointer v base pointer case -
well, not in the way we would want to address it, we could use this
change to make derived pointer and base pointer not compare equal, but
that's not very ergonomic)

I think in a follow up maybe I can use a `TranslatingKeyContext` to
translate `Derived*` to `Base*` in general.

No test coverage for this change, since it's a no-compile situation and
we don't seem to generally do no-compile tests.
    
Discovered while working on #6940

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2026-04-18 01:32:39 +00:00
Geoff Romer ad0a4ea8a4 Restructure action-dependence APIs (#7074)
- Rename `ActionIsDependent` to `ActionIsPerformable` (with negated
meaning), because that name is more concrete and, um, actionable.
- Replace `OperandIsDependent` with `OperandDependence`, which returns a
`ConstantDependence` instead of a bool. We need this additional
generality for handling form actions, where we sometimes need to ask
whether something has _any_ dependence, not just whether it has template
dependence.
2026-04-17 19:03:21 +00:00
Richard Smith f91990aa87 Override Clang class layout for Carbon class types. (#7071)
Use the Carbon-determined size and alignment for Carbon-defined classes,
rather than allowing Clang to work one out for itself using the C++
rules.
2026-04-17 00:03:29 +00:00
Geoff Romer e7626f46cc Get rid of AddPatternInst (#7075)
Instead, use the inst category to select the right block stack. This
simplifies the API for adding insts, and in subsequent changes it will
enable certain inst kinds like `SpliceInst` to seamlessly function as
either procedural insts or pattern insts.
2026-04-16 23:31:31 +00:00
Geoff Romer af04d08965 Track declared form with an InstId instead of a ConstantId. (#7072)
This is mainly in order to track a location associated with the form.
2026-04-16 23:14:31 +00:00
Richard Smith a6061d975c Compute type layouts in SemIR / Check (#7066)
Instead of allowing lower to pick whatever type layout it desires,
compute the layouts of types as part of completing the type, and make
lower build types that match that representation.

For now we assume that all pointers are 64-bit, since we don't have
access to target information. We allow tail padding reuse for structs
and tuple types (and by extension, for classes, since they use structs
as their object representation), but not for arrays.

In order to build matching LLVM types, we create LLVM packed structs
where necessary, and we insert inter-field padding on the end of the
previous field so that GEP indexes still always match Carbon's
ElementIndexes.

We don't yet use the computed alignment much in LLVM IR generation -- in
particular, `alloca`s, `load`s, and `store`s should probably use the
computed type alignment, but don't.

Assisted-by: Gemini via Antigravity
2026-04-16 22:37:48 +00:00
Chandler Carruth 896338d281 Remove duplicate file and fix to include the bin directory (#7073)
Noticed this when testing the Carbon toolchain with a more complex
environment, don't have any way to observe this at the moment in Bazel
though.

Assisted-by: Antigravity with Gemini
2026-04-16 21:42:06 +00:00
Chandler Carruth d8fe95cccb Test and fix make-variable expansion in our toolchains (#7070)
This worked correctly in the system Clang toolchain, but was not
configured correctly in the Carbon toolchains. The test is designed to
let us cover all of these.

Assisted-by: Antigravity with Gemini
2026-04-16 21:08:37 +00:00
Geoff Romer df33276f6b Revert accidental change from #7063 (#7069) 2026-04-16 20:31:54 +00:00
Chandler Carruth 327cb2396a Add a Bazel skill (#7061)
Hopefully this significantly reduces how often agents try to run `bazel`
directly without repeatedly including that in prompts. Also tried to
generally give useful skills for building, testing, and running things.

Also added a specific admonition to the `AGENTS.md` as there is a chance
that agents don't think they need to look at any skills for "standard"
build system commands like `bazel`, as those are "trivial". It seems
like a small chunk of context to spend to avoid churning with bad build
commands.

Assisted-by: Antigravity with Gemini
2026-04-16 18:58:34 +00:00
Richard Smith 1d5113649b Allow non-constant calls to constexpr functions. (#7067)
These turn up frequently in real-world code, for example when converting
a mutable global `Cpp.std.string_view` to a `Cpp.std.string`. Only
reject a non-constant call if the callee is `consteval`, not if it's
`constexpr`.
2026-04-16 17:10:48 +00:00
Chandler Carruth cdfa57f230 Pull in a fix to the new compile commands system (#7068)
This pulls in my PR:
https://github.com/wolfd/bazel-compile-commands/pull/3

Fixes #7065

Assisted-by: Antigravity with Gemini
2026-04-16 16:58:29 +00:00
Richard Smith 46f46a538d Preliminary reverse interop support for base classes. (#7059)
Create a Clang AST representation of the base specifier.
2026-04-16 00:29:40 +00:00
Nicholas Bishop 114cf401c2 Support C++ calling Carbon functions with non-() return type (#7051)
For calling non-`()` functions, the Carbon->Carbon thunk now takes an
extra reference parameter and writes the target function's return value
out to that parameter. (At the SemIR level this is how returns already
work, but adding this extra reference parameter is needed so that the
function is lowered correctly.) The C++ thunk now creates a local
variable to be initialized by the Carbon thunk, and then returns that
value to the original C++ caller.
2026-04-16 00:29:38 +00:00
rit 7c94878c10 fixed a crash when lowering a ref return initialized by value expression (#7049)
Restructured `else-if` into `InitForm` case so that diagnostics are
emitted correctly and does not lead to a crash.
Conversation:
https://discord.com/channels/655572317891461132/1052653651895779359/1492278198405431397

Closes #6891
2026-04-15 20:52:56 +00:00
Chandler Carruth 82fad29028 Switch to conventionally use a name parameter for a macro (#7053)
This is important to allow tools like buildozer to manipulate macro
invocation.
2026-04-15 05:18:25 +00:00
Chandler CarruthandDana Jansens 26ddada3ae Switch from Bazel platforms to build settings (#7052)
The runtimes and bootstrap Bazel logic was previously built around
defining custom Bazel platforms constrained with `constraint_settings`.
The use of platforms added significant complexity, including the need to
"save" and "restore" the original platform, and other complexity
stemming from changing the platform as a whole.

This PR switches to use the simpler tool of build settings, and
`target_settings` on the toolchain rather than platform compatibility.
This remove the entire need to save and restore the platform, and also
generally simplifies things.

This PR also fixes some bugs in the bootstrap that were hidden by the
use of platforms, such as the need to carefully manage the different
inputs to the runtimes build so that generated inputs pick up the
correct exec configuration -- the exec transition happened to do this
"automatically", but it seems better to handle explicitly. And it cleans
up an extraneous copy of `carbon_runtimes.bzl` that snuck in somehow.

Assisted-by: Antigravity with Gemini

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-04-14 21:52:48 +00:00
Geoff Romer bab35c114e Remove the leading /proc/self/cwd/ from file paths in the debug info. (#7060)
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.
2026-04-14 19:34:32 +00:00
Chandler Carruth 96529e16bd Fully switch to the new compilation database system (#7057)
This has been working really well for me, is incredibly faster than the
other approach, and some commits continue to hit bugs in the old system
where files that aren't even going to be run through `clangd-tidy` end
up tripping up the execution. Hopefully all of that is resolved with the
new version.
2026-04-14 13:41:33 +00:00
Richard Smith 43867a678b Reverse interop support for type aliases. (#7043)
Allow any type that has a mapping from Carbon to C++ to be exposed to
C++ via name lookup. This also exposes the logic to export Carbon
classes to C++ to apply during type mapping, which gives very slight
support for passing Carbon types to C++ functions from Carbon, but not
really enough to sensibly test yet.

Depends on #7042.
2026-04-14 00:18:33 +00:00
Richard Smith 5b1de7633c Use the raw import ID, not the tagged ID, as an array index. (#7058)
Previously we'd create a *huge* array here as the tagged ID produced a
very large index value, and spend multiple seconds allocating it and
filling it with zeroes the first time `GetCppLocation` was called.

Reduces test runtime from 26s -> 6s wall time, 450s -> 320s total time
on my machine for `-c dbg`.
2026-04-13 23:53:25 +00:00
Richard Smith f31e1685fd Only export each class or namespace to C++ once. (#7042)
Instead of exporting a class or namespace each time a new C++ name
lookup discovers it, track that we have exported the entity on its name
scope, and if a new name lookup finds the same entity, produce the same
clang declaration.
2026-04-13 19:43:44 +00:00
Christopher Di BellaandDana Jansens 3cdb159067 consistently uses the caller's specific to get the callee's pattern type id (#7036)
`DoVarPreWorkImpl` was provided an incorrect pattern type while trying
to match `var` parameters, which caused the toolchain to crash in
`Convert`. This commit changes `DoVarPreWorkImpl`'s API so it derives
the pattern type from the work item's pattern ID, rather than relying on
an external source.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-04-13 17:41:54 +00:00
Dana Jansens 12d7574636 Include extended named constraints in the type of .Self for a where clause (#7048)
The `.Self` should see all extended constraints from the LHS of the
`where`, which is both interfaces and named constraints.
2026-04-10 18:05:22 +00:00
Dana JansensandRichard Smith cc5a42691e Add where T impls X constraints into the FacetTypeInfo (#7038)
This makes them part of the identified facet type, and we can see the
constraints as part of stringify and format output.

But this does not do enough to make them useful yet: Any `T impls X`
constraint must contain a reference to `.Self` somewhere. And `.Self`
references do not get substituted, so neither `T(.Self) impls X` and `T
impls X(.Self)` will match against an incoming facet value derived from
an `impl T(U) as X` or `impl T as X(U)`, since `U` and `.Self` are never
the same thing until `.Self` can be substituted.

Now that impl lookup runs into facet values containing `.Self` (a
symbolic binding), such as in `C(.Self)`, we were crashing assuming the
type of `.Self` is a FacetType, but it can be `type` in the case of
`type where C(.Self) impls...`. Instead, use an empty facet type for the
type of `.Self` so it is always a facet. This assists with substituting
other facets into it, without having to insert an extra FacetAccessType.
`MakePeriodSelfFacetValue()` now enforces this requirement.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-04-10 14:29:36 +00:00
Chandler Carruth 19efec93be Fix missing runtimes file in the installation (#7044)
Fixes #7031

Also switches the previous symlinks test to be a more full integration
test. While a bit slow, it does seem worthwhile to have something that
tests things end-to-end, both with the prebuilt runtimes and the
on-demand runtimes. This test is already reasonably well separated from
the rest of the toolchain so incremental development shouldn't be
negatively impacted. And since we turned off ASan by default, it isn't
completely infeasibly expensive.

Assisted-by: Antigravity with Gemini
2026-04-09 21:49:19 +00:00
Chandler Carruth 3db691ecef Add ASan to post-merge CI and improve the action structure for GitHub (#7012)
Note that this will require changing the branch protections to use new
names for all of the checks and be somewhat disruptive. There aren't any
really good ways I could find of fixing this. Some options that I
explored:

- Have a single `pre-merge` workflow file that contains all of the other
workflows, splitting as much of the logic as we can into re-usable
files. This would basically merge testing, `pre-commit`, and
`clangd-tidy` checking into a single workflow file. However, it would
also delay the pre-commit suggestions action to only run once _all_ of
these finish, rather than as soon as pre-commit finishes.

- Serialize `pre-commit` and the rest of `pre-merge` to get the effect
of the above option but without the downside. Instead, the downside
would be serializing some of our actions.

- Have a single `pre-merge` workflow that triggers whenever any of the
other workflows completes, and have it check whether all the others have
completed. It will fail until it reaches that point. This requires
passing in GitHub keys to the workflow so that it can check the status
of other checks, and documentation online seems to indicate it is
sometimes flaky, I assume because of racing triggers of events or
check-status not being guaranteed consistent in the queries.

- Have a single `pre-merge` workflow that polls, waiting for all the
other workflows to finish using some Python logic. This requires
building and maintaining code to poll GitHub, keys to authorize that
polling, and handling all of the failure modes of a polling operation --
timeouts, network issues, etc.

Maybe there are others, but not sure what they look like. Suggestions
welcome here.

I'm hesitant to either delay the pre-commit suggestions or serialize
pre-commit execution. And the complexity or flakiness of the other two
options seem worse than having to re-work the branch protections each
time the naming here changes. But interested if folks think a different
direction would be better.

Assisted-by: Antigravity with Gemini
2026-04-09 20:37:23 +00:00
Dana JansensandChandler Carruth 6cc08ae6e6 Remove SymbolicBinding step in TypeIterator (#7039)
TypeIterator has both SymbolicType and SymbolicBinding and these overlap
in their meaning. Clarify the API by removing SymbolicBinding and just
using SymbolicType for `SymbolicBinding` insts and when they are
converted to `type` to make a `SymbolicBindingType` inst. Add the
EntityNameId to the SymbolicType for when it is available, when the
instruction is just a simple reference to a binding.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2026-04-09 13:25:16 +00:00
Richard Smith ab977ee04d Bump vscode extension to 0.0.8. (#7041) 2026-04-09 00:06:39 +00:00
Richard Smith be0c07dc7e Give Carbon -> C++ thunks internal linkage. (#7040)
Also declare them `inline` since we're putting the `always_inline`
attribute on them. Use the `internal_linkage` attribute rather than
`SC_Static` since it's a more precise mechanism and matches what we do
for static member functions in reverse interop (where `SC_Static` means
something else and would not give the function internal linkage).
2026-04-08 21:14:30 +00:00
Dana Jansens b79d9adeca Avoid crashing in custom witness for FacetTypes and symbolic object representations (#7033)
The type must be complete to look for a witness for Destroy. Do this
check through type completion rather than just checking to see if the
ClassInfo says the definition is closed, since completing the type has
side effects (resolves the self specific definition).

Then look for whether the class is abstract through the CompleteTypeInfo
instead of just looking at the inheritance type on ClassInfo, like type
completion does.

Last, FacetTypes are trivially destroyed just like TypeType.
2026-04-08 20:09:03 +00:00
Richard Smith b74e0d1260 Superficial support for exporting complete class types to C++. (#7029)
We don't yet populate the bases or fields, so the class types show up as
empty classes in C++ for now. But we do allow calls to static member
functions.
2026-04-08 19:29:25 +00:00
dependabot[bot] 9f1a0c816c Bump addressable from 2.8.7 to 2.9.0 in /website in the bundler group across 1 directory (#7037)
Bumps the bundler group with 1 update in the /website directory:
[addressable](https://github.com/sporkmonger/addressable).

Updates `addressable` from 2.8.7 to 2.9.0
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md">addressable's
changelog</a>.</em></p>
<blockquote>
<h2>Addressable 2.9.0 <!-- raw HTML omitted --></h2>
<ul>
<li>fixes ReDoS vulnerability in Addressable::Template#match (fixes
incomplete
remediation in 2.8.10)</li>
</ul>
<h2>Addressable 2.8.10 <!-- raw HTML omitted --></h2>
<ul>
<li>fixes ReDoS vulnerability in Addressable::Template#match</li>
</ul>
<h2>Addressable 2.8.9 <!-- raw HTML omitted --></h2>
<ul>
<li>Reduce gem size by excluding test files (<a
href="https://redirect.github.com/sporkmonger/addressable/issues/569">#569</a>)</li>
<li>No need for bundler as development dependency (<a
href="https://redirect.github.com/sporkmonger/addressable/issues/571">#571</a>,
<a
href="https://github.com/sporkmonger/addressable/commit/5fc1d93">5fc1d93</a>)</li>
<li>idna/pure: stop building the useless <code>COMPOSITION_TABLE</code>
(removes the <code>Addressable::IDNA::COMPOSITION_TABLE</code> constant)
(<a
href="https://redirect.github.com/sporkmonger/addressable/issues/564">#564</a>)</li>
</ul>
<p><a
href="https://redirect.github.com/sporkmonger/addressable/issues/569">#569</a>:
<a
href="https://redirect.github.com/sporkmonger/addressable/pull/569">sporkmonger/addressable#569</a>
<a
href="https://redirect.github.com/sporkmonger/addressable/issues/571">#571</a>:
<a
href="https://redirect.github.com/sporkmonger/addressable/pull/571">sporkmonger/addressable#571</a>
<a
href="https://redirect.github.com/sporkmonger/addressable/issues/564">#564</a>:
<a
href="https://redirect.github.com/sporkmonger/addressable/pull/564">sporkmonger/addressable#564</a></p>
<h2>Addressable 2.8.8 <!-- raw HTML omitted --></h2>
<ul>
<li>Replace the <code>unicode.data</code> blob by a ruby constant (<a
href="https://redirect.github.com/sporkmonger/addressable/issues/561">#561</a>)</li>
<li>Allow <code>public_suffix</code> 7 (<a
href="https://redirect.github.com/sporkmonger/addressable/issues/558">#558</a>)</li>
</ul>
<p><a
href="https://redirect.github.com/sporkmonger/addressable/issues/561">#561</a>:
<a
href="https://redirect.github.com/sporkmonger/addressable/pull/561">sporkmonger/addressable#561</a>
<a
href="https://redirect.github.com/sporkmonger/addressable/issues/558">#558</a>:
<a
href="https://redirect.github.com/sporkmonger/addressable/pull/558">sporkmonger/addressable#558</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/sporkmonger/addressable/commit/0c3e8589b23d4402903a9b4e1fdeba4e43c52ca4"><code>0c3e858</code></a>
Revving version and changelog</li>
<li><a
href="https://github.com/sporkmonger/addressable/commit/91915c1f7aafa3e2c9f42e2f4e21d948c7a861b8"><code>91915c1</code></a>
Fixing additional vulnerable paths</li>
<li><a
href="https://github.com/sporkmonger/addressable/commit/a091e39ff02fc321b21dea3a0df585bef2ba3744"><code>a091e39</code></a>
Add many more adversarial test cases to ensure we don't have any ReDoS
regres...</li>
<li><a
href="https://github.com/sporkmonger/addressable/commit/463a819665a3b85ce5ce894c90bd7bfa3b9d2e15"><code>463a819</code></a>
Regenerate gemspec on newer rubygems</li>
<li><a
href="https://github.com/sporkmonger/addressable/commit/0afcb0b9672bee301e5e96ed850fec05b2fcabb0"><code>0afcb0b</code></a>
Improve from O(n^2) to O(n)</li>
<li><a
href="https://github.com/sporkmonger/addressable/commit/c87f768f22ab00376ed2f8cb106f59c9d0652d3a"><code>c87f768</code></a>
Fix a ReDoS vulnerability in URI template matching</li>
<li><a
href="https://github.com/sporkmonger/addressable/commit/0d7e9b259fb0940d1a85064b04f678a7984409a5"><code>0d7e9b2</code></a>
Fix links for 2.8.9 in CHANGELOG (<a
href="https://redirect.github.com/sporkmonger/addressable/issues/573">#573</a>)</li>
<li><a
href="https://github.com/sporkmonger/addressable/commit/e2091200b31553f19248eb871f071852409796f8"><code>e209120</code></a>
Update version, gemspec, and CHANGELOG for 2.8.9 (<a
href="https://redirect.github.com/sporkmonger/addressable/issues/572">#572</a>)</li>
<li><a
href="https://github.com/sporkmonger/addressable/commit/387587492b6536748ed12a11c3fdb44a48885f28"><code>3875874</code></a>
Reduce gem size by excluding test files (<a
href="https://redirect.github.com/sporkmonger/addressable/issues/569">#569</a>)</li>
<li><a
href="https://github.com/sporkmonger/addressable/commit/3e57cc6018f94231aabb47fd341acd1b40f1e71a"><code>3e57cc6</code></a>
CI: back to <code>windows-2022</code> for MRI job</li>
<li>Additional commits viewable in <a
href="https://github.com/sporkmonger/addressable/compare/addressable-2.8.7...addressable-2.9.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=addressable&package-manager=bundler&previous-version=2.8.7&new-version=2.9.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/carbon-language/carbon-lang/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-08 19:05:36 +00:00
Geoff Romer 6f02354d62 Fix malformed split (#7035) 2026-04-08 00:31:43 +00:00
Nicholas Bishop 0635f4628f Add support for C++ calling Carbon functions with parameters (#7024)
This works by generating two thunks, one in C++ and one in Carbon. For
example, given this input:
```c++
// Carbon:
fn Callme(f: f32) {}

// C++:
void F() {
  // This will call `Callme__cpp_thunk`
  Carbon::Callme(1.0);
}
```

These functions are generated:
```c++
// Carbon:
fn Callme__carbon_thunk(ref f: f32) {
  // Call the target function.
  Callme(f);
}

// C++:

// C++ declaration for the Carbon thunk.
void Callme__carbon_thunk(float& f);

void Callme__cpp_thunk(float f) {
  // Call the Carbon thunk with args passed by reference.
  Callme__carbon_thunk(f);
}
```

For now, all arguments are passed by reference, even if they are simple
types like pointers or i32.

Functions with non-void return types are not supported yet.
2026-04-07 23:25:57 +00:00
Dana Jansens d1dc8e820d Resolve the specific definition for a function that is evaluated (#7034)
The function body may make use of values from the specific, so the
specific definition must be resolved before the function is evaluated.
2026-04-07 21:53:54 +00:00
Dana Jansens e1f30669af Remove TODO in impl lookup for discarding unused witnesses (#7032)
In #6972 we stopped finishing instructions added just for EvalOrAddInst,
which prevents adding the instruction to the containing generic eval
block.
2026-04-07 18:11:08 +00:00
Dana Jansens f483a28f2f Refactor WhereExpr evaluation into smaller helper functions (#7006)
This splits off the functionality to handle the base facet type,
rewrites, and impls constraints into separate functions.

We use the Context instead of EvalContext throughout, as the goal is to
move this code to EvalConstantInst in time. That means we do not apply
specifics to the functions in the requirements inst block. That is fine
because WhereExpr never evaluates to an WhereExpr, so this instruction
never survives as a constant value long enough to be re-evaluated with a
specific applied to it.
2026-04-07 13:52:56 +00:00
Richard Smith cc4fd39238 Support round-tripping entities through C++ and Carbon. (#7022)
Use the same C++ -> Carbon map for both interop directions, and when
importing an entity from Carbon -> C++, check whether it was originally
a C++ entity and if so return the original.

Assisted-by: Gemini via Google Antigravity
2026-04-07 08:10:21 +00:00
Chandler Carruth 013a417ea5 Add the static keyword to various syntax highlighting (#7026)
This follows #7016 which suggests using `static var` for non-instance
class data members.

Assisted-by: Antigravity with Gemini
2026-04-06 19:32:24 +00:00
Chandler Carruth 8fd4156616 Update tree_sitter for the new self syntax and static var (#7025)
This implements p7016 for tree_sitter. It also updates the build and
source file to allow this to build successfully and documents how to
successfully run these tests with Bazel given that it is fundamentally
not hermetic.

Assisted-by: Antigravity with Gemini
2026-04-06 19:31:54 +00:00
Richard Smith 05ba1d7356 Add a conversion impl from T* to const T* (#7010)
This is already allowed as a builtin conversion, but the impl allows the
generics system to know about it, so that conversions like
`Optional(T*)` to `Optional(const T*)` are allowed. This in turn allows
a C++ `T*` to be implicitly converted to a C++ `const T*` in Carbon
code.
2026-04-03 22:07:53 +00:00
Richard Smith 8e0d856725 Improve InPlaceInitializing conversion. (#7021)
Fix some situations where we'd drop the storage argument when building
an in-place initializing expression. We now guarantee that an expression
with the in-place initializing category always has a storage argument.
2026-04-03 21:28:54 +00:00
Richard SmithandGeoff Romer ea409f7cbf Fix crash lowering call to generic function with concrete type in signature (#7009)
When a function call appears in a generic, and calls another generic
that has a concrete type in its call-site signature, that concrete type
will be completed only in the file that contains the call. The generic
containing the call won't require completeness to be checked again when
forming a specific call, because the type was concrete. This means that
when lowering the call instruction, there is no single file that is
guaranteed to contain complete types for all of the callee's parameters
-- the file containing the specific callee won't necessarily have
completed the concrete parts of the signature, and the files containing
the definition and call won't necessarily have completed the symbolic
parts of the signature.

To handle this, look at both versions of the function when building its
lowered signature -- the version that we saw when forming the `call`
instruction and the version corresponding to the concrete, specific
callee, and combine information from both to form the LLVM function
type.

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2026-04-03 21:24:00 +00:00
Chandler Carruth fed9e8c878 Create skills for using the gh tool (#7019)
This covers basic usage and using it to make API calls to GitHub. It
also works to establish some reasonable safety guards to avoid
inappropriate commands.

Also introduces a skill specifically for ingesting the content in GitHub
issues using the command line tool. This is especially useful as
otherwise agents may try to browse the web version of an issues that is
significantly slower and harder to ensure the agent correctly gets all
of the context into its window and is able to leverage it.

This also disables the Google documentation style checking for agent
skills, as we want to instead try to follow the conventions, phrasing,
and other patterns that map best for agents' training sets. For example,
this avoids replacing `repo` with `repository` and avoids replacing
`e.g.` with `for example`. While these replacements make lots of sense
for our human-facing documentation, the agent-facing docs probably
benefit from being terse and using the exact patterns that agents are
trained on.

Assisted-by: Antigravity with Gemini
2026-04-03 20:35:39 +00:00
Dana JansensandChandler Carruth 451b50a3ad Add storage for <type> impls <facettype> in the FacetTypeInfo (#7005)
We don't yet actually add any in check, but this adds the storage for
them, and capabilities to import them, evaluate them, substitute into
them with specifics, name them, format them, and stringify them.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2026-04-03 00:19:57 +00:00
rit 912825feaf Add basic test for lowering choice value acquisition (#7014)
Added test for lowering choice value acquisition. Before PR #6992 the
code in issue #6862 would crash/assert saying the instruction
`AcquireValue` is not concrete. I added this test as the fix did not
have one to test this particular case.
2026-04-03 00:01:21 +00:00
Richard Smith 81ed4d829d Perform CppThunkRef conversion as part of category conversion. (#7020)
Instead of recursing back into Convert, make CppThunkRef conversion just
add an extra step to category conversion, performing a copy conversion
followed by an ephemeral reference binding conversion.
2026-04-02 23:39:25 +00:00
Jon Ross-Perkinsandjonmeow 9266ced4e3 Improve CanDestroyType to handle remaining cases (#6943)
This is only fixing the decision about *whether* to produce a witness.
Implementation of the witness is still a TODO, though where a body is
generated, it should also precisely reflect where one _needs_ to be
generated.

Note the tests:

- toolchain/lower/testdata/function/generic/import_core_witness.carbon
- toolchain/lower/testdata/function/generic/import_unused_def.carbon

These tests can probably be produced _without_ Core.Destroy, but I found
the essence of them while trying to build //examples with Core.Destroy
and a simpler minimization wasn't striking me.

Assisted-by: Google Antigravity with Gemini

---------

Co-authored-by: jonmeow <jperkins@google.com>
2026-04-02 22:54:58 +00:00
Dana Jansens 1fa7a64cd4 Add missing named constraints and self in facet type debugger dump (#7018) 2026-04-02 20:50:59 +00:00
Dana Jansens 562b423830 Always dump summaries (single line output) on bulleted details lines (#7017)
The debugger dump format looks something like

```
id: summary
 - detail 1
 - detail 2
```

But if the detail is a full Dump of some other id, then the details
start to combine and get confusing. For instance if you Dump an
interface id as the detail, you get

```
id: summary
  - interface id: summary
  - complete: yes  <-- about the interface
  - detail 2  <-- not about the interface
```

This mixes the contents of multiple Dumps and is super confusing. So
introduce DumpFooSummary for everything that is dumped on a bulleted
details line, and always use the summary version in that situation.
2026-04-02 20:19:57 +00:00
Richard Smith 6f0ec37a8b Make C++ enum types impl Core.Copy. (#7013)
Remove special-case handling in conversion logic for C++ enum types,
synthesize a custom witness of `Core.Copy` using the `primitive_copy`
builtin function.
2026-04-02 19:23:42 +00:00
Geoff Romer 0851d657c8 Add comment and test for special case in NameRef lowering (#7008) 2026-04-02 19:13:06 +00:00
Chandler Carruth 07afa07127 Fix missing include for std::log2 (#7015)
Some standard libraries require this include for the code to compile.
2026-04-02 18:27:46 +00:00
Chandler Carruth f7a767a77b Update LLVM (again) to pick up a workaround crashes the compiler when building with ASan (#7011)
Assisted-by: Antigravity with Gemini
2026-04-02 01:23:21 +00:00
Richard Smith be283a0744 Improve handling of incomplete signatures. (#7004)
Assert cleanly if we try to emit a definition or a call of a function
whose signature we were not able to emit exactly. This should make such
issues a lot easier to debug, as we were previously failing in quite
mysterious ways in this case.
2026-04-01 21:49:57 +00:00
Jon Ross-Perkins cd6ab7ce8e Switch jj settings to 'jj config set' because of repo (#7007)
jj moved the repo config outside the repo. The config.toml might exist
as a symlink in older repos (probably migration), but not clean repos.
So, overall, just switching the advice setup to make it a bit more
robust with config locations.

Also adding "trunk" to the repo config.

Assisted-by: Google Antigravity with Gemini
2026-04-01 21:36:56 +00:00
Nicholas Bishop 0075d530b9 Support const eval when calling a C++ thunk (#6947)
This makes it possible to do const eval when calling a constexpr C++
function with params and return types other than 32/64-bit integers.

Most of the new logic is in `MaybeModifyCppThunkCallForConstEval`, which
is called by `MakeConstantForCall`. This checks if the callee is a C++
thunk (using a new `SpecialFunctionKind::CppThunk` variant), and if so
it:
* Changes the callee from the C++ thunk to the thunk's callee
* Remaps parameters that are passed by pointer to the thunk to the
underlying value
* Drops the return value parameter, if present
2026-04-01 21:34:41 +00:00
Richard SmithandJon Ross-Perkins 5b7c908e8b Add documentation for setting up jj b a. (#6996)
This gives a setup where `jj b a` / `jj bookmark advance` can reliably
be used to advance a bookmark for a github pull request, without
advancing other bookmarks such as `trunk` or pointing the bookmark at an
empty commit.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2026-04-01 16:46:14 +00:00
Chandler Carruth 2bbcfa5e1a Remove ASan from the default build mode (#7003)
Also increases the default optimization to `-Og` which is likely to give
faster turn-around time which is what we want to optimize for here. This
should also _substantially_ shrink binary sizes, etc.

ASan is still available via `--config=asan`, and is added to the CI
infrastructure. However, my current thought is to only run it after push
rather than in PRs and in the merge queue.
2026-04-01 16:45:53 +00:00
Richard Smith dfac728571 Fix pointer sizes in debug info. (#7002)
The size is in bits, so 8 is an unlikely value. Also, don't hardcode a
size, ask the data layout for it.
2026-04-01 16:35:12 +00:00
Dana Jansens 8f3b057179 Don't qualify names after a . in an ImplWitnessAccess when stringifying (#7000)
After the `.` comes a member of the target of the ImplWitnessAccess.
It's already qualified, don't add the namespace/package to the name.
2026-04-01 15:24:57 +00:00
Dana Jansens 17180558e5 Diagnose where clause without a designator (#6995)
> We don’t allow a where constraint unless it applies a restriction to
the current type. This means referring to some
[designator](https://docs.carbon-lang.dev/docs/design/generics/details.html#kinds-of-where-constraints),
like .MemberName, or
[.Self](https://docs.carbon-lang.dev/docs/design/generics/details.html#recursive-constraints).


https://docs.carbon-lang.dev/docs/design/generics/details.html#constraints-must-use-a-designator
2026-04-01 04:16:35 +00:00
Chandler Carruth 39eac6f277 Update LLVM and fix a couple of API usages (#6998)
The `TemplateArgLocInfo` change is more interesting than usual as this
isn't enforced in the type system, and only shows up as a crash.
2026-04-01 00:00:11 +00:00
Chandler Carruth 2787089247 Switch to a Bazel-based runtimes build, and add bootstrapping (#6989)
This also switches to a more Bazel-based install layout, skipping the
FHS-based synthetic layout. The FHS-based layout is still reconstructed
explicitly when building an installable tar-ball.

The biggest change is to configure the just-built install as a Bazel
toolchain, including allowing it to build its own runtime libraries as
native Bazel libraries. This removes the need for a monolithic runtimes
build, all of that code logic is removed.

This should also pave the way to using the just-built toolchain for
doing a full 3-stage bootstrap. Building the 2nd stage is included here
as it was a particularly effective way to test that the Bazel
integration was fully working. Adding a 3rd-stage check for stability is
future work, but should be pretty easy.

There is a down-side: this uses the busybox to do the runtimes
compilation, which means they will be re-built after ~any change to
Carbon. However, the integration with Bazel should largely pay for this,
and we can continue to factor the tests away from depending on built
runtimes in most cases.

Now that we're building and testing the runtimes more directly, this
surfaced a problem with the layout of runtimes on macOS that is fixed
here. All of the Darwin OSes use a custom layout for their resource
directory compared to other targets. We now model this in both the C++
built runtimes and the Bazel built runtimes.

Assisted-by: Gemini via Antigravity
2026-03-31 23:38:03 +00:00
Richard Smith 3578dd6b91 Avoid copying Lower::FunctionInfo. (#7001)
This type is not small and contains two `SmallVector`s.
2026-03-31 22:58:42 +00:00
Richard Smith 8b59e85b16 Add support for inline Cpp declarations. (#6994)
For #6830, add support for inline C++ fragments as a declaration rather
than as a packaging directive. For now, this uses `inline Cpp
<string-literal>;` as syntax. The prior `import Cpp inline
<string-literal>;` is left alone for the time being. We can decide
separately whether to remove that.

`inline Cpp` requires that there was at least one `import Cpp`. It's not
clear to me if that's the right design long-term, but it seems
reasonable for now.

Assisted-by: Gemini via Google Antigravity
2026-03-31 22:27:43 +00:00
Geoff RomerandRichard Smith 47e9d62fd5 Model thunk call as a pattern match (#6988)
This makes the thunk-call logic more general and more supportable by
reusing the existing pattern-matching logic.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-03-31 21:50:06 +00:00
Geoff Romer f4260feee4 Clean up pattern matching (#6987)
The key changes here are:
- The different kinds of pattern match are represented as alternatives
of a `variant`, instead of enumerators of an `enum`, so that they can
hold their own state instead of having a bunch of conditionally-usable
members of `MatchContext`.
- The public API of `MatchContext` is a `Match` operation that's applied
to a single pattern and scrutinee; the worklist is no longer directly
accessible.
- `Match` has a counterpart `MatchWithResult` that returns the result of
matching the pattern.
- `Context` is now a member of `MatchContext` instead of a parameter to
most of its methods.
2026-03-31 20:38:42 +00:00
Geoff Romer aec2534e9d Fix formatting of compound-type variable declarations in macros (#6997)
By default clang-format interprets function-like macro invocations as
function calls. E.g. the argument of `CARBON_KIND(llvm::ListSeparator*
sep)` is interpreted as an expression, meaning the `*` is an infix
binary operator, so it inserts a space before the `*`. This change
teaches clang-format that `CARBON_KIND(x)` and
`CARBON_ASSIGN_OR_RETURN(x)` rewrite to `x`, which is close enough to
the truth to enable it to format them correctly. See the [clang-format
docs](https://clang.llvm.org/docs/ClangFormatStyleOptions.html#macros)
for details.
2026-03-31 19:41:26 +00:00
Richard Smith 2e0d9dc709 Add syntax highlighting for SemIR. (#6958)
This applies to files named *.semir, but more interestingly also to
Carbon source lines starting `// CHECK:STDOUT:`.

Assisted-by: Gemini 3.1 Pro via Antigravity
2026-03-31 18:49:02 +00:00
Nicholas Bishop 396756c151 Handle Temporary values when const-evaling AcquireValue (#6992)
This will be used for const-evaling functions. Splitting into a separate
commit since it touches a lot of test files, and a couple fail_todo
tests are no longer failing.
2026-03-31 15:50:54 +00:00
Nicholas Bishop bf6a14ac39 Support Temporary constants (#6983)
Evaluate `Temporary` constants to a `Temporary` with the `storage` field
set to `None`.
2026-03-30 19:07:46 +00:00
Dana Jansens 9ed045ec25 Add a link to the docs on testing the toolchain to CONTRIBUTING.md (#6981)
It takes a bit of work to track down instructions on running file tests
and autoupdate. Add a link to them directly from CONTRIBUTING.md, since
all searches start there.
2026-03-28 06:21:14 +00:00
Dana Jansens 2318294eb5 Add tests for name lookup through named constraints (#6979)
Tests combinations of extend and impls in a facet type and inside a
named constraint. Name scopes are only extended if the named constraint
extends an interface, and the facet type extends the named constraint.
2026-03-28 04:15:24 +00:00
Richard Smith d9b901394b Add agent skill for producing toolchain tests. (#6986)
Assisted-by: Gemini via Google Antigravity
2026-03-28 00:48:08 +00:00
Richard Smith 181a592b8c Support for parsing expression patterns (#6977)
When parsing a pattern, if we encounter something that isn't pattern
syntax, try parsing as an expression instead. We only need one-token
lookahead to distinguish pattern syntax from expression syntax.

Track a precedence group through pattern parsing so that we can allow
different kinds of expressions in a top-level pattern (such as the
operand of `let`) and in a nested pattern (such as a subpattern of a
tuple pattern or within grouping parens). For example, we do not allow
`case if ...`, and for now I've chosen to also not allow logical or
relational operators at the top level of a pattern, so `case 1 + 1` is
OK, but `case 1 == 1` and `case true and false` require parentheses.
This decision should be ratified or revisited by a design proposal.

Very basic check support is also provided, only sufficient to form an
`ExprPattern` instruction and nothing beyond that. For now, all pattern
matching against an `ExprPattern` fails with a TODO error. To support
that, I've switched from calling `BeginSubpattern` in the parent handler
of a pattern and `EndSubpatternAs*` in the pattern handler itself to
calling both functions in parent handlers, with `EndSubpattern`
converting an expression into an expression pattern where needed.

Depends on #6976.

Assisted-by: Gemini via Google Antigravity
2026-03-28 00:06:06 +00:00
Nicholas Bishop 1ef35e8299 Fix name mangling for Carbon functions called from C++ (#6984)
Since this requires using the `Mangler` class from `toolchain/check`,
moved it from `toolchain/lower` to `toolchain/sem_ir`.

The mangled name is then attached to the `FunctionDecl` with an
`AsmLabelAttr`.
2026-03-27 22:52:11 +00:00
Richard Smith aa8e96ac72 Fix skill file to parse correctly. (#6985)
The license header needs to go after the YAML in order for it to parse.
2026-03-27 21:46:08 +00:00
Dana Jansens 5503f643c6 Introduce typed-inst accessors for ConstantValueStore (#6980)
Add `InstIs`, `GetInstAs`, and `TryGetInstAs` which act on the
underlying constant instruction in a constant value, to save an explicit
call to `GetInstId`.

```carbon
context.insts().GetAs<InstT>(context.constant_values().GetInstId(const_id))
```
can now be written as simply
```carbon
context.constant_values().GetInstAs<InstT>(const_id)
```

For future work, we might provide `GetInst()` so that
`context.insts().Get(context.constant_values().GetInstId(const_id)` can
be shortened also.
2026-03-27 21:41:04 +00:00
Richard SmithandGeoff Romer 899e54de36 Treat (pattern) as grouping parens. (#6976)
Do not treat it as a 1-tuple pattern as we used to. The design indicates
that `(pattern)` is invalid, but this appears to be an oversight, and
grouping parens appear to be the intended interpretation.

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2026-03-27 21:13:57 +00:00
Jon Ross-Perkins a2ba7f1262 Have Specific track whether regions contain errors (#6982)
This removes some loops in type completion, but is motivated by the
thought that eval probably wants to query it.

Assisted-by: Google Antigravity with Gemini
2026-03-27 19:36:52 +00:00
Jon Ross-Perkins 2b1fe7c292 Small improvements to RuntimeVerified logic (#6973)
The `NodeKind` vs `InstKind` naming seems to be an old mistake.

I'm cleaning up to specific `ImportRef` handling after verifying those
were the only actual cases where inst kinds won't be compatible (or are
always compatible, depending on your point of view).

Assisted-by: Google Antigravity with Gemini
2026-03-27 19:32:12 +00:00
Dana Jansens a0416a1250 Don't finish the non-canonical instruction created in EvalOrAddInst (#6972)
EvalOrAddInst has to create a non-canonical instruction for evaluating a
few typed insts, such as LookupImplWitness which uses an InstId to
provide a location for diagnostics.

But the output of the function is a ConstantId. We do not have access to
the non-canonical InstId after the function returns. But if the constant
value was symbolic, it was being attached to the inst, and the inst
would be added to the eval block of the enclosing generic. This
needlessly added semir for a symbolic value.

The ConstantId returned by EvalOrAddInst can be used immediately, such
as to evaluate an ImplWitnessAccess. In that case, the final evaluated
result is all we need to keep in semir.

If the ConstantId needs to be replaced by specifics, it is only as part
of some other instruction, since ConstantIds themselves are not modified
by specifics, instructions are. In that case, the canonical instruction
in the constant value would have been added to some other (now symbolic)
instruction, which would be replaced by a specific.

This has no functional change, but it reduces runtime overhead and semir
output for LookupImplWitness and ImplWitnessAccess.
2026-03-27 19:29:34 +00:00
Christopher Di Bella c68c4007ab removes unused parameters from deep stack (#6971)
`best_impl_type_structure` and `best_impl_loc_id` are required to solve
the problem discussed in #6166. We don't address that issue issue yet.
Requiring them to be propagated through any function depending on
`GetFunctionId` is very tedious.

This commit removes them from `GetFunctionId` until we have a clear
design for how they should be used.
2026-03-27 16:59:25 +00:00
cui 1f7d8e4675 Fix ValueStore::GetRawIndex DCHECK to use id.index in diagnostic (#6975)
## Summary

`ValueStore::GetRawIndex` formatted the first `CARBON_DCHECK` with
`index` before the local `index` is declared. Use `id.index` so the
diagnostic matches the condition being checked.

## Test plan

- `bazelisk build //toolchain/base:base` (or `//toolchain/...` as
appropriate)
2026-03-27 12:48:46 +00:00
cui 557039648b Fix FacetTypeInfo::Print guard for self impls named constraints (#6974)
## Summary

Fixes a copy-paste bug in `FacetTypeInfo::Print`: the "self impls named
constraint" section was gated on `self_impls_constraints.empty()`
instead of `self_impls_named_constraints.empty()`.

## Test plan

- `bazelisk build //toolchain/sem_ir:sem_ir` (not run in this
environment; no Bazel installed)
2026-03-27 12:17:12 +00:00
Richard Smith 786e02cb3e clang-format: Turn off trailing commas in braced lists lint. (#6978)
Our codebase does not conform to this rule, and it's causing havoc for
automated tooling that tries to "fix" it.
2026-03-27 12:03:58 +00:00
Geoff Romer 262e24a2a0 Remove indirection through NameRefs when building a thunk call (#6965)
This reduces the SemIR size of the thunk call, and ensures that the
emitted SemIR remains correct if `pretty_name_id` is not populated.
2026-03-26 19:17:05 +00:00
Geoff Romer 18f87e4f79 Include the type in the location of binding insts (#6963) 2026-03-26 18:43:29 +00:00
Nicholas Bishop 85da6cae01 Support calling simple Carbon functions from C++ (#6967)
For now, only functions with no parameters and a `()` return type are
supported.
2026-03-26 18:14:39 +00:00
Dana Jansens d6be20641c Use earlier require decls inside a named constraint to provide witnesses for Self (#6915)
Performing a lookup against `Self` inside the definition of the named
constraint leads to cycles, as described in the document [Self
contradictions in Named
Constraints](https://docs.google.com/document/d/17rn2XmME8o2MM4OJqatSVuMa1iYZ1PAgcNrf0PXR9Q4/edit?tab=t.0).
To prevent those cycles, this change introduces a large refactoring of
impl lookup.

The impl lookup done inside eval is reduced to only performing
monomorphization. That is it:
- Only looks for an provides final witnesses.
- Is not allowed to identify the facet type of the query self.
- Returns either a final witness or None (or an error)

The paths for finding non-final witnesses are now done outside of eval,
directly in the initial `LookupImplWitness()` function. If no final
witness it found through eval, the resulting non-final
`LookupImplWitness` instruction witness is returned. It does not produce
cycles to identify the facet type of query self outside of eval, since
that does not result in repeating the identification when resolving
specifics of the named constraint or require decl.

Move the ArrayStack for Context::require_impls_stack into a new class
which tracks a NamedConstraintId (or InterfaceId) for each frame of
RequireImplsIds, so that in type completion we always can find the
correct frame for a given named constraint which is still being defined,
in order to find the RequireImplsIds in the in-progress definition.
2026-03-26 15:26:56 +00:00
Dana JansensandRichard Smith 4a0c1ddd8e Identification of a named constraint during definition (#6902)
Allow partially identifying a named constraint inside its definition,
and allow the query self in an impl lookup with a non-identified facet
type to be used to provide witnesses from that facet type. This allows
impl lookup on `Self` to find `require` decls that have been written
earlier in the named constraint, so that the named constraint to be used
to provide witnesses from inside its definition.

But disallow an incomplete named constraint from being part of an
identified facet type, to prevent forming facet values that store a
witness set that can be invalidated as the named constraint adds
interfaces to its identified facet type.

This was discussed in open discussion [on
2026-03-12](https://docs.google.com/document/d/1mjllGO3ZCL4qGt9uJHUtcxKoHAGEY7Y999ie4EtBWB8/edit?tab=t.0#heading=h.1dvbbrp5a6t3).

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-03-26 14:24:45 +00:00
Jon Ross-Perkins 5ae3629e49 Change GEMINI.md to AGENTS.md (#6969)
Per https://antigravity.google/changelog, supported in 1.20.5. Also note
https://agents.md

Assisted-by: Google Antigravity with Gemini
2026-03-26 01:00:13 +00:00
Jon Ross-Perkins 25b85a55ae Remove myself from SECURITY.md (#6964)
Assisted-by: Google Antigravity with Gemini
2026-03-26 00:52:16 +00:00
dependabot[bot] 15dabbfb0d Bump requests from 2.32.4 to 2.33.0 in /github_tools in the pip group across 1 directory (#6968)
Bumps the pip group with 1 update in the /github_tools directory:
[requests](https://github.com/psf/requests).

Updates `requests` from 2.32.4 to 2.33.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/psf/requests/releases">requests's
releases</a>.</em></p>
<blockquote>
<h2>v2.33.0</h2>
<h2>2.33.0 (2026-03-25)</h2>
<p><strong>Announcements</strong></p>
<ul>
<li>📣 Requests is adding inline types. If you have a typed code base
that uses Requests, please take a look at <a
href="https://redirect.github.com/psf/requests/issues/7271">#7271</a>.
Give it a try, and report any gaps or feedback you may have in the
issue. 📣</li>
</ul>
<p><strong>Security</strong></p>
<ul>
<li>CVE-2026-25645 <code>requests.utils.extract_zipped_paths</code> now
extracts contents to a non-deterministic location to prevent malicious
file replacement. This does not affect default usage of Requests, only
applications calling the utility function directly.</li>
</ul>
<p><strong>Improvements</strong></p>
<ul>
<li>Migrated to a PEP 517 build system using setuptools. (<a
href="https://redirect.github.com/psf/requests/issues/7012">#7012</a>)</li>
</ul>
<p><strong>Bugfixes</strong></p>
<ul>
<li>Fixed an issue where an empty netrc entry could cause malformed
authentication to be applied to Requests on Python 3.11+. (<a
href="https://redirect.github.com/psf/requests/issues/7205">#7205</a>)</li>
</ul>
<p><strong>Deprecations</strong></p>
<ul>
<li>Dropped support for Python 3.9 following its end of support. (<a
href="https://redirect.github.com/psf/requests/issues/7196">#7196</a>)</li>
</ul>
<p><strong>Documentation</strong></p>
<ul>
<li>Various typo fixes and doc improvements.</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/M0d3v1"><code>@​M0d3v1</code></a> made
their first contribution in <a
href="https://redirect.github.com/psf/requests/pull/6865">psf/requests#6865</a></li>
<li><a href="https://github.com/aminvakil"><code>@​aminvakil</code></a>
made their first contribution in <a
href="https://redirect.github.com/psf/requests/pull/7220">psf/requests#7220</a></li>
<li><a href="https://github.com/E8Price"><code>@​E8Price</code></a> made
their first contribution in <a
href="https://redirect.github.com/psf/requests/pull/6960">psf/requests#6960</a></li>
<li><a href="https://github.com/mitre88"><code>@​mitre88</code></a> made
their first contribution in <a
href="https://redirect.github.com/psf/requests/pull/7244">psf/requests#7244</a></li>
<li><a href="https://github.com/magsen"><code>@​magsen</code></a> made
their first contribution in <a
href="https://redirect.github.com/psf/requests/pull/6553">psf/requests#6553</a></li>
<li><a
href="https://github.com/Rohan5commit"><code>@​Rohan5commit</code></a>
made their first contribution in <a
href="https://redirect.github.com/psf/requests/pull/7227">psf/requests#7227</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/psf/requests/blob/main/HISTORY.md#2330-2026-03-25">https://github.com/psf/requests/blob/main/HISTORY.md#2330-2026-03-25</a></p>
<h2>v2.32.5</h2>
<h2>2.32.5 (2025-08-18)</h2>
<p><strong>Bugfixes</strong></p>
<ul>
<li>The SSLContext caching feature originally introduced in 2.32.0 has
created
a new class of issues in Requests that have had negative impact across a
number
of use cases. The Requests team has decided to revert this feature as
long term
maintenance of it is proving to be unsustainable in its current
iteration.</li>
</ul>
<p><strong>Deprecations</strong></p>
<ul>
<li>Added support for Python 3.14.</li>
<li>Dropped support for Python 3.8 following its end of support.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/psf/requests/blob/main/HISTORY.md">requests's
changelog</a>.</em></p>
<blockquote>
<h2>2.33.0 (2026-03-25)</h2>
<p><strong>Announcements</strong></p>
<ul>
<li>📣 Requests is adding inline types. If you have a typed code base
that
uses Requests, please take a look at <a
href="https://redirect.github.com/psf/requests/issues/7271">#7271</a>.
Give it a try, and report
any gaps or feedback you may have in the issue. 📣</li>
</ul>
<p><strong>Security</strong></p>
<ul>
<li>CVE-2026-25645 <code>requests.utils.extract_zipped_paths</code> now
extracts
contents to a non-deterministic location to prevent malicious file
replacement. This does not affect default usage of Requests, only
applications calling the utility function directly.</li>
</ul>
<p><strong>Improvements</strong></p>
<ul>
<li>Migrated to a PEP 517 build system using setuptools. (<a
href="https://redirect.github.com/psf/requests/issues/7012">#7012</a>)</li>
</ul>
<p><strong>Bugfixes</strong></p>
<ul>
<li>Fixed an issue where an empty netrc entry could cause
malformed authentication to be applied to Requests on
Python 3.11+. (<a
href="https://redirect.github.com/psf/requests/issues/7205">#7205</a>)</li>
</ul>
<p><strong>Deprecations</strong></p>
<ul>
<li>Dropped support for Python 3.9 following its end of support. (<a
href="https://redirect.github.com/psf/requests/issues/7196">#7196</a>)</li>
</ul>
<p><strong>Documentation</strong></p>
<ul>
<li>Various typo fixes and doc improvements.</li>
</ul>
<h2>2.32.5 (2025-08-18)</h2>
<p><strong>Bugfixes</strong></p>
<ul>
<li>The SSLContext caching feature originally introduced in 2.32.0 has
created
a new class of issues in Requests that have had negative impact across a
number
of use cases. The Requests team has decided to revert this feature as
long term
maintenance of it is proving to be unsustainable in its current
iteration.</li>
</ul>
<p><strong>Deprecations</strong></p>
<ul>
<li>Added support for Python 3.14.</li>
<li>Dropped support for Python 3.8 following its end of support.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/psf/requests/commit/bc04dfd6dad4cb02cd92f5daa81eb562d280a761"><code>bc04dfd</code></a>
v2.33.0</li>
<li><a
href="https://github.com/psf/requests/commit/66d21cb07bd6255b1280291c4fafb71803cdb3b7"><code>66d21cb</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/psf/requests/commit/8b9bc8fc0f63be84602387913c4b689f19efd028"><code>8b9bc8f</code></a>
Move badges to top of README (<a
href="https://redirect.github.com/psf/requests/issues/7293">#7293</a>)</li>
<li><a
href="https://github.com/psf/requests/commit/e331a288f369973f5de0ec8901c94cae4fa87286"><code>e331a28</code></a>
Remove unused extraction call (<a
href="https://redirect.github.com/psf/requests/issues/7292">#7292</a>)</li>
<li><a
href="https://github.com/psf/requests/commit/753fd08c5eacce0aa0df73fe47e49525c67e0a29"><code>753fd08</code></a>
docs: fix FAQ grammar in httplib2 example</li>
<li><a
href="https://github.com/psf/requests/commit/774a0b837a194ee885d4fdd9ca947900cc3daf71"><code>774a0b8</code></a>
docs(socks): same block as other sections</li>
<li><a
href="https://github.com/psf/requests/commit/9c72a41bec8597f948c9d8caa5dc3f12273b3303"><code>9c72a41</code></a>
Bump github/codeql-action from 4.33.0 to 4.34.1</li>
<li><a
href="https://github.com/psf/requests/commit/ebf71906798ec82f34e07d3168f8b8aecaf8a3be"><code>ebf7190</code></a>
Bump github/codeql-action from 4.32.0 to 4.33.0</li>
<li><a
href="https://github.com/psf/requests/commit/0e4ae38f0c93d4f92a96c774bd52c069d12a4798"><code>0e4ae38</code></a>
docs: exclude Response.is_permanent_redirect from API docs (<a
href="https://redirect.github.com/psf/requests/issues/7244">#7244</a>)</li>
<li><a
href="https://github.com/psf/requests/commit/d568f47278492e630cc990a259047c67991d007a"><code>d568f47</code></a>
docs: clarify Quickstart POST example (<a
href="https://redirect.github.com/psf/requests/issues/6960">#6960</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/psf/requests/compare/v2.32.4...v2.33.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=requests&package-manager=pip&previous-version=2.32.4&new-version=2.33.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/carbon-language/carbon-lang/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-26 00:40:18 +00:00
Jon Ross-Perkins 25793358c3 Remove jonmeow from pre-commit config (#6966)
Removing this exception before I forget it's there

Assisted-by: Google Antigravity with Gemini
2026-03-25 23:01:20 +00:00
Richard Smith 37b238fa28 Make C++ types impl Core.Default. (#6962)
C++ classes that are default-constructible now implement `Core.Default`
by calling the default constructor.
2026-03-25 21:07:24 +00:00
Jon Ross-Perkins 311670c84a Improve vscode extension ownership (#6960)
Updates the way to access vscode marketplace for publishing. I've
adjusted CarbonInfraBot's attached email to match.

The `#editor-integrations` change is for inconsistent markdown handling
by MS...
https://marketplace.visualstudio.com/items?itemName=carbon-lang.carbon-vscode
looks fine at the moment, but I was seeing rendering as a title -- maybe
a bug that won't be rolled out, but backticks seem fair here.

Assisted-by: Google Antigravity with Gemini
2026-03-25 20:29:09 +00:00
Richard Smith 965879a9a9 Support for in-place return in eval fn. (#6954)
Ignore storage arguments when evaluating a call, like we do for other
kinds of instruction. Create a placeholder constant to represent each
out parameter so that it can be used in the function body to form more
storage arguments.

Assisted-by: Gemini 3.1 Pro via Antigravity
2026-03-25 16:03:44 +00:00
David Blaikie 415cd6f8f0 Reverse Interop: Class declarations (#6955)
Generate class declarations for Carbon classes referenced from C++

Based on #6940, review from eb62070a01
onwards
2026-03-25 04:50:08 +00:00
Richard Smith 7345f4e860 Use a per-file width for the line number gutter. (#6959)
In in the VSCode extension, use the same width for the per-split line
number gutter across all splits. This makes the visuals more consistent.
2026-03-24 21:55:48 +00:00
Richard Smith 29a8b315d3 Improve vscode line number display for test files. (#6957)
In the Carbon vscode extension, in /testdata/ files with file splits,
add a line number column within the split next to the line number column
for the overall file line number.

Assisted-by: Gemini 3.1 Pro via Antigravity
2026-03-24 21:34:03 +00:00
Jon Ross-Perkins e0305684b0 Add MakeVerifiedLocIdAndInst for runtime validation (#6942)
This follows up on a discussion about wanting to use `Any*` inst
clusters to handle boilerplate construction, with the issue that
`UncheckedLoc` use removes validation. Some context is at
https://github.com/carbon-language/carbon-lang/pull/6930#discussion_r2963157428.

This folds in `MakeImportedLocIdAndInst` because the logic is related,
particularly for `LocId` values which are `ImportIRInstId`, and it
eliminates questions of what the right function is to use.

This uncovers an error in the `NodeKind` associated with
`FormBindingPattern`. For now I'm just adding a TODO regarding that.

Assisted-by: Google Antigravity with Gemini
2026-03-24 20:56:44 +00:00
David BlaikieandJon Ross-Perkins 2af5f971da Reverse Interop: Nested namespace support (#6940)
Start recording the clang::DeclContext* -> InstId mapping for use in
later operations.

The test update includes removing the initial fail_* test because I
hadn't thought about the use of namespace aliases as a way to test for
the presence of a namespace without the failure caused by not finding
the thing inside the namespace.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2026-03-24 19:55:25 +00:00
Nicholas Bishop f9e1806c4a Improve diagnostics for EvaluateAsConstantExpr (#6956)
Initialize the `Diag` field `EvalResult` to get notes from clang when
`EvaluateAsConstantExpr` fails, then emit them using clang's diagnostic
infrastructure.

Also set valid source locations in a couple places, otherwise clang's
diagnostics code crashes.
2026-03-24 19:40:09 +00:00
Geoff Romer e0c6800ab3 Reverse nesting structure of parameter patterns (#6930)
See
[here](https://docs.google.com/document/d/1rWcueFwIfZox6GKVGxiUG4cBzjrZ6djXiIDGyJDtrE4/edit?tab=t.0#heading=h.7mi143mdhr2h)
for an overview of the changes and their rationale.

Assisted-by: Gemini 3.1 Pro via Antigravity
2026-03-23 20:38:20 +00:00
a345a74145 prepares vscode extension for open-vsx (#6834)
We'd like to add the Carbon vscode extension to open-vsx.org so it's
available on vscode-compatible projects (see #6766). This commit
updates documentation so that we're recommending the correct package,
and updates our dependencies to ensure users have the latest security
patches.

---------

Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2026-03-23 16:57:54 +00:00
Chandler Carruth 86d05b598b Move the logic for preparing the installed runtimes files to its own (#6946)
directory

This cleans up the `//toolchain/install/BUILD` file and the tree
generally to be more focused on arranging the actual installation rather
than preparing inputs to that installation.

I picke `//toolchain/runtimes` so we can put other runtimes preparation
logic there, but open to any other suggested organization.

There are other runtimes things that would in theory make sense to move
such as the `prebuilt_runtimes` logic, but a subsequent PR will delete
those and so I'm leaving them where they are for now.
2026-03-23 16:39:45 +00:00
cui 7b6e3dfbb0 Fix ReadlinkSlow buffer when lstat reports zero size (#6948)
When the symlink target length from lstat was 0, the code resized the
buffer using status.size() instead of buffer_size, so the first
allocation stayed empty instead of using MinBufferSize. Align the resize
with the buffer_size path used for readlinkat.
2026-03-23 16:28:51 +00:00
Dana Jansens 17657d0586 CHECK if a SymbolicOnly instruction produces a concrete value of the same inst type (#6938)
The contract for SymbolicOnly is that the instructions are only allowed
to have a symbolic value unless their value is a different instruction
type.
2026-03-23 16:15:56 +00:00
dependabot[bot] 3ef991466d Bump flatted from 3.3.2 to 3.4.2 in /utils/vscode in the npm_and_yarn group across 1 directory (#6944)
Bumps the npm_and_yarn group with 1 update in the /utils/vscode
directory: [flatted](https://github.com/WebReflection/flatted).

Updates `flatted` from 3.3.2 to 3.4.2
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/WebReflection/flatted/commit/3bf09091c3562e17a0647bc06710dd6097079cf7"><code>3bf0909</code></a>
3.4.2</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/885ddcc33cf9657caf38c57c7be45ae1c5272802"><code>885ddcc</code></a>
fix CWE-1321</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/0bdba705d130f00892b1b8fcc80cf4cdea0631e3"><code>0bdba70</code></a>
added flatted-view to the benchmark</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/2a02dce7c641dec31194c67663f9b0b12e62da20"><code>2a02dce</code></a>
3.4.1</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/fba4e8f2e113665da275b19cd0f695f3d98e9416"><code>fba4e8f</code></a>
Merge pull request <a
href="https://redirect.github.com/WebReflection/flatted/issues/89">#89</a>
from WebReflection/python-fix</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/5fe86485e6df7f7f34a07a2a85498bd3e17384e7"><code>5fe8648</code></a>
added &quot;when in Rome&quot; also a test for PHP</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/53517adbefe724fe472b2f9ebcdb01910d0ae3f0"><code>53517ad</code></a>
some minor improvement</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/b3e2a0c387bf446435fec45ad7f05299f012346f"><code>b3e2a0c</code></a>
Fixing recursion issue in Python too</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/c4b46dbcbf782326e54ea1b65d3ebb1dc7a23fad"><code>c4b46db</code></a>
Add SECURITY.md for security policy and reporting</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/f86d071e0f70de5a7d8200198824a3f07fc9c988"><code>f86d071</code></a>
Create dependabot.yml for version updates</li>
<li>Additional commits viewable in <a
href="https://github.com/WebReflection/flatted/compare/v3.3.2...v3.4.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=flatted&package-manager=npm_and_yarn&previous-version=3.3.2&new-version=3.4.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/carbon-language/carbon-lang/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 15:09:36 +00:00
cui 44f2a68ee0 Fix iN/uN type literal width check for multiples of 8 (#6949)
The diagnostic requires bit widths to be multiples of 8, but the test
used a mask of 3 (lower two bits), which only enforces multiples of 4.
Use a mask of 7 so values like 12 incorrectly pass the check.
2026-03-22 02:03:48 +00:00
Jon Ross-Perkins 81215e873e Add missing library in test (#6945)
Adding a library to lower the odds of tripping someone up in the future
(I don't plan to modify this file now)

Assisted-by: Google Antigravity with Gemini
2026-03-20 23:07:21 +00:00
bc38deb16c adds witness support for associated types (#6937)
This commit creates an instance for any associated types in an interface
with a custom witness table. This unlocks interfaces designed for C++
interop that rely on arbitrary return types. For example,
`CppUnsafeDeref` becomes usable as of this commit.

This commit may have also implemented support for non-type associated
constants, but since we're lacking a practical test case, they're still
marked as TODO for the time being.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-03-20 22:03:52 +00:00
Dana Jansens 6d2387cb77 Return a NewAnyPhase result for RequireCompleteType with a CompleteTypeWitness value (#6939)
The `CompleteTypeWitness` can be concrete. This avoids making a symbolic
`CompleteTypeWitness` value which itself has a concrete
`CompleteTypeWitness` value with the same operands.
2026-03-20 20:00:08 +00:00
Geoff Romer 000b4f3fa5 Handle errors in form binding without crashing. (#6936)
Closes #6920
2026-03-20 18:25:00 +00:00
Richard Smith e06eb8f532 Create a placement operator new directly. (#6941)
Instead of injecting code to declare an `operator new`, generate AST for
it directly. In order to use this, directly generate a `CXXNewExpr`
rather than asking Clang to build one.

This is less of a hack, and doesn't visibly leak an `operator new`
declaration that inline C++ code or template instantiations might see.
It also avoids generating a warning in C++26 and later that the
`constexpr` declaration of `operator new` is used but not defined.

Assisted-by: Gemini 3.1 Pro via Antigravity
2026-03-20 16:50:37 +00:00
Geoff Romer 8e824d02be Restructure pattern matching to support producing results (#6929)
See
[here](https://docs.google.com/document/d/1rWcueFwIfZox6GKVGxiUG4cBzjrZ6djXiIDGyJDtrE4/edit?tab=t.0#heading=h.o26vowcup0iq)
for the motivation. Note that this change only provides the
infrastructure for producing and consuming results; the actual usage is
in a separate PR.

Assisted-by: Gemini 3.1 Pro via Antigravity
2026-03-20 16:47:04 +00:00
Geoff Romer 8e5b358ec2 Add the form ID to FormParamPattern (#6928)
This enables some nice simplifications, and it's also a step toward a
broader restructuring of binding and parameter patterns.

Assisted-by: Gemini 3.1 Pro via Antigravity
2026-03-20 01:08:38 +00:00
Richard SmithandGeoff Romer ce50f181f1 Add an interface for initialization of vars without an explicit initializer (#6934)
When a `var` is not explicitly given an initializer, initialize it in
one of two ways:

* If its type implements the new interface `Core.Default`, call
`Core.Default.Op` to initialize it.
* Otherwise, if its type implements `UnformedInit`, leave it in an
unformed state. For now, this is always an uninitialized state, but that
will change in the future.
* If neither of those apply, the `var` declaration is ill-formed.

This is a step towards implementing leads decision #6739 and proposals
#257 and #5913.

Assisted-by: Gemini 3.1 Pro via Antigravity

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2026-03-19 23:46:06 +00:00
Christopher Di BellaandDana Jansens fd2d210c63 changes LookupCppImpl's return to handle multiple associated entities (#6916)
`LookupCppImpl` handles exactly one function ID, so core interfaces with
multiple associated entities were regarded as unsupported. This commit
adds support for a single associated function with a single associated
constant.

Note: associated constants are still TODO.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-03-19 22:03:39 +00:00
Geoff Romer 08148f3a3a Refactor AddBindingPattern into composable pieces (#6927)
This is part of some bigger changes in pattern matching, factored out
because it causes some test churn.

Assisted-by: Gemini 3.1 Pro via Antigravity
2026-03-19 19:20:03 +00:00
Dana Jansens 10beae2c20 Avoid crashing if a C++ type was used to look for an IntFitsIn witness (#6924)
Originally this was handled in LookupCppImpl in the switch on the
CoreInterface, but in subsequent refactorings it was lost, and we now
assume we are always looking for a C++ witness and CHECK that the
interface is not `IntFitsIn`.

Refactor LookupCppImpl to have a single switch up front on the
CoreInterface enum, instead of multiple. It's a quick early out for
`IntFitsIn` and delegates work to helper functions specific to each
other CoreInterface value.
2026-03-19 18:34:45 +00:00
Geoff Romer 6d1130f657 Allow no-op conversions on incomplete types. (#6926)
This resolves some todos, and makes `Convert` safer to call, which
unblocks some changes in pattern matching that I'm working on.

Assisted-by: Gemini 3.1 Pro via Antigravity
2026-03-19 17:08:23 +00:00
David Blaikie 14b72f16da SemIR::Namespace->clang::NamespaceDecl interop (#6935)
Rough-in with TODO for caching and scoping/nesting, this only handles
top level namespaces and doesn't nest them appropriately.
2026-03-18 23:33:49 +00:00
Jon Ross-Perkins 7b3f120f97 Make Any* macros reusable (#6933)
Use parens to delay macro expansion to address the comma separator case,
allowing reuse in AnyBindingOrExportDecl. Also add
CARBON_INST_CATEGORY_ANY_EXPAND to reduce some boilerplate.

Assisted-by: Google Antigravity with Gemini
2026-03-18 19:27:46 +00:00
Nicholas Bishop 0482b27c6b Support more types in MapConstantToAPValue by refactoring code out of ConvertArgToTemplateArg (#6923)
This doesn't change any of the current tests, but will be useful for
calling constexpr functions with bool/float params.
2026-03-18 16:11:42 +00:00
Richard SmithandDana Jansens 98e2567524 Add a skill to produce a summary report for changes to testdata files. (#6925)
Example output from Gemini:
https://gist.github.com/zygoloid/b4aaaf919173d639cf0ffa90fd0898e4

Assisted-by: Gemini 3.1 Pro via Antigravity

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-03-18 16:05:10 +00:00
Jon Ross-Perkins d47b6221ae Fix invalid digit caret (#6921)
Stumbled on this playing with numeric literals

Assisted-by: Google Antigravity with Gemini
2026-03-17 18:13:55 +00:00
Dana Jansens 87fc05750b Test that a named constraint can't be used inside its definition through an alias to its name (#6922)
We only want to allow using the named constraint through `Self`, as
proposed in #6902.
2026-03-17 17:31:20 +00:00
Jon Ross-Perkins 2e32f309eb Small improvements to APInt handling (#6918)
I was looking for uses of APInt that care about the bit width we're
using, just searching for uses of "64", since #6908 started applying the
minimum with of 64 bits more explicitly.

- numeric_literal.cpp: piping through the sign bit request, allowing
`exponent` to assume it's already 64-bit (putting the CHECK in to just
expose the logic, keeping it outside the `if` because the `if` is an
edge case and I was thinking to avoid edge case inconsistencies slipping
by)
- inst_fingerprinter.cpp: reducing logic to copy words

Assisted-by: Google Antigravity with Gemini
2026-03-17 17:11:30 +00:00
Geoff Romer 1d71e7a707 Change .size() == 0 to .empty() (#6917)
This resolves a readability-container-size-empty clang-tidy finding.
2026-03-17 11:35:04 +00:00
Jon Ross-PerkinsandChandler Carruth 613a139bef Add support for octal numbers (#6909)
This implements the leads decision made in #6821, proposal #6910. The
proposal is pending, but I figured it's relatively safe to just do given
the decision.

Assisted-by: Google Antigravity with Gemini

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2026-03-16 21:28:37 +00:00
Jon Ross-Perkins c5761d2d16 Improve parsing large integers (#6908)
Though I started this thinking about performance of parse of large
decimal integers, I extended it to generally improve performance of
integer values (TBH I hadn't expected such a difference for binary/hex,
but I'll take it).

Note I think tests change because I'm making subtle changes to bit
widths. The changes themselves appear harmless to me, but happy to make
changes if it'd help.

Bumping up the number of digits by 10x because it's not really a
performance issue anymore (eh, maybe somebody will want to specify a
256-byte value in binary). But, at a certain point it still seems like a
mistake if somebody has that many digits in a row.

Fixes #980

Highlighting benchmark differences:
```diff
- BM_ComputeValue_IntDecimalN/1           37.1 ns         37.1 ns     18887116
+ BM_ComputeValue_IntDecimalN/1           21.9 ns         21.9 ns     31902433
- BM_ComputeValue_IntDecimalN/10000 1251228680 ns   1250457559 ns            1
+ BM_ComputeValue_IntDecimalN/10000     458818 ns       458626 ns         1523
- BM_ComputeValue_IntBinaryN/1            29.0 ns         29.0 ns     24058533
+ BM_ComputeValue_IntBinaryN/1            22.2 ns         22.1 ns     31566949
- BM_ComputeValue_IntBinaryN/10000     1390557 ns      1389782 ns          506
+ BM_ComputeValue_IntBinaryN/10000       16402 ns        16396 ns        42744
- BM_ComputeValue_IntHexN/1               34.0 ns         34.0 ns     20562432
+ BM_ComputeValue_IntHexN/1               22.4 ns         22.4 ns     31238055
- BM_ComputeValue_IntHexN/10000        5387942 ns      5385262 ns          130
+ BM_ComputeValue_IntHexN/10000          39249 ns        39233 ns        17859
```

Benchmark before:
```
----------------------------------------------------------------------------
Benchmark                                  Time             CPU   Iterations
----------------------------------------------------------------------------
BM_Lex_Float                            10.6 ns         10.6 ns     66138191
BM_Lex_Int                              15.5 ns         15.4 ns     45149703
BM_Lex_IntDecimalN/1                    3.11 ns         3.11 ns    225524908
BM_Lex_IntDecimalN/10                   11.8 ns         11.8 ns     56719805
BM_Lex_IntDecimalN/100                   102 ns          102 ns      6867468
BM_Lex_IntDecimalN/1000                  943 ns          942 ns       745313
BM_Lex_IntDecimalN/10000                9465 ns         9461 ns        73970
BM_ComputeValue_Float                   61.6 ns         61.6 ns     11377463
BM_ComputeValue_Int                      106 ns          106 ns      6587381
BM_ComputeValue_IntDecimalN/1           37.1 ns         37.1 ns     18887116
BM_ComputeValue_IntDecimalN/10          87.7 ns         87.7 ns      7960837
BM_ComputeValue_IntDecimalN/100         7963 ns         7956 ns        88858
BM_ComputeValue_IntDecimalN/1000     1212577 ns      1211906 ns          578
BM_ComputeValue_IntDecimalN/10000 1251228680 ns   1250457559 ns            1
BM_ComputeValue_IntBinaryN/1            29.0 ns         29.0 ns     24058533
BM_ComputeValue_IntBinaryN/10           69.4 ns         69.4 ns     10108642
BM_ComputeValue_IntBinaryN/100           963 ns          962 ns       726982
BM_ComputeValue_IntBinaryN/1000        21562 ns        21551 ns        32506
BM_ComputeValue_IntBinaryN/10000     1390557 ns      1389782 ns          506
BM_ComputeValue_IntHexN/1               34.0 ns         34.0 ns     20562432
BM_ComputeValue_IntHexN/10              70.4 ns         70.4 ns      9953165
BM_ComputeValue_IntHexN/100             1474 ns         1473 ns       472776
BM_ComputeValue_IntHexN/1000           61818 ns        61762 ns        11363
BM_ComputeValue_IntHexN/10000        5387942 ns      5385262 ns          130
```

Benchmark after:
```
----------------------------------------------------------------------------
Benchmark                                  Time             CPU   Iterations
----------------------------------------------------------------------------
BM_Lex_Float                            10.9 ns         10.9 ns     63993114
BM_Lex_Int                              15.1 ns         15.1 ns     46869766
BM_Lex_IntDecimalN/1                    3.16 ns         3.16 ns    220923300
BM_Lex_IntDecimalN/10                   12.2 ns         12.2 ns     57731654
BM_Lex_IntDecimalN/100                   102 ns          102 ns      6875516
BM_Lex_IntDecimalN/1000                  942 ns          942 ns       742359
BM_Lex_IntDecimalN/10000                9353 ns         9350 ns        75096
BM_ComputeValue_Float                   44.9 ns         44.9 ns     15619691
BM_ComputeValue_Int                     48.9 ns         48.9 ns     14361507
BM_ComputeValue_IntDecimalN/1           21.9 ns         21.9 ns     31902433
BM_ComputeValue_IntDecimalN/10          30.3 ns         30.3 ns     23134117
BM_ComputeValue_IntDecimalN/100          224 ns          223 ns      3092567
BM_ComputeValue_IntDecimalN/1000        5834 ns         5830 ns       117469
BM_ComputeValue_IntDecimalN/10000     458818 ns       458626 ns         1523
BM_ComputeValue_IntBinaryN/1            22.2 ns         22.1 ns     31566949
BM_ComputeValue_IntBinaryN/10           32.9 ns         32.9 ns     21306927
BM_ComputeValue_IntBinaryN/100           198 ns          198 ns      3545277
BM_ComputeValue_IntBinaryN/1000         1671 ns         1669 ns       419656
BM_ComputeValue_IntBinaryN/10000       16402 ns        16396 ns        42744
BM_ComputeValue_IntHexN/1               22.4 ns         22.4 ns     31238055
BM_ComputeValue_IntHexN/10              47.8 ns         47.7 ns     14694407
BM_ComputeValue_IntHexN/100              436 ns          436 ns      1609794
BM_ComputeValue_IntHexN/1000            3966 ns         3962 ns       177109
BM_ComputeValue_IntHexN/10000          39249 ns        39233 ns        17859
```

Assisted-by: Google Antigravity with Gemini
2026-03-16 20:00:51 +00:00
Nicholas Bishop 943cd41924 Support constexpr pointers (#6907)
This moves the LValue path code from macros.cpp to constant.cpp, so that
it can be called from `MapAPValueToConstant`. TODO messages are updated
accordingly to avoid referring to macros. Added a constexpr pointer test
to `constexpr.carbon` to show the result of this change.
2026-03-16 19:19:20 +00:00
Jon Ross-Perkins c006013e0c Change multi-input error to warning (#6914)
Mainly so that Compiler Explorer's command line doesn't need to change.

Assisted-by: Google Antigravity with Gemini
2026-03-16 17:35:58 +00:00
dependabot[bot] aeed8f608b Bump undici from 6.21.3 to 6.24.0 in /utils/vscode in the npm_and_yarn group across 1 directory (#6911)
Bumps the npm_and_yarn group with 1 update in the /utils/vscode
directory: [undici](https://github.com/nodejs/undici).

Updates `undici` from 6.21.3 to 6.24.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/nodejs/undici/releases">undici's
releases</a>.</em></p>
<blockquote>
<h2>v6.24.0</h2>
<h1>Undici v6.24.0 Security Release Notes (LTS)</h1>
<p>This release backports fixes for security vulnerabilities affecting
the v6 line.</p>
<h2>Upgrade guidance</h2>
<p>All users on v6 should upgrade to <strong>v6.24.0</strong> or
later.</p>
<h2>Fixed advisories</h2>
<ul>
<li>
<p><a
href="https://github.com/nodejs/undici/security/advisories/GHSA-2mjp-6q6p-2qxm">GHSA-2mjp-6q6p-2qxm</a>
/ CVE-2026-1525 (Medium)<br />
Inconsistent interpretation of HTTP requests (request/response smuggling
class issue).</p>
</li>
<li>
<p><a
href="https://github.com/nodejs/undici/security/advisories/GHSA-f269-vfmq-vjvj">GHSA-f269-vfmq-vjvj</a>
/ CVE-2026-1528 (High)<br />
Malicious WebSocket 64-bit frame length handling could crash the
client.</p>
</li>
<li>
<p><a
href="https://github.com/nodejs/undici/security/advisories/GHSA-4992-7rv2-5pvq">GHSA-4992-7rv2-5pvq</a>
/ CVE-2026-1527 (Medium)<br />
CRLF injection via the <code>upgrade</code> option.</p>
</li>
<li>
<p><a
href="https://github.com/nodejs/undici/security/advisories/GHSA-v9p9-hfj2-hcw8">GHSA-v9p9-hfj2-hcw8</a>
/ CVE-2026-2229 (High)<br />
Unhandled exception from invalid <code>server_max_window_bits</code> in
WebSocket permessage-deflate negotiation.</p>
</li>
<li>
<p><a
href="https://github.com/nodejs/undici/security/advisories/GHSA-vrm6-8vpv-qv8q">GHSA-vrm6-8vpv-qv8q</a>
/ CVE-2026-1526 (High)<br />
Unbounded memory consumption in WebSocket permessage-deflate
decompression.</p>
</li>
</ul>
<h2>Not applicable to v6</h2>
<ul>
<li><a
href="https://github.com/nodejs/undici/security/advisories/GHSA-phc3-fgpg-7m6h">GHSA-phc3-fgpg-7m6h</a>
/ CVE-2026-2581 affects <code>&gt;= 7.17.0 &lt; 7.24.0</code> only.</li>
</ul>
<h2>Affected and patched ranges (v6)</h2>
<ul>
<li>CVE-2026-1525: affected <code>&lt; 6.24.0</code>, patched
<code>6.24.0</code></li>
<li>CVE-2026-1528: affected <code>&gt;= 6.0.0 &lt; 6.24.0</code>,
patched <code>6.24.0</code></li>
<li>CVE-2026-1527: affected <code>&lt; 6.24.0</code>, patched
<code>6.24.0</code></li>
<li>CVE-2026-2229: affected <code>&lt; 6.24.0</code>, patched
<code>6.24.0</code></li>
<li>CVE-2026-1526: affected <code>&lt; 6.24.0</code>, patched
<code>6.24.0</code></li>
</ul>
<h2>References</h2>
<ul>
<li>GitHub Security Advisories: <a
href="https://github.com/nodejs/undici/security/advisories">https://github.com/nodejs/undici/security/advisories</a></li>
<li>NVD CVE-2026-1525: <a
href="https://nvd.nist.gov/vuln/detail/CVE-2026-1525">https://nvd.nist.gov/vuln/detail/CVE-2026-1525</a></li>
<li>NVD CVE-2026-1528: <a
href="https://nvd.nist.gov/vuln/detail/CVE-2026-1528">https://nvd.nist.gov/vuln/detail/CVE-2026-1528</a></li>
<li>NVD CVE-2026-1527: <a
href="https://nvd.nist.gov/vuln/detail/CVE-2026-1527">https://nvd.nist.gov/vuln/detail/CVE-2026-1527</a></li>
<li>NVD CVE-2026-2229: <a
href="https://nvd.nist.gov/vuln/detail/CVE-2026-2229">https://nvd.nist.gov/vuln/detail/CVE-2026-2229</a></li>
<li>NVD CVE-2026-1526: <a
href="https://nvd.nist.gov/vuln/detail/CVE-2026-1526">https://nvd.nist.gov/vuln/detail/CVE-2026-1526</a></li>
</ul>
<h2>v6.23.0</h2>
<h2>⚠️ Security Release</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/nodejs/undici/commit/8873c947271faf1ebc455bdc6158ecbc022ecfa9"><code>8873c94</code></a>
Bumped v6.24.0</li>
<li><a
href="https://github.com/nodejs/undici/commit/411bd01a42e7917009bbf686f7628b99d67bbce9"><code>411bd01</code></a>
test(websocket): use node:assert for Node 18 compatibility</li>
<li><a
href="https://github.com/nodejs/undici/commit/844bf59699d778944f78a24ae819c0e8f295766e"><code>844bf59</code></a>
test: fix http2 lint regressions in backport</li>
<li><a
href="https://github.com/nodejs/undici/commit/a444e4f13e8958b4e1ac42bc0d53ace7fba0a9c1"><code>a444e4f</code></a>
test: stabilize h2 and tls-cert-leak under current test runner</li>
<li><a
href="https://github.com/nodejs/undici/commit/dc032a1050d5489b8ce9b4c22aafba98a942f87b"><code>dc032a1</code></a>
fix: h2 CI (<a
href="https://redirect.github.com/nodejs/undici/issues/4395">#4395</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/4cd3f4b3a2ef910ba728c47ae78294d956410450"><code>4cd3f4b</code></a>
test: increase bitness in <code>test/fixtures/*.pem</code> (<a
href="https://redirect.github.com/nodejs/undici/issues/3659">#3659</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/7df6442194b7a54e9ac734335e6e0a56a9bc6666"><code>7df6442</code></a>
fix: adapt websocket frame-limit handling for v6 parser</li>
<li><a
href="https://github.com/nodejs/undici/commit/4e0179ae643e6f4380f24cc3683c1b1ca2afb094"><code>4e0179a</code></a>
fix: reject duplicate content-length and host headers</li>
<li><a
href="https://github.com/nodejs/undici/commit/5a97f0893b53ba7d1d5549d3df7e55d9c2673f89"><code>5a97f08</code></a>
Fix websocket 64-bit length overflow</li>
<li><a
href="https://github.com/nodejs/undici/commit/e43e898603dd5e0c14a75b08b83257598d664a39"><code>e43e898</code></a>
fix: validate upgrade header to prevent CRLF injection</li>
<li>Additional commits viewable in <a
href="https://github.com/nodejs/undici/compare/v6.21.3...v6.24.0">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for undici since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=undici&package-manager=npm_and_yarn&previous-version=6.21.3&new-version=6.24.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/carbon-language/carbon-lang/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 15:54:05 +00:00
Jon Ross-Perkins 8b907b5a60 Support octal literals (#6910)
Support octal literals, mainly for migrating Unix file permissions.
Reflects leads decision #6821.
2026-03-14 00:50:58 +00:00
6f1f59a385 Initial Reverse Interop implementation (#6901)
Add a clang::ExternalASTSource to begin exposing Carbon entities to
Clang - initially only a single `Carbon` top level namespace.

Subsequent work will add Carbon entities to this namespace.

Likely this CarbonExternalASTSource will be refactored into another
file, tie into/reference SemIR::File and CppFile, etc eventually - but
that'll wait for future patches.

If there's mechanical problems with the current implementation - how I'm
creating the new NamespaceDecl, etc - I'm all ears. It's very much in
the "it seems to work" state, not much more than that.

This does break Clang Modules (header modules, C++20 modules,
precompiled headers, etc) since they're implemented as an
ExternalASTSource as well, and Clang's ASTContext only supports one
ExternalASTSource at a time. To fix that regression we'll need to
implement some kind of ExternalASTSource multiplexing support - either
in Clang or Carbon (unclear which).

This regression of modules support can be observed by the following:
`A.h`
```
inline void f1() { }
```
`module.modulemap`
```
module A {
  header "A.h"
  export *
}
```
`test.carbon`
```
import Cpp inline '''
// Hardcode the pragma to ensure this isn't silently falling back to
// textual inclusion.
void f2() {
  f1();
}
''';
```
```
carbon compile test.carbon -- -I . -fmodules -fimplicit-modules -fmodules-cache-path=module_cache
```

I wrote a `file_test` test for this, but it doesn't /quite/ work because
`file_test` provides an in-memory filesystem for tests to make them more
hermetic, but Clang's Filesystem abstrtaction is for reading only - so
the module that's written out successfully can't be found when it needs
to be read back in - so the test doesn't pass as a baseline. Clang does
have support for `llvm::vfs::OutputBackend` which allows virtualizing
output - which I guess we could tie together with the InMemoryFilesystem
we use for input to make such a test work. But I guess that's not worth
the effort here?

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2026-03-13 23:04:49 +00:00
Dana Jansens 27cc14848a Use a single work queue in RequireIdentifiedFacetType (#6904)
Use a single vector instead of two. This reduces the number of memory
allocations required.
2026-03-13 22:16:41 +00:00
Jon Ross-Perkins fbe917b949 Create a UnifiedDiffMatcher to make golden test failures easier to understand (#6897)
Right now I think everyone has the habit of doing an autoupdate then
using source control for a diff. This is offering an option of better
diff output from the test.

For example:

```
TEST: toolchain/driver/testdata/fail_flush_errors.carbon !
Ran 1 tests in 81 ms wall time, 8 ms across threads
testing/file_test/file_test_base.cpp:264: Failure
Value of: SplitOutput(test_file.actual_stderr)
Expected: matches elements with union diff
  Actual: { "fail_flush_errors.carbon:22:3: error: name `undeclared1` not found [NameNotFound]", "  undeclared1;", "  ^~~~~~~~~~~", "", "fail_flush_errors.carbon:31:3: error: `Core.String` implicitly referenced here, but package `Core` not found [CoreNotFound]", "  \"undec\\x6Cared2\";", "  ^~~~~~~~~~~~~~~~", "", "fail_flush_errors.carbon:35:3: error: name `undeclared2` not found [NameNotFound]", "  undeclared2;", "  ^~~~~~~~~~~", "", "fail_flush_errors.carbon:43:3: error: name `undeclared3` not found [NameNotFound]", "  undeclared3;", "  ^~~~~~~~~~~", "", "" }, union diff (- expected, + actual):
=== diff in expected elements 0 to 2:
+ fail_flush_errors.carbon:22:3: error: name `undeclared1` not found [NameNotFound]
    undeclared1;
    ^~~~~~~~~~~

=== diff in expected elements 4 to 9:
    "undec\x6Cared2";
    ^~~~~~~~~~~~~~~~

+ fail_flush_errors.carbon:35:3: error: name `undeclared2` not found [NameNotFound]
    undeclared2;
    ^~~~~~~~~~~

=== diff end

Stack trace:
  0x55e476d29efd: Carbon::Testing::FileTestCase::TestBody()
  0x55e476dbd1f2: testing::internal::HandleExceptionsInMethodIfSupported<>()
  0x55e476dbcf57: testing::Test::Run()
  0x55e476dbf0bf: testing::TestInfo::Run()
... Google Test internal frames ...


To test this file alone, run:
  bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/driver/testdata/fail_flush_errors.carbon

testing/file_test/file_test_base.cpp:277: Failure
Failed
Autoupdate would make changes to the file content. Run:
bazel run //toolchain/testing:file_test -- --autoupdate --file_tests=toolchain/driver/testdata/fail_flush_errors.carbon
Stack trace:
  0x55e476d2a5f0: Carbon::Testing::FileTestCase::TestBody()
  0x55e476dbd1f2: testing::internal::HandleExceptionsInMethodIfSupported<>()
  0x55e476dbcf57: testing::Test::Run()
  0x55e476dbf0bf: testing::TestInfo::Run()
... Google Test internal frames ...

[  FAILED  ] ToolchainFileTest.toolchain/driver/testdata/fail_flush_errors.carbon, where GetParam() = toolchain/driver/testdata/fail_flush_errors.carbon (93 ms)
```

Assisted-by: Google Antigravity with Gemini
2026-03-13 21:39:21 +00:00
Dana Jansens bad9beddc7 Diagnose using named constraint's name inside its definition (#6906)
Using a named constraint inside itself is problematic:
- If there were not require decls written above, it identifies as an
empty set. This makes `Z(Self)` essentially disappear in the identified
facet type, which produces "no use of Self" diagnostics while the user
can see a use of Self in the code.
- It won't include require decls that are written after, and so `require
T impls Z` won't actually enforce that `T` impls all of `Z`.

Previously this was an error because using the named constraint would
require it to be identified, and it's not identified until it is
complete. But this will change in proposal #6902. So that proposal also
includes changes to preserve diagnostics for incorrect use of a named
constraint before it's complete, which is implemented here.

Discussed in open discussion [on
2026-03-12](https://docs.google.com/document/d/1mjllGO3ZCL4qGt9uJHUtcxKoHAGEY7Y999ie4EtBWB8/edit?tab=t.0#heading=h.1dvbbrp5a6t3).

The new tests exposed a bug where we're not copying named constraints in
a facet type on the RHS of `where .Self impls` into the facet type on
the left, which is now fixed. The
`fail_require_impls_incomplete_self_in_period_self_impls.carbon` test
would not diagnose its error without this fix.
2026-03-13 16:54:58 +00:00
Jon Ross-Perkins 6706162582 Error when passing multiple input files with --output (#6896)
Fixes #6895

Note this is just a short-term fix to avoid confusion, as the compile
structure needs to change on the whole.

Assisted-by: Google Antigravity with Gemini
2026-03-13 16:07:12 +00:00
Christopher Di Bella ffe8f8f67d Revert "refactors LookupCppImpl to handle multiple associated functions (#6816)" (#6900)
We discussed whether associated functions should be processed in a
general manner. Since many associated functions will have some amount of
unique processing, we're probably better off not having a general
utility, and we can return to the original `CoreInterface`, which was
much simpler in design.

This reverts commit 4d0003765d.
2026-03-13 15:09:42 +00:00
Dana Jansens 5d1973ab93 Support --remote in new_proposal script with jj (#6903) 2026-03-12 21:57:56 +00:00
Jon Ross-Perkins 610094ccfd Make included files insert before main files (#6899)
This is so that the last file is more likely what we're trying to
compile in tests. Just splitting out the churn-y change of reordering.

Assisted-by: Google Antigravity with Gemini
2026-03-12 21:01:16 +00:00
Christopher Di BellaandRichard Smith 4df2b6ea9d adds checking support for CppUnsafeDeref witness (#6890)
Iterators, smart pointers, optional, and expected types depend on
`operator*`. This commit adds `CppUnsafeDeref` as a core interface, with
an associated function, so that the compiler can dereference
user-defined C++ types.

Things not implemented in this commit:

* `operator*` overload resolution
* SemIR lowering

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-03-12 18:02:34 +00:00
Jon Ross-Perkins 1e9708e2cc Update python version for black (#6877)
This is making it consistent with other places we set a Python version:
- contribution_tools.md
- .python-version
- bench_runner.py
- build-setup-common/action.yml

Assisted-by: Google Antigravity with Gemini
2026-03-12 16:45:58 +00:00
Dana Jansens 4c69a1baf0 Use min-prelude in fail_assoc_const_alias.carbon (#6894)
Remove the local `Core` package from the test file and use the
`convert.carbon` min-prelude.
2026-03-12 16:10:23 +00:00
Nicholas Bishop c1fd771242 Support calling constexpr functions at compile time (#6878)
Example:

```carbon
import Cpp inline '''
constexpr int f(int a, int b) { return a + b; }
''';

let a: array(i32, Cpp.f(1, 2)) = (1, 2, 3);
```
2026-03-12 01:45:31 +00:00
Chandler CarruthandDana Jansens 5d41529590 Introduce a Bazel-integrated build for the installed runtimes (#6872)
This shifts the Bazel toolchain configuration of our installation to
build all of the Clang runtimes Carbon uses on-demand natively in Bazel.
We export the information about how to build into a generated Starlark
file, and emit BUILD files and Starlark logic into the installation to
orchestrate the build.

This requires some complex management of Bazel toolchains -- we need to
first set-up a "runtimes toolchain" that doesn't have runtimes of its
own, but can be used to _build_ runtimes. Then we build the runtimes
using that toolchain, and assemble them into the standard layout for a
Carbon runtimes tree. Finally we configure the _actual_ toolchain with
this built tree.

Currently, this is only setup for the installed toolchain, but I plan to
factor this runtimes build into one that can be used directly as well to
break up the monolithic runtimes build step into Bazel-integrated build
of the runtimes. This will also serve as the foundation for adding
bootstrapping support directly to our Bazel build.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-03-12 01:24:56 +00:00
Richard Smith 0a4fd2cb7e Fix thunk generation for &&-qualified methods. (#6881)
Use the object parameter type when creating a reference to the thunk
parameter so that we create an xvalue rather than an lvalue for the
`*this` expression in the thunk.
2026-03-11 20:34:18 +00:00
Richard Smith 2e5b195813 Make {} as Class an initializing expression. (#6882)
Previously we forced a temporary materialization, resulting in it being
treated as an ephemeral reference expression. This change allows

```carbon
var x: Class = {} as Class;
```

even when `Class` is not copyable.
2026-03-11 20:21:21 +00:00
Nicholas Bishop 6ac561afe9 Add "Fixing conflicts with trunk" to code_review.md (#6889) 2026-03-11 19:30:20 +00:00
Jon Ross-Perkins 70c401f85f Updates the llvm-raw commit to HEAD as of 2026-03-09 (#6879)
Test changes are the result of autoupdate_testdata.py

Assisted-by: Google Antigravity with Gemini
2026-03-11 14:47:40 +00:00
Richard Smith 39fd358059 Map Carbon value expressions to const-qualified C++ prvalues. (#6880)
In C++ overload resolution, when mapping a Carbon value expression into
a C++ argument, produce a const-qualified argument where possible. This
has two effects:

* Overload resolution does not consider non-const-qualified member
functions to be viable for a prvalue self any more. This is desirable
since such functions are not actually callable with a prvalue self, and
permits overload resolution to pick a const-qualified overload instead.

* Overload resolution does not allow a Carbon value expression to be
passed to a C++ `T&&` parameter any more. This is desirable since it's
not correct to move from a value expression. Previously we allowed this
and moved from the value!
2026-03-11 03:42:19 +00:00
972 changed files with 49631 additions and 28089 deletions
+83
View File
@@ -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.
+171
View File
@@ -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)
+95
View File
@@ -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)
@@ -52,9 +52,13 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
### Updating test data
Carbon tests often use `file_test` (for example,
`//toolchain/testing/file_test`). 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:
`//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
+136
View File
@@ -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 -5
View File
@@ -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
+6
View File
@@ -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
@@ -26,3 +27,8 @@ 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
@@ -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
+33
View File
@@ -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."
-4
View File
@@ -75,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
+1 -1
View File
@@ -93,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
@@ -28,8 +28,7 @@ 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
+23 -5
View File
@@ -22,13 +22,30 @@ 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@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
@@ -74,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:
@@ -85,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`.
+5
View File
@@ -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:
+7
View File
@@ -14,6 +14,7 @@ assistant, **read this first** to avoid common pitfalls.
- [General instructions](#general-instructions)
- [Project structure](#project-structure)
- [Bazel usage](#bazel-usage)
- [Toolchain development](#toolchain-development)
## General instructions
@@ -40,6 +41,12 @@ assistant, **read this first** to avoid common pitfalls.
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
+37
View File
@@ -2,6 +2,8 @@
# 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"],
@@ -13,3 +15,38 @@ 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"],
)
+10 -2
View File
@@ -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)
@@ -232,7 +233,7 @@ 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 [GEMINI.md](/GEMINI.md) for high-density
assistant yourself, please consult [AGENTS.md](/AGENTS.md) for high-density
technical context and tips.
All submissions to Carbon need to follow our
@@ -308,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.
@@ -427,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.
+11 -12
View File
@@ -40,6 +40,14 @@ bazel_dep(name = "tcmalloc", version = "0.0.0-20250927-12f2552")
bazel_dep(name = "tree-sitter-bazel", version = "0.26.5")
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)
git_override(
module_name = "bazel_clang_tidy",
@@ -56,16 +64,7 @@ use_repo(bazel_cc_toolchain, "bazel_cc_toolchain")
register_toolchains("@bazel_cc_toolchain//:all")
# TODO: Trying out `wolfd_bazel_compile_commands`, figure out if there are
# issues. Once people have had a chance to try and check for problems, remove
# one or the other.
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",
)
register_toolchains("//toolchain/install:all")
# Required for llvm-project.
bazel_dep(name = "platforms", version = "1.0.0")
@@ -84,8 +83,8 @@ git_override(
build_file_content = "# empty",
# 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-02-12.
commit = "6811a83c81500ee373adfc0d9978ff9625a4cf1c",
# HEAD as of 2026-04-01.
commit = "b71eacea7687f68c11299e3bda5654fbbaa1e20e",
patch_cmds = ["echo \"module(name='llvm-raw')\" > MODULE.bazel"],
patch_strip = 1,
patches = [
+1 -53
View File
@@ -287,8 +287,6 @@
"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/wolfd_bazel_compile_commands/0.5.2/MODULE.bazel": "74527ae5c60c4974e5b6c9fc2f39b78af47b44559b1913324c8185ff4f2f3900",
"https://bcr.bazel.build/modules/wolfd_bazel_compile_commands/0.5.2/source.json": "bbf0b6d7d2a2e58d238ef580fbf3072018e1c9447c9e2295b6a2b32d87a74338",
"https://bcr.bazel.build/modules/yq.bzl/0.1.1/MODULE.bazel": "9039681f9bcb8958ee2c87ffc74bdafba9f4369096a2b5634b88abc0eaefa072",
"https://bcr.bazel.build/modules/yq.bzl/0.1.1/source.json": "2d2bad780a9f2b9195a4a370314d2c17ae95eaa745cefc2e12fbc49759b15aa3",
"https://bcr.bazel.build/modules/zlib-ng/2.0.7/MODULE.bazel": "3ca640b745b55f287e95aa0477e6cd76dfa0a565725d5412b7d8dae4274436c8",
@@ -305,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": {},
@@ -362,56 +360,6 @@
"recordedRepoMappingEntries": []
}
},
"@@hedron_compile_commands+//:workspace_setup.bzl%hedron_compile_commands_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": []
}
},
"@@protobuf+//python/dist:system_python.bzl%system_python_extension": {
"general": {
"bzlTransitiveDigest": "pmsA+awieucfllLc2n7k8xEoPp0i5LF9Hw6mGX0cqSQ=",
-1
View File
@@ -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
View File
@@ -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,
}),
)
+30
View File
@@ -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(
+59
View File
@@ -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",
)
+1 -1
View File
@@ -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}"
+2 -2
View File
@@ -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,7 +1,7 @@
Commit ID: 959284a466ca392a5ccd501cf1c1622d1f423c06
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-08 07:43:17)
Committer: Chandler Carruth <chandlerc@gmail.com> (2026-03-11 07:54:02)
Improve compiler-rt build structure and export compilation info
@@ -12,7 +12,7 @@ Committer: Chandler Carruth <chandlerc@gmail.com> (2026-03-08 07:43:17)
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..0c3a7daaee 100644
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 @@
@@ -98,12 +98,14 @@ index 4ded226174..0c3a7daaee 100644
] + [
AARCH64_OUTLINE_ATOMICS_FMT.format(pat, size, model)
for (pat, size, model) in AARCH64_OUTLINE_ATOMICS
@@ -328,10 +360,18 @@
@@ -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",
],
),
)
@@ -117,7 +119,7 @@ index 4ded226174..0c3a7daaee 100644
BUILTINS_ARM_VFP_SRCS_PATTERNS = [
"lib/builtins/arm/*vfp*.S",
"lib/builtins/arm/*vfp*.c",
@@ -348,9 +388,19 @@
@@ -348,9 +390,19 @@
),
)
@@ -138,7 +140,7 @@ index 4ded226174..0c3a7daaee 100644
srcs = glob(
[
"lib/builtins/arm/*.S",
@@ -359,14 +409,52 @@
@@ -359,14 +411,52 @@
"lib/builtins/arm/*.h",
],
allow_empty = True,
@@ -196,7 +198,7 @@ index 4ded226174..0c3a7daaee 100644
[
"lib/builtins/ppc/*.S",
"lib/builtins/ppc/*.c",
@@ -377,17 +465,64 @@
@@ -377,17 +467,64 @@
),
)
@@ -272,7 +274,7 @@ index 4ded226174..0c3a7daaee 100644
)
# Source files for the x86 architecture specific builtins (both 32-bit and
@@ -402,8 +537,14 @@
@@ -402,8 +539,14 @@
# Source files for the x86-64 architecture specific builtins.
filegroup(
@@ -289,7 +291,7 @@ index 4ded226174..0c3a7daaee 100644
[
"lib/builtins/x86_64/*.S",
"lib/builtins/x86_64/*.c",
@@ -411,13 +552,29 @@
@@ -411,13 +554,29 @@
"lib/builtins/x86_64/*.h",
],
allow_empty = True,
@@ -321,7 +323,7 @@ index 4ded226174..0c3a7daaee 100644
[
"lib/builtins/i386/*.S",
"lib/builtins/i386/*.c",
@@ -429,28 +586,16 @@
@@ -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",
-4
View File
@@ -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
+1 -1
View File
@@ -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) {
+37 -7
View File
@@ -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>;
})
+8
View File
@@ -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.
+1
View File
@@ -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";
+54
View File
@@ -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";
}
+1
View File
@@ -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";
+11
View File
@@ -44,6 +44,17 @@ 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*) {
+11
View File
@@ -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;
}
+3
View File
@@ -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";
}
+6
View File
@@ -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 {
+9 -2
View File
@@ -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,9 +30,13 @@ 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 {
@@ -48,3 +53,5 @@ class CppCompat.NullptrT {
}
}
}
impl CppCompat.NullptrT as UnformedInit {}
+3
View File
@@ -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 {
+3
View File
@@ -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 {
+3
View File
@@ -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 {}
+18 -5
View File
@@ -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;
}
+3
View File
@@ -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";
}
+3
View File
@@ -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 {
+4 -3
View File
@@ -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
+89
View File
@@ -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:
@@ -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)
+8
View File
@@ -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
+49 -15
View File
@@ -24,6 +24,7 @@ contributions.
- [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)
@@ -256,31 +257,50 @@ system that can be used instead of or alongside Git. See the
for more information.
If you use `jj`, you may find the following configuration snippets (added to
`~/.config/jj/config.toml`) helpful for your workflow:
`jj config path --user`) helpful for your workflow:
```toml
[aliases]
```sh
# Clean up untracked or abandoned commits.
abandon-untagged = ["abandon", "all() & ~ancestors(@ | bookmarks() | remote_bookmarks())"]
jj config set --user aliases.abandon-untagged '["abandon", "all() & ~ancestors(@ | bookmarks() | remote_bookmarks())"]'
[ui]
# Use Git-style conflict markers, which VS Code can provide merge support for.
conflict-marker-style = "git"
jj config set --user ui.conflict-marker-style 'git'
[ui.diff]
# Produce Git-compatible diff format.
format = "git"
jj config set --user ui.diff.format 'git'
[remotes.origin]
# Automatically track all remote bookmarks.
auto-track-bookmarks = "*"
[templates]
# Automatically add a trailer to commits to indicate that they were AI-assisted.
commit_trailers = '''
"Assisted-by: My AI Tool"'''
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
@@ -310,6 +330,20 @@ 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
+2
View File
@@ -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)) {
+2
View File
@@ -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;
+2
View File
@@ -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)) {
+2
View File
@@ -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)) {
+4
View File
@@ -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)) {
+2
View File
@@ -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+"
+2
View File
@@ -23,6 +23,8 @@ fn Mod(a: i32, d: i32) -> i32 {
}
class Robot {
impl as Core.UnformedInit {}
fn Read() -> Robot {
returned var me: Robot;
SkipString("p=");
+2
View File
@@ -45,6 +45,8 @@ let Empty: Square = ('.' as char) as Square;
let Robot: Square = ('@' as char) as Square;
class Grid {
impl as Core.UnformedInit {}
fn Read() -> Grid {
returned var me: Grid;
var y: i32 = 0;
+2
View File
@@ -9,6 +9,8 @@ library "day4_common";
import library "io_utils";
class Wordsearch {
impl as Core.UnformedInit {}
fn Read() -> Wordsearch {
returned var s: Wordsearch;
// TODO: Use for loops once they're implemented.
+4
View File
@@ -16,6 +16,8 @@ fn PageMask(page: i32) -> Core.UInt(100) {
}
class Rules {
impl as Core.UnformedInit {}
fn Read() -> Rules {
returned var rules: Rules;
for (i: i32 in Core.Range(100)) {
@@ -39,6 +41,8 @@ class Rules {
};
class PageList {
impl as Core.UnformedInit {}
fn Empty() -> PageList {
returned var me: PageList;
me.num_pages = 0;
+2
View File
@@ -15,6 +15,8 @@ fn Visited() -> i8 { return 1; }
fn Wall() -> i8 { return 2; }
class Maze {
impl as Core.UnformedInit {}
fn Read() -> Maze {
returned var me: Maze;
+2
View File
@@ -23,6 +23,8 @@ fn Concat(a_val: i64, b_val: i64) -> i64 {
}
class Equation {
impl as Core.UnformedInit {}
fn Read() -> Equation {
returned var me: Equation;
me.num_operands = 0;
+2
View File
@@ -11,6 +11,8 @@ import Core library "range";
import library "io_utils";
class Grid {
impl as Core.UnformedInit {}
fn Read() -> Grid {
returned var me: Grid;
for (y: i32 in Core.Range(50)) {
+2
View File
@@ -11,6 +11,8 @@ import Core library "range";
import library "io_utils";
class SectorList {
impl as Core.UnformedInit {}
fn Read() -> SectorList {
returned var me: SectorList;
me.size = 0;
+3 -1
View File
@@ -21,7 +21,7 @@ class BazelExampleTest(test_base.TestBase):
test_base.TestBase.setUp(self)
self.runfiles = runfiles.Create()
self.install_module = self.runfiles.Rlocation(
"carbon/toolchain/install/prefix/lib/carbon"
"carbon/toolchain/install"
)
self.startup_flags = [
"--ignore_all_rc_files",
@@ -62,7 +62,9 @@ class BazelExampleTest(test_base.TestBase):
# Retry transient errors with a brief delay.
print(f"Attempt {attempt + 1} failed with exit code {exit_code}")
time.sleep(attempt)
self.AssertExitCode(exit_code, 0, stderr)
return stdout
def test_compile_lib(self) -> None:
# TODO: Can remove this in favor of always running `test_run` if we can
+1 -1
View File
@@ -40,7 +40,7 @@ fn Run() -> i32 {
return 1;
}
// TODO: Should be able to zero-initialize this with `= ()` or `= {}`.
// TODO: We should be able to use `= ()` or `= {}` to perform zero-initialization.
var address: Cpp.sockaddr_in6;
Cpp.memset(&address, 0, Cpp.SOCKADDR_IN_SIZE);
// TODO: Should this be valid without a cast? `AF_INET6` is defined to an
+2
View File
@@ -8,6 +8,8 @@ import Core library "range";
// Compute and return the number of primes less than 1000.
class Sieve {
impl as Core.UnformedInit {}
fn Make() -> Sieve {
returned var s: Sieve;
for (n: i32 in Core.Range(1000)) {
+3 -3
View File
@@ -117,9 +117,9 @@ promise==2.3 \
# via
# gql
# graphql-core
requests==2.32.4 \
--hash=sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c \
--hash=sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422
requests==2.33.0 \
--hash=sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b \
--hash=sha256:c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652
# via gql
rx==1.6.3 \
--hash=sha256:ca71b65d0fc0603a3b5cfaa9e33f5ba81e4aae10a58491133595088d7734b2da
+253
View File
@@ -0,0 +1,253 @@
# Identification of a named constraint during definition
<!--
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
-->
[Pull request](https://github.com/carbon-language/carbon-lang/pull/6902)
<!-- toc -->
## Table of contents
- [Abstract](#abstract)
- [Problem](#problem)
- [Background](#background)
- [Proposal](#proposal)
- [Example with `Self`](#example-with-self)
- [Motivating the partially identified state](#motivating-the-partially-identified-state)
- [Disallowing conversions to incomplete named constraint](#disallowing-conversions-to-incomplete-named-constraint)
- [Rationale](#rationale)
- [Alternatives considered](#alternatives-considered)
- [Considering a facet type of a named constraint to be identified in its definition](#considering-a-facet-type-of-a-named-constraint-to-be-identified-in-its-definition)
- [Restricting to `Self`](#restricting-to-self)
- [Allowing limited conversions to partially identified facet types.](#allowing-limited-conversions-to-partially-identified-facet-types)
<!-- tocstop -->
## Abstract
This proposal updates the criteria for when a facet type is considered
"identified." Specifically, it relaxes the requirement for named constraints,
allowing them to be incrementally identified inside the definition, rather than
requiring them to be fully complete, when used through the `Self` facet. This
change enables impl lookups with `Self` within a constraint's definition to
correctly resolve witnesses based on prior `require impls` statements in the
definition.
## Problem
Under the rules established in [Proposal #5168](/proposals/p5168.md), a facet
type is identified only if all its referenced interfaces are declared and all
its referenced named constraints are complete.
This definition creates a circularity problem during the definition of a named
constraint. If a `require impls` statement inside a named constraint definition
relies on an impl lookup with `Self`, that lookup will fail because the facet
type of `Self` is not identified before the named constraint is complete. This
prevents `require impls` statements in a named constraint from depending on
earlier ones.
## Background
- [Proposal #5168](/proposals/p5168.md): Introduced rules for facet type
identification and completion.
## Proposal
We propose redefining the identification criteria for facet types by introducing
a new partially identified state.
A facet type can be in one of three states: unidentified, partially identified,
or identified. A facet type's identifiedness is the minimum of that of its
constituents:
- When a facet type refers to an interface, the facet type is not identified
until the interface is declared, and is fully identified after. This
includes inside the definition of the interface.
- When a facet type refers to a named constraint, the facet type is not
identified until the named constraint is declared. It is partially
identified during the definition of the named constraint, and it is fully
identified after.
The change from previous rules is that a facet type containing a named
constraint is now partially identified inside the definition of that named
constraint.
As in [#5168](/proposals/p5168.md), an `impl` declaration and `require`
statement each requires its constraint to be identified.
We define the rules for facets in impl lookups, which are representable as
`<self> as <target facet type>` conversions as follows:
- The target facet type of an impl lookup must be defined.
- This allows the full set of interfaces to be known, which allows a
stable ordering of witnesses for those interfaces to be produced by the
impl lookup.
- If the self is a facet, its facet type may be in any state of
identifiedness.
- The impl lookup may provide a witness from the facet type of self, using
the known constraints of any partially identified or identified
constituent of the facet type.
In particular, this means that `Self as I` inside the definition of a named
constraint `N` may use any `require impls` statements before that use of `Self`
in order to provide a witness for `I`.
To improve diagnostics, we also propose to disallow using a named constraint
inside its own definition, except through the type of `Self`. Any other use is
diagnosed as an error. This provides a clear error when a named constraint
appears in the constraint of a `require` statement inside its definition.
### Example with `Self`
This change allows the compiler to treat a named constraint as partially
identified for the purposes of impl lookup while it is still being typechecked.
As the compiler processes a series of `require impls` statements within a named
constraint, the partially identified facet type of the named constraint, which
can be accessed through `Self`, is built up incrementally. The partially
identified facet type of `Self` will contain interfaces provided by
`require impls` statements written prior to that use of `Self`. Thus later
`require impls` statements can use the partially identified facet type of `Self`
to find witnesses provided by earlier `require impls` statements during impl
lookup.
The following example demonstrates a scenario that is currently invalid but
would be enabled by this proposal:
```carbon
interface Y {}
interface NeedsY(T:! Y) {}
constraint W {
require impls Y;
// This requires an impl lookup where the query self value is `Self`
// (which is of type `W`) and the query interface is `Y`. The lookup
// requires identifying the facet type of `Self` to find a witness.
// After this proposal, W is partially identified because it has begun being
// defined. The lookup for `Self as Y` can now succeed due to the previous
// `require impls` statement.
require impls NeedsY(Self);
}
```
In this example, identifying `W` while it is being defined allows the lookup for
`Self as Y` in order to form a facet value for `NeedsY` to succeed because the
compiler knows `Self` (of type `W`) implements `Y` from the previous
`require impls` statement.
### Motivating the partially identified state
If a facet type for a named constraint was considered identified (not partially
identified) inside its definition, the following becomes possible:
```carbon
constraint W {
require C impls W;
require impls Z;
}
```
This says that `C` must implement `W`, yet `W` is not fully defined. At that
line `W` is still empty, so it places no requirements on `C`. The next line
requires that anything implementing `W` must implement `Z`.
To prevent this, the constraint of a `require` statement must still be
identified, and the facet type of the being-defined named constraint is only
partially-identified.
Note this also disallows the use of `W` through an alias:
```carbon
constraint W;
alias X = W;
constraint W {
// Error: X refers to named constraint `W` that is not identified.
require impls X;
}
```
### Disallowing conversions to incomplete named constraint
By requiring the target facet type of an impl lookup to be identified, we
disallow an incomplete named constraint from being part of the target of an impl
lookup.
The result of an impl lookup stores witnesses for the target facet type. If the
target facet type was partially identified, the same facet type may have a
different set of interfaces later. A change in the set of interfaces would
invalidate the set of stored witnesses.
For example, if this was allowed:
```carbon
interface Z {}
interface X {}
constraint W;
class C(T:! W) {}
class D {}
interface Y(T:! type) {}
constraint W {
require impls Z;
// Constructs a `D as W` facet value.
require impls Y(C(D));
require impls X;
}
```
In this example the argument to `C` will be `D as W` which will store a witness
for each interface in the identified facet type `W`. If we allow a partially
identified facet type, then it will store a witness for the interface `Z`. But
later uses of the facet value in `Y(C(D))` would expect witnesses for `Z`, `Y`
and `X`, leading to unsoundness.
## Rationale
This change aligns with Carbon's goal of
[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),
by allowing expressive generics as they have been designed.
This follows the
[Information accumulation](/docs/project/principles/information_accumulation.md)
principle by increasing the information available to the program with each
statement.
## Alternatives considered
### Considering a facet type of a named constraint to be identified in its definition
Initial versions of this proposal did not differentiate between partially
identified and identified. This led to unsoundness by allowing conversion to a
facet with the incomplete named constraint in the facet's type, as described in
[Disallowing conversions to incomplete named constraint](#disallowing-conversions-to-incomplete-named-constraint).
### Restricting to `Self`
We considered restricting the use of the partially identified facet type to only
be on the `Self` facet value. This provided a way to reduce exposure of the
partially identified facet type. But by differentiating the the partially
identified state from identified, we can form the rules around the state of the
facet type instead of the identity of the facet.
### Allowing limited conversions to partially identified facet types.
We considered allowing conversions from `N & J` to `N & K` where `N` is
partially identified, and `J` and `K` are identified.
It seems possible to support this for symbolic facets, by not storing the set of
witnesses in the facet value. If the facet type is partially identified, we can
defer the collection of witnesses, and just store the facet types that the facet
was converted from. In this model, the facet type itself acts as a type of
witness that we will will be able to find a witness later once the facet type is
identified.
We leave this to a future proposal if and when we find this additional
complexity worth adding to the language model.
+107
View File
@@ -0,0 +1,107 @@
# Support octal literals
<!--
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
-->
[Pull request](https://github.com/carbon-language/carbon-lang/pull/6910)
<!-- toc -->
## Table of contents
- [Abstract](#abstract)
- [Problem](#problem)
- [Background](#background)
- [Proposal](#proposal)
- [Future work](#future-work)
- [File permissions API](#file-permissions-api)
- [Rationale](#rationale)
- [Alternatives considered](#alternatives-considered)
- [No octal literals](#no-octal-literals)
<!-- tocstop -->
## Abstract
Support octal literals, mainly for migrating Unix file permissions. Reflects
leads decision
[#6821](https://github.com/carbon-language/carbon-lang/issues/6821).
## Problem
Carbon currently does not support octal numeric literals, because they're very
rare, as previously decided in proposal
[#143: Numeric literals](https://github.com/carbon-language/carbon-lang/pull/143).
However, as part of interoperability with POSIX file system calls such as
[`umask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/umask.html),
we want an easy way to express octal file permissions.
## Background
Leads discussed support of octal literals in issue
[#6821: Support octal literals](https://github.com/carbon-language/carbon-lang/issues/6821).
Unix file permissions written in octal are familiar to both programmers and
non-programmers who have experience administering Unix-like machines. For
example:
- `chmod OCTAL-MODE FILE...`
- [POSIX `mode_t` values](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html),
including the argument to
[`umask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/umask.html).
However, they are are not likely to be readable to those unfamiliar with them,
nor are they very common in code. We also expect these to be the primary use of
octal numeric literals in Carbon.
Given these issues, proposal #143
[rejected octal literals](/proposals/p0143.md#octal-literals). Now, we're
testing interoperability of POSIX file system calls, and we are considering
octal literals as a potential solution.
Proposal #143 [discussed the Carbon-style `0o` versus C++-style `0` prefix for
octal literals. The same logic still applies, so we will not address it here.
## Proposal
Introduce support for octal literals using the `0o` prefix (for example,
`0o755`), followed by one or more octal digits (`0-7`). This provides a very
simple lexical space for octal numbers, mapping clearly from C++ and building
consistently off the existing `0x...` syntax for hexadecimal and `0b...` syntax
for binary.
## Future work
### File permissions API
We may still provide a file permissions API in Carbon, for example as part of a
`Core` file system API. This proposal takes no stance on what that API should
look like. The only decision being made right now is that supporting octal
literals is worthwhile for interoperability and migration.
## Rationale
This proposal effectively advances Carbon's goals by focusing on:
- [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code):
Providing a direct counterpart for C++ octal literals simplifies the
migration of Unix file system code without needing to wait for a better file
permission API.
- [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):
The explicit `0o` prefix avoids the frequent confusion caused by C++'s
leading `0` syntax, while maintaining consistency with hex and binary
prefixes.
- [Software and language evolution](/docs/project/goals.md#software-and-language-evolution):
The `0o` octal literal syntax is consistent with other literals. We don't
expect it to hinder future language features.
## Alternatives considered
### No octal literals
Proposal #143 rejected octal literals. The main argument was that they are
rarely used. However, the cost of octal literal syntax is low, and the benefit
for C++ interoperability and migration is enough that we should add them.
+10
View File
@@ -194,6 +194,16 @@ def main() -> None:
assert jj_bin # For mypy.
_run([jj_bin, "new", parsed_args.branch_start_point])
_run([jj_bin, "bookmark", "create", branch])
_run(
[
jj_bin,
"bookmark",
"track",
branch,
"--remote",
parsed_args.remote,
]
)
# Copy template.md to a temp file.
template_path = "proposals/scripts/template.md"
+1 -1
View File
@@ -4,5 +4,5 @@
[tool.black]
line-length = 80
target-version = ['py36', 'py37', 'py38']
target-version = ['py310']
include = '\.pyi?$'
+5 -46
View File
@@ -24,7 +24,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""
import argparse
import json
import subprocess
import sys
from typing import Any, Dict
@@ -78,6 +77,9 @@ def _build_generated_files(
# We also need the Bazel C++ runfiles that aren't "generated", but are
# not linked into place until built.
+ ["@bazel_tools//tools/cpp/runfiles:runfiles"]
# Also include any deps that require `_virtual_includes` to be fully
# populated through a special C++ rule.
+ ["//scripts:deps_for_clangd_tidy"],
)
@@ -97,44 +99,6 @@ def _get_config_for_entry(entry: Dict[str, Any]) -> str:
return str(obj_file.split("/")[1])
def _filter_compilation_database(file_path: str) -> None:
"""Filters out duplicate exec-config entries from the database."""
print("Filtering out duplicate exec-configuration entries...")
try:
with open(file_path, "r") as f:
commands = json.load(f)
except FileNotFoundError:
print(f"Error: The file '{file_path}' was not found.")
sys.exit(1)
except json.JSONDecodeError:
print(f"Error: The file '{file_path}' is not a valid JSON file.")
sys.exit(1)
# We want to skip compiles that were in the "exec" configuration for tools.
# Because we generate compile commands for every bazel cc_* target in the
# main configuration, even if only used by tools, their sources should be
# covered and the exec configuration would simply be a duplicate.
#
# Detecting this based on the `-exec-` string in the configuration name of
# the directory is a bit of a hack, but even using the `--notool_deps`
# argument, Bazel seems to sometimes include this configuration in the query
# that produces the compilation database.
filtered_commands = [
entry
for entry in commands
if "-exec-" not in _get_config_for_entry(entry)
]
with open(file_path, "w") as f:
# Use indent=4 for a human-readable, pretty-printed output file
json.dump(filtered_commands, f, indent=4)
print(
"Filtered out "
f"{len(commands) - len(filtered_commands)} "
"duplicate entries..."
)
def main() -> None:
parser = argparse.ArgumentParser(
description=__doc__,
@@ -179,17 +143,12 @@ def main() -> None:
]
+ args.extra_bazel_flag
+ [
"@hedron_compile_commands//:refresh_all",
"//:generate_compile_commands",
"--",
]
+ args.extra_bazel_flag
+ [
"--notool_deps",
]
+ [f"--extra_aquery_arg={arg}" for arg in args.extra_bazel_flag]
)
_filter_compilation_database("compile_commands.json")
if __name__ == "__main__":
main()
+12
View File
@@ -295,6 +295,18 @@ def main() -> None:
all_missing_deps: list[tuple[str, set[str]]] = []
any_ambiguous = False
for rule_name, rule in carbon_rules.items():
# Skip rules building runtimes as the rules that provide their sources
# are not analyzed by this script.
if rule_name in [
"//toolchain/install:builtins",
"//toolchain/install:builtins_internal",
"//toolchain/install:libc_internal_libcxx",
"//toolchain/install:libcxx",
"//toolchain/install:libcxxabi_internal",
"//toolchain/install:libcxxabi",
"//toolchain/install:libunwind",
]:
continue
missing_deps, ambiguous = get_missing_deps(
header_to_rule_map, generated_files, rule
)
+1 -1
View File
@@ -18,7 +18,7 @@ $(git diff --summary "${COMMIT_SHA}^!")
# Setup global git configuration.
GIT_USERNAME="CarbonInfraBot"
git config --global user.email "carbon-external-infra@google.com"
git config --global user.email "infra-role@carbon-lang.dev"
git config --global user.name "$GIT_USERNAME"
declare -A MIRRORS
+23
View File
@@ -137,3 +137,26 @@ cc_test(
"@llvm-project//llvm:Support",
],
)
cc_library(
name = "unified_diff_matcher",
testonly = 1,
hdrs = ["unified_diff_matcher.h"],
deps = [
"//common:check",
"@googletest//:gtest",
"@llvm-project//llvm:Support",
],
)
cc_test(
name = "unified_diff_matcher_test",
size = "small",
srcs = ["unified_diff_matcher_test.cpp"],
deps = [
":gtest_main",
":unified_diff_matcher",
"@googletest//:gtest",
"@llvm-project//llvm:Support",
],
)
+300
View File
@@ -0,0 +1,300 @@
// 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
#ifndef CARBON_TESTING_BASE_UNIFIED_DIFF_MATCHER_H_
#define CARBON_TESTING_BASE_UNIFIED_DIFF_MATCHER_H_
#include <gmock/gmock.h>
#include <algorithm>
#include <optional>
#include <string>
#include <utility>
#include "common/check.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SmallVector.h"
namespace Carbon::Testing {
// Matcher that compares the elements of two containers and produces a unified
// diff on failure.
template <typename Container>
class UnifiedDiffMatcher {
public:
explicit UnifiedDiffMatcher(Container expected)
: expected_(std::move(expected)) {}
// Matches `actual` against `expected_`. Returns true on a match; returns
// false and prints a unified diff to `listener` on a mismatch.
template <typename ActualContainer>
auto MatchAndExplain(const ActualContainer& actual,
testing::MatchResultListener* listener) const -> bool;
auto DescribeTo(std::ostream* os) const -> void {
*os << "matches elements with unified diff";
}
auto DescribeNegationTo(std::ostream* os) const -> void {
*os << "does not match elements with unified diff";
}
private:
// A 2D array, stored contiguously. Rows correspond to `expected_`'s elements,
// and columns correspond to the actual container's elements.
template <typename T>
class Table;
// The result of a `Matches` check between an expected and actual element.
enum class MatchResult : uint8_t { Unknown, Matches, DoesNotMatch };
// Checks whether `actual_element` matches `expected_[expected_index]`. It
// first checks whether a cached result exists. If not, it evaluates the
// match and stores the result in `match_results`.
template <typename ActualElement>
auto IsElementMatch(size_t expected_index, size_t actual_index,
const ActualElement& actual_element,
Table<MatchResult>& match_results) const -> bool {
MatchResult cached_result = match_results.Get(expected_index, actual_index);
if (cached_result != MatchResult::Unknown) {
return cached_result == MatchResult::Matches;
}
bool is_match =
testing::MatcherCast<const ActualElement&>(expected_[expected_index])
.Matches(actual_element);
match_results.Set(
expected_index, actual_index,
is_match ? MatchResult::Matches : MatchResult::DoesNotMatch);
return is_match;
}
// Returns true if every element in `expected_` matches the corresponding
// element in `actual`. Stores comparisons in `match_results`.
template <typename ActualContainer>
auto IsEqual(const ActualContainer& actual,
Table<MatchResult>& match_results) const -> bool;
// Populates `subsequences` with the longest common matching subsequences
// found when comparing `actual` and `expected_`. Stores comparisons in
// `match_results`.
template <typename ActualContainer>
auto GetLongestCommonSubsequences(const ActualContainer& actual,
Table<MatchResult>& match_results,
Table<int>& subsequences) const -> void;
// Prints the unified diff.
template <typename ActualContainer>
auto PrintDiff(const ActualContainer& actual,
Table<MatchResult>& match_results,
const Table<int>& subsequences,
testing::MatchResultListener* listener) const -> void;
// The expected elements.
Container expected_;
};
// Returns a polymorphic matcher that acts similarly to
// ElementsAreArray but produces a unified diff on failure.
template <typename Container>
auto ElementsAreArrayWithUnifiedDiff(Container expected) {
return testing::MakePolymorphicMatcher(
UnifiedDiffMatcher<Container>(std::move(expected)));
}
// -----------------------------------------------------------------------------
// Internal implementation details follow.
// -----------------------------------------------------------------------------
template <typename Container>
template <typename T>
class UnifiedDiffMatcher<Container>::Table {
public:
// Constructs a table with dimensions of expected_size and actual_size,
// corresponding to the containers being compared.
Table(int expected_size, int actual_size, T default_value)
: actual_size_(actual_size),
data_(expected_size * actual_size, default_value) {}
// Sets the value at the given expected_index and actual_index.
auto Set(int expected_index, int actual_index, T value) -> void {
data_[expected_index * actual_size_ + actual_index] = std::move(value);
}
// Gets the value at the given expected_index and actual_index.
auto Get(int expected_index, int actual_index) const -> T {
return data_[expected_index * actual_size_ + actual_index];
}
private:
// The actual_size of the table.
int actual_size_;
// The contiguous data storage for the table.
llvm::SmallVector<T> data_;
};
template <typename Container>
template <typename ActualContainer>
auto UnifiedDiffMatcher<Container>::MatchAndExplain(
const ActualContainer& actual, testing::MatchResultListener* listener) const
-> bool {
Table<MatchResult> match_results(expected_.size(), std::size(actual),
MatchResult::Unknown);
if (IsEqual(actual, match_results)) {
return true;
}
if (listener->IsInterested()) {
Table<int> subsequences(expected_.size() + 1, std::size(actual) + 1, 0);
GetLongestCommonSubsequences(actual, match_results, subsequences);
PrintDiff(actual, match_results, subsequences, listener);
}
return false;
}
template <typename Container>
template <typename ActualContainer>
auto UnifiedDiffMatcher<Container>::IsEqual(
const ActualContainer& actual, Table<MatchResult>& match_results) const
-> bool {
if (expected_.size() != std::size(actual)) {
return false;
}
for (auto [i, actual_element] : llvm::enumerate(actual)) {
if (!IsElementMatch(i, i, actual_element, match_results)) {
return false;
}
}
return true;
}
template <typename Container>
template <typename ActualContainer>
auto UnifiedDiffMatcher<Container>::GetLongestCommonSubsequences(
const ActualContainer& actual, Table<MatchResult>& match_results,
Table<int>& subsequences) const -> void {
for (auto expected_index : llvm::seq(expected_.size())) {
for (auto [actual_index, actual_element] : llvm::enumerate(actual)) {
int subsequence_value;
if (IsElementMatch(expected_index, actual_index, actual_element,
match_results)) {
// If the elements match, the LCS length increases by 1 relative to
// the prefixes where both elements are excluded.
subsequence_value = subsequences.Get(expected_index, actual_index) + 1;
} else {
// Otherwise, the LCS length is the maximum of the LCS lengths
// relative to the prefixes where one element is excluded.
subsequence_value =
std::max(subsequences.Get(expected_index, actual_index + 1),
subsequences.Get(expected_index + 1, actual_index));
}
subsequences.Set(expected_index + 1, actual_index + 1, subsequence_value);
}
}
}
template <typename Container>
template <typename ActualContainer>
auto UnifiedDiffMatcher<Container>::PrintDiff(
const ActualContainer& actual, Table<MatchResult>& match_results,
const Table<int>& subsequences,
testing::MatchResultListener* listener) const -> void {
// A line in the diff output.
struct DiffLine {
enum class Kind { Match, ActualOnly, ExpectedOnly };
Kind kind;
// Only used for `Match` and `ActualOnly`.
const ActualContainer::value_type* actual_value;
int expected_index;
};
llvm::SmallVector<DiffLine> diff;
// Reserve a quick upper bound of the size.
diff.reserve(expected_.size() + std::size(actual));
// Reconstruct the diff by backtracking from the end of the table.
int expected_index = expected_.size() - 1;
int actual_index = std::size(actual) - 1;
auto actual_it = std::end(actual) - 1;
while (expected_index >= 0 || actual_index >= 0) {
auto match_result = (expected_index >= 0 && actual_index >= 0)
? match_results.Get(expected_index, actual_index)
: MatchResult::DoesNotMatch;
CARBON_CHECK(match_result != MatchResult::Unknown);
if (match_result == MatchResult::Matches) {
// The element is in both lists for the diff.
diff.push_back({.kind = DiffLine::Kind::Match,
.actual_value = &*actual_it,
.expected_index = expected_index});
--expected_index;
--actual_index;
--actual_it;
} else if (actual_index >= 0 &&
(expected_index < 0 ||
subsequences.Get(expected_index + 1, actual_index) >=
subsequences.Get(expected_index, actual_index + 1))) {
// Dropping an element from `actual` preserves the LCS length, so treat it
// as an insertion.
diff.push_back({.kind = DiffLine::Kind::ActualOnly,
.actual_value = &*actual_it,
.expected_index = std::max(0, expected_index)});
--actual_index;
--actual_it;
} else {
// Otherwise, treat it as a deletion from `expected`.
diff.push_back({.kind = DiffLine::Kind::ExpectedOnly,
.actual_value = nullptr,
.expected_index = expected_index});
--expected_index;
}
}
struct PrintRange {
int begin;
int end;
};
llvm::SmallVector<PrintRange> print_ranges;
constexpr int ContextLines = 3;
for (auto [i, line] :
llvm::reverse(llvm::zip_equal(llvm::seq<int>(diff.size()), diff))) {
if (line.kind != DiffLine::Kind::Match) {
PrintRange range = {
.begin = std::max(0, i - ContextLines),
.end = std::min<int>(diff.size() - 1, i + ContextLines)};
if (print_ranges.empty() || print_ranges.back().begin > range.end + 1) {
print_ranges.push_back(range);
} else {
// Merge diffs with overlapping context.
print_ranges.back().begin = range.begin;
}
}
}
*listener << "unified diff (- expected, + actual):\n";
for (const auto& range : print_ranges) {
*listener << "=== diff in expected elements "
<< diff[range.end].expected_index + 1 << " to "
<< diff[range.begin].expected_index + 1 << " (1-based index):\n";
for (auto i : llvm::reverse(llvm::seq_inclusive(range.begin, range.end))) {
const auto& line = diff[i];
if (line.kind == DiffLine::Kind::Match) {
*listener << " " << *line.actual_value << "\n";
} else if (line.kind == DiffLine::Kind::ActualOnly) {
*listener << "+ " << *line.actual_value << "\n";
} else {
*listener << "- ";
expected_[line.expected_index].DescribeTo(listener->stream());
*listener << "\n";
}
}
}
*listener << "=== diff end\n";
}
} // namespace Carbon::Testing
#endif // CARBON_TESTING_BASE_UNIFIED_DIFF_MATCHER_H_
+247
View File
@@ -0,0 +1,247 @@
// 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 "testing/base/unified_diff_matcher.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <string>
#include "llvm/ADT/SmallVector.h"
namespace Carbon::Testing {
namespace {
using ::testing::Matcher;
using ::testing::StrEq;
// Asserts that when expected does not match actual, the string
// representation of the produced diff equals expected_diff.
auto ExpectUnifiedDiff(const llvm::SmallVector<std::string>& actual,
const llvm::SmallVector<Matcher<std::string>>& expected,
const std::string& expected_diff) -> void {
testing::StringMatchResultListener listener;
EXPECT_FALSE(testing::ExplainMatchResult(
ElementsAreArrayWithUnifiedDiff(expected), actual, &listener));
EXPECT_THAT(listener.str(), testing::Eq(expected_diff));
}
TEST(UnifiedDiffMatcherTest, Matches) {
llvm::SmallVector<std::string> actual = {"A", "B", "C"};
llvm::SmallVector<Matcher<std::string>> expected = {StrEq("A"), StrEq("B"),
StrEq("C")};
EXPECT_THAT(actual, ElementsAreArrayWithUnifiedDiff(expected));
}
TEST(UnifiedDiffMatcherTest, MismatchMissing) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 3 (1-based index):
A
- is equal to "B"
C
=== diff end
)";
ExpectUnifiedDiff({"A", "C"}, {StrEq("A"), StrEq("B"), StrEq("C")},
ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, MismatchExtra) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 2 (1-based index):
A
+ B
C
=== diff end
)";
ExpectUnifiedDiff({"A", "B", "C"}, {StrEq("A"), StrEq("C")}, ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, MismatchBoth) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 2 (1-based index):
A
- is equal to "C"
+ B
=== diff end
)";
ExpectUnifiedDiff({"A", "B"}, {StrEq("A"), StrEq("C")}, ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, MismatchMultiple) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 5 (1-based index):
A
- is equal to "B"
+ X
C
- is equal to "D"
+ Y
E
=== diff end
)";
ExpectUnifiedDiff(
{"A", "X", "C", "Y", "E"},
{StrEq("A"), StrEq("B"), StrEq("C"), StrEq("D"), StrEq("E")},
ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, MismatchLongContext) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 2 to 8 (1-based index):
1
2
3
- is equal to "X"
+ 4
5
6
7
=== diff end
)";
ExpectUnifiedDiff({"0", "1", "2", "3", "4", "5", "6", "7", "8"},
{StrEq("0"), StrEq("1"), StrEq("2"), StrEq("3"), StrEq("X"),
StrEq("5"), StrEq("6"), StrEq("7"), StrEq("8")},
ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, Mismatch5LineContext) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 7 (1-based index):
- is equal to "X"
+ 0
1
2
3
4
5
- is equal to "Y"
+ 6
=== diff end
)";
ExpectUnifiedDiff({"0", "1", "2", "3", "4", "5", "6"},
{StrEq("X"), StrEq("1"), StrEq("2"), StrEq("3"), StrEq("4"),
StrEq("5"), StrEq("Y")},
ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, Mismatch6LineContext) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 8 (1-based index):
- is equal to "X"
+ 0
1
2
3
4
5
6
- is equal to "Y"
+ 7
=== diff end
)";
ExpectUnifiedDiff({"0", "1", "2", "3", "4", "5", "6", "7"},
{StrEq("X"), StrEq("1"), StrEq("2"), StrEq("3"), StrEq("4"),
StrEq("5"), StrEq("6"), StrEq("Y")},
ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, Mismatch7LineContext) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 4 (1-based index):
- is equal to "X"
+ 0
1
2
3
=== diff in expected elements 6 to 9 (1-based index):
5
6
7
- is equal to "Y"
+ 8
=== diff end
)";
ExpectUnifiedDiff({"0", "1", "2", "3", "4", "5", "6", "7", "8"},
{StrEq("X"), StrEq("1"), StrEq("2"), StrEq("3"), StrEq("4"),
StrEq("5"), StrEq("6"), StrEq("7"), StrEq("Y")},
ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, MismatchEmptyExpected) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 1 (1-based index):
+ A
=== diff end
)";
ExpectUnifiedDiff({"A"}, {}, ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, MismatchEmptyActual) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 1 (1-based index):
- is equal to "A"
=== diff end
)";
ExpectUnifiedDiff({}, {StrEq("A")}, ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, MismatchLongDifference) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 4 (1-based index):
1
- is equal to "2"
- is equal to "3"
+ X
+ Y
+ Z
4
=== diff end
)";
ExpectUnifiedDiff({"1", "X", "Y", "Z", "4"},
{StrEq("1"), StrEq("2"), StrEq("3"), StrEq("4")},
ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, MismatchGreedyResyncActualMissing) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 6 (1-based index):
1
2
- is equal to "3"
+ X
+ 7
4
5
6
=== diff end
)";
ExpectUnifiedDiff({"1", "2", "X", "7", "4", "5", "6", "7", "8", "9"},
{StrEq("1"), StrEq("2"), StrEq("3"), StrEq("4"), StrEq("5"),
StrEq("6"), StrEq("7"), StrEq("8"), StrEq("9")},
ExpectedDiff);
}
TEST(UnifiedDiffMatcherTest, MismatchGreedyResyncExpectedMissing) {
constexpr char ExpectedDiff[] = R"(unified diff (- expected, + actual):
=== diff in expected elements 1 to 7 (1-based index):
1
2
- is equal to "X"
- is equal to "7"
+ 3
4
5
6
=== diff end
)";
ExpectUnifiedDiff(
{"1", "2", "3", "4", "5", "6", "7", "8", "9"},
{StrEq("1"), StrEq("2"), StrEq("X"), StrEq("7"), StrEq("4"), StrEq("5"),
StrEq("6"), StrEq("7"), StrEq("8"), StrEq("9")},
ExpectedDiff);
}
} // namespace
} // namespace Carbon::Testing
+1
View File
@@ -54,6 +54,7 @@ cc_library(
"//common:raw_string_ostream",
"//common:set",
"//testing/base:file_helpers",
"//testing/base:unified_diff_matcher",
"@abseil-cpp//absl/flags:flag",
"@abseil-cpp//absl/flags:parse",
"@abseil-cpp//absl/strings",
+3 -7
View File
@@ -50,6 +50,7 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/ThreadPool.h"
#include "testing/base/unified_diff_matcher.h"
#include "testing/file_test/autoupdate.h"
#include "testing/file_test/run_test.h"
#include "testing/file_test/test_file.h"
@@ -119,7 +120,6 @@ static auto SplitOutput(llvm::StringRef output)
llvm::StringRef(output).split(lines, "\n");
return llvm::SmallVector<std::string_view>(lines.begin(), lines.end());
}
// Verify that the success and `fail_` prefix use correspond. Separately handle
// both cases for clearer test failures.
static auto CompareFailPrefix(llvm::StringRef filename, bool success) -> void {
@@ -259,13 +259,9 @@ auto FileTestCase::TestBody() -> void {
} else {
EXPECT_THAT(SplitOutput(test_file.actual_stdout),
ElementsAreArray(test_file.expected_stdout))
<< "Actual text:\n"
<< test_file.actual_stdout;
ElementsAreArrayWithUnifiedDiff(test_file.expected_stdout));
EXPECT_THAT(SplitOutput(test_file.actual_stderr),
ElementsAreArray(test_file.expected_stderr))
<< "Actual text:\n"
<< test_file.actual_stderr;
ElementsAreArrayWithUnifiedDiff(test_file.expected_stderr));
}
if (HasFailure()) {
+2 -2
View File
@@ -104,10 +104,10 @@ static auto CollectOutputIfCapturing(TestFile& test_file) -> void {
auto RunTestFile(const FileTestBase& test_base, bool dump_output,
TestFile& test_file) -> ErrorOr<Success> {
llvm::SmallVector<TestFile::Split*> all_splits;
for (auto& split : test_file.file_splits) {
for (auto& split : test_file.include_file_splits) {
all_splits.push_back(&split);
}
for (auto& split : test_file.include_file_splits) {
for (auto& split : test_file.file_splits) {
all_splits.push_back(&split);
}
+1 -1
View File
@@ -10,4 +10,4 @@
// TIP: To dump output, run:
// TIP: bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_empty.carbon
// CHECK:STDOUT: 3 args: `default_args`, `include_empty.carbon`, `empty.carbon`
// CHECK:STDOUT: 3 args: `default_args`, `empty.carbon`, `include_empty.carbon`
+1 -1
View File
@@ -11,4 +11,4 @@
// TIP: To dump output, run:
// TIP: bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_extra_args.carbon
// CHECK:STDOUT: 6 args: `default_args`, `include_extra_args.carbon`, `include_files/extra_args.carbon`, `bar`, `baz`, `foo`
// CHECK:STDOUT: 6 args: `default_args`, `include_files/extra_args.carbon`, `include_extra_args.carbon`, `bar`, `baz`, `foo`
+1 -1
View File
@@ -10,5 +10,5 @@
// TIP: To dump output, run:
// TIP: bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_no_split.carbon
// CHECK:STDOUT: 3 args: `default_args`, `include_no_split.carbon`, `include_files/no_split.carbon`
// CHECK:STDOUT: 3 args: `default_args`, `include_files/no_split.carbon`, `include_no_split.carbon`
// CHECK:STDOUT: include_files/no_split.carbon:5: no split
+1 -1
View File
@@ -10,7 +10,7 @@
// TIP: To dump output, run:
// TIP: bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_recursive.carbon
// CHECK:STDOUT: 6 args: `default_args`, `include_recursive.carbon`, `c.carbon`, `d.carbon`, `a.carbon`, `b.carbon`
// CHECK:STDOUT: 6 args: `default_args`, `c.carbon`, `d.carbon`, `a.carbon`, `b.carbon`, `include_recursive.carbon`
// CHECK:STDOUT: c.carbon:2: c
// CHECK:STDOUT: d.carbon:2: d
// CHECK:STDOUT: a.carbon:2: a
+1 -1
View File
@@ -12,5 +12,5 @@
// TIP: To dump output, run:
// TIP: bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_repeated.carbon
// CHECK:STDOUT: 3 args: `default_args`, `include_repeated.carbon`, `include_files/no_split.carbon`
// CHECK:STDOUT: 3 args: `default_args`, `include_files/no_split.carbon`, `include_repeated.carbon`
// CHECK:STDOUT: include_files/no_split.carbon:5: no split
+1 -1
View File
@@ -10,6 +10,6 @@
// TIP: To dump output, run:
// TIP: bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_split.carbon
// CHECK:STDOUT: 4 args: `default_args`, `include_split.carbon`, `a.carbon`, `b.carbon`
// CHECK:STDOUT: 4 args: `default_args`, `a.carbon`, `b.carbon`, `include_split.carbon`
// CHECK:STDOUT: a.carbon:2: a
// CHECK:STDOUT: b.carbon:2: b
+1 -1
View File
@@ -11,7 +11,7 @@ run_tool(
name = "carbon",
data = ["//toolchain/install:install_data"],
env = cc_env(),
tool = "//toolchain/install:prefix/bin/carbon",
tool = "//toolchain/install:carbon-busybox",
)
# A convenience target for running the toolchain with the full prelude
+4
View File
@@ -8,6 +8,10 @@ load("runtimes_build_info.bzl", "generate_runtimes_build_info_cc_library")
package(default_visibility = ["//visibility:public"])
exports_files([
"runtimes_build_vars.tpl.bzl",
])
cc_library(
name = "block_value_store",
hdrs = ["block_value_store.h"],
+2 -3
View File
@@ -21,8 +21,7 @@
namespace Carbon {
// The location within our Bazel output tree of the install root.
static constexpr llvm::StringLiteral BazelRoot =
"carbon/toolchain/install/prefix/lib/carbon/";
static constexpr llvm::StringLiteral BazelRoot = "carbon/toolchain/install/";
// Path within an install root for our marker of a valid install.
static constexpr llvm::StringLiteral MarkerPath = "carbon_install.txt";
@@ -84,7 +83,7 @@ auto InstallPaths::ReadClangHeadersManifest() const
// root. Consider whether this manifest should be within the install or
// consider moving the code to access it to be separate and specific to the
// infrastructure needing it.
return ReadManifest(root_ / "../../..", "clang_headers_manifest.txt");
return ReadManifest(root_, "clang_headers_manifest.txt");
}
auto InstallPaths::ReadManifest(std::filesystem::path manifest_path,
+3 -3
View File
@@ -148,7 +148,7 @@ class InstallPaths {
auto SetError(llvm::Twine message) -> void;
// Check that the install paths have a marker file at
// `root()/lib/carbon/carbon_install.txt". If not, calls `SetError` with the
// `root()/carbon_install.txt". If not, calls `SetError` with the
// relevant error message.
auto CheckMarkerFile() -> void;
@@ -162,7 +162,7 @@ class InstallPaths {
//
// When run from Bazel (for example, in unit tests or development binaries)
// this will look like:
// `bazel-bin/some/bazel/target.runfiles/_main/toolchain/install/prefix/lib/carbon`
// `bazel-bin/some/bazel/target.runfiles/_main/toolchain/install`
//
// When installed, it's expected to be similar to the CMake install prefix,
// followed by `lib/carbon`:
@@ -177,7 +177,7 @@ class InstallPaths {
// our installation to behave in a similar and compatible way.
//
// The hierarchy of files beneath the install root can be found in the
// BUILD's `install_dirs` entry for `lib/carbon`.
// BUILD rules in `//toolchain/install`.
std::filesystem::path root_;
// The opened root directory.
+4 -13
View File
@@ -32,7 +32,6 @@ namespace {
using ::bazel::tools::cpp::runfiles::Runfiles;
using ::testing::_;
using ::testing::EndsWith;
using ::testing::Eq;
using ::testing::HasSubstr;
using Testing::IsSuccess;
@@ -61,14 +60,6 @@ class InstallPathsTest : public ::testing::Test {
ASSERT_THAT(root_result, IsSuccess(_));
Filesystem::Dir root = *std::move(root_result);
// Check that the root is located in the expected part of the FHS layout.
// TODO: Adjust this to work equally well on Windows.
EXPECT_THAT(root_path.native(), EndsWith("lib/carbon/"));
EXPECT_THAT(
root.Access("../../bin/carbon", Filesystem::AccessCheckFlags::Execute),
IsSuccess(Eq(true)))
<< "path: " << (root_path / "../../bin/carbon");
std::filesystem::path core_package_path = paths.core_package();
ASSERT_THAT(core_package_path, StartsWith(root_path));
EXPECT_THAT(Filesystem::Cwd().Access(core_package_path / "prelude.carbon"),
@@ -93,8 +84,8 @@ class InstallPathsTest : public ::testing::Test {
};
TEST_F(InstallPathsTest, RootBusybox) {
std::string installed_busybox_path = test_runfiles_->Rlocation(
"carbon/toolchain/install/prefix/lib/carbon/carbon-busybox");
std::string installed_busybox_path =
test_runfiles_->Rlocation("carbon/toolchain/install/carbon-busybox");
auto paths = InstallPaths::MakeExeRelative(installed_busybox_path);
ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();
@@ -102,8 +93,8 @@ TEST_F(InstallPathsTest, RootBusybox) {
}
TEST_F(InstallPathsTest, RootExplicit) {
std::string marker_path = test_runfiles_->Rlocation(
"carbon/toolchain/install/prefix/lib/carbon/carbon_install.txt");
std::string marker_path =
test_runfiles_->Rlocation("carbon/toolchain/install/carbon_install.txt");
llvm::StringRef root_path = marker_path;
CARBON_CHECK(root_path.consume_back("carbon_install.txt"),

Some files were not shown because too many files have changed in this diff Show More