For a symbolic value with a type being a facet, we need to find a
witness either from the facet's type or from an impl. Custom witness is
for producing a concrete final witness, but there is no such witness in
this case. We should fail to find a witness, and defer to impl lookup to
find the Destroy witness.
Currently it tries to find a witness from the facet type, but it ignores
named constraints, which means it's incomplete at best. But there's no
value in trying to say that the value is trivially destroyable, when it
has a type that impls Destroy. It may not be trivial, and we can't
actually make a witness for it while symbolic.
We checked that requirements inside the impl-as target interface were
satisfied. But we also need to check that requirements coming from the
constraint facet type, or named constraints that it targets, are
satisfied.
The check for a specific in `TryMapClassType` is unnecessary;
immediately after it calls `ExportClassToCpp`, which has the same check.
The latter also has a `context.TODO`, which provides a clearer error.
Also improved the `LocId` in `ExportClassToCpp` to use the location of
the first decl rather than the empty location of the class type. This is
the same fix as
https://github.com/carbon-language/carbon-lang/pull/7533, just applied a
little more broadly. This makes the `context.TODO` above point at the
class rather than the start of the source file.
rumdl error broke the proposal script execution:
```
rumdl check..............................................................Failed
- hook id: rumdl
- exit code: 1
proposals/p000003-test-proposal.md:15:5: [MD051] Link anchor '#todo-initial-proposal-setup' does not exist in document headings
Issues: Found 1 issues in 1 file (11ms)
```
So update the script to remove the TODO entry in the ToC to match
removing the TODO section.
Setting "type" to bright red to make comparison obvious:
(screenshots taken from VSCode)
Before
<img width="446" height="150" alt="Screenshot 2026-07-20 135558"
src="https://github.com/user-attachments/assets/81249005-99f1-47bb-af4f-ad6e8f2404fb"
/>
After
<img width="429" height="149" alt="Screenshot 2026-07-20 135738"
src="https://github.com/user-attachments/assets/acc83086-fe19-4a18-a833-968daed56229"
/>
I'm not super familiar with textmate/highlightjs, but I think what was
happening on line 5 is that the "type" scope is being extended to the
`=` after `.y`.
Adding `,` as an "end" token fixes this, and I think this is what
highlightjs already does.
I've also added "unused" as a keyword.
I wanted to move it to check but there'd still be an
IdentifiedFacetTypeId and we keep all Ids in sem_ir. So leaving it in
sem_ir, but moving it to its own file. This more clearly separates
DeclaredFacetTypes and IdentifiedFacetTypes.
Add a `return_type_id` field to `FunctionInfo` in
`toolchain/check/cpp/export.cpp`. As with the `explicit_params` field,
`ExportFunctionSpecializationToCpp` updates this to the return type in
the specific.
Refactored `BuildCppFunctionDeclForCarbonFn` into
`BuildCppFunctionDeclForNonGenericCarbonFn` and
`BuildCppFunctionDeclForGenericCarbonFn`, with `BuildCppFunctionDecl`
containing shared code.
The `generic_type_impls_interface.carbon` test is updated to include a
generic return type.
The `carbon_prelude` macro was defined in bazel/carbon_rules/defs.bzl.
This file contains `carbon_library` and `carbon_binary` which are
mostly intended as example Bazel rules for building Carbon binaries.
The `carbon_prelude` macro, however, is used now to build the runtimes
for the Carbon toolchain. We move it to a more central location where
the rest of the runtimes are processed, in
toolchain/runtimes/carbon_runtimes.bzl.
If the `match_first` is not followed by `{` avoid consuming whatever
comes after it. Recover by leaving whatever comes next alone. It could
even be the `FileEnd` token, and then we would crash when we read off
the end of the token stream looking for `FileEnd`.
The specific location's not ideal (rather than the open curly, or
semicolon for a declaration - the two locations should be the `class`
and then the class name), but the same as we do for functions for now &
enough to get by.
This specifically also fixes a crash I found due to dtors being
generated without a location (because implicitly created functions would
use the class's location), creating a function call without a debug
location, which fails the LLVM IR verifier.
We can end up emitting the same thunk from multiple compilations in some
cases -- in particular, when the thunk is wrapping a function that is
either synthesized by the compiler or imported from C++. When this
happens, we will have multiple-definition link errors unless we allow
redefinitions across multiple files.
It'd be nice to detect when we need to do this and when we don't, but
that's a bit tricky to do in practice. Ideally, in fact, we would use a
different strategy, and emit the thunks as discardable definitions in
each compilation that *uses* them. But for now emitting them with
weak_odr linkage seems like a good way to make progress.
Split up the CppRange interface into smaller parts, with the intent of
improving the diagnostic quality and making the implementation easier to
understand.
This also makes the implementation details of the CppRange machinery
private, which breaks one of the existing tests; that test is split into
two files, one which tests the low-level machinery works, and another
that tests the resulting prelude behavior.
This change exposes a crash in `where` expression handling, where we
would perform a substitution that creates a new `SpecificConstant` that
refers into a region of a generic that has never been resolved. Fix that
by resolving the definition region of a generic if eval sees a
`SpecificConstant` that refers into it. This is usually not necessary
because something else should have resolved that region first, but that
doesn't happen here.
---------
Co-authored-by: Dana Jansens <danakj@orodu.net>
As discussed in the 2026-06-14 toolchain open meeting, `Range`
is a better fit for the prelude than as a general library in
`Core`. This PR moves `Range` into the prelude, and updates
the build infrastructure and various tests to reflect that
change.
This supports impl lookup choosing an impl that targets a generic
interface through a named constraint, without crashing.
Instead of assuming the impl's target is a facet type containing an
interface, we use the identified facet type to find the specific
interface it targets.
The constant value may lose the designator during eval, such as an
`ImplWitnessAccess` that resolves to some concrete type. Look in the
non-canonical instructions instead.
Since the introduction of `other_requirements`, we now have a dedicated
step in impl lookup for checking that the requirements of the query
facet type are satisfied. That is the place where we will be checking
same-type constraints, which `other_requirements` signals the presence
of.
Consolidate all checking of `other_requirements` to that step, which
reduces our use of `FacetTypeInfo` (as opposed to the
`IdentifiedFacetType`) and removes interest in same-type constraints
from code that is not related to them.
Refactors the link driver to automatically compile and cache the carbon
prelude for use in linking.
Implements a `carbon_library` rule for compiling the Core library
dependencies in the examples.
We can't use a `CallExpr` to call a constructor; use a
`CXXConstructExpr` instead. While this fixes the crash and gets us past
the initial constant evaluation, we still can't map the constant value
back into Carbon, so this doesn't actually make constexpr constructors
work yet. But it does stop Clang from crashing.
Fixes#7498.
Instead of tracking the cleanup scope depth on entry to each scope,
track an "ambient" cleanup scope depth that's *after* the destructors of
local variables in that scope. This gets increased to include the
destructors of local variables when we create a name-binding
declaration. Then, when we reach a point where temporaries should be
destroyed, run cleanups that are after the ambient cleanup scope depth
on the stack. This happens:
* At the `;` of a statement expression.
* At the `)` of an `if` or `while` statement.
* After performing the implied `HasValue()` call in a `for` statement.
Per informal agreement with leads, this means we lifetime-extend all
temporaries created in the initializer of a name-binding declaration to
the full scope of that declaration, but that temporaries created in an
expression statement are destroyed at the `;`.
Allow (don't diagnose) impls that have the same type structure if they
are associated with the same match_first block. Similarly, allow final
impls (made final by their enclosing match_first block) that overlap in
type structure when they are associated with the same match_first block.
If the type structures are the same, choose the first impl from the
match_first block.same.
If the type structures overlap but are not the same, and share a
match_first block, then we should choose the first overlapping impl from
the match_first block. This is true both for final and non-final impls.
See
https://github.com/carbon-language/carbon-lang/blob/de8b03faa3178ae683d8e7124fbcba81eb88e00c/proposals/p005337-interface-extension-and-final-impl-update.md#impl-selection-algorithm
But in the non-final case if there is an overlapping impl outside the
match_first, it can win if it's more specific.
When a Carbon virtual function overrides a C++ virtual function, we need
to export it with the C++ signature in order for it to work as an
override. Instead of mapping the C++ signature into Carbon and then back
again, use the original C++ signature from the base class as the
signature exported to C++.
Also add documentation explaining how we use thunks in C++ interop,
including in this new virtual function handling logic.
Replace the llvm::map_range based anonymous ranges returned by values()
and enumerate() with custom range and iterator types. This avoids
exposing complex template return types and improves encapsulation. But
most importantly, it is *much* cheaper to compile.
This change:
- Defines ValueStoreIterator, ValueStoreEnumerateIterator, and
ValueStoreRange templates in the Internal namespace.
- Exposes them via aliases in ValueStore: Iterator, ConstIterator,
Range, MutableRange, and EnumerateRange.
- Supports safe implicit conversion from Iterator to ConstIterator.
- Supports operator-> even when the value type is returned by value
(e.g., llvm::StringRef) by conditionally const-qualifying the pointer
type.
- Ensures C++20 comparison consistency with custom operator<=> and
operator== definitions.
- Restricts construction of these iterators and ranges to ValueStore
methods by using private constructors and friend declarations.
Assisted-by: Antigravity with Gemini
Previously the last decl had to be the definition. Now we allow a
declaration after a definition, so that the user can write a match_first
block last, and put (re-)declarations of impls in it, after the
definitions have already been written elsewhere.
We track the location of the decl that was associated with a match_first
block so that we can correctly point to it in diagnostics when an impl
is written twice in match_first blocks. Since impls may not be
redeclared across an import boundary, we will never have a `SemIR::Impl`
with a match_first from a different file in a redeclaration, so we don't
need to import the location of a previous decl that was in a match_first
for diagnostics. As such we just store a LocId on the `SemIR::Impl`
struct.
The `//@include-in-dumps` and `//@dump-sem-ir-begin`/`-end` tooling
directives were consumed for their side effects without a comment
record, so the tokens and comments together no longer reconstructed the
source: tooling that re-emits a file from them, such as `carbon format`,
silently dropped the directive lines. Now each recognized directive line
is also recorded as an ordinary full-line comment alongside its side
effect.
Adjacent full-line comments coalesce into one comment record only within
a category, determined by the byte after the `//` introducer: ordinary
comments (whitespace, or the end of the line or file), `//@...`
directives, and invalid introducers. A transition between categories
starts a new record, so a directive next to a comment block is its own
comment, while all the invalid spellings lump together to keep the
diagnostic noise at one per run.
The category boundary also fixes a lost directive: the invalid-comment
bulk skip compared only the `//` prefix, so `//!x` directly above
`//@dump-sem-ir-begin` absorbed the directive line and its side effect
was never recorded. Invalid comment runs now skip line by line (they
start from a diagnosed error, so they are not hot) and stop at a
whitespace or `@` introducer; the SIMD bulk skip handles only ordinary
comment blocks, whose prefix comparison already includes the whitespace
byte.
Nothing outside the lexer and the formatter reads comment records, and
lex dumps do not include comments, so no other behavior changes.
Assisted-by: Claude Code
Remove toolchain/parse/typed_nodes.h from transitive imports of tree.h
and node_stack.h to reduce compile-time overhead in toolchain/check.
Add an explicit include of typed_nodes.h to tree_and_subtrees.cpp where
it is needed for instantiating templates.
Assisted-by: Antigravity with Gemini
Remove clang/Frontend/CompilerInvocation.h from check_unit.h and forward
declare clang::CompilerInvocation instead to reduce header exposure.
Add an explicit include of CompilerInvocation.h to check_unit.cpp.
Assisted-by: Antigravity with Gemini
Remove clang/CodeGen/ModuleBuilder.h from toolchain/lower/file_context.h
to reduce transitive dependencies. Forward declare clang::CodeGenerator
and clang::FunctionDecl instead.
Add an explicit include of ModuleBuilder.h to context.cpp where the
complete types are required.
Assisted-by: Antigravity with Gemini
Because we merge cleanups across scopes in various cases, and want to
use linear indexes into the complete stack, the ArrayStack abstraction
is getting in the way more than it's helping. Switch to just a
SmallVector.
This loses the unit testing of the MergeIntoGrandparent logic. This is
covered indirectly by check tests still, but direct testing of it is a
bit tricky given that ScopeStack isn't set up for use without a Context.
Add extern template declarations and explicit template instantiations
for ValueStore<InstId, Inst> and ValueStore<EntityNameId, EntityName> to
prevent redundant template instantiations.
Place them in their respective domain files (inst.h/cpp and
entity_name.h/cpp) to maintain modularity.
Assisted-by: Antigravity with Gemini
The type of `.Self` introduced by `where` may contain a `.Self` inside
it. Freeze the type so that we have a consistent view of `.Self` inside
the facet type, where they are all frozen.
The type of `.Self` only has extend constraints from the LHS of the
`where`. So we need to copy any non-extend constraints into the
`where_stack` so they are available as early-impls and can be used for
impl lookups on the RHS of the where. We need to freeze any `.Self`
references in these just as we do for rewrite constraints.
Destroy local variables and temporaries at each `}`, and when branching
with `break` and `continue`. In `for` statements, destroy loop variables
along with anything created within the loop at the end of each loop
iteration, and destroy the cursor and range object when the loop
terminates.
Assisted-by: Gemini via Antigravity
---------
Co-authored-by: Geoff Romer <gromer@google.com>
Fix a few API issues. There's also a newly-added file in compiler-rt
that is not supposed to be built by default but is not being excluded
properly by a glob. Added a patch to exclude that and sent
https://github.com/llvm/llvm-project/pull/208861 upstream.
Instead of manually creating a map from symbolic types to concrete
types, create a Specific and look up parameter types via that Specific.
This allows C++ to call a Carbon function like `fn F[T: type](unused t:
T*) {}`. See generic_pointer.carbon.
Document the phase of associated constants, which the discussions of
contextual phase defaults never covered: an associated constant is
always a checked generic binding. This is deliberately not presented as
a contextual default, because no other phase is possible for the
construct; correspondingly, no phase keyword (including `template`) is
allowed on one. Also rework the associated constants section of the
design README where the migration left a non-sequitur ("set to
compile-time values ... and so are defined using a `let` declaration"):
describe the `let` syntax and the binding's contextual phase separately.
Use consistent terminology for bindings versus constants. Bindings are
"checked" or "template" (generic) bindings, replacing the "symbolic
binding" and bare "generic binding" terms, so "symbolic" now only
describes constants and values. The "Symbolic facet bindings" section of
the generics details becomes "Checked facet bindings". The
expression-phase terms "symbolic constant" and "template constant" are
unchanged, and the binding-pattern definitions now name the constant
each kind binds. Template bindings are additionally described as
dependent and late checked, with each instantiation providing the
binding's value.
Also normalize the remaining "regular parameter" mentions to "runtime
parameter" to match the binding terminology, and describe the
compile-time "let template" as introducing a template generic binding
"T: C" whose uses are template constants.
Assisted-by: Claude Code
When we check an `impl` decl, find the containing `match_first` block,
if any, and store a connection to it in the `SemIR::Impl` structure,
along with the impl's position in that `match_first` block so that we
can sort/prioritize the `SemIR::Impl`s later.
Also, update the `is_final` flag if the `match_first` block is modified
as `final`. But ensure we diagnose trying to put a `final impl`, or a
redeclaration of one, in a `match_first` block. Also diagnose if an impl
is attached to a `match_first` block more than once - either in two
different blocks or in the same block at different positions.
Putting the `match_first` connection on the `SemIR::Impl` structure
means we have to import it, so implement import and add a smoke test for
that, which ensures nothing explodes.
Drop the `scope_stack` entry for the `match_first` block, as it was not
needed. Once we started tracking the `match_first` size on the `Context`
class, it became more straightforward to just store the `match_first`
decl `InstId` in the same place. The `match_first` block is not supposed
to act like a different scope for the purpose of redecls anyhow, so it's
a bit simpler this way.
It must be in a namespace, function, or class. In particular, it can't
be in another match_first, doing so immediately associates any impl
inside with two different match_first scopes, but we only want them
associated with one for prioritization.
Push a scope_stack entry for match_first blocks, and handle impls being
inside those scope entries. An impl should not use the `match_first`
block as its "enclosing scope" for the purpose of deciding if the impl
is a redecl of another impl. We should look through it to the class or
namespace the impl (and match_first) are located inside.
We don't yet store the relationship between the impl and its match_first
block, nor then can we use it in impl lookup for prioritization.
Implement the toolchain side of proposal #7254, removing the `:!`
binding
syntax for generic and template parameters in favor of the keywords
`generic`,
`template`, and `runtime` plus contextual defaults for phase.
For valid programs this is semantics-preserving: each binding resolves
to the
same phase, and produces the same SemIR, as it did under `:!`/`:`. The
parser
derives a binding's phase from its syntactic context plus any explicit
phase
keyword; new diagnostics and error recovery for misused keywords are
described
below.
Implementation details for each component:
- Lexer: remove the `:!` (`ColonExclaim`) token, move its virtual
parse-node
budget onto `:`, and add the `generic` and `runtime` keywords.
- Parser: thread a `BindingContext` (`ExplicitParam`, `DeducedParam`, or
`CompileTimeEntityParam`) from declaration introducers down through
parameter
lists to each binding pattern, using a one-token lookahead to
distinguish a
name-qualifier parameter list from a declaration's own final list.
Parameters
of a compile-time entity (`class`, `interface`, `constraint`, `choice`,
`alias`, `export`, `namespace`) and deduced `[]` parameters default to
checked
generic; explicit function parameters and local bindings default to
runtime.
`HandleBindingPattern` resolves the phase from that context plus the
keyword: a
`generic` keyword needs no node of its own (the phase is carried by the
binding's node kind), while a `runtime` keyword is preserved as a
`RuntimeBindingName` node so `check` can name it in a diagnostic. A
phase
keyword that is merely redundant with the contextual default is
diagnosed
here, without invalidating the parse tree.
- Check: a phase keyword that is invalid for its context (for example
`runtime`
on a checked-generic parameter) is diagnosed here, and recovers by
building an
error binding that still introduces the name so that later uses of it do
not
produce cascading errors.
The removed `:!` syntax is now rejected as an ordinary parse error.
The `form`/`:?`/`->?` ("extended types") portion of proposal #7254 is
left for a
separate change.
Assisted-by: Claude Code
When formatting an impl definition, include in the textual output if the
impl is final. Since we (mostly) write them as `final impl` in the code,
use the same notation in the textual semir.
The implicit/explicit `.Self` concept is a heuristic at best, so we
should avoid relying on it. The ImplicitOnly option is no longer used,
as it was used to remove/disambiguate `.Self` in nested facet types, but
we have banned nesting `where` on the RHS of a `where`. So we no longer
have to worry about ambiguous `.Self`.
We can remove all the designator tracking heuristics in `.Self`
substitution as well now, as they were used for the now-removed
ExplicitOnly (removed in
https://github.com/carbon-language/carbon-lang/pull/7460) and
ImplicitOnly options.