Commit Graph
255 Commits
Author SHA1 Message Date
Jon Ross-Perkins 8fb5bcedd5 Add range flag settings to interface files (#5563)
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:41:55 +00:00
Richard Smith 5b884ae14d Improve lowering for global variables. (#5492)
- Track the `VarPattern` instruction on the `VarStorage` instruction so
that it's available for name mangling.
- Mangle global variables based on the first binding name within their
pattern.
- Give global variables external rather than internal linkage, except if
they have no bindings whatsoever in their pattern.
- To support lowering references to bindings nested within a global var,
such as for `var (x: i32, b: i32)`, add some basic initial support for
reference constant expressions. Treat a global `var` as a reference
constant, and treat an aggregate access into a reference constant as a
reference constant.
2025-05-21 00:09:10 +00:00
Geoff RomerandRichard Smith fbc5994750 Support importing var parameters (#5400)
This restructures the import and merge logic to support parameter
patterns in a more scalable way.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-05-19 22:50:16 +00:00
Jon Ross-Perkins e78a57bb82 Adjust formatting of blocks and scopes (#5474)
This is making two inter-related changes:

- Change `file` to reuse the formatter logic of `constants` and
`imports`, meaning empty `file` scopes will be omitted
- Mark `<elided>` sections in blocks (not in non-block scopes, because
they're not as sequential)
2025-05-16 22:50:28 +00:00
Jon Ross-Perkins dc61460b5a Change default flags for min_prelude tests (#5471)
I think this would probably have prevented the missed include in #5469
-- it would've just failed completely with a "missing prelude"
diagnostic.

Also note this excludes the included IR from output, because it's
probably low-value to print.
2025-05-13 18:02:24 +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
Jon Ross-Perkins 281e79e83b Prepare tests for adding a prelude dependency to destruction (#5346)
Adds an empty `min_prelude/destroy.carbon` in anticipation of turning it
into an interface. Update `no_prelude` tests to be `min_prelude` and
import it where needed; in some cases, modify the file to remove the
dependency (i.e., rewrite code to have nothing to destruct).
2025-04-23 21:41:59 +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
Richard Smith 89c9714825 Fix handling of member types of generic classes. (#5332)
Instead of evaluating a non-parameterized class or interface to a
constant with `SpecificId::None`, use the self specific for that class
or interface, which will not be `None` if there is an enclosing generic.
2025-04-18 15:09:50 +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
Dana Jansens c15dea4fa2 Stop erasing ImplWitnessAssociatedConstant instructions from the witness table (#5283)
Unintentionally, we were adding ImplWitnessAssociatedConstant to the
witness table and then immediately evaluting and replacing it with its
constant value instruction, which is incorrect. The point of the
instruction is to be a symbolic value in the witness table that is a
dependent of the generic impl declaration being built.
2025-04-09 23:03:45 +00:00
Dana Jansens d07f70cfb3 Add insts for witness table entries that are unset or associated constants (#5255)
Instead of using None, use an explicit ImplWitnessTablePlaceholder in
the witness table for entries that have not yet been populated, to aid
debugging. This would ensure they would show up very clearly in the
SemIR. This uncovered some `<invalid>` in the SemIR under erroneous
conditions that have now been turned into `<error>`.

Add the ImplWitnessAssociatedConstant instruction which wraps the
canonical instruction found from the constant value of the rewrite
constraint. This ensures that we have an instruction inside the eval
block for a generic impl declaration for each rewrite constraint's
value, which allows Subst to be performed to rewrite the symbolic
constant of the ImplWitnessAssociatedConstant instruction to associate
it with the generic. This will prevent the otherwise orphaned symbolic
constant of the rewrite's value from being used which can not have a
specific applied to them.

While applying the new insts in InitialFacetTypeImplWitness(), rearrange
the function to use less nesting. And avoid using entity names from
imported instructions (as we found is not effective in deduce.cpp) and
use a local instruction by going through the constant value.

This PR is part of the effort to allow a rewrite to name a generic
parameter, such as `impl forall [T:! type] T as Z where .X = T`, however
tests for this involve a final impl so that we can typecheck that the .X
value is a specific T, so the tests will come with that work. This piece
is split off because introducing new instructions causes a lot of SemIR
churn, and I wanted to get that done separately.
2025-04-08 19:10:49 +00:00
4af0c8f8d1 Implement ...where .Self impls... (#5238)
* Also remove facet type deduction, since we decided against it on
[2025-04-02](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?pli=1&resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.95phmuvxog9n).

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Dana Jansens <danakj@orodu.net>
2025-04-07 20:45:45 +00:00
Richard Smith a45dc42d82 Store an InterfaceId and a SpecificId in AssociatedEntityType. (#5252)
Instead of storing a `TypeId` that always refer to a facet type that
always contains exactly a single interface, store the interface
directly.

Also improve stringification of `LookupImplWitness` and witness access
into it, switching to using newly-added functionality for stringifying
specific interfaces.
2025-04-05 16:08:09 +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
Dana Jansens 164310c6b8 Facet values (like type values) can be copied around at runtime (#5242)
Give them a value representation of copy, and allow conversions between
two facet values of the same type to work.

Convert was assuming that facet values are compile time constants, but
thye can also be runtime values. In that case, we have no support for
converting to a different facet value of a different facet type. But if
the types are equal then it's all fine.

In theory it seems that we should be able to convert if the target facet
type can be found through the source value's FacetType. But currently
that happens through impl lookup and it requires constant values. Adding
a test for this.

Related to #5241
2025-04-03 19:34:54 +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
josh11bandJosh L df958940c3 Builtin facet type conversion is final (#5220)
Don't look for a user-defined conversion (implementation of `As` or
`ImplicitAs`) if the builtin conversion to a facet type fails impl
lookup. This is the behavior we want, and reduces noise in diagnostics.

Partial implementation of #5122. Still to do:
* Give an error if the users tries to implement such a conversion, since
it is now unreachable.
* Add notes to the diagnostic explaining why impl lookup failed.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-03-31 16:11:07 +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
josh11bandJosh L c7a338be59 Replace uses of "defined" with "complete" (#5196)
As of #5087, these terms are no longer synonyms. This change preserves
the original meaning.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-03-27 18:14:26 +00:00
Richard Smith 4acc9cac5d Replace GetInstForSpecific with direct support for rendering a SpecificId in diagnostics. (#5192)
Avoids misbehavior caused by GetInstForSpecific's side effects, such as
recursively reentering constant evaluation.
2025-03-26 22:53:32 +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
Richard Smith e25f58adec Rebuild the type of a bind_symbolic_name when building an eval block (#5174)
When transforming instructions with symbolic constant values into the
eval block, we previously special-cased `bind_symbolic_name` (and
`symbolic_binding_pattern`) because they are places where symbolicness
is introduced, rather than propagated from operands, and just copied
them into the eval block. However, `bind_symbolic_name` can be dependent
on other symbolic constants, because it can have a type that is
dependent. In this case, the copy in the eval block would not have its
type properly adjusted to refer to the type within the eval block.

Fix this by performing substitution into `bind_symbolic_name` rather
than copying it directly, and instead, detect cases where substitution
determined that the instruction was unchanged despite having a symbolic
constant value, and force it to be rebuilt in that case.

I've not found any way that the previous behavior actually caused
problems, or affected the observable behavior of the toolchain. The type
of these instructions in the eval block doesn't make much difference to
anything because they get immediately replaced by their corresponding
argument values when we run the eval block. But this came up and caused
some test output churn when I was making a different change, and it
seems like a fix to our representation even if it's not changing
behavior, so I'm splitting it out so it can be handled separately.
2025-03-25 22:53:25 +00:00
Dana Jansens 6dbcc78e6c Rewrite symbolic constants in generic redeclarations (#5154)
When a generic function declaration was encountered for the second or
more time, we would FinishGenericRedecl() for the function decl, but
this just popped the generic region stack and moved on.

The issue with that is when the stack entry is gone, we lose the
symbolic constants from that declaration, and are unable to rewrite them
to point to the actual generic. This left us with a function declaration
with abstract symbolic values that were not useful, and in a function
call we use the declaration attached to the definition, which would be a
declaration with broken symbolic values. Then the function would be
uncallable since deduce would be unable to determine argument types
without the generic bindings.

This resolves the issue for functions, as well as ensuring the correct
generic id from a previous declaration is used for other generic entity
types that have redeclarations.

When a function declaration is qualified, such as defining a class
method outside the class body, we need only the function declaration to
contribute to its generic region stack. The code was collecting constant
values from all qualifier segments together incorrectly.

So when we PushNameQualifierScope(), we also drop the current generic
region stack and rewrite its constant values by calling
FinishGenericRedecl(), and open a new stack entry for the next part of
the qualified declaration.

If a generic declaration somehow has more dependent instruction than a
previous declaration, it would add new instructions to its eval block
with indices beyond the elements in the actual declaration eval block,
since we only store the block from the first declaration found. To avoid
this we plumb through that we are in a redeclaration, and terminate with
an ICE instead of adding new instructions to crash on later.

Fixes #5136.
2025-03-21 22:26:08 +00:00
Jon Ross-Perkins 868efb7c86 Make INCLUDE-FILE less sensitive to path changes (#5159)
It's helpful for stability to not have the path in the repo reflected in
test files, something I'm separately running into. So to reduce this,
align INCLUDE-FILE with other split behavior:

- Use the filename (with a "include_files/" subdir to disambiguate),
rather than the full path.
- Note if we eventually want to support splits in these, the same
approach could be extended.
- Only provide as an arg if the user requests files as args.

Factoring AddFile back because it's hard to share; I'm also advocating
to remove the prelude manifest, which would mean the remaining call
could be removed.
2025-03-21 16:03:25 +00:00
Dana Jansens b10c1ccbb9 Look through FacetAccessType and FacetValue self types in impl lookup (#5160)
If a self type is FacetAccessType, we look through it at the facet
value, both for the query and the impl declaration. This ensures that
while FacetAccessTypes match each other for constant value equality
still, they an also match with facet value queries, such as:
```
impl forall [T:! Y] T as Z {}
                    ^ FacetAccessType for BindSymbolicName of type FacetType(provides Y).

fn F(y:! Y) {
  y as Z;
  ^ Facet value
}
```

Here the facet value and FacetAccessType don't have the same constant
value. Deduction will give the `T!: y` binding the facet value of `y`,
but the `T` in `T as Z` is a FacetAccessType to that binding, which is a
different constant value. Looking through the FacetAccessType gives us
the desired constant value for comparison with the query.

Additionally if the query self value is a FacetValue instruction, look
through that at the underlying type value. Impl lookup is used to
convert from one type or facet value to a new facet value of the desired
facet type. We want facet values to always be able to convert to
everything possible, rather than to have that restricted to just their
current FacetType:
https://github.com/carbon-language/carbon-lang/issues/5137. So this
allows queries such as `(C as Y) as Z` for a class `C` and interfaces
`Y` and `Z`.
2025-03-20 23:47:45 +00:00
josh11bandJosh L d431e1fbf4 Never perform instance binding with implicit Self in an interface (#5121)
Resolves TODO by creating new function `GetAssociatedValue` with the
logic from `PerformCompoundMemberAccess` restricted to the
non-instance-binding case.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-03-20 04:25:35 +00:00
Richard Smith 584426dfa2 Initial work on support for templates (#5081)
This broadly follows the design described in [this design
document](https://docs.google.com/document/d/1eWW8MTko3PIqxZ32-GhsdaRSYqoDicxMB1VeessMTOg/edit?pli=1&tab=t.0).

Support is provided for only two primitives for now -- simple member
access and type conversion -- to demonstrate the basics of the
functionality.
2025-03-19 20:19:21 +00:00
Richard Smith 4d2cca48c7 Compute a correct SpecificFunction when resolving an indirect call to an impl function (#5116)
When performing a call through an impl witness, the callee that we
type-check against is the function in the interface, so we form a
specific for that callee. However, once the impl witness access
resolves, the eventual callee is a different function -- the function in
the impl -- so this would cause us to form a `SpecificFunction` where
the callee is one function but the specific refers to a different
function.

Address this by adding another instruction, `SpecificImplFunction`, that
takes a function in an impl and a specific for the corresponding
function in the interface, and computes and returns a `SpecificFunction`
referring to the corresponding specific function in the impl, or returns
a direct reference to the function in the `impl` if it's not a generic
function.
2025-03-18 21:26:52 +00:00
Jon Ross-Perkins dfe1c880ea Clean up node kind information for namespaces (#5120)
This flows out of #5084 and trying to reduce UnsafeMake use. It turns
out imports and namespaces were using unexpected node kinds (previously
ImportIntroducer instead of ImportDecl, for example). This fixes and
adds validation.

I was uncertain about whether to just remove the is_convertible check,
since I don't see it as motivating creation of a conversion between
NodeIdOneOf types. So I've just left a TODO for now.
2025-03-18 00:44:18 +00:00
Jon Ross-Perkins 8738497301 Fix parse support for 'fn F[];' (#5135)
According to approved syntax at
https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p3848.md#syntax-defined,
`fn F[]` without explicit parameters should be valid. This makes it
work, then adds some validation to prevent `class C[]` in check.

Note that for `fn`, positional parameters are a TODO -- but this allows
me to test validation in `fn destroy[]` which is rejected, not just a
TODO.
2025-03-18 00:31:17 +00:00
josh11bandJosh L fb3721df9a Impl lookup allowed for incomplete facet types (#5132)
New planned direction is to not require completeness. Updated comments
to reflect that some care will be needed once named constraints are
supported. Long term plan is [discussed in
#5089](https://github.com/carbon-language/carbon-lang/pull/5089#discussion_r1985908453):

> We have some options. In our last conversation, it sounded like it
would be beneficial for named constraints to have their own witnesses,
with entries in declaration order. This would allow accesses to the
named constraint while it was being defined. So there would be something
of a hierarchy in a facet type witness, with a named constraint taking a
single slot in a facet type witness, independent of its definition.

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-03-15 02:21:49 +00:00
Dana Jansens ce7a0a4d07 Support conversion from facet value to facet value (#5085)
When converting from a facet value (an instruction whose type is
FacetType), we require making a FacetAccessType
to have a type instruction when building the resulting FacetValue.
Otherwise, the conversion is the same for values of type TypeType, and
we relax the convert function to support either.

Corrects the test expectations for converting `Goat as Animal`, a facet
value of type FacetType, into `Eats`, a facet type of type TypeType.
This would be a promotion in the typish hierarchy which is incorrect. We
had an extra case in Convert that was handling this, and it's now
removed. `Animal`, a facet type, does still correctly convert into
`Eats`, a facet type, if `impl Animal as Eats` exists.
2025-03-14 23:58:36 +00:00
Dana Jansens 417b3833e2 Produce helpful diagnostics when converting to a facet fails (#5109)
When converting to a facet there are three different failure modes:

1. You provided a non-type value. Only types can convert to facets. So
we tell you that we found a non-type value.
2. You provided a facet type (which has type TypeType) which does not
have witnesses for the the target facet's type. So we tell you that the
type `T` implements `X` but needs to implement `Y`.
2. You provided a (non-facet-type) concrete type (of type TypeType)
which does not implement the target facet's type (which is a FacetType).
So we tell you that we need the type to implement the FacetType but it
does not.
3. You provided a FacetAccessType (which is of type TypeType also, but
we special case this), whose underlying FacetType is not compatible with
the target facet's type. So we tell you that we need the type to
implement `X` but found a FacetAccessType `T` which implements `Y`.

Closes #5027
2025-03-14 15:50:03 +00:00
Jon Ross-Perkins db21c38550 Use the NameComponent's name_id when making an entity base (#5125)
This changes the SemIR of invalid redeclarations, because previously
they lacked a name. We've avoided this in diagnostics so it doesn't
otherwise come up, but I plan to use it for more easily validating
redeclarations.
2025-03-14 15:27:24 +00:00
josh11bandJosh L 5966fbc758 Get impl witnesses from facets cast to type (#5115)
Addresses a TODO in `impl_lookup.cpp`.

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-03-12 20:55:07 +00:00
Richard Smith 6fd139b805 Renumber inner parameters when checking an impl function against an interface function. (#5113)
This allows the numbering of the parameters to match when checking for a
valid redeclaration. It also prepares us to produce the proper numbering
when generating a thunk.
2025-03-12 13:54:49 +00:00
josh11bandJosh L ebaf62efb9 Associated constants can be used in member function signatures (#5089)
This required allowing incomplete facet types where previously
completeness was required. Once we support named constraints, we will
need a way to consistently go from an interface to a facet type witness
index without requiring the interface to be complete in these cases.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-03-12 00:33:46 +00:00
Jon Ross-Perkins 10eb8ed314 Reuse a merged function's type ID (#5099)
This makes inline and out-of-line functions produce the same type.

I was looking at this and wasn't sure if it was deliberate. It seems
desirable to reuse the type when possible, since it's probably cheaper
too.
2025-03-11 16:21:57 +00:00
Dana Jansens d58b523a5e Add INCLUDE-FILE: and --custom-core for file tests to specify a minimal prelude library (#5080)
The INCLUDE-FILE option is only used in the toolchain tests for now. If
specified in a file test, the given file path is added to the test's
arguments. For toolchain tests this makes the file's package available
to the test. The `--custom-core` command line flag is added to the
driver, which avoids adding the production `Core` package to the command
line. Together, these allow a test to provide their own minimal `Core`
package.

For example, this would replace `Core` with the package and prelude in
`facet_types.carbon`.
```
// INCLUDE-FILE: toolchain/testing/min_prelude/facet_types.carbon
// EXTRA-ARGS: --custom-core
```

To support this:
* //testing knows how to parse INCLUDE-FILE out of the header of a test
file.
* //testing adds the file to the virtual file system, and includes it in
the test's arguments.
* //toolchain/driver grows the --custom-core command line flag to avoid
loading the production `Core` package.

Tests that were creating their own minimal prelude to define BitAnd on
types are now pointed to
toolchain/testing/min_prelude/facet_types.carbon as the prelude. They no
longer need to `import Core` in each test as a result.

Such tests are no longer `no_prelude`, but instead have their own
prelude. So they are moved to a `min_prelude` subdirectory.

Closes #5076
2025-03-10 19:44: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
josh11bandJosh L b3be298f7f Fix test that used i32 in a no_prelude directory (#5086)
Exclude SemIR since the point of the test is that it diagnoses something
invalid, not that any particular SemIR is produced.

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-03-08 06:18:18 +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
josh11bandJosh L aa90ab3862 Fix non-instance compound member access (#5059)
Implements the rule:

> For compound member access `a.(b)` where `b` names a _non-instance_
member of an interface `I`:
> * `a` is implicitly converted to `I`
> * let `T` be the result of symbolically evaluating the converted
expression
> * `impl` lookup is performed for `T as I`.
>
> Instance binding is never performed.

See
https://docs.carbon-lang.dev/docs/design/expressions/member_access.html#impl-lookup-for-compound-member-access.
Before this PR, non-instance members were treated as instance members.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2025-03-07 01:37:07 +00:00