Commit Graph
34 Commits
Author SHA1 Message Date
Jon Ross-Perkins 8567e02aa7 Refactor handling of cross-package imports. (#3783)
This revamps the support for cross-package imports, making them look
more like a namespace. The planned model is mentioned on
[#toolchain](https://discord.com/channels/655572317891461132/655578254970716160/1217586076022210670).
This does not implement name lookup into the new namespace structure.

A few key changes in this PR (it's a little sprawling) are:

- Moves logic for adding package imports from context.* to import.*
- Remove SemIR::Import, which was the prior model. This is instead now a
SemIR::Namespace with the NameScope getting a new import_ir_scopes
field.
- Allow SemIR::Namespace to use Parse::ImportDirectiveId in addition to
the prior Parse::NamespaceId
- The import_ir_scopes field includes a NameScopeId so that as we
traverse to child namespaces, we can directly perform name lookup in the
other IR.
- is_closed_import now tracks whether a namespace comes from a different
package. This has a diagnostic implemented in decl_name_stack.
2024-03-14 22:03:30 +00:00
Richard SmithandJon Ross-Perkins 1d720dc001 Basic support for looking up impl members when naming an associated entity. (#3776)
When a member access names an interface member, perform impl lookup to
find the impl and its corresponding member.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-03-14 18:31:21 +00:00
Jon Ross-Perkins 0217ec2d3b Switch Check's TODO to use SemIRLocation (#3779)
Allows dropping a few GetNodeId calls for code cleanliness.
2024-03-14 17:57:09 +00:00
Jon Ross-Perkins 86a7c9ff45 Rename parse_node -> node_id (#3760)
This was previously discussed at
https://discord.com/channels/655572317891461132/655578254970716160/1209975051588210729.
I'm initiating this mainly because we typically use "id" suffixes to
indicate an `IdBase` being passed around and the non-id suffix of
`parse_node` suggests at it carrying more data than it actually does.
There used to be more reason for avoiding `node_id` because
`SemIR::InstId` used to be named `NodeId`, but that's no longer
necessary. As a consequence, I'd like to rename `parse_node` to more
precisely reflect its type.

In full, this is doing:

```
parse_node_kind -> node_kind
parse_node -> node_id
ParseNodeCategory -> NodeCategory
ParseNodeKind -> NodeKind
ParseNode -> NodeId
```

This is primarily in check and sem_ir, but with some `parse_node_kind`
references in parse too.

Pluralization is consistent with name forms on both sides, so that
wasn't part of my replacements.
2024-03-09 00:21:29 +00:00
Richard SmithandJon Ross-Perkins abf23ae7fe Initial scaffolding for building a witness table for an impl. (#3743)
Add an instruction to hold the witness table, along with a corresponding
type to keep things simpler. Add `check/impl.{h,cpp}` to house the new
logic. No checking of impls against interfaces is performed yet.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-03-07 23:10:14 +00:00
Richard Smith f5a3a9a7e0 Add Self into scope in interface definitions and using facets as types. (#3740)
`Self` is modeled as a `bind_symbolic_name` with no corresponding value,
for now at least. In the future it might make sense to model it as a new
kind of instruction, or as a `bind_symbolic_name` whose value is a
`param`, but for now we just want it to introduce a symbolic constant.

In order to convert a value like the `Self` of an interface to a type, a
new instruction `facet_type_access` is introduced. This notionally
accesses the "type" field within a facet, converting it from a pair of
(type, witness) into just the type.
2024-03-06 22:33:33 +00:00
Richard Smith 8e956baca8 Basic support for associated constant declarations (#3737) 2024-03-04 21:23:06 +00:00
Richard SmithandJon Ross-Perkins 33c1e9ca95 Add an associated entity instruction and corresponding type for interface elements. (#3730)
When declaring an associated entity in an interface -- just associated
functions for now -- create an associated entity value and corresponding
type to represent a "slot in a witness table". Also track the list of
associated entities on the interface so that we will eventually be able
to check impls against them.

Associated entities are represented as the integer index of their slot
in a witness table.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-02-28 01:56:27 +00:00
Jon Ross-Perkins d2056ef4b9 Split classes in file.h and value_stores.* to separate files (#3725)
I'm proposing a different split, along the line of "what does this
relate to". I view impl.h as having started down this route. Moving the
inst store stuff to inst.h feels odd to me given how much else is there
right now, but maybe it's still the best approach. Some files only
contain a store, no structured class, but I felt the consistency in file
naming (without _store suffixes) might help.
2024-02-26 20:24:51 +00:00
Jon Ross-Perkins 364ea5d3f2 Assign a constant to ClassDecl/InterfaceDecl for name references. (#3722)
By adding a constant to ClassDecl/InterfaceDecl, we're able to remove
name reference special-casing. Use TryEvalInst on the Decl to generate
the Type. For ClassDecl, then use the generated constant for
self_type_id.
2024-02-24 00:00:18 +00:00
Jon Ross-Perkins 1437b0e26d Implement 'alias' with transparent semantics. (#3701)
Adds `BindAlias` with a hybrid of `BindName` and `NameRef` semantics. I
think it's slightly closer to `BindName` because it introduces a name,
so I'm going more in that direction. This also matches the need for
`bind_name_id` with imports on enclosing scopes.

Note, only things that look like a name reference are being allowed on
the RHS of `alias`. This includes builtins that look like name
references, such as `bool`, but not ones that turn into values
underneath, such as `false`.
2024-02-14 18:33:18 +00:00
Jon Ross-Perkins 1bf4dc53d9 Add diagnostic support so that we can just pass in TypeId. (#3695)
Note we may also want to do this with NameId, maybe some other things,
but the TypeId use is pretty broad and repetitive -- I thought I'd start
with it first.
2024-02-09 16:25:23 +00:00
Richard SmithandJon Ross-Perkins 0e053703f8 Build Impl entity to represent an impl declaration. (#3683)
Collect the contents of an `impl` into a scope, and start doing very
basic checking for `impl` declarations and definitions.

This change adds two new `Id` types to the set of type that `NodeStack`
supports -- `ImplId` and `NameScopeId`.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-02-06 18:49:21 +00:00
Jon Ross-Perkins 3a489fd7b4 Implement ConstantId::Invalid (#3674)
Right now, ConstantValueStore defaults to having unknown values use
NotConstant. This generally works for the current IR, but with imports
we're expecting sparse entries which are generally unknown -- and
distinguishing between NotConstant and simply unset would be helpful. As
a consequence, add Invalid.

We discussed whether to simply have ConstantValueStore default to
Invalid going forward, or to make the default flexible. The upside to
the former is consistency, the upside to the latter is that it should
result in fewer Sets when operating on the current IR (which will more
frequently have known non-constant values). This PR offers both
approaches in separate commits, but I somewhat lean towards the latter
for fewer array resizes.

Note, a totally different approach would be to use a different class
(not ConstantValueStore) for imported IRs -- then the default of Invalid
versus NotConstant would be type-dependent. However, I expect we're
going to want to do at least somewhat consistent lookups, and using the
same ConstantValueStore for both cases allows avoiding a virtual
interface or templating. Also, I'm hoping to only maintain the
ConstantValueStore for an imported IR as part of Context (not File),
which would mean the SmallVector storage overhead is ephemeral,
mitigating one of the potential advantages of using a different type for
imported IRs.
2024-02-02 04:23:56 +00:00
Richard Smith 9e7a17b1a1 Scaffolding for checking impls. (#3672)
Consume the components of the `impl` declaration, and set up scopes for
the child elements. We don't yet build a representation for the impl
itself.

Also, add an interface type value. This is necessary so that we have a
value for the expression on the right-hand side of `as` in an `impl`.
2024-01-31 22:18:29 +00:00
Jon Ross-Perkins 8167c44a03 Merging CrossRef into ImportRefUsed, shifting builtins over. (#3659)
This is a bit of a cleanup; I probably should've just renamed CrossRef
instead of adding ImportRefUsed.

Adding `is_builtin` to InstId is more about providing a standard API for
the check, which I expect to add a little more of.

Shifts import tests to validate that the BuildValueRepr CHECK isn't
accidentally hit.
2024-01-27 00:36:58 +00:00
Chandler CarruthandJon Ross-Perkins 13de9e9d06 Fix outstanding clang-tidy errors. (#3654)
Recent runs of `clang-tidy` for me started showing more errors, and this
is a collection of changes to address them.

First, I've systematically applied the disabling tag to all C++ rules
under //explorer/... with `buildozer` so we don't spend time analyzing
this code or reporting errors from it. Not sure this was strictly
necessary, but it seemed like a nice consistency improvement.

Next, I disabled a buggy check for missing `default` cases in
`switch`es. It seems to get confused by the fancy conversions in our
`enum_base.h`. We don't miss much with this as the Clang compiler
warnings for `switch` catch most of our actual bugs. I also removed the
local disabling of this now that it is turned off centrally.

Lastly, I added error checking to two file descriptor manipulating calls
in the `file_test` infrastructure.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-01-26 18:20:47 +00:00
Jon Ross-Perkins c1a894fca7 Start adding ImportRefUsed, removing older copy behavior. (#3657)
Builds on #3656.

Under the prior "lazy" model, we had been planning to copy instructions.
Under the current "unused+used" model, we're restricting that to
constants. I'm trimming back some of the ResolveIfImportRefUnused logic
because it was more appropriate for the former model.

Right now, I'm adding ImportRefUsed direct creation in import.cpp for
namespaces. I think I'll need to do something similar in
RseolveIfImportRefUnused... I'm still trying to think about how to
manage type information there (which needs to come in as an import
reference itself, and probably have some amount of deduplication before
forming a TypeId). So ImportRefUnused lacks a type because I'm hesitant
to aggressively load it, whereas ImportRefUsed should *always* have a
type but it's just an error while I think things through.

For reference, ImportRefUnused and ImportRefUsed are mainly split in
order to track the boolean "used" without making fundamental
modifications to Inst for bit packing (this effectively instead packs a
bit into InstKind). AnyImportRef currently excludes the type because
it's mainly for diagnostic printing at the moment. It could end up with
a TypeId that would end up Invalid for ImportRefUnused, though it could
also be that the TypeId is only accessed when using ImportRefUsed
explicitly.
2024-01-26 17:26:15 +00:00
Jon Ross-Perkins adad286b74 Refactor LazyImportRef into ImportRefUnused. (#3656)
This makes some changes to the formatter so that ImportRefUnused and
ImportRefUsed will both be labeled as "import_ref" with an "unused ->
used" argument change in textual IR, but is otherwise not changing
logic.
2024-01-26 03:10:00 +00:00
Richard Smith 439a644960 Propagate the phase of a type from its constituent types. (#3645)
To avoid bouncing through `constant_values()` to determine whether a
type is symbolic or template, store the `ConstantId` on the `TypeInfo`
not just the `InstId`.

In addition to propagating the symbolic / template phase, this also
propagates whether a type contains an error, resulting in our no longer
producing types such as `<error>*` -- these now evaluate to simply
`<error>`. While this makes our types less precise after an error, it
also removes some follow-on diagnostics, so it seems to be an
improvement on the whole.
2024-01-25 01:00:37 +00:00
Richard Smith 099bd5ce26 Produce a more descriptive error if an array type's bound is too large. (#3638) 2024-01-23 21:01:34 +00:00
Richard Smith afd194de9d Runtime : name bindings are not constants. (#3639)
Do not create runtime name bindings for `FieldDecl`s even though they're
declared with `:`, so that we can still constant-evaluate references to
fields.
2024-01-23 17:02:08 +00:00
Richard Smith e2f21c0052 Check for a constant rather than a literal in indexing. (#3637)
In array indexing, move the check for an out-of-bounds index into the
constant evaluation logic, so that we will also benefit from it when
constant evaluating a compile-time function.

In tuple indexing, require a template constant index instead of an
integer literal.
2024-01-23 16:56:30 +00:00
Richard Smith aba3c47467 Constant evaluation for aggregate access. (#3625)
Also, form `addr_of error` instead of `addr_of operand` when `operand`
is not a reference expression, so that we don't try to constant-evaluate
a meaningless expression.

Also, expect a constant for an array bound rather than specifically an
integer literal. This allows constant evaluation results to be more
easily tested by inspecting array bounds.
2024-01-20 01:44:13 +00:00
Richard Smith 87ecb34f6b Constant evaluation support for initializing expressions. (#3624)
The constant value we associate with an initializing representation is
the object representation that the initializing expression will store to
its destination.

Also include the type in the profile of an instruction. This is now
necessary for array values, which are represented as tuple_value
instructions with array type, to avoid instructions with different types
being merged by constant canonicalization.
2024-01-19 23:28:53 +00:00
josh11b 816a48ca45 Fix typo in comment (#3622) 2024-01-19 18:03:13 +00:00
Richard Smith b138c90c9e Use constant evaluation to determine the identity of types. (#3617)
Remove the type canonicalization mechanism and instead rely on constant
canonicalization to deduplicate types.

Rename the `Canonicalize*Type` functions to reflect that they're no
longer performing canonicalization. Switch code that creates types due
to semantic checking, rather than due to source syntax, to directly
create type constants through evaluation rather than creating an
instruction and evaluating it to produce a separate constant
representation.

The mapping from `const (const T)` that was previously performed by type
canonicalization is now implemented in expression evaluation instead.

The value `<error>` is now treated as a constant value, with a special
property that an instruction involving `<error>` that could possibly be
constant evaluates to `<error>`. This helps avoid producing follow-on
errors when an error occurs as a subexpression of an expression, such as
a type, that is intended to be constant.
2024-01-19 00:47:37 +00:00
Richard Smith 29c294880d Deduplicate and canonicalize all constants. (#3611)
Rather than producing multiple constants with the same value, fold all
instances of a given constant to the same constant instruction.

A future PR will use this to replace the current type canonicalization
system.
2024-01-18 21:42:19 +00:00
Richard Smith b7c21a7fa7 Add constant evaluation for namespace expressions. (#3612) 2024-01-17 21:12:25 +00:00
Richard Smith d712bf12a6 Remove parse nodes from constants. (#3599)
These instructions are intended to be shared across all uses and so
don't have a meaningful location. So far, only type constants are
shared.
2024-01-13 04:52:25 +00:00
Jon Ross-PerkinsandRichard Smith f197219c10 Split parse nodes out from instructions because they're rarely used. (#3590)
The parse nodes are still tracked as part of the same value store
interface in order to ensure parity, but they're split out from Inst
itself in order to reduce the size of Inst -- the expectation is that
they don't need to be passed around quite as much.

This change doesn't actually reduce the passing very much, although
there are hints of it: AddInstAndPush doesn't typically need a separate
parse node from the one on the Inst itself, for example. In a couple
spots I changed code to rely a little more on the InstId until the
ParseNode is needed, but it's very low hanging fruit where done. I think
convert could do more to not eagerly fetch the parse node before its
use, but more cleanup felt it would be easier to handle separately. I'm
currently viewing this as making such cleanup _possible_ rather than
executing on it up-front.

But also, I want to make sure there's a consensus to head in this
direction before pulling the trigger. We speculated that this would
result in the parse node being passed around less, and I do think that's
the case, although it's a bit fuzzy in the change.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-01-12 19:01:51 +00:00
Richard SmithandChandler Carruth a3154356f0 Distinguish between template constants and symbolic constants. (#3595)
This is accomplished by tracking an extra bit on the ID we store in the
constant values table, and propagating that from subexpressions to the
enclosing expression. This extra bit is not yet computed correctly for
types; that will be addressed in later PRs.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2024-01-12 02:56:22 +00:00
Richard Smith a2012d4777 Add evaluation for conversion instructions. (#3594)
Also some finessing of evaluation for other instruction kinds and some
additional testing.
2024-01-11 23:50:04 +00:00
Richard Smith 7553d864e1 Very basic support for constant evaluation of expressions. (#3581)
Form a side table with constant values for each instruction. Evaluation
is only supported for a few very simple kinds of instruction for now.
This is not observable outside of the SemIR output, because nothing
depends on expressions having a constant value phase yet.
2024-01-11 23:12:58 +00:00