Commit Graph
137 Commits
Author SHA1 Message Date
Richard Smith e8cd229e74 When performing an impl lookup, only import impls for related interfaces. (#6040)
This avoids impl lookups involving, say, `Core.Int` pulling in all ~65
impls in "prelude/types/int", which resulted in a lot of unnecessary
importing work, followed by a lot of unnecessary inst namer and inst
formatter work.

Before:
```
Ran 1335 tests in 6186 ms wall time, 146818 ms across threads
  Slowest tests:
  - toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon: 5611 ms, 5532 ms in Run
  - toolchain/check/testdata/interop/cpp/function/operators.carbon: 2034 ms, 1981 ms in Run
  - toolchain/check/testdata/primitives/import_symbolic.carbon: 1796 ms, 1786 ms in Run
  - toolchain/lower/testdata/operators/arithmetic.carbon: 1729 ms, 1728 ms in Run
  - toolchain/lower/testdata/function/generic/call_recursive_sccs_deep.carbon: 1700 ms, 1697 ms in Run
[==========] 1335 tests from 1 test suite ran. (682 ms total)
```

After:
```
Ran 1335 tests in 2419 ms wall time, 109587 ms across threads
  Slowest tests:
  - toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon: 1748 ms, 1665 ms in Run
  - toolchain/check/testdata/interop/cpp/function/operators.carbon: 1106 ms, 1057 ms in Run
  - toolchain/lower/testdata/function/generic/call_recursive_diamond.carbon: 1044 ms, 1041 ms in Run
  - toolchain/lower/testdata/function/generic/call_recursive_sccs_deep.carbon: 1015 ms, 1012 ms in Run
  - toolchain/lower/testdata/operators/arithmetic.carbon: 998 ms, 997 ms in Run
[==========] 1335 tests from 1 test suite ran. (652 ms total)
```

That's still slower than it should be, but a large improvement
nonetheless.

Fixes #6029
2025-09-10 21:40:27 +00:00
Dana Jansens ed43fd2c1c Give the BindSymbolicName for .Self in a binding pattern a FacetType type (#6036)
If it's just `TypeType` then the `BindSymbolicName` appears directly in
type positions, but if it is replaced with another facet value, then we
would need to insert a `FacetAccessType` around it. By giving it a
`FacetType` type, like other `BindSymbolicName`s we make it consistent
and avoid having to introduce extra instructions.
2025-09-10 17:57:08 +00:00
Jon Ross-Perkins 0518fdebbc Fix potential fingerprint conflict in constraints (#6033)
This uses each vector's size as a barrier between lists, to eliminate
the possibility of incidental collisions between entries of different
lists. This is the same as is done inside `AddBlock`.
2025-09-09 21:44:03 +00:00
Richard Smith db0a00d713 Fix double-destruction of temporaries. (#6010)
Attach the cleanup to the `Temporary` instruction instead of to the
`TemporaryStorage` instruction. We create `TemporaryStorage`
instructions speculatively when creating an initializing expression, and
may overwrite those instructions with other instructions if it turns out
that a temporary is not required. Instead, wait until we finalize the
temporary and create a `Temporary` instruction to register the cleanup.
2025-09-04 19:19:59 +00:00
Dana JansensandJon Ross-Perkins 4b0e2b03b6 Add the .Self name for the type expression of a compile time binding (#5937)
We add a virtual node (`CompileTimeBindingPatternStart`) as the first
child of `CompileTimeBindingPattern` which holds the identifier
underneath it, so that it is checked just before the type expression of
the `CompileTimeBindingPattern`. When we reach this virtual node during
check, we add `.Self` as a name in the current scope, and when we reach
`CompileTimeBindingPattern` we remove it from scope, which ensures it's
present during only the checking of the type expression for the compile
time pattern.

At the moment the `.Self` has a different type (it's a `TypeType`) than
other `.Self` in the facet type (which are a single `FacetType`), but
the intention is to immediately substitute it out of the facet type
entirely, replacing it with a reference to the compile time binding (a
`BindSymbolicName`) itself. A TODO has been added for this.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-08-12 16:27:07 +00:00
Jon Ross-Perkins b410ebd088 Fix destruction of generic types (#5943)
The self access is important; for the test `generic_class.carbon` being
added to `toolchain/check/testdata/class/destroy_calls.carbon`, it was
using `%T.as.Destroy` instead of `%D.as.Destroy`, indicating the default
blank impl was being used instead of the type-specific version. That
test is trying to focus on the issue, but the delta is visible in a
couple other files in this PR, for example
`toolchain/check/testdata/class/generic/init.carbon`.

I'm separately working on getting rid of the default impl, which is how
I noticed this.
2025-08-12 00:10:43 +00:00
Jon Ross-Perkins 55085de6aa Use GetStructType when building object repr structs (#5923)
I was thinking about this for destruction, which I may not be able to
use it for, but still think this may be a good change to keep features
consistent.
2025-08-06 23:55:05 +00:00
Jon Ross-PerkinsandGeoff Romer 7209ad7c9f Generate Destroy impls for classes (#5873)
Although this focused on `Destroy` support, some choices here around
`implicit_type_impls` are because copy/move will likely follow a similar
approach. I'm trying not to predict too much about how we'll structure
those, but I'm putting `Destroy` impl logic in a file that could perhaps
be shared with those. They'd likely be interested in similar things,
e.g. traversing members of types (particularly class, struct literal,
tuple literal).

At present this sets the destroy function as `no_op` which is consistent
with current logic, but has a TODO to correctly define.

Constant importing for functions changes slightly due to some issues I
was having with `GetFunctionType`. zygoloid suggested this approach to
avoid `EvalInst` logic.

Adds a flag for controlling whether to generating these impls. While
this does generation for `class`, as noted above this'll also need to be
done for tuples and struct literals, which would leave the `none.carbon`
min_prelude unable to use any types. Note if destruction *would* occur,
it'll still look up `Core.Destroy` for that and fail, but that's already
true of any test using `none.carbon`. I'm trying to use the flag to see
if we can keep `none.carbon` working mostly-consistently.

I'd tried separating out the flag to #5852, but that got a lot of
pushback over whether the behavior was appropriate. I'm hoping that the
interactions here make it clearer why the particular approach -- the
goal is not to enable advanced testing, or create some new end-user
behavior that we really support, it's just to keep no-prelude tests
functional. The main question raised there was why not just keep
generating `impl T as Core.Destroy` if `fn destroy` is present -- but I
think here it should be apparent that would require additional
complexity, as the generation of `impl T as Core.Destroy` is not
currently conditioned based on the implementation of `fn destroy`. I'd
rather add complexity to this flag only if it's enabling interesting
test functionality.

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2025-08-04 19:39:22 +00:00
Jon Ross-Perkins 7ccc1e0144 Expand naming for impls and functions (#5808)
Change impls from `<interface>.impl` to `<self>.as.<interface>.impl`,
and *member* functions to `<parent scope>.<fn>` (non-member functions
exclude their parent scope). Stop special-casing builtin functions,
given the new naming scheme.

The purpose of this is to make it clearer when a member function is
being accessed and, if so, which member function. In particular, we
often access interface `Op` functions. The builtin function
special-casing was intended to help with that, but we still have lots of
`Op` functions. This particular approach should make the interactions
clearer.

This changes up queueing of block IDs a little because, in particular,
we need to process bodies of entities only after constants finish
processing. But, it should also result in less memory usage during
processing because it means we have less on the insts stack at any given
time, since we track a block rather than all instructions contained by
the block.
2025-07-21 18:45:07 +00:00
Jon Ross-PerkinsandGeoff Romer eae3491129 Switch inst namer to queue entities when reached (#5806)
This switches from the `CollectNamesInBlock` approach for entities, to
instead traversing entities as they're encountered. For example, when
traversing constants, when a type is found, the entity will have its
block queued for processing.

This leads to a change in the traversal order, which affects
disambiguation done by numeric sequencing (since that's just showing the
traversal order).

This will allow for simpler "name based on name" logic. This is
something I plan to use for:

- impls: `<type>.as.<interface>.impl`
- functions: `<entity>.<member function>`
  - Note an impl may be used as the entity for a bound function.

By naming the entities as they're encountered, I'll be able to rely on
the generated names rather than recalculating them.

To assist this, I'm also differentiating between the ambiguous and
disambiguated name. Otherwise, we could end up with things like
`<function>.<disambiguator>.<call>.<other disambiguator>`, where the
repeated disambiguator may not be necessary in order to get full
disambiguation. It's also a smaller delta from the current output.

Note, changing `Name` to a class felt appropriate given its shape. I was
also noticing that parts of its API were unused, and the class helps
detect unused private members.

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2025-07-21 17:58:55 +00:00
Jon Ross-Perkins 8cd1307711 Include the interface name in impl names (#5798)
i.e., `impl` -> `<interface>.impl`
2025-07-11 19:52:53 +00:00
Jon Ross-Perkins e855f38b8c Tag destruction as desugaring (#5790)
In `BuildUnaryOperator`, `GetOperatorOpFunction` is treated as
desugaring, but `PerformCompoundMemberAccess` and `PerformCall` are not.
This treats all of destruction as desugaring.

This leads to some instructions being elided, because of `GetOrAddInst`
behaviors:

> // If the instruction has a desugared location and a constant value,
returns
> // the constant value's instruction ID. Otherwise, same as AddInst.

This changes instructions that previously had a non-desugared location
to instead have a desugared location, so if they also have a constant
value then the constant value can be used directly.
2025-07-10 21:21:19 +00:00
Jon Ross-Perkins 6a53947c5c Handle destruction for return statements (#5785)
This just catches uses equivalent to `return;` and `return <expr>;`.
Note it's just extending the current implicit return logic, not really
adding much unique here.

I'm still delaying break and continue because those require partial
destruction, which is more work and I want to be careful to get it
right.
2025-07-10 16:32:39 +00:00
Dana Jansens 28fea821b7 Add min-preludes to more slow tests (part 4) (#5682)
Adds min-preludes more tests which were seen as slow and their
surrounding neighbours. This drops the file_test runtime on my machine
from about 6s to about 4.5s.

For a few files that are clearly only testing diagnostics, we drop the
if-present semir ranges and the associated TODO.
2025-06-17 21:10:04 +00:00
Dana JansensandJon Ross-Perkins 19d59b2a8d Reduce use of the prelude in tests (#5683)
Remove use of i32/bool when a builtin type or test-define class type can
work. Make `Sub` user-defines in a test that is testing builtin
functions and not trying to test the prelude, in the same way that it
defines its own Negate. Reduce use of the + operator when it isn't
contributing to the test's coverage, since the + operator needs the full
prelude. Remove use of Core.Print when it's not required for the test.

Move `deduce_nested_facet_value.carbon` to its own file since it uses
TypeAnd, and the rest of deduce.carbon does not, but uses i32. This
means they can each use a different min-prelude.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-06-17 17:58:59 +00:00
Richard Smith 344f0b7550 Support for heterogeneous operators. (#5653)
Replace the binary `Operation` interfaces with the `OperationWith(T:!
type)` interfaces described in the design, and add a `Result` associated
type for both unary and binary operations. Update the `impl`s in the
prelude for integer types to use the new form, including supporting
implicit conversion of either operand.

I've tried to split this PR up into commits focused on distinct changes
for review convenience. It may be simplest to review it one commit at a
time.
2025-06-13 01:55:24 +00:00
Jon Ross-Perkins 4193c306a4 Add range flag settings to function files (#5558)
Where `--no-dump-sem-ir` is used, change to `--dump-sem-ir-ranges=only`.
Otherwise, add `--dump-sem-ir-ranges=if-present` with a TODO to change
to `only`.

Note, SemIR is affected just because the extra comments change line
numbers in files where splits aren't in use.
2025-05-29 18:43:14 +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
Richard Smith 797b14eb8e Import ImplWitnessTable into the imports block instead of the constants block. (#5374)
Don't import `ImplWitnessTable` into the `constants` block, because we
generally don't put `Unique` constants there. This matches the handling
of the other kinds of `Unique` constants. In order to keep the
instruction visible in formatted SemIR, add it to the `imports` block
instead.

Also fix a bug in the instruction formatter that resulted in
instructions in the `imports` block being omitted from the output if
they were only referenced by earlier instructions in the `imports` block
and by instructions in the `constants` block. This was already resulting
in some referenced instructions being omitted from the output, but also
occurred frequently for `impl_witness_table` instructions after this
change because it is common for the only reference to those instructions
to be from `impl_witness` instructions in the `constants` block.
2025-05-01 00:08:43 +00:00
Geoff Romer 34887403ab Model patterns as constant values (#5385)
This will enable us to simplify support for parameter and return
patterns in import, which operates primarily on constants.
2025-04-30 22:32:41 +00:00
Geoff Romer 7c85397f8b Stop treating symbolic binding patterns as constants (#5361)
This was originally needed to support constant evaluation of name
expressions, but that's now done in a different way.

This is actually a step toward treating all patterns as constants. The
upcoming change will do so in a slightly different way, and so it will
simplify the review to start from a baseline where patterns are never
constant.
2025-04-28 23:45:15 +00:00
Geoff Romer fafb655d39 Separate pattern types from expression types (#5360)
This is a step toward treating patterns as compile-time constants, so
that we can import them more easily.
2025-04-28 16:54:37 +00:00
51498547c9 Always use LookupImplWitness instructions for symbolic witnesses (#5321)
We eliminate the `FacetAccessWitness` instruction, which would sometimes
immediately evaluate to a concrete `ImplWitness`, and sometimes remain
symbolic. This instruction is now replaced by `LookupImplWitness` in all
cases. To support the same use cases, when it is evaluated,
`LookupImplWitness` will look in the self value if it's a facet value,
and attempt to return a concrete `ImplWitness` from it before looking
for an `impl` statement.

The `LookupImplWitness` instruction's value is now canonical, even when
it evaluates to a symbolic `LookupImplWitness` instruction, by
canonicalizing the self value of the lookup query. This canonicalization
unwraps `FacetAccessType` and `FacetValue` instructions to get to an
underlying canonical facet value. However we must preserve and use the
non-canonical query while evaluating the instruction in order to look
for a concrete `ImplWitness` if the query self value was a concrete
`FacetValue`. The canonicalization ensures that symbolic witnesses
obtained from a facet value are compatible with those obtained from an
impl statement, as long as the self types originate from the same
canonical facet value though they may have been narrowed.

Member access now unconditionally does a `LookupImplWitness()`
operation, instead of only sometimes doing the lookup for a final impl
declaration.

`EvalImplLookupResult` is marked `[[nodiscard]]` so that we don't
construct it and forget to return it. This was a mistake made at one
point during the creation of this PR. And the `has_concrete_value()`
method no longer has a precondition that `has_value()` is true, since we
want to look for a concrete result only in the new use of
`EvalImplLookupResult` returned from lookup into the query self facet
value.

The TODO from `FacetAccessWitness` evaluation is addressed by ensuring
the index of the witness in the `FacetValue` comes from the required
interfaces of the `FacetValue`'s type, and that the type (a `FacetType`)
is the same facet type used in the query to construct the `FacetValue`'s
witness block. This is made possible by eliminating the
`FacetAccessWitness` indirection. The lookup into a `FacetValue` happens
while evaluating `LookupImplWitness` and it does so directly on the self
value. This gives a consistent view of the witness set and the facet
type, as they both come from the same instruction.

All of this with 400 less lines of code. :)

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-04-23 16:39:09 +00:00
Richard Smith ca8df34d0d Format the call parameters of a function, not the patterns. (#5342)
This makes the parameters printed in a SemIR `fn` declaration match the
arguments printed in a SemIR `call` instruction.
2025-04-22 18:52:21 +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
Richard Smith a74ca9071b Remove all remaining uses of TypeIds as instruction operands. (#5280)
In preparation for shifting from `TypeId`s potentially representing
attached types to always representing unattached types, using
[terminology suggested on
Discord](https://discord.com/channels/655572317891461132/963846118964350976/1359286326779973712).
This change causes us to track slightly more type spelling information
through SemIR.

One change that has significant impact on the SemIR output is that we
now build a `struct_type` instruction in each class representing the
types of the fields, including the spelling used for those types. This
is now no longer always identical to the corresponding canonical
`struct_type` for the object representation, so it's built separately
and owned by the class.

Also remove `TypeBlock` support entirely, as its only use was
representing `TupleType`s, which now use an `InstBlock`.
2025-04-10 20:53:42 +00:00
Richard SmithandDana Jansens bba32900c3 Preserve type sugar in ArrayType, ConstType, and PointerType. (#5235)
Each of these types takes another type as an operand. Instead of storing
that other type as a `TypeId`, store it as an `InstId` so that we can
track how it was written, not only its canonical form.

The canonical constant values of these types continue to store the
canonical constant values of their operands, as normal.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2025-04-03 21:14:03 +00:00
Richard Smith 265968b396 Make evaluation of symbolic bindings simpler and more uniform (#5215)
Factor out logic to evaluate `EntityNameId` instead of duplicating it
between `BindSymbolicName` and `SymbolicBindingPattern`. Remove support
in `SymbolicBindingPattern` for evaluating a pattern to the constant
value of the corresponding binding, which doesn't really make any sense
given that patterns don't generally evaluate to the value that they
matched.

This results in the handling for `SymbolicBindingPattern` being simply
the default handling for an always-constant instruction, so remove the
special case for it entirely and change its constant kind to `Always`.
It's not entirely clear that it makes sense for `SymbolicBindingPattern`
to be treated as a constant when other patterns aren't, but we seem to
be relying on this in various places, so leave it as a constant for now.
Changing it to never be constant will be a smaller change now -- it just
requires changing the `constant_kind`.

The IR changes in the tests are fairly widespread, but mechanical, and
there are two kinds of things changing:

- `symbolic_binding_pattern`s in specifics now evaluate to
`symbolic_binding_pattern`s, not to the argument values. This means in a
few cases we end up with additional `symbolic_binding_pattern`
constants.
- We evaluate the type operand of `symbolic_binding_pattern` now, so an
error in the type will now properly be propagated into an error in the
pattern's constant value.
2025-04-01 20:24:00 +00:00
Dana Jansens 3469922275 Rename ImplSymblicWitness to LookupImplWitness (#5201)
The instruction does act somewhat like a witness, saying that an impl
does exist for a lookup, but the instruction more concretely represents
an impl lookup - since that is done when it is evaluated.
2025-03-27 21:46:08 +00:00
Dana JansensandJon Ross-Perkins 53c98a8619 Support specialization in impl lookup with a symbolic query/impl. (#5169)
Add a new instruction called ImplSymbolicWitness which represents a
search for an impl declaration given a self type and an interface to
find implemented for the self type. The self type is stored as a
constant instruction id, rather than as a ConstantId, as instructions
don't currently support holding ConstantId. The interface is stored as a
SpecificInterface but we can't fit all of it directly into the
instruction. So we add a new id to refer to the SpecificInterface as
follows.

Add a new SpecificInterfaceId which indexes into a canonical value store
on SemIR::File. This tracks all `SpecificInterface`s stored in an
instruction - specifically the ImplSymbolicWitness instruction.

The SpecificInterface on Impl is still stored there as a value, not as
an id, and no id is eagerly constructed for it. We wait until an id is
needed to make one. Since they are canonical, a new id is only create
when a new SpecificInterface value is seen.

When doing impl lookup, and the query is not concrete, and the impl is
not effectively final, the query needs to consider future impls that may
specialize either the self type or the constaint to make a more precise
match and replace the found impl declaration. Instead of returning the
ImplWitness instruction from the found impl, we generate a
ImplSymbolicWitness instruction, storing the query so that it can be
replayed later. This instruction is added to the generic eval block and
thus will be re-evaluated later with a SpecificId that may make the
query more concrete. When evaluating the instruction and replaying the
query, the lookup has the same conditions and if it does not decide to
use the found impl concretely, then the same instruction is returned
from eval, leaving it as symbolic.

--- Impl lookup changes ---

Impl lookup gets a little more interesting now. It continues to look in
the facet value for a witness if the self type is a facet value. Then
falls back to looking for an impl declaration. This step is no longer
done directly. Instead, we construct a ImplSymbolicWitness instruction
and evaluate it immediately for each interface that are in the query
facet type.

The ImplSymbolicWitness instruction, when evaluated, calls back to the
impl lookup code, with a query specific interface. There we resume back
into the same code path as from before, finding a witness in an impl
declaration. But we may return "found a non-final impl" instead of a
concrete witness. If eval receives this back, it evaluates to the
current ImplSymbolicWitness instruction as the resulting constant value.

To pass lookup failures back through eval, a result of InstId::None from
the second step of impl lookup will result in a non-constant value,
which is used as a signal back up the stack to the original impl lookup
function that the lookup failed. Using a non-constant value here would
break evaluation of the generic eval block if impl lookup could fail
there, however we know it will not since we only leave behind an
ImplSymbolicWitness instruction in the eval block if we found at least
one matching impl already, and we just want to look for a better match
with a more specific query.

We must take care to not store a reference into any value store across
computation in impl lookup, since impl lookup can recurse into itself
invalidate those stores. That includes the SpecificInterface obtained
from a SpecificInterfaceId, which impl lookup also inserts into the
store.

--- The long tail ---

Adding a new instruction and a new id type requires a myriad of changes
to support them:

We add Dump() support for SpecificInterfaceId. And fix a crash in Dump
for SpecificId::None. We also add MakeSpecificInterfaceId() for dumping
arbitrary ids.

The type of ImplSymbolicWitness is a new singleton builtin type
instruction called WitnessSymbolicType (like WitnessType is the type for
an ImplWitness).

Both ImplSymbolicWitness and WitnessSymbolicType are given `Value` as
their expression category as they are builtin constant values. And
BuildInfo() in TypeCompleter is taught about them both, returning a
`ValueRepr::Copy`.

WitnessSymbolicType is added to the set of SingletonInstKinds, so that
it can have a singleton instrution id as a static member.

Lower's BuildTypeForInst() is taught to make an empty struct for
WitnessSymbolicType, similar to WitnessType.

Instruction formatter (FormatterImpl) grows support for printing a
SpecificInterfaceId so that it can print both arguments of
ImplSymbolicWitness on the RHS when printing the SemIR instruction. To
print a SpecificInterfaceId, it prints both the interface id and the
specific id (if there is one). For example, for a query on a generic
interface `Z` with one parameter, the RHS includes the query, interface,
and specific:
```
%Z.impl_symbolic_witness: <symbolic witness> = impl_symbolic_witness %U, @Z, @Z(%U.as_type) [symbolic]
```

IdKind is extended to include SpecificInterfaceId.

InstFingerprinter is taught to look through SpecificInterfaceId and use
the interface and specific ids in the fingerprint.

InstNamer is taught about SpecificInterfaceId, counting the interfaces
when building an index. It is also tought about ImplSymbolicWitness,
using the name of the interface within and the `.impl_symbolic_witness`
suffix. For example, here the LHS is named after the interface in the
query:
```
%Z.impl_symbolic_witness: <symbolic witness> = impl_symbolic_witness %U, @Z, @Z(%U.as_type) [symbolic]
```

StringifyTypeExpr is taught about WitnessSymbolicType, which uses its IR
name since it's a singleton. And about ImplSymbolicWitness which uses
its constant value. The handling of ImplWitnessAccess also needed to be
adjusted, since it assumed that ImplWitnessAccess::witness_id would
always be a FacetAccessWitness, but it can now also be an
ImplSymbolicWitness. (It seems that the witness_id is also assigned
ImplWitness instructions, but those ImplWitnessAccess instructions don't
ever seem to get stringified in a diagnostic at this time.) At the
moment the ImplWitnessAccess with a symbolic witness is just stringified
as "<symbolic>", such as in:
```
x.carbon:1:2: error: cannot implicitly convert value of type `()` to `<symbolic>` [ConversionFailure]
  let a: C(D).(Z.X) = ();
                      ^~
```

There is a TODO left behind to include more information there.

The TypeStructure builder is made to handle WitnessSymbolicType and
WitnessType. These come up now in deduce where a generic impl will have
a ImplSymbolicWitness in a FacetValue for a generic self type. The query
may have a concrete ImplWitness in the same position. Since deduce tries
to deduce through the FacetValue, it tries to convert ImplWitness to
ImplSymbolicWitness, tries to do an impl lookup for `impl ImplWitness as
ImplicitAs(ImplSymbolicWitness)` and causes us to build type structures
with each of these.

Subst is updated to handle pushing and popping SpecificInterfaceId.
Without this, when finishing a generic's eval block, we would walk into
the ImplSymbolicWitness instruction, and its arguments, and fail to
recurse down into the SpecificInterfaceId. Then any specifics inside
would be left as "orphaned" without any generic id attached to them, and
we would never update the instructions in the SpecificInterface's
instructions (inside its own SpecificId) with new constant values when
evaluating the generic eval block against a specific. To do this we push
the specific_id inside the SpecificInterface, and when popping we pop
the specific_id then construct a new canonical SpecificInterface with it
and return that id.

We add support for importing ImplSymbolicWitness by importing its self
constant instruction and specific interface id. However we also had to
add import support for SpecificImplFunction, which can now appear in the
generic eval block for a generic impl declaration, and thus must be
imported with the declaration. This is done very similarly to
SpecificFunction, except the `type_id` is a singleton value.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-03-26 15:10:23 +00:00
Dana JansensandRichard Smith 11ae0e27ab Deduce through FacetValue (#5158)
When the parameter is a deduced symbolic FacetValue, refering to a
BindSymbolicName, and the argument is a concrete FacetValue that would
match the FacetType requirements on the BindSymbolicName's type, we
currently do not deduce that the argument matches the parameter.

The argument is not _converted_ to the parameter type because they are
both FacetValues of the same FacetType type. However they are also not
equal constant values so the argument is not saved as a deduced match
for the parameter.

In order to accept the FacetValue, we need to consider them as
`deduce_through`, which attempts to deduce each of the fields in the
argument FacetValue against the fields in the parameter FacetValue.
This deduces that the argument's concrete type matches the symbolic
BindSymbolicName and its witnesses are the same.

Since the parameter is a FacetValue, its argument is not the type that
needs to be recorded as the deduced type for the binding. The
BindSymbolicName inside the parameter is the place that we need to find
the deduced type for the binding. So simply walking into the FacetValue
gets us to that position, where we eventually record the deduced
argument type as being the concrete type from the original argument
FacetValue.

Similarly, when determining what interfaces are satisfied by a
FacetValue for deduce, we want to use the full type available in the
FacetValue rather than just those from its FacetType. Determining
availability of interfaces here is equivalent to converting, and we want
converting a FacetValue to always work on the full available type info.
Only API access (member lookup) is restricted by a FacetValue to the
interfaces provided by its FacetType type.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-03-20 23:52:50 +00:00
Dana Jansensandjosh11b 4539114c21 Return a set of ImplWitnesses from impl lookup (#5075)
A query facet type may contain multiple required interfaces, in which
case impl lookup should return an ImplWitness for an impl that is used
for each interface in the query. We bundle these together into an
instruction block and return that from impl lookup. The witnesses are in
the same order as the interfaces in the
`CompleteFacetType::required_interfaces`. This allows walking the
`required_interfaces` to find an interface to give an index that can
also be used to grab a witness from this set, or from FacetValue.

FacetValue now has an InstBlockId for the set of witnesses of the
FacetType, instead of a single ImplWitness instruction id.

FacetAccessWitness includes the index of the witness (determined from
the position in `required_interfaces`) of the witness it's accessing
from the FacetType.

The
toolchain/check/testdata/facet/no_prelude/fail_todo_call_combined_impl_witness.carbon
test demonstrates the fix in the resulting SemIR. We can see the calls
to methods on a multi-interface FacetType result in a FacetAccessWitness
with an index of the correct interface, and this results in a witness
that leads to the correct impl's function.

There is a TODO in member access, where it does not have a
`CompleteFacetType` yet, so it uses the index in
`FacetTypeInfo::impls_constraints` instead, but this can be incorrect in
the presence of named constraints, which when completed can add more
interfaces to the `CompleteFacetType` and which are sorted into an
arbitrary order with the rest there.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2025-03-10 16:00:35 +00:00
Alina Sbirlea 7fd54eded0 Reverse nesting of BoundMethod and SpecificFunction. (#5079)
During SemIR, when identifying a specific in a specific context, we'd
have to either look through a specific or through a bound method.
Canonicalize which one to look through first, by having the BoundMethod
created around a SpecificFunction instead.
This changes a lot of check tests.

TODO: As the SemIr does not currently allow removal (access to insts()
is intentionally const), the bound instruction created prior to finding
the specific is not removed from the instructions.
Options: (1) leave as is, (2) add a way to remove the previous bound,
(3) rethink how/when the BoundMethod inst is created.
2025-03-08 01:34:06 +00:00
Geoff Romer f08e046d9e Update text representation of CallParamIndex to match new name (#5067) 2025-03-04 23:28:42 +00:00
Geoff Romer d264f14027 Clean up handling of Call params (#5061)
- Explicitly document that `*Param` and `*ParamPattern` insts represent
`Call` parameters.
- Stop wrapping compile-time parameter patterns in `ValueParamPattern`
insts (because they aren't `Call` parameters).
- Document how `MatchContext::results_` relates to the `Call`
parameters, and be more consistent about when it's written to.
- Remove `RuntimeParamIndex::Unknown`: we no longer need to distinguish
"this `Param`'s runtime index is unknown" from "this `Param` isn't a
runtime param", because we no longer use `Param`s at all in the latter
case.
- Rename `RuntimeParamIndex` to `CallParamIndex`.

As a side effect of removing the `ValueParamPattern` insts, this fixes a
minor diagnostic bug where `NoteInitializingParam` didn't identify the
specific parameter that led to a deduction failure, because it expects
generic parameters to only be represented by `SymbolicBindingPattern`s,
but before this change they could be wrapped in `ValueParamPattern`s.
2025-03-04 21:01:59 +00:00
Dana Jansens 0beda27192 Fingerprint impl blocks in semir (#5021)
This avoids the suffix changing when adding new impls to the prelude, or
in user code.
2025-02-26 22:47:57 +00:00
Richard Smith c6d35e1c4a Rename template constant -> concrete constant. (#4939)
This implements a direction decided in a
[recent
discussion](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.mas1g68xx9ct)
to switch away from "template constant" when naming a constant that
doesn't depend on any generic parameters, because that creates confusion
with template-dependent constant values that depend on a template
parameter.
2025-02-12 21:24:51 +00:00
Richard SmithandJon Ross-Perkins fcfb1345d5 Support accessing associated functions by member access into facets (#4872)
For an expression such as `(Type as Interface).AssocFn()`, track the
`Self` type `Type` in the result of the member access so that it's
available when checking the function call.

This introduces a new kind of type, `ImplFunctionType`, that represents
the type of a function that is expected within an impl, modeled as the
type of the function within the interface plus a value to use as `Self`.
Calls to values of this type behave like calls to the underlying
function except that the `Self` parameter is pre-bound to the self type
from the facet.

In order to support this, fix an issue where the imported list of
generic bindings lost their association with their enclosing generic.
This adds a little complexity to `import_ref`, including a new recursive
cycle that I intend to address in a follow-up PR.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-02-04 22:38:38 +00:00
Jon Ross-Perkins 6b5eb1a101 Id::Invalid -> Id::None (#4834)
High level, replacing `Id::Invalid` with `Id::None` and `Id::is_valid`
with `Id::has_value` for clarity, as discussed
[here](https://discord.com/channels/655572317891461132/655578254970716160/1331664574545395794).
The `IntId` refactoring is needed together with `AnyIdBase` because it's
also used with `ValueStore`.

Note, trying to be careful not to rewrite `EnumBase::InvalidIndex`, or
`is_valid` in general (e.g., `IdKind::is_valid`).

I've tried to sequence commits here:

1. Automatic replacements:

- `((?:Id|Index)(?: |::|\(|Base(?:\(|::)))Invalid((?:Index)?\W)` ->
`$1None$2`
  - `<invalid>` -> `<none>`
  - `InvalidNodeId` -> `NoneNodeId`
  - `/\*invalid\*/` -> `/*none*/`
  - `id((?:_|\(\))(?:\.|->))is_valid` -> `id$1has_value`

2. Manual edits:

  - In `int.h` and `int_test.cpp`
    - `IntT` has `is_value`, which I'm renaming to `is_embedded_value`.
    - Manual edits to comments in this file.
  - `AnyIdBase` and `IdBase`
- Declaration of `is_valid` -> `has_value`, `InvalidIndex` ->
`NoneIndex`.
  - In `ids.h` and `ids.cpp`
    - `is_valid` -> `has_value`
- `// An explicitly invalid ID.` -> `// An ID with no value.`; similar
for index
    - Various math on `InvalidIndex` -> `NoneIndex`
    - Various mentions of "valid" in comments
  - In `value_store.h`, for `IdT::Invalid`, plus one comment
- In `impl.h` and `tokenized_buffer.h`, we had different initialization
of `::None` values (versus `ids.h` syntax) that I fixed manually.
  - Spot checks to compile
- Particularly where `is_valid` replacements didn't catch spots due to
different naming.

3. Autoupdate tests

4. verbose.carbon (NOAUTOUPDATE)

5. Comment spot checks

Note there are probably other mentions of "Invalid" that should be swept
up, but I'd like to argue for merging and separating out remaining
cleanup since this is so sweeping (and likely to hit merge conflicts
from churn). We'll probably have lingering mentions of "invalid" for a
bit regardless, just because there are uses of "invalid" in non-Id APIs.
2025-01-22 23:15:00 +00:00
Calvin 3f4de65ad8 Improve SemIR naming of import_refs (#4824)
Changes the name of SemIR `import_ref`s to use the format
`<package>.<entity>`.

<table>
<tr><th>Before</th><th>After</th></tr>
<tr>
<td><code>%import_ref.05a: type</code></td>
<td><code>%Main.D: type</code></td>
</tr>
<tr>
<td><code>%import_ref.8f2: &lt;witness&gt;</code></td>
<td><code>%Main.import_ref.8f2: &lt;witness&gt;</code></td>
</tr>
</table>

* [Discord discussion in
#toolchain](https://discord.com/channels/655572317891461132/655578254970716160/1330253540999827577)
* Closes #4769
2025-01-22 07:22:07 +00:00
David Blaikie 667a010ae6 Readd the missing class !members list. (#4828)
Thanks to danakj for spotting this was removed accidentally in #4732
2025-01-21 20:37:07 +00:00
David BlaikieandJon Ross-Perkins e6c1f0630a Add a newline after diagnostic output when testing (#4818)
This removes some churn when adding new diagnostic cases to test files
(where previous to this change the newly added newline would cause the
previous diagnostic CHECKs to be updated including changes to the line
number because the CHECK for the blank line meant an extra line between
CHECK and source line).

A few alternatives discussed here:
https://discord.com/channels/655572317891461132/655578254970716160/1329573358475673723

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-01-16 23:23:57 +00:00
a8b46cf561 Add SemIR Vtable instruction and usage (#4732)
Add a Vtable typed inst with a type_id (of the type this vtable applies
to) and list of virtual function decls (or import refs to function
object constants).

This doesn't add lowering/emission of the vtable, or usage when
initializing objects of the type.

Some questions in case they're interesting to discuss:
* is it right/worth having the type_id in the vtable? (probably makes it
easier to emit - using the type to get the class name to figure out the
mangled name for the vtable) perhaps it should be a ClassId?
* I'm thinking the logic in CheckCompleteClassType could be the place we
handle diagnostics for mismatched keywords (virtual/abstract for a
function that's already virtual/abstract, maybe checking for non-virtual
functions with the same name in a base class, or derived class functions
without `impl`, etc) - but we could move some of that to the moment we
walk the function decl, and record our findings in the function decl
(record the base function it overrides, or the index of the vtable to
slot to use when building the vtable at the end of the class)
* the Vtable typed inst has `constant_kind = InstConstantKind::Always`
and `is_lowered = false`, I think I added that in to workaround/address
some failures in lowering. And seems correct for this intermediate step
- I'll add lowering in a follow-up patch. But the constant_kind - what
should this be? We can just say all vtables are of VtableType (in which
case the `Always` constant kind sounds right to me) or we could have
them introduce a type with each virtual function as a named member,
even?

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-01-16 20:19:22 +00:00
Dana Jansens 6aba386eeb Move the complete_witness_type above the !members label. (#4808)
When printing a Class, the complete_type_witness was printed last but
this gave a somewhat misleading representation as it appeared to be part
of the !members label. Move it above the label so that the label more
clearly refers to everything below it.
2025-01-15 22:13:19 +00:00
Richard Smith b1230218d5 Make fingerprinting stable across compatible source changes. (#4789)
Include the index rather than the name in the fingerprint of a symbolic
binding. While both the index and the name contribute to the canonical
identity, using either one of them in the fingerprint is sufficient to
ensure that distinct entities get different fingerprints. Changing the
name of a symbolic binding should ideally not result in fingerprint
changes, so exclude the name from the fingerprint when we have an index.

Use the canonical type and constraint when fingerprinting an impl, so
that uses of names in `name_ref` instructions aren't considered, only
the entity the name resolves to, and different ways of spelling the same
type have the same fingerprint. This similarly allows compatible changes
to be made to impls without changing the fingerprint.

Exclude the declaration block when determining the fingerprint of a
declaration. The declaration block contains the declarations of
parameters of the declaration, which do affect whether two declarations
are identical, but not whether they denote the same entity, because it
would be invalid to have different declaration blocks for declarations
with the same name in the same scope. Therefore changes to the
declaration block are compatible, and it's useful for such changes to
not affect the fingerprint.

This is not easy to test in isolation with our current testing
machinery. However, a follow-on PR will change the name of a parameter
in the prelude, and with this in place, will not cause any changes to
occur elsewhere in the toolchain tests.
2025-01-10 22:30:22 +00:00
Richard SmithandDana Jansens 19182f08aa Compute a fingerprint for constants and import_ref instructions. (#4763)
Use it in the instruction namer to make instruction names more stable
across unrelated changes to the toolchain or the prelude.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2025-01-07 20:41:44 +00:00
c5fd8f42b8 ImplWitness (#4679)
* Change `InterfaceWitness` -> `ImplWitness`
* Include a `SpecificId` in the `ImplWitness`. This allows the
`InstBlock` it contains to have its own identity, allowing it to be
changed as the impl is processed. Evaluation only updates the specific.
* Create the `ImplWitness` at the start of the impl definition. In the
future, this will be populated with the values of non-function
associated constants. For now, it starts full of invalid instruction
ids.
* Implements the model suggested in #4672 .

Note that the non-SemIR testdata changes are to these file:
* `toolchain/check/testdata/impl/lookup/fail_todo_undefined_impl.carbon`
* `toolchain/check/testdata/struct/import.carbon`
* `toolchain/check/testdata/tuple/import.carbon`

The last two are due to an import of generics bug exposed by this PR,
which will be fixed in a follow-on.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-01-02 23:03:11 +00:00
josh11bandJosh L 5169a1862e Require a definition in the same file as an impl declaration (#4719)
This PR detects the failures that #4709 fixes.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2024-12-20 17:00:53 +00:00
Dana Jansensandjonmeow 6cb660f5ad Avoid recursion in InstNamer::CollectNamesInBlock (#4706)
Use a deque to maintain the set of instructions to be walked over. so
that the loop can append more instructions (with their related scope)
during iteration without requiring recursion.

---------

Co-authored-by: jonmeow <jperkins@google.com>
2024-12-20 16:12:06 +00:00
Richard Smith 6fe8e0b5aa Provide generic impls for Core.Int and Core.UInt operations. (#4693)
Instead of providing operations only for `i32`, provide them for all
`iN` and `uN` types.

For now, this excludes the `*Assign`, `Inc` and `Dec` interfaces,
because the implementations for those are defined as Carbon functions
rather than builtins, and we can't yet lower definitions for specific
functions, so converting those to be generic breaks the build for our
examples.
2024-12-19 22:02:18 +00:00