Commit Graph
96 Commits
Author SHA1 Message Date
Jon Ross-PerkinsandGeoff Romer 03e693873b Detect control flow in entities nested inside functions (#5336)
Right now, return_scope_stack is being used to determine whether logic
is in a function scope. However, we need to handle nested entities
inside function scopes. For example where this crashes right now:

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

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

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

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

---------

Co-authored-by: Geoff Romer <gromer@google.com>
2025-04-23 19:03:53 +00:00
Richard Smith 19532967fa Stop pushing a fake generic for the duration of check. (#5326)
This fake generic was used for two reasons:

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

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

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

Then I tried `SemIR::InstId::Is<SemIR::ErrorInst>`, which generally
worked with types but generated the complaint that it didn't shorten
*all* singleton uses. So pulling back on `::Is`, and instead just
dropping `Singleton`.
2025-04-15 22:40:29 +00:00
Jon Ross-Perkins 1ffd56ac3e Use Get*Type in a couple spots (#5257)
These seemed like spots that didn't need to call `TryEvalInst` directly.
I'm relying on tests for coverage. :)
2025-04-07 22:41:27 +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 832c6398d6 Reduce explicit SemIR::LocIdAndInst construction (#5153)
Building on #5151 reducing `UncheckedLoc` use, further remove uses of
the `SemIR::LocIdAndInst` constructor where we typically have overloads
that don't need it. Add parallel convenience wrappers for placeholder
insts.

Also refactors `MergeReplacing`. I don't think it makes sense to add an
overload for `ReplaceLocIdAndInstBeforeConstantUse`, but we can still
reduce the `LocIdAndInst` construction there.
2025-03-21 21:45:53 +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 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
eb69d7420e First iteration of completing and resolving facet types (#4920)
* Add `RequireCompleteFacetType` and `ResolveFacetTypeImplWitness` to
`check::Context`. Goal was to move code from `impl.cpp` (mostly) without
functional changes.
* Complete type information is cached with the facet type, and is stored
in a `complete_facet_types()` table.
* Main functional change is to diagnose attempts to use a rewrite
constraint on an associated function. Some existing diagnostics have
been updated.
* Remove `check::Context::RequireDefinedType`:
  * For class types, use `RequireCompleteType`
  * For facet types, use `RequireCompleteFacetType`
* Introduce a `SemIR::SpecificInterface` to hold an interface and
specific id pair.
* Keep the specific interface ids in the impl object.
* Avoid some extra copies in `Dump` functions.
* Future work missing from this PR:
  * Resolving for member access or actions that require impl lookup.
  * Resolving rewrites constraints that refer to non-concrete values.
* Any support for adding implied constraints that result from a `where`
clause (though TODOs have been added).

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Dana Jansens <danakj@orodu.net>
2025-02-19 22:10:11 +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
Jon Ross-Perkins 311b4ff03d Refactor AddInst-family functions to their own file (#4941)
This in particular uses free functions because it's likely to end up
more consistent with types (versus a wrapper object for InstStore).
Note, this is unlikely to have a performance impact, but if it does, we
can look into related approaches (and we've already discussed using
LTO).

Renames `PendingBlock::AddInst` to `PendingBlock::Add` because
`MakeElementAccessInst` expects the matching name to exist.
2025-02-14 19:44:36 +00:00
Boaz Brickner dd7c64bad0 When diagnosing a duplicate name, point to the name instead of the instruction (#4953)
Left TODOs where more work is necessary before this change can be
applied or its impact can be verified.

Includes #4952, to avoid regression in some cases.

Similar to #4938. See
https://discord.com/channels/655572317891461132/655578254970716160/1339007384361762857.
2025-02-14 19:21:50 +00:00
Jon Ross-Perkins dc8f47e6ad Move type functions off Context (#4951)
This creates a new check/type.h for most logic, and also moves some
functions to TypeStore in sem_ir/type.h. My approach for TypeStore is to
focus on moving the read-only functions there.
2025-02-13 23:02:38 +00:00
Jon Ross-Perkins e70f9cd71d Move diagnostic helpers from Context to other files (#4949)
Trying to find more specific homes for shared diagnostic function calls.
2025-02-13 18:08:11 +00:00
Richard Smith 6dda094928 Superficial support for template modifier on symbolic bindings. (#4948)
Change parse tree from `template (T:! type)` to `(template T):! type`,
so that we have information about whether a binding is a template
binding available when forming the representation of the binding
pattern. This incidentally fixes a bug that we would accept `template
addr A:! B` instead of the intended `addr template A:! B`.

Track whether a symbolic binding is a template binding on the
`EntityName` object. I'm borrowing a bit from the `CompileTimeBindIndex`
for this in order to avoid making `EntityName`s larger. Longer-term, we
should think about using a different representation for symbolic
bindings, to avoid including these fields in all `EntityName`s, but
that's out of scope for this change.

So far, template bindings are treated as having the same phase as
checked bindings, but that will change in a future PR.
2025-02-13 02:15:22 +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
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 f4e19f4390 Change DeclNameStack::LookupOrAddName() to return SemIR::ScopeLookupResult instead of a pair (#4852)
This makes the lookup API more consistent and would make it easier to
add poisoning location.
Part of #4622.
2025-01-28 21:36:20 +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
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
Geoff RomerandJon Ross-Perkins 4f10735751 Track params in the parser (#4777)
This change splits `NodeKind::IdentifierName` into separate node kinds
depending on whether the identifier is followed by parameters, and
similarly splits `NameQualifier` based on whether the qualifier has
parameters. This enables us to only push a pattern block when it's
actually needed, rather than "defensively" pushing one when it might be
needed.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-01-10 22:11:07 +00:00
Boaz Brickner 74395ce693 Change name poisoning implementation to allow better diagnostics (#4764)
Change the implementation to use an explicit `is_poisoned` bit instead
of `InstId::PoisonedName` value.
Zero behavior change.
This would allow to more easily change the API to support accessing the
poisoning declaration so we can have better name poisoning diagnosis.
#4622
2025-01-08 08:36:14 +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
9c8773da1b Basic name poisoning support (#4654)
https://github.com/carbon-language/carbon-lang/issues/4622
When using an unqualified name, disallow declaring that name in all
scopes that would make it ambiguous in retrospect.
Doesn't include support for poisoning in `impl library` (see new test
for that with TODO).
Implemented by introduce `InstId::PoisonedName` and entries with it to
`NameScope`.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Geoff Romer <gromer@google.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: josh11b <josh11b@users.noreply.github.com>
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2024-12-17 21:08:26 +00:00
Jon Ross-Perkins 0e92e6cc5a Switch TypeId::TypeType to TypeType::SingletonTypeId, and similar (#4619)
`ids.h` and `ids.cpp` are the manual edits, everything else is
search-and-replace.

The full list of things moved is:

- `TypeId::TypeType`
- `TypeId::AutoType`
- `TypeId::Error`
- `ConstantId::Error`

This is to unblock removing `InstId::Builtin*`.
2024-12-04 18:40:50 +00:00
a69c2630f9 Replace InterfaceType with FacetType (#4499)
This does a few things:
* Replaces the single `TypeId` in the `FacetTypeInfo` struct with a
vector of `InterfaceId`, `SpecificId` pairs (sorted in id order)
representing the set of interface requirements of the facet type. This
will later be used to support facet types with multiple interface
requirements (as in `I & J` or `I where .Self impls J`).
* Replace `InterfaceType` instructions (used as the type of an
`InterfaceDecl` instruction) with `FacetType` instructions (introduced
in #4460) with a (newly introduced) `FacetTypeFromInterface()` function.
* Replace code that consumed `InterfaceType` values with code that
consumed `FaceType` values. I've generally left the assumption in the
code that it is dealing with a single interface, using the (newly
introduced) `FacetTypeInfo::TryAsSingleInterface`, and producing an
error otherwise. There isn't yet support for the `&` operator or `where
.Self impls`, so this is generally a good assumption for now, except you
can get a facet type with no associated interfaces from a `type
where`... expression. In some cases, the facet type value is pulled from
the evaluation of an `InterfaceDecl` instruction, where the single
interface assumption will hold permanently.
* Some related cleans up: nicer stringification and formatting of facet
types, suppression of some errors when there already was an error.

There is still a lot left to do, including:
* Type `type` should be a facet type with a reserved id, replacing the
built-in instruction.
* Code using `TryAsSingleInterface` should generally be upgraded to
handle more than (or less than) one interface. Name lookup should be
particularly exciting.
* Operator `&` should be defined on facet types, unioning their
interface and other requirements.
* Requirements from a `where` clause don't do anything yet.
* Impls and impl lookup need to resolve facet types, and do things like
determine if all the associated constants are given values.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Geoff Romer <gromer@google.com>
2024-11-11 18:01:50 +00:00
Geoff Romer 223c5cb04b Restructure handling of runtime parameters (#4422)
- Generate runtime indices as part of pattern matching, rather than as a
separate postprocessing/rewriting step.
- In contexts where runtime parameters aren't permitted, avoid emitting
insts for them to begin with, rather than trying to detect the problem
and rewrite the IR to remove them later on.
2024-10-21 19:53:38 +00:00
Geoff RomerandJon Ross-Perkins 9d942f4633 Generate parameter pattern-match IR from pattern IR (#4388)
Also propagate the pattern IR along with the pattern-match IR, and use
it where appropriate.

Strictly speaking, some parts of the pattern-match IR are allocated
eagerly, while traversing the pattern's parse tree, but they still
aren't actually emitted until we traverse the associated pattern insts.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-10-16 19:15:29 +00:00
josh11bandJosh L d6d70bf80d Handle runtime implicit parameters, and self outside of methods (#4361)
Closes #4356, #4359

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2024-10-03 20:24:28 +00:00
Geoff RomerandJon Ross-Perkins dc32aa2690 Initial support for binding patterns in SemIR (#4221)
Introduces the `BindingPattern` and `SymbolicBindingPattern` insts, and
a separate stack of pattern blocks that they are emitted into. The
intent is to generate the corresponding pattern-matching insts (like
`BindName`) from them in a separate pass, but that is deferred to future
PRs.

See
[here](https://docs.google.com/document/d/1U_vQH17V893J9aF1LJXUnFYBNSs2MjKl4bJPaWCB2zo/edit?usp=sharing&resourcekey=0-w0xGYZ0An31Kpz-wvzSXwQ)
for the design this is based on, but note that during review we have
chosen to deviate from that design by putting the patterns in separate
blocks, and omitting the "forward references" from a `BindingPattern` to
its corresponding `BindName`. This in turn necessitates having separate
inst kinds for symbolic and non-symbolic binding patterns.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-09-25 19:12:58 +00:00
Richard Smith 0354efa1fc Rework how we check calls to support deduced implicit parameters (#4302)
Instead of the `call` instruction having a block with one argument per
explicit argument, preceded optionally by `self` and followed optionally
by a return slot, change the `call` to store only the *runtime*
arguments. Store an index on the runtime parameters to make it easier to
determine the correspondence between arguments and parameters in a call.
Compile-time parameters, whether implicit or explicit, are no longer
included in the call argument list. Instead, they're tracked only in the
`specific_id` on the callee.

For calls to generic classes and generic interfaces, it no longer makes
sense to form a `call` instruction, given that the entirety of the
result is determined by the `specific_id`, which is now formed when
checking the call. Instead, the `call` instruction now only models
function calls, and not calls to other kinds of parameterized entity
names, and we create a `class_type` or `interface_type` instead of a
`call` instruction to model these kinds of calls. Notionally the model
here is that we're following the #3720 approach for calls, but for now
we inline the `Call.Op` function when forming SemIR.

We now also track the enclosing specific for a generic class or generic
interface that appears within an enclosing generic. This is necessary in
order for deduction of the inner generic parameters to not get confused
by the outer generic parameters being absent.

In order to not regress diagnostics, the template argument deduction
mechanism has been extended to specify the name of the parameter we're
deducing against when possible, and call arity mismatch errors are now
diagnosed before performing deduction rather than afterwards.
2024-09-13 21:31:43 +00:00
4845f40dff Switch CARBON_CHECK to a format string API (#4285)
This switches `DCHECK` and `FATAL` as well.

The goal is to reduce the code size impact of these assertions so that
we can keep more of them enabled. Currently, the largest cost I see from
`CHECK` is not the actual check or the cold code itself, but actually
the failure to inline trivial functions due to the presence of the cold
code. This means that our goal isn't to reduce apparent code size in the
final binary but the LLVM IR cost assessed for these routines in the
inliner, which closely correlates with code size but is a bit different.

As discussed in #4283, experimentation shows that a single function call
with a minimal number of arguments is the lowest cost model for these.
This is easily achieved with a format-string API that internally uses
`llvm::formatv`. This PR is essentially the `CHECK` version of #4283.

However, the check macros are substantially harder to make work with
both format strings and streaming because they also take a condition.
Also, unexpectedly, I was very successful at devising a regular
expression based automated rewrite from the streaming to the format
string form with only low 10s of manual fixes. This includes compacting
strings broken up across lines, etc. Given how well that went, I've
prepared this PR which just directly switches to the format string API
and migrate everything to use it.

One nice side-effect is that the format string approach ends up greatly
simplifying the implementation here as well.

This is ... *shockingly* effective. Parsing speeds up by more than 3%
with just this change. And checking speeds up by **8%** with this change
alone:
```
BM_CompileAPIFileDenseDecls<Phase::Parse>/256      86.3µs ± 1%  82.9µs ± 1%  -3.94%  (p=0.000 n=17+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/1024      431µs ± 1%   415µs ± 1%  -3.76%  (p=0.000 n=18+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/4096     1.77ms ± 1%  1.71ms ± 1%  -3.18%  (p=0.000 n=18+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/16384    7.44ms ± 1%  7.17ms ± 2%  -3.56%  (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/65536    30.7ms ± 1%  29.7ms ± 1%  -3.15%  (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/262144    131ms ± 1%   127ms ± 1%  -2.81%  (p=0.000 n=18+18)
BM_CompileAPIFileDenseDecls<Phase::Check>/256       878µs ± 2%   800µs ± 1%  -8.91%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/1024     1.88ms ± 2%  1.72ms ± 1%  -8.56%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/4096     5.78ms ± 2%  5.28ms ± 1%  -8.70%  (p=0.000 n=20+18)
BM_CompileAPIFileDenseDecls<Phase::Check>/16384    21.9ms ± 1%  20.1ms ± 1%  -8.02%  (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/65536    90.4ms ± 2%  83.1ms ± 1%  -8.04%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/262144    381ms ± 2%   352ms ± 1%  -7.79%  (p=0.000 n=19+19)
```

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2024-09-12 16:42:08 +00:00
Jon Ross-Perkins 2d3842fc06 Implement 'extern library' support for functions. (#4220)
Support for types (particularly classes) is left as a TODO.

There's also an issue I'm observing with a "define in impl" test, but
this is probably an issue with resolving the prior declaration which is
imported indirectly. The PR was already feeling big, so I'm choosing to
cut here.

Note, this does not implement the rule "The owning library's API file
must import the `extern` declaration, and must also contain a
declaration."
2024-08-19 22:12:21 +00:00
Jon Ross-Perkins e62973a8ef Address the LocIdAndInst::ReusingLoc TODO (#4211)
The TODO for switching to ReusingLoc (previously Untyped) had been there
for a while, so I'm trying to address it here. The intent had been to be
clearer about when the construction is validated, particularly so that
we aren't accidentally accepting an incorrect NodeId. Note, this does
fix an incorrect use of InvalidNodeId where NoLoc should've been called.

Since this changes the semantics of when `Parse::NodeId` is helpful in
`typed_nodes.h`, I'm doing a pass to either refine or switch to
`Parse::InvalidNodeId` where it compiles. I think most remaining
`Parse::NodeId` examples are things we _should_ be able to refine with a
little more work (versus before where `Parse::NodeId` also indicated
`LocId` construction might be used).

I'm also changing context.h to use `requires` that match what
`LocIdAndInst` has, I think it makes the diagnostics a little better.
And note I do add an overload for `ImportIRInstId`, also matching
`LocIdAndInst`, and widely used for import refs.
2024-08-13 18:52:24 +00:00
Jon Ross-Perkins a3a4c14960 Error on non-constant parameters to a type. (#4215)
At present, this is a crash bug. I don't know whether this is the best
fix, but I figure it'll work until zygoloid has a chance to look.
2024-08-13 18:35:10 +00:00
Jon Ross-Perkins 0feb757de0 Add fields for extern to EntityWithParamsBase (#4206)
This adds fields to `EntityWithParamsBase` to reflect the intention with
`extern library` design. I'm renaming `decl_id` because it shouldn't be
expected to be assigned anymore. import_ref.cpp I'm deliberately keeping
on `first_owning_decl_id` (which will break when importing `extern
library` declarations). Most other cases are for diagnostics, and I'm
using `latest_decl_id` to try and get the closest declaration to the
error. Note I'm partly splitting out this PR to show the test effect,
which apparently we don't test related cases.
2024-08-12 19:50:15 +00:00
Jon Ross-Perkins 3d13b8f71c Fix handling of interface redefinitions. (#4198)
The prior code crashed when trying to find the function's `Self`
parameter, I believe. `fail_redefine_with_dependents.carbon` handles
this case. It wasn't caught by the prior case because the `F` didn't
have any dependent parameters.

Note this also ran into a formatter crash, with invalid constants. I'm
fixing that here, but will also note it on #4145 (the crash in
FinishGenericDecl was muddled by a crash in Formatter code).
2024-08-07 21:30:44 +00:00
Richard Smith f6ff5b11b5 Distinguish between whether an entity has its own parameter lists and whether it is generic. (#4191)
It's actually possible to get into all four combinations of having
parameter lists versus being generic:

- An entity nested within a generic, such as a member class, can be
generic even if it has no parameters.

- As a corner case, an entity with an *empty* parameter list has
parameter lists, but isn't a generic because it doesn't have any generic
parameters.
2024-08-06 15:50:27 +00:00
Richard Smith 3cb769a053 Rename "generic instance" to "specific" throughout the toolchain. (#4165)
As discussed in toolchain meeting, we want to avoid overloading the
meaning of "instance", and "specific" was the best name we found. It's a
little unorthodox and inventive, but hopefully over time will become as
unsurprising as the term "generic" is.
2024-07-25 16:42:01 +00:00
Jon Ross-Perkins bf89652a4d Move common entity fields to a 'base' struct. (#4161)
I'd considered moving DeclParams uses over, but when handling qualified
names, there's a parse node instead of an instruction. I did try to
unify a couple other uses though, including adding MergeDefinition. I
expect `interface` will use a little more once it's more completely
implemented, but maybe I'm wrong about that.
2024-07-24 23:26:00 +00:00
Jon Ross-Perkins db022658c6 Implement syntactic merge checks for parameters. (#4149)
Note this isn't implementing checking through imports. The parse node
there is harder to access through the context, so would require
examining the entity in order to get the import declaration, to get at
the ImportIR. We also don't have a parse tree attached in that case, and
would need to add one to SemIR::File. But I believe we do want to add
that, so it's explicitly a TODO.

Note GetTokenText re-lexes literal values, so there's a bit of potential
overhead there. Not sure if we want a more efficient manner for
comparing in cases like this.
2024-07-23 20:32:24 +00:00
Geoff Romer 326609857d Rename BindNameInfo to EntityName (#4090) 2024-07-19 22:43:50 +00:00
Jon Ross-Perkins 99696b9812 Rename check handlers to HandleParseNode overloads. (#4121)
This is for consistency with #4120. Similar to that, we can use
overloads on the typed NodeId rather than individually named handlers.
There isn't the same caller benefit here though, since the calls from
check.cpp are already boilerplate.
2024-07-12 22:38:06 +00:00
Richard SmithandJon Ross-Perkins 50d56aa7c9 Add an instruction to represent a use of a dependent value from a generic instance. (#4122)
We can't use the instruction from the generic directly, because it
doesn't have the right constant value. Instead add an instruction that
models the transition from the constant value in the generic to the
constant value in the generic instance.

Also start associating the self generic instance with unqualified
lookups that find results in an enclosing generic, so that we track the
information necessary to create the new instruction.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-07-12 14:59:01 +00:00
Richard Smith fa11050961 Track a list of dependent instructions created within a generic (#4092)
When checking a declaration or definition of a generic, track a list of
created instructions that depend on the generic's parameters in some
way, along with information on how they depend on the parameters. This
will eventually be used to determine what information we need to compute
when creating instances of the generic, but for now we're just building
the list.

Information is tracked separately for the declaration region and the
definition region of the generic, because in general these may be first
provided in separate declarations, and they should be substituted into
at different times.
2024-07-01 20:33:44 +00:00
Richard Smith 10a198a9e6 Use the correct type for Self in generic classes and generic interfaces (#4087)
In a `class C(T:! type)`, the type `Self` should be `C(T)`, not merely
`C`. Similarly, in an `interface I(T:! type)`, the type of self should
be `I(T)`, not merely `I`.
2024-06-28 20:20:40 +00:00
Richard SmithandJon Ross-Perkins 19c5596fd8 Build Generic objects for generic classes and interfaces. (#4086)
In `ClassType`s and `InterfaceType`s, track a `GenericInstanceId` for
the instance rather than just the argument list.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-06-27 20:22:10 +00:00
Richard Smith e7b0529957 Create a Generic object to represent a generic. (#4081)
Build a `Generic` object for generic functions. This object tracks the
generic parameters that are in scope for the generic entity. Eventually
it will track other information about the generic too.

Add basic SemIR formatting support for generic functions.
2024-06-26 20:13:26 +00:00