Commit Graph
131 Commits
Author SHA1 Message Date
Geoff RomerandDana Jansens e67b6db910 Give files shorthand names in textual SemIR (#8104)
Shorthand names are intended to be used in the textual format of
references to instructions in another IR (which can't happen now, but
will be possible in a forthcoming PR). The shorthand name uses the file
name (minus the `.carbon` suffix) as a base, and if that base name is
ambiguous within the compilation, it is given a numerical suffix `.N`,
just like other textual IR names. Shorthand names are prefixed with `$`
in the textual format, to distinguish them from inst and scope names.

For example, a file `foo/bar.carbon` has the shorthand name `$bar`, and
an instruction `@baz.%qux` in that file can be referenced from another
file as `$bar.@baz.%qux`.

This PR adds `toolchain/check/testdata/basics/file_name.carbon` to test
this behavior. All other test changes are just applying this change to
the existing textual SemIR dumps.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-11-12 23:34:32 +00:00
Dana Jansens 9fb428d713 Ensure specific in ImplWitness has resolved definition before accessing witness table (#8040)
When impl lookup results in an `ImplWitness`, either directly or later
through `LookupImplWitness` evaluating to an `ImplWitness` inside some
specific, it represents a dependency on the eval blocks of the
`ImplDecl` that the `ImplWitness` comes from. The `ImplWitness` contains
a `SpecificId` of the `ImplDecl`, and the constants in the witness table
must be viewed through that `SpecificId`. The constants may depend on
the declaration or the definition block of the `ImplDecl`'s specific, so
any use of the witness table from `ImplWitness` requires the specific
from the `ImplWitness` to be fully resolved: both the decl and
definition blocks.

The specific declaration block is always resolved immediately when
forming a specific id, so there's nothing to do there. And things are
simple when the `ImplWitness` returned from impl lookup is concrete. We
would simply resolve the specific definition directly in the evaluation
of `LookupImplWitness`.

But when the `ImplWitness` is symbolic, meaning there's a dependency on
generic parameters in its referenced specific, then we have a dependency
on resolving the specific definition in the `ImplWitness` for every
specific that gets applied to the `ImplWitness`, eventually resulting in
a concrete specific.

Previously we attempted to do this by representing a dependency edge
from the eval block containing the `ImplWitness` instruction to the
definition block of the specific inside the `ImplWitness`. We
represented this dependency edge with the `RequireSpecificDefinition`
instruction.

The challenge with the `RequireSpecificDefinition` instruction was
ensuring it always landed in the _same eval block_ as the one holding
the symbolic `ImplWitness`. Ultimately, we've found a way to do this
without the `RequireSpecificDefinition`. The witness table is accessed
through `ImplWitnessAccess`, so we resolve the specific definition
before each access to the witness table. If the definition is already
resolved, this just costs a lookup of the Specific from the value store.

We document the other things we tried, which don't work or were too
complex, below.

In PR #6236, we added the `RequireSpecificDefinition` instruction in the
eval of `LookupImplWitness`, but this is too late. If impl lookup
resolved to a symbolic `LookupImplWitness`, the `LookupImplWitness` is
added some eval block. Later, we form specifics and re-evaluate that
eval block, and the `LookupImplWitness` can evaluate to an
`ImplWitness`. Adding the `RequireSpecificDefinition` instruction at
this point inserts the instruction into whatever generic's eval block
happens to be on the top of the generic stack, not the eval block of the
generic we are building a specific for. And indeed we can't add
instructions to a generic's eval block later like this, as it would be
missing from specifics that were already resolved for the generic. This
incorrect insertion shows up as a crash in eval at the CHECK introduced
but commented out in [eval.cpp in
#7981](https://github.com/carbon-language/carbon-lang/blob/56d9bbc40add1e9263f2f9b2555c3a27292d1725/toolchain/check/eval.cpp#L3507-L3512).
This is covered by the
`require_specific_impl_definition_through_specific_instantiation.carbon`
test.

We tried moving the insertion of `RequireSpecificDefinition` to be
earlier - at the point where the `LookupImplWitness` is constructed, in
the `LookupImplWitness()` function, instead of inside evaluation. This
seemed like a straightforwardly correct answer, as the eval block that
contains the `LookupImplWitness` will then also contain the
`RequireSpecificDefinition`. However, this can cause us to lose the
`RequireSpecificDefinition` entirely. Because it's a separate
instruction, not an operand of `LookupImplWitness`, it does not get
treated as a dependency of the witness. When we do an impl lookup inside
an `alias`, we build a generic for the alias and then discard it. This
discards the eval block containing the `LookupImplWitness`. Then, in an
enclosing generic, we refer to the constructed `AliasDecl` instruction,
which pulls all its dependent operands into the enclosing eval block.
This pulls in the `LookupImplWitness` into the enclosing eval block, but
it does not preserve the `RequireSpecificDefinition`. This is covered by
the
`require_specific_impl_definition_from_lookup_impl_witness_in_class_definition.carbon`
test.

We tried having `ImplWitness` evaluation resolve the specific definition
of the specific `ImplDecl` it refers to. This seems like the simplest
approach by far as we should always be working with the correct eval
block and nothing can get lost. However it does not work because of the
recursive nature of `ImplWitness`. The `ImplWitness` instruction appears
in the declaration of an `ImplDecl`, and the `ImplWitness` holds a
`SpecificId` for that same `ImplDecl`. When building a specific
`ImplDecl`, we evaluate the `ImplWitness` in the `ImplDecl`'s
declaration block which then immediately resolves the specific
definition before the declaration is finished. This leads to missing
instructions in the specific definition. In short, this puts the
dependency edge to the `ImplDecl`'s specific inside the `ImplDecl`
itself, which is problematic.

We tried wrapping `ImplWitness` in another instruction,
`ImplWitnessUse`. Inside the `ImplDecl` declaration there is still
`ImplWitness`, but then in the definition there is `ImplWitnessUse` and
that is what is returned from the evaluation of `LookupImplWitness`. The
`ImplWitnessUse` is an `ImplWitness` plus it ensures the specific
referred to by the witness has its definition resolved. However this
breaks constant comparisons, as we get different witnesses inside an
impl versus outside.

The first iteration of this PR's solution had us insert the
`RequireSpecificDefinition` into the eval block when we sniffed a
`LookupImplWitness` instruction, however that missed cases where impl
lookup immediately resolved to a symbolic `ImplWitness`, which is why we
now sniff for the `ImplWitness` in the eval block. This is covered by
the
`require_specific_impl_definition_from_symbolic_impl_in_class_definition.carbon`
test.

We also originally made a mistake of not inserting
`RequireSpecificDefinition` when inside the impl definition that the
`ImplWitness` refers to. But we can form specifics ImplWitness values
through function signatures, and these must add the dependency edge on
that specific ImplDecl definition. This is covered by the
`require_specific_impl_definition_from_inside_impl_definition.carbon`
test.

Finally, we did have a working solution. It was to sniff instructions
added to the eval block of a generic, and when an `ImplWitness` is added
to the eval block (it is implied that it is symbolic), also add a
`RequireSpecificDefinition` to that eval block immediately. We also
resolved the definition of a specific referred to by `ImplWitness` when
`LookupImplWitness` evaluates to `ImplWitness` to cover the concrete
witness case. This complicated the construction of the eval block
immensely, however. It caused a situation where adding one inst to the
eval block actually adds two, which we needed to avoid when importing.
And it required inst-kind specific behaviour in the very general
construction of an eval block, completely outside of eval itself.
2026-11-03 14:15:14 +00:00
Christopher Di Bella 05a7ecbd34 Move SubobjectDestroy and SelfDestruct out of interface Destroy (#7942)
Determining that a type has trivial destruction requires checking
whether all of its subobjects have trivial destruction and whether its
type has a custom witness for `Destroy.Op`. This isn't possible when
`Destroy` is the custodian for `Destroy.Op` and `SubobjectDestroy.Op`,
so we need to make `SubobjectDestroy` its own interface.

`Destroy.SelfDestruct` becomes a standalone function because it depends
on `SubobjectDestroy` and `Destroy` being implemented, and is also
responsible for generating any custom witnesses for both interfaces.
Making `SelfDestruct` an interface was experimented with, but this
required a blanket impl that caused issues for facet types.

`Destroy` depends on `SubobjectDestroy` to be implemented. We'd ideally
use `require impls SubobjectDestroy`, but it isn't complete yet, and it
also causes problems when `Destroy` is implemented inside the class
definition. We work around this by temporarily renaming the `Destroy`
interface to `DestroyImpl`, and introducing a constraint called
`Destroy` so that user code doesn't need to write `Core.SubobjectDestroy
& Core.Destroy`.
2026-10-26 21:35:01 +00:00
Dana Jansens 24766e213e Defer evaluation of witnesses substituted while identifying a facet type (#7930)
When identifying a facet type, defer evaluation of LookupImplWitnesses
by redirecting them to evaluate into IdentifiedWitness. Then the caller
of identify will need to substitute the IdentifiedWitnesses, either with
witnesses of their own, or with LookupImplWitness to cause a lookup
operation.

This allows:
- An `impl as` on a named constraint can subst the witnesses in
designators from the named constraint with a witness to the impl itself.
This prevents them from looking for and finding some other overlapping
impl. (This PR)
- Impl lookup to collect rewrite/equality requirements from all named
constraints and then use the impls it has already found to evaluate any
designators in those requirements instead of performing impl lookup
again (creating a cycle). (Done in
https://github.com/carbon-language/carbon-lang/pull/7944)
- Similarly, an `impl as` can collect impls and equality requirements
from all named constraints and verify them correctly by replacing
witnesses that should refer to the impl with the correct witness instead
of performing a lookup and finding an overlapping impl. (Done in
https://github.com/carbon-language/carbon-lang/pull/7937)
- ImplWitnessAccess to be able to find rewrites from a named constraint,
not just from the initial DeclaredFacetType. (TBD)

To do this we need to introduce the concept of "identified" specifics.
In order to identify a facet type, we must construct a specific for each
require decl in a named constraint. These specifics will have
IdentifiedWitnesses inside them, but their args would otherwise match a
specific for the require decl constructed in another context. To avoid
polluting the canonical specific namespace, we introduce a second
namespace of specifics that are "identified" since they are created by
identifying.

As we have introduced a new global state that modifies eval behaviour,
we must disable that state when resolving a specific (as per
https://github.com/carbon-language/carbon-lang/pull/7923). But inside an
"identified" specific, we preserve the behaviour so that the witnesses
modified by identify (through SubstPeriodSelf or through evaluating a
require specific) have their evaluation deferred.
2026-10-14 14:12:56 +00:00
Geoff Romer 62f1cc6a35 Rename GenericClassType to ParameterizedClassType (#7953)
The old name was potentially confusing, because non-parameterized
generic classes do not use this inst kind.
2026-10-11 23:09:12 +00:00
Christopher Di Bella 6abcfa24b2 Classify decorated built-in types as trivially destructible (#7847)
Types like constant pointers and `MaybeUnformed(i32)` should have
trivial destruction, but were classified as non-trivially destructible.
2026-09-28 23:16:19 +00:00
Christopher Di Bella b227419d8d Classify classes with no struct fields as trivially destructible (#7846) 2026-09-28 22:39:03 +00:00
Christopher Di Bella f7cd39428e Add Destroy.SubobjectDestroy as a temporary replacement for Destroy.Op (#7773)
This change partially implements [PR #7362], which revises how objects
are destroyed. It is a partial implementation for two reasons:

1. This change moves `Destroy.Op`'s current behaviour into
`Destroy.SubobjectDestroy`, but it doesn't add support for objects with
non-trivial destruction.
2. `Destroy.SubobjectDestroy` is a workaround for `require impls
SubobjectDestroy`. We aren't able to use the latter until the dependents
add their requirements' implementations to their own witness tables.

[PR #7362]: https://github.com/carbon-language/carbon-lang/pulls/7362
2026-09-24 00:06:28 +00:00
Dana Jansens fcae9610bd Make SemIR::TypeType be an empty FacetType instruction (#7813)
The type `type` is now a `FacetType` inst with no constraints. This
brings the model implemented in the toolchain into better alignment with
the language design. The `SemIR::TypeType` struct remains as a scope for
holding the `TypeInstId`, `ConstantId`, and `TypeId` constants, but is
not an `InstKind` anymore.

The `TypeType` inst looks a lot like singletons, but there are many
`FacetType` insts so it doesn't quite fit that model. So we put it
alongside singletons with a fixed inst id but refer to it as a more
general "builtin" inst that is not a singleton.
`Namespace::PackageInstId` is similar, and we group it with `TypeType`
conceptually as another builtin instruction with a fixed id.

No conversion is needed anymore to use a `type` as a facet, since types
also have a `FacetType` type. This simplifies and removes a number of
helpers and branches throughout the code.

The `TypeType` inst is now part of the constant store, so we end up
printing it in the constants block in every test. But it's also named
`type` rather than `%type` to preserve the majority of existing
formatting behaviour, though this does look different from other
constants.

Assisted-by: Opus 5 was used to generate a first draft and validate the
refactoring. Though nearly everything non-trivial the tool wrote has
been modified or rewritten.
2026-09-22 15:04:40 +00:00
Dana Jansens 4416f3525b Canonicalize generated functions for Core witnesses (#7729)
Use a single `SemIR::Function` per `Core` interface method, whether it's
generated locally or imported. This prevents generating duplicate
functions, which lead to different types when the witness appears in a
`FacetValue` as part of a specific for a class.

We use a `CanonicalValueStore` of `GeneratedFunction` objects that allow
finding an existing FunctionId for a `Generated` special function before
(re-)generating it. Mangling for `Generated` functions is also moved to
use the values from the `GeneratedFunction`'s canonicalization key, so
that we have a consistent source of truth for the unique ID of a
`Generated` function across all files.

New tests are in
`toolchain/check/testdata/impl/custom_witness/destroy.carbon`.
2026-09-15 16:02:13 +00:00
Christopher Di BellaandRichard Smith 4ea5ef45dd Skip ImplWitnessTable::elements_id when generating fingerprints (#7629)
Implementing interface modifiers causes an infinite loop when generating
fingerprints because the witness value generates a fingerprint that's
dependent on something dependent on the witness value. We've debugged
this to the witness table's `elements_id` field.

This hack is a workaround for creating a new block type whose value is
not codependent with its identity.

Co-authored-by: Richard Smith <richard@metafoo.co.uk>

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-08-11 22:39:30 +00:00
Dana Jansens a5ba0a0f45 Use GetConstantValueInSpecific to get the impl's specific interface after deduction (#7584)
During impl lookup, for each (generic) impl candidate, we form a
specific for that impl by deducing its generic arguments. Then we
compare the query interface against the impl's specific interface. That
comparison needs the deduced arguments applied to the impl's specific
interface. Previously we were doing this by getting the impl's
constraint facet type with the impl's specific applied (via
`GetConstantValueInSpecific()`) and then identifying that facet type
with the impl's deduced self.

Identify is a fairly expensive operation. It runs subst, trying to
replace `.Self` references. It walks named constraints. It collects
require declarations. We're looking at making it do _more_ in the future
too, including rewrite constraint resolution and collecting rewrite and
same-type constraints. For this reason we have a cache to make it cheap
on the second run, but it's still a very heavyweight operation to
involve in impl lookup, when all we want is to apply the impl's specific
to its target interface.

We almost have all the information we need to avoid the identification
step. We have the impl's specific after deduction. And we have the
SpecificInterface that the impl is targeting in the `Impl` struct. When
we form the specific for the impl itself, we resolve the declaration
block and form new constant values for all instructions in there, but
that does not cover the SpecificInterface that we're storing in the
`Impl` struct. So we add a new instruction to the impl's eval block,
which will be symbolic when the impl is generic and the target interface
depends on a generic parameter. And we store the `InstId` in the `Impl`
struct. This allows us to gets its constant value later with the impl's
specific applied. From that constant value we can then pull out the
SpecificInterface that the impl is targeting.
2026-07-30 19:59:10 +00:00
Richard Smith a8afc45ed5 Omit empty observe: blocks from formatted SemIR. (#7487)
Also add SemIR ranges to observe test, removing 5K lines of
uninteresting SemIR output.
2026-07-13 20:38:19 +00:00
Özgür T. ÖnsoyandDana Jansens 08385adeb5 Implement checking observe declarations (#6709)
This adds SemIR structs and implements building `observe` lists, as well
as naming, formatting, and importing `observe` declarations.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-07-08 17:07:10 +00:00
Geoff Romer 8945305dfc Emit NameBindingDecl after the initializer (if any) (#7467)
In some cases the pattern block can depend on the initializer, so it
must be sequenced after it. See #7469 for a more detailed explanation of
why this is necessary.
2026-07-07 19:18:33 +00:00
Geoff Romer 0460f6b7ba Label VarStorage as var_storage instead of var (#7447)
This makes the textual format clearer and more self-explanatory, and
avoids ambiguity about whether this inst refers to the storage or the
pattern.
2026-07-02 01:02:19 +00:00
Geoff Romer e4b0903d2e Remove ValueBinding and RefBinding (#7427)
These inst kinds are now redundant with `WrapperBinding`.
2026-06-29 17:41:23 +00:00
Geoff RomerandRichard Smith e023f75254 Implement thunking in terms of constant evaluation (#7332)
The bulk of this change is changing most pattern insts to be `Always`
rather than `AlwaysUnique` constants, so that they can be wrapped in
`SpecificConstant`s to perform substitution. That then lets thunking
rely much more on `SpecificConstant` wrappers instead of deep-copying
the inst tree with modified types.

This approach to thunking should scale better, particularly as things
like form generics make function signatures more complex, because we can
leverage the existing support for constant evaluation and substitution.
Unfortunately, applying this approach to binding patterns will require
more work; see the TODO near the top of `thunk.cpp` for details.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-06-13 00:22:00 +00:00
Richard Smith cefa0397bb More fixes to package and library fingerprinting. (#7297)
Fix import logic to make all imported packages be children of the
`NameScopeId::Package` scope. Previously, indirectly-imported packages
would end up as children of their importing package's scope, which
resulted in them not being treated as packages at all, and in particular
not being fingerprinted as packages.

Fixing that caused a failure in the fingerprinting logic as we started
to encounter packages with no correspoding import scopes. Instead of
looking for import scopes, use a simpler mechanism to map packages to
their package names, and clean up.

Unfortunately the latter change churns all the fingerprints again :(
Hopefully this is the last time for a while.
2026-06-04 17:41:46 +00:00
Richard Smith f5e9c61f11 Don't include the library name in most fingerprints. (#7292)
When we import from another library in the same package, its entities
end up with our library as their parent scope, resulting in cross-file
fingerprint mismatches. Instead, only include the library ID when
fingerprinting either a package-private entity or an `ImportIRId` that
refers to a particular `SemIR::File`.
2026-06-02 19:31:30 +00:00
Richard Smith 05cc09daca Fix cross-package signature mismatches. (#7232)
Fixes link failures when referencing a symbol involving a fingerprint
from a different package.

Previously we included the `Namespace`'s `import_id` as part of its
fingerprint, which caused local and imported namespaces to get different
fingerprints. We now store the `import_id` on the `NameScope` instead of
on the `Namespace` inst to avoid this problem.

Also, when we reach a package-level `NameScopeId`, consistently
fingerprint it as a (package name, library name) pair. Previously the
fingerprinting depended on whether it was imported or not, as an
imported `NameScopeId` had a parent scope (the current package). We need
to include the library name here so that private entities with the same
name in different libraries have different fingerprints.
2026-05-21 00:02:29 +00:00
Dana Jansens f8dd4d85bf Do not treat impls in different scopes as redeclarations (#7161)
An impl in a different scope, with the same parameters, will overlap and
get diagnosed for that later by the [prioritization
rule](https://docs.carbon-lang.dev/docs/design/generics/details.html#prioritization-rule),
if they are not in a match_first block. But they are not considered as
redeclarations.

See [proposal
p5366](https://github.com/carbon-language/carbon-lang/blob/62b94f79322039acc3fc8e175896a64a32df470e/proposals/p5366.md)
for the rule.
2026-05-04 19:11:51 +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
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
21291b4cc3 Remove InitForm::index (#6817)
This ensures that equal forms always have equal representations (because
the index depends on how the form is used, not on the value of the form
itself).

As a byproduct, also remove `NextCallParamIndex`.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Nicholas Bishop <nicholasbishop@google.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: Dana Jansens <danakj@orodu.net>
Co-authored-by: Boaz Brickner <brickner@google.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
Co-authored-by: MK4070 <60286678+MK4070@users.noreply.github.com>
Co-authored-by: Christopher Di Bella <cjdb@google.com>
2026-03-06 17:35:48 +00:00
Geoff RomerandJon Ross-Perkins 6dba8ee111 Remove index fields from ParamPatterns (#6815)
This is a step toward removing the index from `InitForm`, so that equal
form values always have equal representations.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2026-03-03 00:19:47 +00:00
Jon Ross-Perkins b14015602b Make Destroy.Op functions able to have a body (#6729)
This is iterating on how `Destroy.Op` generates, to start adding body
capabilities. This changes the way the signature is created, and adds a
`CoreWitness` function kind so that mangling can prevent name
collisions. The result is that what _was_ `DestroyOp` is now
`Core.Destroy.Op` or, as can be seen in
toolchain/lower/testdata/interop/cpp/nullptr.carbon,
`_COp.<hash>:core.Destroy.Core` where `:core` is indicating that it's a
core witness (taking a note from `:thunk`).

Assisted-by: Google Antigravity with Gemini 3 Flash
2026-03-02 17:57:31 +00:00
Dana Jansens cea52ad2d8 Format the InterfaceWithSelf and NamedConstraintWithSelf generic name with its ".WithSelf" suffix (#6798)
We used the ".WithSelf" suffix when formatting a parent scope, but
missed the suffix when formatting the scope name on its own.
2026-02-27 13:50:56 +00:00
Richard Smith f9ab963bd6 Add a type_literal instruction to represent syntactic type literals. (#6781)
This allows us to capture the location at which a type literal was used,
even in the cases where we don't otherwise need to create a new
instruction to represent the type such as for `char` or `str`.

The logic used to build the underlying type is now marked as desugaring.
For cases such as `iN`, this causes the call to `Core.Int` to no longer
be added as a dedicated IR instruction, and instead its constant value
is used directly as the value of the `type_literal`. This results in
this being on balance a reduction in the size of the IR.

This also fixes a crash in C++ interop when using a `char` literal as a
template argument. The crash was caused by the template argument not
having an associated location when mapping to a C++ location. See
changes to check/testdata/interop/cpp/template/type_param.carbon for an
example that used to crash before this change.

Update alias handling to allow an alias to point at any type literal,
reinstating support for aliases for type literals such as `bool` and
`i32` that had previously worked but stopped working when we
transitioned those types to being defined in the prelude. See changes to
toolchain/check/testdata/alias/builtins.carbon.

All the test changes other than the two mentioned above are mechanical
autoupdate changes switching to the new instruction.
2026-02-26 20:10:50 +00:00
Dana Jansens 917a6ea971 Add an interface-with-self generic to each interface and same for constraints (#6667)
Currently each interface has a `Self` facet internally that becomes a
binding to every entity inside the interface: associated constants,
functions, and require decls. Each of these has to be independently
generic as a result. This makes is challenging in extended name lookup
to move into an extended scope of an interface, as we have a specific
for the interface, but the names within require a different specific
that includes a `Self` facet value.

We generalize this relationship by adding a second generic to Interface,
called `generic_with_self`. When we want to work with entities inside
the interface, we move from the interface-without-specific to the
interface-with-self specific by adding a Self to the specific. This is
done independently of any particular entity inside the Interface, as
those entities are now all members of the interface-with-self generic.

Associated constants no longer need a generic of their own, as they do
not have separate generic bindings. Functions retain a generic, but if
the function has no generic arguments, it will have no bindings of its
own now.

Require decls retain a generic so that their specific can be
instantiated separately from the interface. Requiring the interface to
be complete does not require the types in a require decl to be complete
unless it is modified by `extend`. So we allow them to be completed
later by keeping them in a separate generic.

Named constraints look like interfaces and gain the additional inner
generic-with-self, with the same relationship to require decls.

This removes the need for name lookup to perform Substitution of a Self
facet into the extended scope instruction. Instead, the
`SpecificConstant` instruction inserted by a `require` decl is part of
the interface-with-self generic. When looking through a FacetType for
extended scopes, for each interface, we push the scope with the specific
for the interface-with-self. Then the constant value of the
`SpecificConstant` is correctly modified by the provided self
automatically through applying that specific.
2026-02-19 16:24:07 +00:00
Geoff Romer 3c324e4877 Add category to parameter format, and share some code. (#6730) 2026-02-13 22:20:05 +00:00
Geoff Romer 1c885a629e Format FormType as "Core.Form" (#6734) 2026-02-13 19:44:21 +00:00
Geoff Romer 4329a83e4c Form-aware textual format for return parameters and arguments (#6588)
The key changes are:
- Function output parameters are now prefixed with `out`, and more
consistently formatted as named parameters.
- Function and inst output arguments are now written as part of the inst
form, rather than as one of the inst arguments.

As a drive-by fix, this also changes `Temporary::storage_id` from
`DestInstId` to `InstId`, because it doesn't represent an output
parameter of the `Temporary` inst itself.

See the review of
[#6532](https://github.com/carbon-language/carbon-lang/pull/6532) and
[this Discord
discussion](https://discord.com/channels/655572317891461132/999638000126394370/1458268977020141589)
for additional background.
2026-01-14 23:27:21 +00:00
Geoff Romer e1ec8d42d1 Give ReturnExpr a target only when initialization is in-place (#6570)
Also clarify and enforce that `ConversionTarget::init_id` is used only
as storage for in-place initialization, and correspondingly rename it to
`storage_id`.
2026-01-13 01:20:15 +00:00
Geoff Romer 6985ecb1d4 Replace GetCurrentReturnSlot with GetReturnedVarParam (#6571)
Not all functions have a return slot, and once we have composite forms,
functions will be able to have any number of return slots. Obtaining a
unique return slot for a function only makes sense in `returned var`
handling.
2026-01-10 01:56:32 +00:00
Geoff Romer 505b1c86b9 Initial support for return forms (#6556)
The main changes here are:
- Introducing `InitForm` and `RefForm` to represent initializing and
reference forms (the two return forms currently supported by the
parser).
- Introducing the `FormType` singleton inst to represent their type
(i.e. `Core.Form`).
- Emitting an inst representing a function's declared return form as
part of handling the function signature.

The return form inst is currently ignored. Subsequent PRs will expose it
in `SemIR::Function` and use it to determine the form of call
expressions.
2026-01-07 00:54:18 +00:00
Jon Ross-Perkins c5eba90317 Change Destroy to use a CustomWitness instead of a blanket impl (#6512)
Pursuant to recent decisions on #6124, switch `Destroy` to use a
`CustomWitness` for its implementation. Right now this is manufacturing
no-op implementation functions on each lookup, which obviously isn't
ideal but is intended as a first pass. I'm mostly trying to find the
right balance between updating the approach to reflect new decisions,
while still breaking apart work in a way.

The `CoreInterface` logic is intended to build on `CoreIdentifier`
support. We have a number of additional interfaces that require
specialized logic, and that'll extend pretty far with C++ interop, so it
seemed easiest to have a generic function for it. That's what's
replacing the logic inside C++ interop that was doing string comparisons
(which could have already been moved to `CoreIdentifier`, I just missed
it in my first pass).

This adds `CustomWitness` support because the `Destroy` witnesses can be
imported cross-file. `CustomWitness` was previously only used for C++
types, which don't yet support import, which is why that wasn't
previously an issue. The addition of `query_specific_interface_id` is
similarly needed in order to get correct sorting of witness blocks when
imported.

This PR also removes builtin constraint logic (note this is in a
separate commit to help review; it's not a separate PR because it's
difficult to split apart without tests breaking). This had been made
generic with the expectation that destroy, copy, move, and conversions
would all need related support. Under the new decision, we are not going
to do blanket impls and will instead just manufacture a `CustomWitness`
for everything.

A lot of SemIR fingerprints change, but that's probably because the
addition of `Destroy` on core classes is yielding structural changes.
2025-12-19 18:36:06 +00:00
Jon Ross-Perkins 47e551141f Change the package namespace to use the package name (#6495)
Instead of naming the root namespace `package` (because it's accessed by
the `package` keyword), change it to use the current package name. Note,
buried in the checksum changes,
`toolchain/check/testdata/package_expr/fail_not_found.carbon`:

```
-  // CHECK:STDERR: fail_not_found.carbon:[[@LINE+4]]:16: error: member name `x` not found in `package` [MemberNameNotFoundInInstScope]
+  // CHECK:STDERR: fail_not_found.carbon:[[@LINE+4]]:16: error: member name `x` not found in `Main` [MemberNameNotFoundInInstScope]
```

for:

```
  // CHECK:STDERR:   var y: i32 = package.x;
  // CHECK:STDERR:                ^~~~~~~~~
```

I'll leave it to you if you prefer this; the alternative I see is to
just rename `IsCorePackage` to `IsImportedCorePackage`, and/or change it
to a helper that takes a `Context` and does the right thing with
`parse_tree` (which, I need for `Destroy`-related reasons and was my
default approach).
2025-12-16 01:33:53 +00:00
Richard Smith 154e4012c4 Include the parent scope when fingerprinting an entity name. (#6473)
This is a prerequisite for support for interop with C++ template names.
No behavior change here, except that it sadly changes the fingerprinting
for a lot of tests.
2025-12-08 15:31:13 +00:00
Geoff Romer 2b8fdf3417 Switch the prelude to use ref instead of addr (#6359) 2025-11-14 00:40:26 +00:00
Geoff Romer 0811d996e1 Finish renaming BindName and related insts. (#6281)
Resolves the TODO from #6235
2025-10-28 17:17:38 +00:00
Geoff Romer 09710d102f Separate binding insts for refs and values (#6235)
This resolves a TODO in `expr_info.cpp` by using the inst kind rather
than the bound value to track the binding's category.

Since we're churning all the `bind_name` insts in testdata anyway, I'm
also taking this opportunity to align the inst naming with the design's
terminology, by calling these insts "bindings" (this aspect of the PR is
dependent on #6231 resolving an ambiguity in that terminology). For
consistency we'll need to rename several other insts as well (see the
TODO on `RefBinding`); I'm deferring that to a separate PR to minimize
the review load, but I think those name changes are in-scope for this
review.
2025-10-23 01:46:24 +00:00
Dana Jansens e682a6660d Avoid adding extraneous local instructions while importing witness table entries (#6180)
When deducing arguments for generic parameters of an `impl`, the
deduction calls `Convert` on the input arguments. Often, the input
argument is a facet, and needs to be converted to a type via
FacetAccessType in order to produce a different facet. These
instructions end up being added to the semir, but only their constant
values are needed for the resulting specific returned from Deduce.

In the best case, these extra instructions are just noise in the semir,
or they just cause instruction names to get differentiated with larger
suffixes.

In the worst case, these extra instructions contain references to
instructions from a generic context, and leak them out of that generic
context and into another. In particular, when importing a
LookupImplWitness instruction, the re-evaluation of it can do deduce
(when the lookup is against a generic `impl`). The instructions created
in Deduce are not part of the import, and end up referring to imported
instructions from the local context, which leads to confusion in the
toolchain, and can crash.

The `import_self_specific.carbon` test demonstrates this. It causes the
`I.F` function to be imported from the `I` interface when building the
witness table for the `impl`. Doing so imports the specific of `C` which
includes a LookupImplWitness for `Self.Accoc` in `I`. The `Self` is a
BindSymbolicName with generic binding index 0, in `I`. When Convert
creates instructions in the generic `impl forall D`, however, they end
up referencing and including this BindSymbolicName into its eval block.
But the generic binding 0 in the `impl` is a very different thing (a
value of type `E`). This confusion leads to crashes.
2025-10-09 16:07:30 +00:00
Dana Jansens fe020ee08b Make FacetAccessType evaluate to SymbolicBindingType for type-of a BindSymbolicName (#6115)
The SymbolicBindingType refers to the type value that will be
substituted in for the BindSymbolicName, but holds onto the EntityNameId
from the BindSymbolicName instead of (or in addition to, for now) the
instruction.

The EntityNameId will be used to look in the ScopeStack to find the
witnesses either from the BindSymbolicName instruction, or other
instructions that specify `impls` constraints against the EntityName.

This will allow us to have the `T` in `I(T)` resolve to a `.Self`
reference in the type so that we get type equality with the binding's
type: `T:! I(.Self)`.
2025-10-06 18:56:43 +00:00
Jon Ross-Perkins 4a6376cf59 Rename/restructure Destroy logic to better reflect #6124 (#6144)
This also does a little restructuring in the same direction, following
#6124.

Leads want `Destroy` to work similarly now for all types. As a
consequence, there doesn't seem to be as much benefit to splitting off
aggregate destruction. In this PR, the `type.destroy` function can now
be expected to destroy anything that's destructible; that means it'll be
usable for the `final fn` once that support is available.

Similarly, this gets rid of the impls other than the single blanket
impl, now using `type.can_destroy`. Since they all need to use the same
function, there's no benefit to splitting approaches. Also, now it can
just be a `final impl` since there should be no need for people to
create specializations -- if this blanket impl applies, it means the
`final fn` is the same.

This also slips in `partial` support since there's no reason to have it
diverge anymore. Also `abstract`, which I'm not sure is broadly testable
since most cases it'd come up, the `abstract` keyword is explicitly
detected/rejected.

Note though that this doesn't make any really big changes. It's just
realigning on the leads decision. I'm going this way to try to reduce
name-related churn for other changes.
2025-09-30 20:43:36 +00:00
Jon Ross-Perkins 47081be67a Reduce test sensitivity to small import loc changes (#6145)
Locations are similarly fragile, because adding a comment changes them.
This has made me pause when making prelude changes in #6144, so dropping
them for those cases.

Instruction ids aren't actually that interesting outside debugging, and
can be churny when doing other structural changes. I've seen this in
particular when doing singleton changes, which bump every instruction
id.

Note there are still other ways fragility from locations can crop up.
This shouldn't be considered a complete fix, but hopefully a small
improvement.
2025-09-30 17:20:14 +00:00
Jon Ross-Perkins 49ba8cf3e1 Switch class to use a blanket impl for Destroy (#6125)
Right now, the class destroy impl is incorrectly generated (first
discussed [in
Discord](https://discord.com/channels/655572317891461132/941071822756143115/1418614787449032826)).
If we want it to be correct, deferred definition logic would need to be
added, and the declaration would need to be moved inside the `class`
scope (along with whatever generic logic that needs).

This instead switches to a blanket impl, to avoid creating latent bugs
with generating the `impl` and function body in the wrong scope. This
approach uses the same blanket impl as aggregate destruction that was
added by #6098.

The intent here is to allow progress on other parts of `Destroy`. For
example, under this model the implementation of the function body could
be done as part of lowering the specific.
2025-09-29 16:05:06 +00:00
Jon Ross-Perkins 9704dc670e Change the Destroy blanket impls to be more specific (#6098)
The main direction of this change is the edits to `destroy.carbon`
(matching in both prelude and min_prelude).

Previously there was a no-op blanket impl for `Destroy`, which hid all
missing implementations of `Destroy`. This does a few things:

- Sets up builtin aggregate destruction for struct and tuple types as
before, but also adds C++ class types and array types to the same
handling. (all as a TODO for actual implementation)
- Also maybe-unformed destruction, for now at least. (there's a chance I
may try a different approach on this, but the impl lookup wasn't working
as I'd hope in order to write it in code)
- Adds handlers for simple things that are easy to do in code: `type`,
`bool`, pointers. (because these are no-op destruction)
- Redirect `const T` destruction to `T` destruction.

This leaves as future issues:

- `partial T` destruction. (this can't be done similar to `const`
because it only works for non-`final` class types; I think `class`
definitions should just generate what's needed)
- Destruction of other prelude-provided types. (will probably come up as
we implement class destruction, that the adapted builtin type doesn't
implement `Destroy` -- but may end up special-casing that in a way that
moots it)

This moves the `&` operator from `facet_types.carbon` to
`convert.carbon` because more things need to handle type and now that
we're getting separate copy and destroy interfaces. It should be
low-cost (an interface and builtin) so hopefully this is the right
balance for complexity and re-use.

A few tests are also edited in order to focus them more on what they
intend to test, and avoid a `Destroy` dependency.
2025-09-18 22:10:50 +00:00
Jon Ross-PerkinsandDana Jansens 5e3bb523f8 Add builtin functions for destroy, with special requirements in facet types (#6035)
This is in support of a goal of changing the blanket `destroy` impl to
use (roughly):

```
private fn CanAggregateDestroy() -> type = "type.can_aggregate_destroy";

// Handles aggregate type destruction.
impl forall [AggregateDestroyT:! CanAggregateDestroy()] AggregateDestroyT as Destroy {
  fn Op[addr self: Self*]() = "type.aggregate_destroy";
}
```

That isn't done here because there's still other issues that migrating
raises. What this *does* do is add the builtin functions, and in
particular, support to `FacetTypeInfo` to make `CanAggregateDestroy`
work.

The "special requirement" approach in `FacetTypeInfo` allows us to
support restricting a blanket impl under the current approach of impls.
Maybe we'll find a cleaner approach that can work in the future, but
this fits into the current model by propagating similar to other
requirements. I'm using an enum mask because we have a number of similar
things to add (e.g. copy, move) but I'm not sure we need a full vector.

A few alternatives considered were:

- Supporting syntax more like `where .Self impls
TypeCanAggregateDestroy(.Self, SupportedInterface,
UnsupportedInterface)`. I think it'd be a little cleaner, but requires
better compile-time evaluation in order to assess the type of the call.
Right now it's expected to be a `FacetType` too early to make this work,
and I was concerned about pouring too much more time down this route.
- Providing an actual interface, in particular doing name lookup back
into `Core.` for an interface. This would've added name lookup overhead,
and the question of whether an `impl` exists.
- Generating an interface. This avoids the name lookup, but would still
raise the question of whether an `impl` should also be generated. Work
I've previously done generating interfaces for class destruction also
feels complex to both write and understand (an unfortunate issue).
- Still modeling as an `ImplsConstraint`, for example by defining a
special `InterfaceId::CanAggregateDestroy = -2` similar to what we do on
other ids. I was hesitant because of how this expands the number of
modes of `InterfaceId`, and things for consuming code to watch out for,
for what feels like a relatively niche set of use-cases that are only
interface-like.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2025-09-15 17:03:43 +00:00
Richard Smith d60900cbeb Remove special case for returning value expressions by copy (#6052)
When returning a value from a function whose return type has a by-copy
initializing representation, perform initialization like we do when the
return type has an in-place initializing representation. This makes our
SemIR representation more uniform, as the return expression will now
always be an initializing expression rather than a value expression, but
more importantly it means that attempts to return a non-copyable type by
value now fail, even if the type has a by-copy initializing
representation.

This catches a bunch of places where we were returning a value of an
unconstrained template parameter `T:! type`, which we were incorrectly
allowing because we didn't notice it was not copyable. Unfortunately
this then requires quite a few test updates.

Like #6034, this exposes a lowering issue where lowering crashes when
attempting to lower a specific copy operation for certain types; a
couple more tests are temporarily disabled here. An upcoming PR
dependent on this one will fix the issue and re-enable those tests.
2025-09-12 00:13:33 +00:00