Commit Graph
169 Commits
Author SHA1 Message Date
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
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
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
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
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
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
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 RomerandRichard Smith 6d4f2567a7 Add support for var patterns (#5069)
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-03-06 19:06:51 +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
Boaz Brickner 28de6c9b7d Add --no-dump-sem-ir to all name_poisoning tests (#5053)
Follow up of previous PR discussions
([#4950](https://github.com/carbon-language/carbon-lang/pull/4950/files/89c2e66dc3190159e2f8d94c31bff31bdd0d81a1..a1650a7d73c8f4013b4b77e4d7d60933f1f6d676#r1972257889),
[#4987](https://github.com/carbon-language/carbon-lang/pull/4987/files#r1964105413)).
Part of #4622.
2025-03-03 19:25:55 +00:00
Boaz Brickner fc5dcfe957 Add a test for the case that impl function is poisoned (#4950)
This adds missing coverage.
Part of #4622.
2025-02-28 21:10:37 +00:00
Richard Smith 0d2f364f39 Split evaluation up into one function per instruction kind (#5008)
Replace the large and growing `TryEvalInstInContext` function with one
function per kind. While we still have special-case handling for a small
number of instruction kinds, most instructions are now handled either
fully automatically or use a common codepath that evaluates the
instruction operands and then performs an eval-context-independent
evaluation of the instruction.

To support this, `InstConstantKind` is expanded to describe more
fine-grained details about how each kind of instruction interacts with
constant evaluation. Also, the operand kinds of instructions become
slightly more fine-grained: we now distinguish between operands that
describe the destination of an initializing expression (`DestInstId`)
from other `InstId` operands, because `DestInstId` operands need
different treatment during constant evaluation. In particular, an
initializing expression can have a constant value even if its
destination is non-constant or has not yet been set, because evaluation
of an initializing expression doesn't include the store to the
destination.

Some minor test changes:

- We now more consistently propagate errors into the results of constant
evaluation, so more instructions that depend on errors have a constant
value of `<error>`.
- Diagnostic location for invalid array types now point at the whole
array type rather than the array index expression, because
`EvalConstantinst` doesn't have access to the original expression.
- Diagnostic for failed `RequireCompleteType` doesn't print the original
type any more because `EvalConstantInst` doesn't have access to the
original expression.

As a follow-up, some of this -- in particular, the `EvalConstantInst`
overloads -- will be moved to a separate file, in an effort to split the
overall constant evaluation machinery apart from the logic to evaluate
each individual kind of instruction.
2025-02-27 01:31:26 +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
Boaz Brickner 5b67bb8981 Refactor name poisoning tests to be more organized, complete and consistent (#4987)
This is also following
https://github.com/carbon-language/carbon-lang/pull/4900#discussion_r1945606053,
which points that name poisoning tests are not in the correct place.
Part of #4622.
2025-02-24 08:59:36 +00:00
Alina Sbirleaandjonmeow 1d48270dc4 Emit diagnostics missing declaration of owned function. (#4962)
Emit diagnostics for a function declared in a non-owning library, that
is not redeclared (or defined) in the owning library.

---------

Co-authored-by: jonmeow <jperkins@google.com>
2025-02-22 01:29:22 +00:00
Dana Jansensandzygoloid 24bde46181 Change array syntax from [T; N] to array(T, N) (#4981)
In line with the proposal in #4682, this changes the array syntax to be
array(T, N). `array` is a builtin keyword which must be followed by
parens containing two expressions and a separating comma.

The array type expression is still fully builtin, it does not forward to
a Core.Array library type yet. It merely adds the `ArrayType`
instruction, as was done with the previous syntax.

Followup work will change the instruction to reference to Core.Array,
once the library type exists and can be used directly.

---------

Co-authored-by: zygoloid <richard@metafoo.co.uk>
2025-02-20 22:42:47 +00:00
Geoff RomerandJon Ross-Perkins 74e1a9949f Support tuple patterns outside parameter lists (#4923)
Parameter lists need substantially different treatment than tuple
patterns in other contexts, so this change splits them into separate
parse node kinds.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-02-20 03:17:45 +00:00
Boaz Brickner 6a99c4e970 When diagnosing a duplicated name, add the name to the diagnosis (#4902)
In order to have the name available for diagnostics, we now always set
`NameId` in `NameContext` and put `poisoning_loc_id` as part of the
union with `resolved_inst_id` instead (since we never need both).
2025-02-19 07:19:23 +00:00
Boaz Brickner 4a93b6667e Add the used name to the NameUseBeforeDecl diagnostic (#4901)
Part of #4622.
2025-02-14 21:54:35 +00:00
Dana Jansensandjosh11b d5f3d3365a Allow checking to continue after 'impl as' outside class (#4937)
Currently it returns false which just ends typechecking. Instead handle
the error state later and avoid firing overlapping diagnostics in
'extend impl as'.

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2025-02-14 20:02:10 +00:00
Boaz Brickner 986a2a064c Add poisoned names to the format (#4961)
Part of #4622.
2025-02-14 19:18:51 +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
Boaz Brickner 1aa6573d4e When diagnosing poisoned name, point to the declared name instead of the entire declaration (#4938)
See
https://discord.com/channels/655572317891461132/655578254970716160/1339007384361762857.

Part of #4622.
2025-02-12 20:59:55 +00:00
Dana Jansens 7d6cd3da6d Add a test and check-support for positional params with a return type (#4899)
Functions with positional parameters omit any implicit or explicit
parameter lists. This causes them to not have a pattern block, which
crashes if there is a return type that needs to add to the pattern
block.

Add a test covering this and handle it by having the ReturnTypeId
handler peek at the node stack and conditionally add the missing pattern
block. To do so it looks to see if the previous node is a
`IdentifierNameNotBeforeParams` which implies it was not expecting a
pattern (since there are no params) and thus the pattern block was not
added to the stack.

Note that lambdas also allow functions to omit an identifier, which will
need a pattern block on the stack for implicit parameters, explicit
parameters or a return type, without seeing any IdentifierName-like
parse nodes. To handle this, we will need to look for additional nodes
in the future and add the missing pattern block to the stack - possibly
for the FunctionInitializer, but the parse support needs to be created
for lambdas first.
2025-02-06 17:49:00 +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
Boaz Brickner c67920e631 When diagnosing name used before declared, set the location of the usage (#4860)
Done by adding a poisoning location for each poisoned name.
Part of #4622.
2025-02-03 20:01:09 +00:00
Boaz Brickner 7c01bb4e5c Return the NameId for a new instruction regardless if it's unresolved because it's poisoned or not (#4861)
i.e. Support `Poisoned` in `NameContext::name_id_for_new_inst()`.
Part of #4622.
2025-01-29 14:20:05 +00:00
Richard Smith 5f888e1124 Treat associated constants as entities parameterized by Self (#4837)
Add a full entity representation for associated constants, and build a
`Generic` object for them. This `Generic` is parameterized by the
enclosing `Self` type, allowing the use of `Self` within the type of the
associated constant to be supported.

When performing impl lookup for an associated constant, produce the type
with the provided self type substituted for its `Self` along with any
generic parameters of the interface.

Split the handling of associated constant declarations into two parts,
corresponding to the code before the `=`, and the code between the `=`
and `;` (if any). The former goes into the generic declaration region;
the latter into the generic definition region. This prepares us to
handle the default value for an associated constant, but for now we're
just storing the information and not actually using it.

Remove the entity type field from `assoc_entity_type`, because it's
almost unused and is an attractive nuisance -- it must necessarily be a
type in the generic scope of the associated constant rather than in the
scope of the instruction (because there is no `Self` anywhere else),
which means that it's hard to substitute into or derive meaning from.

See `toolchain/check/testdata/impl/assoc_const_self.carbon` for tests of
the new functionality; these used to cause the toolchain to crash.
2025-01-25 02:13:52 +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
Geoff Romer 943acf1ec2 Separate node kind for bindings inside var (#4822)
This is a step toward making binding pattern handling more robust, by
removing its reliance on the node stack for context.
2025-01-21 20:15:19 +00:00
Geoff RomerandRichard Smith 13434f0e8a Model var as a pattern operator (#4720)
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-01-17 17:51:34 +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
Jon Ross-Perkins d958caaff3 Refactor CheckIsAllowedRedecl and stop function definition merging (#4800)
Rename `CheckIsAllowedRedecl` to `DiagnoseIfInvalidRedecl` to try to
better document behavior, and clean up comments.

This extends the no-merge-if-defined behavior to functions. It was
already the case for class/interface, and just added for impl, so if
anything functions were now inconsistent. I was kind of tempted to make
a helper for it, but I didn't think of a great structure/name to get
there: `DiagnoseRedef` isn't always called when it's a redefinition, for
example due to `extern` diagnostics, it's hard to combine.

Cleans up `is_defined` calls to rely more on `has_definition_started`,
removing some code paths that are unused since definitions aren't
merged.
2025-01-14 21:13:21 +00:00
Richard Smith 6bc36b045f Rearrange name poisoning logic to do a little less work. (#4766)
Insert the poison at the same time we do the name lookup to avoid doing
two hash table lookups into each scope. This adds a bit of complication
because import logic now needs to cope with importing a name that is
already poisoned, but the complexity seems worthwhile to reduce the
number of name lookups performed.

This incidentally fixes a bug where we wouldn't poison any name scopes
if we found the name in an enclosing lexical scope, leading to one extra
diagnostic in existing tests.

Part of #4622
2025-01-14 17:34:33 +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
Jon Ross-Perkins 8f685b6953 Change how diagnostics are ordered (#4778)
This change deliberately breaks away from the line/column ordering, and
instead focuses on a last byte offset corresponding to the final token
processed as part of producing the message. Where that's equal, this
maintains stable ordering in order to reflect the order that diagnostics
were produced.

The intent of this approach is that lex, parse, and check diagnostics
are interleaved based on where they are produced, but that
subexpressions still have diagnostics emitted prior to containing
expressions. In particular, the prior line/column sort essentially
sorted on the _start_ of where a diagnostic was associated, and this is
closer to sorting based on the _end_. As a consequence, something like
`F(1 2)` will have the error for `1 2` emitted _before_ a diagnostic for
`F(1 2)` not matching parameters, instead of _after_.

In check, we track the last handled node. This provides a
last_byte_offset _separate_ from where a diagnostic is associated. The
intent is that this creates an ordering of diagnostics which may be
associated with earlier code, to cause the diagnostics to be emitted
later. An example consequence of this is the change in ordering of
modifier diagnostics: we are diagnosing those from the same place, but
they have the same last_byte_offset, so we print them out in the order
produced.

I've added similar tracking to parse, but cannot identify any test which
is affected by it (note the separate commit, I thought about this late).
I'm not sure whether we have good out-of-order errors we could produce
for this.

A significant number of tests have reordered diagnostics as a
consequence of this change, so this change does not add further testing.
2025-01-10 18:36:24 +00:00
Boaz Brickner 7d92aa7bbf Add a test that shows names are not poisoned when lookup fails (#4774)
#4622
2025-01-08 16:59:26 +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
Boaz Brickner 72e594dfd0 Do not try to recover from using impl outside class error (#4755)
This prevents crashing when the wrongly used `impl` uses a poisoned
name.
#4622
2025-01-03 20:20:35 +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
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