126 Commits
Author SHA1 Message Date
Richard Smith efbe1d2489 Add default fns and final fns to the eval block for a generic impl (#7817)
When a generic impl uses a default or final fn, it picks the specific
function value out of the interface to put in the witness table.
However, because this is done by modifying an existing instruction
block, the generics machinery has no hook to convert the function
constant into an attached constant, and because it was found in a
specific for a different generic, the constant inst will be unattached.
Fix this by manually mapping to an attached constant inst in the current
generic when building the witness table.
2026-09-23 01:19: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
Lucile Rose Nihlen e962b12e53 Fix typo in ImplDeclInInvalidScope diagnostic (#7785)
And update the associated file test.
2026-09-15 16:43:22 +00:00
Christopher Di Bella 431e349757 Allow witness tables to support aliases and other types of StructValue (#7738)
Changing the check from "is `FunctionDecl`" to "has `FunctionType`"
provides us with more flexibilty to use aliases and other types of
`StructValue`.
2026-09-09 19:35:43 +00:00
Christopher Di BellaandRichard Smith 0f06fe65fa Add interface modifiers (#7625)
This adds most support for default and final methods. Missing components
include rejecting definitions for non-default/final methods, and
permitting out-of-line definitions.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-08-17 20:49:23 +00:00
Dana Jansens 2f58185c44 Find the current impl from accesses in a named constraint being implemented (#7592)
When implementing a named constraint, like `impl as N`, any accesses
through `Self` in the named constraint need to get the value of the
associated constant from the impl's witness table. This isn't possible
immediately, since the impl does not even exist until the declaration is
complete. We use the same model as for accesses found directly in the
impl declaration, but applied to the point where accesses in the named
constraint are substituted during identify to point at the impl's self
type. To get there, we need LookupImplWitness instructions in the named
constraint, when re-evaluated during construction of their enclosing
specific, to evaluate to ImplSelfWitness when they are a reference to
the type and interface being implemented.
2026-07-31 20:17:06 +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
Dana Jansens f51c075f8b Avoid symbolic witnesses for .Self in an impl decl (#7564)
Point symbolic witnesses into `.Self` written inside an impl decl at the
impl that is being declared. This is tricky because the impl does not
yet exist. So we use a new instruction `ImplSelfWitness` which _will_ be
replaced by the `ImplWitness` once it becomes available. The
`ImplSelfWitness` acts like a symbolic witness, except it does not
perform lookup, since we know which impl we will get a witness from.

This prevents us from finding other impls when performing lookups into
`.Self` in an impl decl, which produces incorrect/incoherent results.
2026-07-29 16:25:23 +00:00
Dana Jansens 63757d281e Require all impls constraints in impl as to be satisfied (#7531)
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.
2026-07-21 19:31:54 +00:00
Dana Jansens 4b46e63b41 Move IdentifiedFacetType to its own file (#7542)
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.
2026-07-20 21:45:17 +00:00
Özgür T. Önsoy 40028098ce Rename FacetTypeInfo to DeclaredFacetType (#7528)
This resolves a TODO comment in code.
2026-07-20 19:15:09 +00:00
Dana Jansens 168420f805 Allow impl redecl in match_first after a definition (#7491)
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.
2026-07-15 14:12:37 +00:00
Dana Jansens c74bb933d2 Avoid impl lookup cycles from evaluating lookup instructions inside an impl decl (#7454)
`LookupImplWitness` instructions inside the impl declaration can't use
the impl they are apart of. Previously we had an heuristic in eval which
would try to prevent finding the impl for a lookup from inside that
impl. But it breaks when the `.Self` is replaced in a generic impl with
a symbolic, and then that symbolic is replaced in a specific. The
specific's decl block contains that `LookupImplWitness` instruction and
it tries to use the impl it came from. This causes the same specific to
be formed again, but now it exists, so it's used as-is but it has no
decl block yet, and so we crash.

Now we ban an impl while we resolve its specific, both deduction of its
arguments and from any other substitution. The prevents instructions
from inside the impl (which are evaluated when resolving the specific)
from finding their own impl. We do so by adding the ImplId to a stack on
the Context, and then skipping such impls when looking for candidates
during eval.

This fixes a crash, which was demonstrated by the new test being added.
It also makes another todo test pass.

There's a whole lot of other semir churn, which seems to be mostly
reordering of constants. There are some fingerprint changes in
constants, but it appears they are the same canonical instructions, so
they don't represent a behaviour change. For example in
`toolchain/check/testdata/for/actual.carbon` the `%N.patt` constant has
been given its fingerprint suffix now as `%N.patt.aa5`. But they are
both this instruction, so it is just a formatting change:

```
inst6100001A: {kind: SymbolicBindingPattern, arg0: entity_name61000002, type: type(inst61000018)}
  - name: `N`
  - type: type(inst61000018): <pattern for Core.IntLiteral>; {kind: PatternType, arg0: inst(IntLiteralType), type: type(TypeType)} (concrete)
  - value: symbolic_constant61000001
```
2026-07-09 20:38:56 +00:00
Dana Jansens 06e31437b9 Some slight tweaks to comments in/on WitnessQueryMatchesInterface (#7475)
I attempted the TODO as stated but we can't remove the `.Self` from the
LHS of a rewrite right now, without causing evaluation to run and
potentially find a concrete value to replace the access with, which then
breaks the association with the associated constant. There's a separate
TODO about that in SubstPeriodSelfInFacetType.
2026-07-09 19:34:55 +00:00
Dana Jansens bd3ca2b72b Subst the whole facet type to replace .Self in identify (#7449)
This performs `.Self` substitution in a single step, for the whole facet
type, instead of doing it individually for each constraint visited in
the top-level facet type. Then we don't need to track state to avoid
subst in constraints that come from other named constraints.

The semir changes are because we now generate a whole other FacetType
from the substitution.
2026-07-07 13:30:53 +00:00
Richard Smith c33fb9fc48 Support signature mismatch between virtual fn and override fn. (#7198)
For now, hide `override fn`s from name lookup, so that the base class
version is always used, as the derived-class version does not have its
own vptr entry and so would not do the right thing if a further-derived
class adds a new override. This is implemented via a new access kind of
`Hidden`.

When checking the overriding function, pass in the expected `Self` type
and check the `self` parameter against that; the signature that we
generate for the thunk in the derived class is the base class signature
with the `self` parameter's type changed to the derived class.

When we generate a thunk for a virtual function, the thunk is assigned a
`virtual_index`, and the virtual function itself is not. When the thunk
makes a direct call to the virtual function, recognize this situation by
checking for a `virtual_index`, and perform a non-virtual call if there
isn't one.

Assisted-by: Gemini via Antigravity
2026-05-13 17:40:45 +00:00
Dana JansensandRichard Smith 6326bbdbe1 Resolve cycles in .Self replacement in nested designators (#7183)
A nested designator like `.(X.X1).(Y.Y1)` results in nested
ImplWitnessAccess instructions, which can produce cycles in the
toolchain easily when replacing `.Self`.

First, when constructing a facet type like `V:! Z where .Z1 impls (Y
where .Y1 = U)` we substitute replace `.Self` in the nested facet type,
and in this case we replace `.Self` with `.Z1` which contains a `.Self`
of its own. This was coming from us being lazy about replacing `.Self`
in an `impl as` declaration, such as `impl C as Z where .Z1 = .Self`.
The self type is known there, so we can more eagerly replace `.Self` as
we do in a `require impls` declaration. Then the replacement for `.Self`
never comes with a `.Self` that needs to also be replaced. Any resulting
`.Self` would always be the top-level one.

Second, when evaluating ImplWitnessAccess, we were replacing .Self in
the LHS of rewrite constraints, but the `.Self` may itself have a type
that contains rewrite constraints. If one of those rewrite constraints
has nested ImplWitnessAccess instructions, we evaluate the new
ImplWitnessAccess, which again finds rewrite constraints to replace
`.Self` in, and we repeat forever. For this one we just stop replacing
.Self in the LHS of rewrite constraints. Since they are always against
.Self, we can always look in the access facet's type for a value.

While fixing ImplWitness access, also correct the lookup to search
through the types of nested ImplWitnessAccess instructions to find a
rewrite value, since it may find it at any level up to the eventual
`.Self`.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2026-05-13 16:11:20 +00:00
Dana Jansens 6776e2b804 Detect impl redecls in non-declarative scopes (#7170)
Avoid crashing on the fact that block scopes have no related InstId. So
we can't push the InstId of the current scope in the ImplIntroducer
node, as it can be None. Instead we have to find the parent InstId when
we're building the ImplDecl, because the ImplDecl has a node at the top
of the scope stack for the DeclNameStack.

Impls are allowed in sequential (non-declarative) scopes (functions,
blocks), but [redeclarations are not
allowed](https://github.com/carbon-language/carbon-lang/blob/db24042fe56d22275aa801696e2f8f5c4171e35b/proposals/p3763.md?plain=1#L279).
We now diagnose these redecls as invalid.
2026-05-07 13:44:40 +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
Dana Jansens 46bb0fecd4 Properly diagnose ambiguous .Self in T impls X where... (#7132)
A `where` expression nested inside a `T impls X` constraint makes
`.Self` ambiguous on the right-hand side of the `where` if `T` is
anything other than `.Self`. After the `where`, the value of a `.Self`
could be `T` or could be the value of `.Self` before the `impls`
constraint: the so-called top-level value of `.Self`.

Implicit use of `.Self` in designators is always allowed, and they are
bound (and replaced by a reference) to the inner-most possible value of
`.Self`. On the right-hand side of the nested `where` above, they have
the value `T as X`.

`.Self impls ...` is also always allowed, since it acts more as a
keyword here, and it always refers to the inner-most possible value of
`.Self`.

Any other explicit use of `.Self` is diagnosed when ambiguous, in any
kind of constraint. This is done in the handling of `WhereExpr` since it
has enough context to allow `.Self impls` (which is an explicit use)
while disallowing other explicit uses. And because it has non-canonical
instructions to work with, so it is able to diagnose errors with precise
locations.

Since `.Self` is no longer going to be marked with depth modifiers, the
eval of `WhereExpr` does not need an input facet value instruction
representing `.Self` to compare with, as they are now going to all be
equivalent. So revert it back to just looking for the `PeriodSelf` name
id, through a shared helper being introduced as `IsPeriodSelf`. And drop
the period self InstId from the `WhereExpr` instruction. This causes
most of the formatted SemIR changes.

Move helpers for working with and replacing `.Self` to their own file,
out of the `facet_type.h` header/cpp files. These are working with
`.Self` facet values more than facet types, though `.Self` is a name
that only exists inside the scope of a facet type.
2026-05-01 21:22:32 +00:00
Dana Jansens 235267680b Subst .Self in impl as rewrites (#7105)
This makes rewrites of a constraint that requires a generic `I(Self)`
work. The `Self` there is replaced in the identified facet type by the
impl-as self type. But the rewrite is for the interface `.I(.Self)`, so
they don't match. Once `.Self` is replaced with the impl-as self type,
then they match and the rewrite is applied.
2026-04-24 20:51:20 +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
Dana Jansens 142596b49c Diagnose unidentified type-of-self in impl lookup query (#6769)
The type of the query self is looked into for a witness, but that type
may be unable to be identified. For example when the query is against
`Self` inside the declaration of a named constraint. Before this PR, we
would crash when identification failed. Now we produce a diagnostic.

This makes `RequireIdentifiedFacetType` take a `ContextScope` callback
(like it used to with an `AnnotationScope` callback) since all callers
now expect to handle diagnostics, and can provide useful context.

This is a followup to #6761.
2026-02-25 20:23:21 +00:00
Dana Jansens fbc8d59d32 Introduce Diagnostics::ContextScope and remove diagnoser callbacks in type completion (#6761)
Introduces `Context` and `SoftContext` messages, which can be introduced
through a `ContextBuilder`:
- The `Context` messages come before the diagnostic in the output.
- The first `Context` message steals the diagnostic level from the main
diagnostic, and turns the main diagnostic into a Note attached to the
context.
- A `SoftContext` message works similarly, but if it's preceeded by a
`Context` or `SoftContext` message, then it is dropped. This can be used
as a default/backup scope when nothing more interesting is provided up
the stack, such as in `TryEvalBlockForSpecific`.

The `ContextBuilder` is provided to a callback through
`Diagnostics::ContextScope`, an RAII type `AnnotationScope` but for
context messages.

This allows a high level operation to provide a context message like
"failed to identify facet type {0}" which will then be used as the error
if a diagnostic is produced during identification, with the latter
diagnostic attached as a note to explain why the contextual operation
failed.

In particular, this allows monomorphization errors (such as an array
bound being negative) to be attached to a higher lever operation instead
of being top-level diagnostics themselves, with the monomorphization
site being a note. This inverts the source code locations that appear in
the diagnostic, so that the top-level diagnostic points to the "user
code" which causes the monomorphization.

This is presented as an alternative strategy to #6753, which plumbed
diagnoser callbacks around to achieve the same goals.

We replace the diagnoser callbacks in type completion and operators with
ContextScope callbacks instead, which now provide better diagnostics for
monomorphization errors. Other callers to MakeSpecific do not yet have
ContextScopes introduced in order to turn monomorphization errors into
more interesting diagnostics.
2026-02-25 15:15:29 +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
Jon Ross-Perkins 45ca3d28f5 Drop "diagnostic" from some filenames in the "diagnostics" folder (#6686)
Mainly because "sorting_diagnostic_consumer" is legacy, since
`SortingDiagnosticConsumer` became `SortingConsumer`. Also better
reflecting contents of these files.

Where I'm not renaming, I'm less positive about dropping "diagnostics"
from "file_diagnostics" and "null_diagnostics" (which contain both a
consumer and emitter, and "null.h" seems like poor naming), so not doing
that here. Also "diagnostic.h" contains `struct Diagnostic`, so is a
decent fit.

Assisted-by: Google Antigravity with Gemini 3 Flash
2026-02-04 17:24:55 +00:00
Dana Jansens 7f7186c227 Extended name lookup replaces inner Self (#6632)
When doing name lookup into an extended scope of an interface or named
constraint, the containing scope has an inner `Self` facet which can
appear in the specific of the extended scope. For instance a constraint
`N` which requires an interface `Z(Self)`:

```js
constraint N {
  extend require impls Z(Self);
}
```

When doing member lookup into a facet constrained by `N`, we need to
find the specific interface `Z(...)` where the `Self` is replaced by the
self-type the member lookup is happening on in order for impl lookup to
find a witness later.

Inside that specific interface we repeat the name lookup to find an
associated entity. Then to produce a witness we perform impl lookup
against the specific interface that name lookup returned with the
self-type of the member access. So if we do member access into `A:! N`
for a member `F`, like `A.F`, we would be doing impl lookup with a query
self of `A` and looking for the interface `Z(...)` returned from name
lookup.

When impl lookup has a facet as the query self, which we do here as `A`,
it takes its type (a facet type) and identifies it to find all the
required interfaces, and it substitutes the query self into those
specific interfaces for `Self`. If the `Z(...)` we acquired from name
lookup is `Z(Self)` it will fail the lookup for `A as Z(Self)`, since in
the facet type of `A` it finds a witness for `Z(A)` instead.

Thus, we replace the inner `Self` in extended scopes, such as `N`, with
the self-type of the member access, which produces the extended scope
`Z(A)` for this example. This allows the impl lookup for `A as Z(A)` to
find a witness from the facet type of `A`.

In order to do this, we include an instruction for the inner self when
registering the extended scope. Then, when we find the extended scope in
name lookup, we can use its CompileTimeBindIndex to replace any instance
of that `Self` facet with a new facet. If the self-type of member access
is a type, we construct a FacetValue with an empty facet type that
refers to the type.
2026-01-21 17:48:18 +00:00
Dana Jansens 4bb2935770 Look through extend require in an interface or named constraint in name lookup (#6630)
Add the required facet type as an extended scope of the containing
interface/named constraint, and teach name lookup to look for extended
scopes in named constraints.

This makes name lookup work properly when the facet type does not have a
specific that involves `Self`. Support for `Self` needs further work in
another PR.

Note that when an _interface_ requires another interface, this PR lets
us find the name, but we still fail to find a witness for the interface
named through `extend require`, and this is future work. For a named
constraint, things work correctly as the identified facet type chases
through the named constraint and includes the required interface, so
impl lookup is able to provide a witness.
2026-01-20 22:26:10 +00:00
Dana Jansens 848eddc9dd Avoid cyclic lookup of an impl inside its own definition (#6629)
An interface A requiring another interface B means that an impl of A
must verify that the self-type also impls B. The instructions created
from this can involved a lookup that the self-type impls A, which end up
finding the impl being defined. This is not problematic of itself, but
it is problematic if these lookup instructions become part of the impl's
generic definition. When we find a specific of that `impl as A` during
impl lookup of A, and we resolve the specific definition, those lookup
instructions are replayed. Doing so does another lookup for `impl as A`,
which creates an infinitely recursive loop.

To break this loop we move the lookup instructions done to verify that
the self-type impls B outside of the definition of `impl as A`. This
prevents them from being specialized. But it doesn't prevent us from
diagnosing monomorphization errors properly. They just get diagnosed at
the use of that invalid specific, instead of inside the verification of
`impl as B` in the definition of `impl as A`.
2026-01-20 19:28:46 +00:00
Dana Jansens 32aa7cb1fa Make identifying a facet type an operation on a (self+facet type) pair (#6592)
Identifying a facet type takes both a self and facet type as a pair, and
then encode the self into the IdentifiedFacetType. This makes a
constraint that requires some _other_ type implements an interface
visible in the IdentifiedFacetType. And it will help to enable facet
types with `where T impls Z` for `T` that is not `.Self` in the future.

IdentifiedFacetTypes are now stored in a CanonicalValueStore instead of
a RelationalValueStore as they key is the combination of self and
(declared) facet type together now.

When the self-type is a facet value (has type FacetType) this is most
straightforward. But when it's a type we need to construct a FacetValue
to construct a specific for a require decl, to replace the generic
binding of the symbolic `Self`, which has type FacetType. To do so, we
make a FacetValue with an empty FacetType (equivalent to TypeType). This
prevents any looking for witnesses through the FacetType, which matches
what you can get from a type directly, requiring witnesses to come from
finding an `impl` decl.

Add additional InstNamer logic for such empty facet types so they print
as `<typename>.type.facet` if possible instead of as just `facet_value`.
2026-01-14 17:34:56 +00:00
Dana Jansens 3a7c44c5c4 Check required implementations when an enclosing interface is implemented (#6522)
If an interface contains `require impls`, then implementing the
interface requires each of the `require impls` statements to be true at
the point of the impl definition for the containing interface.
2026-01-07 17:05:41 +00:00
Jon Ross-Perkins 655932da0b Refactor BuildCustomWitness out to its own file (#6515)
Per request at
https://github.com/carbon-language/carbon-lang/pull/6512#discussion_r2627265838
2025-12-17 21:36:44 +00:00
Dana Jansens efec4e4658 Move generic stack operations into handle_impl.cpp (Refactor Impl construction 8/7) (#6484)
Instead of burying operations to pop the generic stack in
`GetOrAddImpl`, we move them up to handle_impl.cpp in `BuildImplDecl`,
which puts them at the same level as other operations on the generic
stack, like `StartGenericDecl` or `FinishGenericDefinition`.

To do so, we split `GetOrAddImpl` into a few pieces:
- `FindImplId` finds an existing Impl that matches the declaration, or
returns a LookupBucketRef and whether an error was diagnosed instead.
- `AddImpl` takes a fully built `Impl`, makes an `ImplId` for it, and
does additional steps for a new `Impl` verifying it and applying
`extend`.
- `AddImplWitnessForDeclaration` constructs the `Impl`'s witness, which
must be done between two generic steps in order to use the generic's
self specific but also add the witness instruction to the generic.

We group the logic to build the initial table in the definition and to
complete it in the definition together in `impl.cpp`. And we save a
lookup into the ImplStore by passing Impl by reference to
`FinishImplWitness`, as we now do for other similar functions in
`impl.h`.

This is based on #6470.
2025-12-16 15:32:56 +00:00
Jon Ross-Perkins 25f63140e6 Refactor CppWitness as CustomWitness (#6491)
This is in anticipation of using the same construct for all
implementations of `Destroy`, as well as other similar use-cases with
language-defined interfaces.
2025-12-15 19:41:14 +00:00
Dana Jansens fbcaf34494 Defer RequireCompleteType to impl definition (Refactor Impl construction 7/7) (#6470)
Explicitly run `RequireCompleteType` for an impl's facet type constraint
in two places:
- For a new `Impl` declaration that is `extend`
- At the start of the `Impl` definition

Stop trying to RequireCompleteType in the definition when constructing
the witness. If we have a rewrite of a name in `.Self`, then we can
construct a full witness, otherwise we defer to the definition.

Now GetOrAddImpl does not need to track `is_definition` anymore, so we
remove a lot of plumbing.

We inline the `AllocateFacetTypeImplWitness` since it has a single
caller and it is just 2 lines, to help improve understanding of the
steps and comments in setting up the impl definition.

Note that this puts the `RequreCompleteType` instruction into the
definition's generic eval block always, avoiding the issue of ensuring
that each generic redecl has the exact same instructions, and forcing
coordination to have `RequireCompleteType` inserted into every
declaration's eval block or none. The result also more closely matches
the design, with the complete type not being required until inside the
definition.

This is part of #6420 which is being split up into a chain of smaller
PRs. It is based on #6469.
2025-12-11 23:50:10 +00:00
Dana Jansens 463ba0e1db Clean up helpers for GetOrAddImpl (Refactor Impl construction 5/7 and 6/7) (#6469)
Make the `AssignImplIdInWitness` into a `static` helper function since
it's only used inside `GetOrAddImpl`. Restructure the diagnostic for
unused generic bindings to move more logic into the helper, and out of
`GetOrAddImpl` so that it has more clear steps.

This is part of #6420 which is being split up into a chain of smaller
PRs. It is based on #6468.
2025-12-11 22:22:43 +00:00
Dana Jansens 35d505a985 Check the orphan rule for impls (#6488)
The orphan rule is defined here:
https://docs.carbon-lang.dev/docs/design/generics/details.html#orphan-rule

**Orphan rule:** Some name from the type structure of an `impl`
declaration must be defined in the same library as the `impl`, that is
some name must be *local*.

Update tests that were running afoul of the orphan rule unintentionally.
Add tests that do violate the rule intentionally and test edge cases.
2025-12-11 19:44:39 +00:00
Dana Jansens 14998d6045 Consolidate error handling behaviour for ApplyExtendImplAs (Refactor Impl construction 4/7) (#6468)
Propagate error state in an `extend impl` declaration out to the
enclosing scope. We can do this generically in `ApplyExtendImplAs` so we
don't have to do it explicitly in other places.

Collapse `DiagnoseExtendImplOutsideClass` into `ApplyExtendImplAs` as it
had only the one caller and is very small, so this simplifies the code,
making `ApplyExtendImplAs` a clear set of diagnostics. And push the
construction of the SpecificConstant down into `ApplyExtendImplAs` so it
is only constructed if it's needed, instead of constructing it and
throwing it away in error cases.

Ensure any error in the declaration results in the witness being an
ErrorInst so the impl will not be used in impl lookup. This simplifies
some branches by combining them into a single if statement.

This is part of #6420 which is being split up into a chain of smaller
PRs. It is based on #6467.
2025-12-11 19:05:17 +00:00
Dana Jansens 1c3d3e9284 Move forward-decl-only code out to the handler of the forward decl node (Refactor Impl construction 3/7) (#6467)
Rather than run the code for both decl and defn and make it conditional
on not being a definition, put the code in the handler for the
`Parse::ImplDeclId` node, which is handled when there's no definition.
This will help lead us to no longer needing to plumb around
`is_definition` later.

Make some naming consistent to call the reference to an `Impl` as `impl`
instead of sometimes `impl_info`.

This is part of #6420 which is being split up into a chain of smaller
PRs. It is based on #6466.
2025-12-10 21:55:01 +00:00
Dana Jansens b07b8a122a Make StartImplDecl into a more explicit GetOrAddImpl (Refactor Impl construction 2/7) (#6466)
The GetOrAddImpl operation looks for an existing `Impl` with a matching
declaration and returns its ImplId, or finished the construction of a
new `Impl`, adds it to the store and returns a fresh `ImplId`.

This makes the case of reusing an existing `Impl` into a short
early-out, demonstrating more clearly that we are reusing existing work,
and avoiding duplicate work such as checking for diagnostics that would
have already been checked in the previous (matching) declaration.

The `ExtendImpl` helper is renamed to be more explicit about its
behaviour, as `ApplyExtendImplAs`, and it constructs the data it needs
from the `Impl` and the `extend_node_id`, eliminating the need for a
`ExtendImplDecl` struct.

This is part of #6420 which is being split up into a chain of smaller
PRs. It is based on #6465.
2025-12-09 22:02:50 +00:00
Dana Jansens 2d38978756 Diagnose explicit Self in extend in the parse node handler (Refactor Impl construction 1/7) (#6465)
We encode the state of looking that the parent scope is a Class into a
type so that we can avoid extra lookups. Then use that in refactoring
where diagnostics are generated for an explicit `Self` in an `extend
impl` declaration.

We add tests that we don't double-diagnose the Self type when it's
already an error, and make the behaviour of `extend require` match that
of `extend impl as`.

This avoids some fragile/complex parse-node lookups (such as
`context.parse_tree_and_subtrees().ExtractAs<Parse::ImplTypeAs>`) by
using the parse node at the point where we are handling it instead of
much later.

This is part of #6420 which is being split up into a chain of smaller
PRs.
2025-12-09 20:38:50 +00:00
372f632d9d Implement support for copying C++ classes. (#6434)
When performing impl lookup for `Core.Copy` for a C++ class type, look
for a copy constructor. If we find one, synthesize an impl witness that
calls the constructor.

This adds initial support for impl lookup to delegate to the C++ interop
logic for queries involving C++ types. For now, we don't implement the
rules from #6166 that compare a synthesized type structure for the C++
impl against the best Carbon type structure, but the framework for
building that support is established here.

Currently there is no caching of the lookup here, and we build unique
`ImplWitnessTable`s for each lookup, which leads to each impl lookup
producing a distinct facet value. This results in some errors in generic
contexts; this will be addressed in follow-up changes. This PR aims only
to support the non-generic case.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2025-12-02 02:52:23 +00:00
Dana Jansens 0cf2448505 Get specific interfaces with correct specific from named constraints (#6435)
When forming an IdentifiedFacetType, we collect interfaces named by
require decls in named constraints that the facet type refers to. These
interfaces come with a specific, but the require decl is inside an named
constraint which may be generic. So we need the specific being applied
to the containing named constraint to also be applied to the require
decl and its target interfaces.

This uncovered that the facet type in require decls was not being
imported correctly, as it was not being attached to the require decl's
generic. This is fixed by making import of RequireImplsDecl multiphase,
so that the decl instruction exists before we resolve the facet type
within it. And by pointing the generic importing machinery to the
RequireImplsDecl, and from there to the RequireImpls structure to get
the generic id.

Then `ImplStore::GetOrAddLookupBucket` can use an IdentifiedFacetType to
correctly get the interface being impl'd, both in the local and the
imported named constraint case. Which allows us to correctly diagnose
redeclarations in the impl file of an impl of an interface through a
named constraint. And to correctly _not_ diagnose them when the specific
in the generic named constraint differs from other decls.
2025-12-01 18:59:02 +00:00
Jon Ross-Perkins fbc7690157 Switch zip to zip_equal where possible (#6389)
There are two uses I'm not converting here, that seem to want the
"shortest" behavior. For everything else, I'm going to `zip_equal` since
it's more restrictive.

I wish `zip` were named `zip_shortest`.
2025-11-18 00:28:06 +00:00
Dana Jansens e62678e682 Identify and complete facet types as needed for p5168 (#6369)
Proposal #5168 defines when a facet type must be identified or complete,
and what it means for an interface and a named constraint to be
identified or complete. This updates the toolchain to match the
requirements.

This implements identification of a facet type to require completed
named constraints and to include any interfaces from named constraints
into the resulting IdentifiedFacetType.

To complete a facet type, each interface in the IdentifiedFacetType, and
any interface named though a require declaration from them, must be
complete.
2025-11-14 19:24:02 +00:00
Dana Jansens ca3f95faa6 Make named constraint eval to a FacetType with itself in it (#6308)
This requires declared FacetTypes to hold NamedConstraintIds (along with
a specific) that are named in an extend or impls requirement. We add
support to stringify and formatter to display the named constraints in
the facet type, and special case when a facet type contains a single
extend named constraint, like we did for a single extend interface.

This means that `RequireIndentifiedFacetType` can now fail, if the facet
type contains a forward-declared named constraint. Add the appropriate
diagnostics for each call to this function, and note the ones that
should change to `RequireCompleteFacetType` in the future with TODOs.

We also add tests for using facet types that can or can't be identified,
or completed, with named constraints in them.
2025-10-31 22:10:35 +00:00
Jon Ross-PerkinsandDana Jansens a1fd86cf27 Change ImplWitnessTablePlaceholder from instruction to InstId value (#6294)
`ImplWitnessTablePlaceholder` is the only non-type singleton instruction
(`ErrorInst` is a type; while `ImplWitnessTablePlaceholder` exposes
`TypeInstId`, it's only used as an `InstId`).

In order to allow simpler handling of singleton instructions, replace
`ImplWitnessTablePlaceholder::TypeInstId` uses with
`InstId::ImplWitnessTablePlaceholder`. Since the placeholder instruction
was never evaluated, this has no significant effect on behavior.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2025-10-29 18:10:24 +00:00
Dana Jansens 26381f6eaf Handle parsing of require...impls declarations (#6255)
Check is not implemented yet, but some tests are added.
2025-10-23 18:34:52 +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
Jon Ross-Perkins ef748ab36d Factor out an impl declaration helper function (#5851)
In trying to have types implicitly define `impl Self as Destroy`, I'm
wanting to use standard impl declaration support. For example, this
should produce more consistent errors if someone writes code that would
conflict with the generated impl. I'm also concerned, with the
complexity involved, that I'd get something wrong if I tried to write a
divergent implementation.

I'm only factoring out the start of the declaration. Right now the
finishing portion seems much simpler and lower risk to duplicate; I may
also factor it out separately. But either way, I think `StartImplDecl`
here is high churn risk due to its size (`CheckConstraintIsInterface` I
also expect to be used).
2025-07-25 18:34:07 +00:00