Commit Graph
137 Commits
Author SHA1 Message Date
Lucile Rose Nihlen 994bad5143 Use non-canonical instructions in default values. (#7737)
Per feedback on #7665, this PR switches the default value
table storage from canonical constant inst_ids to
non-canonical.

Furthermore, this PR simplifies the default value support in
check by requiring that the first owned declaration of a
function completely specify all of its default values.
Updates the diagnostic code and tests to reflect this new
stricter requirement.
2026-09-17 22:04:43 +00:00
Lucile Rose Nihlen 3e64670122 Transform pattern default values to SemIR (#7649)
Adds check functionality to transform the parse node to SemIR. Only
supported for single declarations of functions, re-declaration and
imports to come in a subsequent PR.

Per #7521.
2026-09-01 16:12:34 +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 48a03e6a1c Remove TODO to check for orphan impls (#7562)
Orphan impls are found at the end of checking the file, in
`ValidateImplsInFile()`.
2026-07-24 19:11:21 +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 cda1f256bb Use match_first to prioritize impls (#7492)
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.
2026-07-15 21:25:25 +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 d46b040290 Connect impls to their containing match_first block (#7486)
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.
2026-07-13 19:14:38 +00:00
Dana Jansens a46f4863db Basic checking for match_first blocks (#7481)
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.
2026-07-11 14:01:38 +00:00
Richard Smith ce080b3549 Support unqualified lookup into extended interfaces from classes and impls (#7217)
When a class extends an interface, referring to a member name of the
interface as an unqualified name should refer to the class's
corresponding associated entity value, not to the associated entity
itself. Similarly, in an `impl`, unqualified names of associated
entities should refer to the `impl`'s corresponding value for that
entity.

To support this, we treat `impl`s as `extend`ing their implemented facet
type, and we make lookups into an extended facet type use the `Self`
type of the extending `impl` or `class` if lookup finds an associated
entity. We already did the latter if the extending entity was an
interface; this extends the existing support for these other cases.
2026-05-19 18:01:54 +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
Geoff RomerandChandler Carruth 49c7288619 Restructure return declaration handling (#7076)
- A function with a return declaration always has exactly one
`ReturnSlotPattern`, representing the whole return declaration (whereas
previously that was omitted for value and reference returns).
- The `ReturnSlotPattern` always has a subpattern with the same form.
`OutParamPattern` already plays that role for initializing forms, and
`TuplePattern` will play that role for tuple forms. This change
introduces `ValueReturnPattern` and `RefReturnPattern` to represent
value and reference return forms.
- As before, the `ReturnSlotPattern` has a corresponding `ReturnSlot`
that represents the output that is initialized by a `return` statement.
Its structure parallels the structure of the `ReturnSlotPattern`, so we
need `ValueReturn` and `RefReturn` insts that correspond to
`ValueReturnPattern` and `RefReturnPattern`.

This is a step toward supporting generic return forms, where the
`ReturnSlotPattern`'s subpattern may be an action: this change ensures
that evaluating the action for a specific form produces the same SemIR
as if the form were concrete to begin with. More speculatively, this
should simplify the implementation of `return` statements with compound
return forms.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2026-04-22 23:38:21 +00:00
Geoff RomerandJon Ross-Perkins 18cfeb7476 Add support for ->? return forms (#6849)
This includes checking and lowering for concrete form literals. Support
for symbolic forms is future work.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2026-03-09 22:30:16 +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
Jon Ross-Perkins 2c6d9c7f66 Rename type's GetInstId to GetTypeInstId, reflecting returned type (#6708)
Discussed briefly [on
Discord](https://discord.com/channels/655572317891461132/655578254970716160/1470442830118912265),
done to reduce confusion.

Assisted-by: Google Antigravity with Gemini 3 Flash
2026-02-09 22:00:21 +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
Geoff Romer a2737a3189 Add Call param patterns to Function (#6586) 2026-01-13 19:30:15 +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
Dana Jansens 7c1798d96d Format impl witness instructions as part of the impl (#6485)
The impl's body block has to end before we make its ImplDecl
instruction, and the witness instructions come later, so they don't end
up in the body block. Currently they just end up in the enclosing (file,
typically, or class) scope block.

Add a new InstBlockId to Impl for holding witness instructions, and
explicitly insert them into that block. Then include those instructions
into the scope of the Impl for naming, and format them into the Impl
right after the body block.

This is based on #6484
2025-12-17 15:46:30 +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
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 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
Geoff Romer bf45b1cbf5 Refactor function return type representation (#6463)
This separates the return type from the return pattern, and replaces the
return pattern with a block of return patterns. This is a step toward
support for `ref` returns (where there's no corresponding return
pattern) and compund-form returns (where there may be multiple return
patterns).
2025-12-10 18:34:23 +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
Dana Jansens 81e55bed8a Generate a RequireDecl instruction for require declarations (#6318)
The `RequireDecl` instruction points, via a `RequireImplsId` to a
`RequireImpls` structure in a `ValueStore`. That structure holds the
self-type and facet type, as well as the generic id and parent scope.
`RequireImpls` is always a generic since it only appears in an
`interface` or `constraint`, which both have a generic parameter `Self`
applied to all their members.

The `RequireDecl` instruction evaluates to itself, but drops the
decl_block_id since the instructions within the `require` declaration
are not required in the canonical value which is only used for import.
And import will want to import the `RequireImpls` structure along with
the `Interface` or `NamedConstraint` structure it is in, rather than
recreate it from the decl's instructions. This also avoids repeating all
the instructions within the `require` decl in the textual semir's
constants block.

Adding the `RequireImpls` to the `Interface` or `NamedConstraint`
structure is not yet done, so they are not available for impl lookup or
import yet.
2025-11-11 14:16:09 +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
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
Jon Ross-Perkins 2bb8e98849 Change SemIR formed for 'as' errors (#5792)
Direct use of an error means we can delay looking at the actual type,
and also use the `self_id` of the stored `ImplInfo` directly.

Note, I'm assuming we should be okay with this not always being a
`NameRef`. In error cases though, it seems like we shouldn't mind it
being an error instead of a name reference to an error.
2025-07-10 21:56:03 +00:00
Dana Jansens 493bea1647 Fearlessly hold references into ValueStore again (#5589)
Undo changes that were meant to prevent use of a reference into
`ValueStore` after being invalidated. After #5576, the `ValueStore`
makes such references stable, so there's no need to worry about
invalidation.
2025-06-03 18:07:23 +00:00
Dana Jansens ccc94439e5 Don't reuse the reference into the ImplStore after doing deduce (#5456)
Deduction can import stuff which can invalidate all of the value stores.
Refactor out the code that diagnoses unused generic bindings, and scope
the reference into the ImplStore so it can't be used after. Fetch the
impl from the store again when setting the witness to error afterward if
needed.
2025-05-09 20:35:18 +00:00
Dana Jansens 90898a8e19 Avoid witnesses in redecls when handling errors in handle_impl (#5409)
When we fill the witness table with errors, set the witness id to an
error too, which signals to impl lookups to not use the impl.

Make the use of the `Impl` from the store more consistent once it's been
added to the store (or known to be there already).
2025-05-02 19:49:06 +00:00
Richard SmithandJon Ross-Perkins 95903dc624 Generate thunks for functions in impls (#5390)
Generate a thunk when a function in an `impl` has a different signature
than the function in the interface. This follows the design in
[#3763](https://docs.carbon-lang.dev/proposals/p3763.html#impl-members-vs-interface-members),
although some of the checks described there are not yet implemented.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-05-01 22:17:55 +00:00
Richard SmithandDana Jansens 4f5d11a28b Build generic eval blocks incrementally (#5313)
Instead of building an eval block as a separate pass at the end of a
generic, build the eval block incrementally.

The larger change here is that asking for the type or constant value of
an instruction now always returns an unattached type or constant value,
in order to preserve the behavior that we previously achieved by doing
the rewrite to attached types and constant values at the end of handling
the generic.

This also incidentally fixes some subtle issues where attached types and
constant values would leak out into check and cause it to get confused
about differences between attached and unattached values. Check should
no longer see attached values except where it explicitly asks for them.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2025-05-01 20:24:15 +00:00
Dana JansensandJon Ross-Perkins 315e206ff1 Construct LocId from InstId directly (explicitly) instead of doing lookups when possible (#5355)
Remove calls to `InstStore::GetLocId()` to build a LocId from an InstId
now that they can be constructed directly from the InstId. Most uses of
LocId are just plumbing, so this does not affect them. However places
that want to look inside the LocId do not want to work with the InstId
form. In these places, introduce `InstStore::GetResolvedLocId()` which
converts a LocId (or an InstId as an optimization) into a LocId which is
not backed by an InstId. These locations can be printed (they have a
line and column when they are a NodeId), they can have flags added to
them (`ToImplicit`, `ToTokenOnly`), they can be converted to an
underlying ImportIRInstId, or they may be `None`.

`Dump()` is made to print a resolved location instead of printing the
InstId in the location, since (at least in my experience) the resolved
location is what is interesting in debugging, and this saves manual
`MakeInstId` steps in the debugger every time a location is of interest.

The LocId constructor from InstId is made `explicit` to add clarity to
function calls passing an `inst_id` now directly instead of calling
`context.insts().GetLocId(inst_id)`. To avoid needing to construct
`SemIR::LocId(...)` explicitly in all cases though, the diagnostics code
in Check uses `DiagnosticLocId` as its template parameter which accepts
InstId as well and does the construction of LocId from it.

Because LocId now requires an explicit construction from InstId, any
callers to `AddInst()` functions will have to explicitly convert to
LocId if they had an InstId, but not if they pass a NodeId. To make this
difference clear to callers, we `requires` that the input type can be
converted to LocId. This ensures that passing an InstId results in an
error at the callsite where the InstId is passed, instead of generating
a compiler error when trying to construct `LocIdAndInst` inside
`AddInst()`, which is less clear about what went wrong and doesn't seem
entirely intentional.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-04-28 19:06:24 +00:00
Jon Ross-PerkinsandGeoff Romer 03e693873b Detect control flow in entities nested inside functions (#5336)
Right now, return_scope_stack is being used to determine whether logic
is in a function scope. However, we need to handle nested entities
inside function scopes. For example where this crashes right now:

```
base class C(B:! bool) {}

fn F() {
  class B {
    extend base: C(true or false);
  }
}
```

This is doing a few things to make this kind of code not crash:

- Split `scope_stack().Push` into `PushForDeclName`, `PushForEntity`,
`PushForExpr`, and `PushForFunction` so that better decisions can be
made about behaviors.
- Hide `return_scope_stack` in the API, instead using interfaces to get
at the underlying data.
- Also using `PushForFunction` to update it similar to the other stacks
that `ScopeStack` manages.
- Add `IsInFunctionScope` as the best way to determine presence in
function scope.
- Remove `PeekIsLexicalScope` since destruction really wants function
scope information anyways.
- Clean up `destroy_id_stack` handling to be for function scopes rather
than lexical scopes.
- Return after related `context.TODO`s in a couple more spots, so that
code doesn't proceed to add control flow in spite of the lack of
support.

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2025-04-23 19:03:53 +00:00
Dana Jansens 94dca7967b Allow extend final impl as for impl declarations (#5345)
In a class, an `impl as` can now be both `final` and `extend` instead of
only one or the other.

In https://github.com/carbon-language/carbon-lang/issues/5319 we decided
this is already allowed by the design but was an oversight in the
implementation.
2025-04-23 15:20:18 +00:00
Richard Smith 19532967fa Stop pushing a fake generic for the duration of check. (#5326)
This fake generic was used for two reasons:

- The declaration name stack assumes that each declaration name is
processed within a generic scope. This is important if the name might
have generic parameters, which are always parsed even for declarations
that disallow them in check.
- Out-of-line redeclarations of generic entities produce instructions
with symbolic constant values in non-generic scopes.

The former case is addressed by pushing a generic each time we start a
declaration name, even if we will reject generic parameters later. The
latter case is worked around for now by not building a symbolic constant
type or value for instructions that appear outside of any generic, and
will be addressed more completely by #5310 and follow-ups.
2025-04-17 21:58:37 +00:00
Thomas Köppe bf32da8dad Add missing standard library header inclusions (#5316)
Discovered by clang-tidy.
2025-04-17 15:37:57 +00:00
Jon Ross-Perkins 4923445e3a Drop Singleton from ErrorInst::SingletonInstId and similar (#5304)
We frequently want to operate on singletons. Per discussion, drop
`Singleton` to make the code shorter.

This started off as wanting to write `inst_id.is_error()`, but the
dependency relationship between ids.h and singleton_insts.h would
require some kind of delayed evaluation to allow the implementation to
remain in headers (which I suspect is helpful to have for inlining). I
could have added something like `IsErrorInst`, forward declared in ids.h
and defined in singleton_insts.h (which would always be included by
typed_insts.h), but the template approach felt like a decent balance
between (a) removing the boilerplate `::SingletonInstId`, (b)
understandability, (c) still visually mirroring if we immediately return
a singleton, and (d) flexibility for more than just `ErrorInst`. But TBH
I'd probably still have written `is_error()` if it didn't require
addressing the cross-header cycle.

Then I tried `SemIR::InstId::Is<SemIR::ErrorInst>`, which generally
worked with types but generated the complaint that it didn't shorten
*all* singleton uses. So pulling back on `::Is`, and instead just
dropping `Singleton`.
2025-04-15 22:40:29 +00:00
Dana JansensandRichard Smith 0e8d354567 Split the witness table into a separate ImplWitnessTable instruction (#5272)
This allows us to import the table for a given impl only once, while we
can import many ImplWitness instructions with different specifics for a
generic impl.

For example in convert_facet_value_to_narrowed_facet_type.carbon we see
that a single witness table is imported for the BitAnd interface, with
multiple witnesses (for different specifics) imported and sharing the
same table.

The ImplWitnessTable now contains a back-link to the Impl the witness is
for, allowing inst namer to name that interface in the textual semir,
and allowing the interface to be found when debugging from a witness.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-04-11 20:30:04 +00:00
Dana Jansens c34a8d0a3a Convert remaining type-value InstId fields to TypeInstId (#5294)
After #5280 there are a few more typed instructions that have an `InstId
type_inst_id` that always holds a type value. These are converted to
`TypeInstId` to encode this fact in the type system. The
`ConvertAggregateElement()` function in convert.cpp is now able to
receive `TypeInstId` for a couple arguments as well.

Additionally, the `type_inst_id` field of `StructTypeField` is made into
a `TypeInstId`.

The `TupleType::elements_id` is renamed to `TupleType::type_elements_id`
to try record the fact that it's an InstBlock of type value
instructions. We don't introduce a TypeInstBlockId at this time, but it
might be nice to make blocks of TypeInstIds in the future.

To assist in working with a block of InstId that are type values, two
additional helpers are added to the TypeStore:
- GetBlockAsTypeInstIds which turns an `ArrayRef<InstId>` into a range
of `TypeInstId`
- GetBlockAsTypeIds which turns an `ArrayRef<InstId>` into a range of
`TypeId`

We use these helpers in places that iterate over the
`TupleType::type_elements_id`.
2025-04-11 20:11:03 +00:00
Dana JansensandRichard Smith cf57c85545 Introduce TypeInstId (#5288)
TypeInstId is an InstId whose constant value has a type of TypeType.
This includes:
- Type value instructions, the `ClassType` or `IntLiteralType`
instructions.
- Constraint value instructions, which are the `FacetType` and
`TypeType` instructions, each of which also have type TypeType.

TypeInstId encodes in the type system that it is safe to convert the
instruction's value to a TypeId, and CHECKs at construction that this
invariant is maintained.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-04-10 22:59:02 +00:00
Dana JansensandRichard Smith 76c68153a2 Look for final impl when accessing associated constant in facet (#5269)
While facets may come with a rewrite for an associated constant, they
are symbolic. A final impl has the ability to provide a concrete value
instead, which allows generic code to use the concrete value in place of
the associated constant's (fully qualified) name.

For instance, instead of `I.Type`, the concrete type `()` can be used if
there is an `impl final [T:! type] T as I where .Type = ()` impl.

This does not yet cache the result of the lookups.

Depends on https://github.com/carbon-language/carbon-lang/pull/5255

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-04-10 13:48:49 +00:00