Commit Graph
747 Commits
Author SHA1 Message Date
Jon Ross-Perkins 2fee4d072f Factor param/arg ref logic to a class. (#3728)
Just segmenting out a chunk of logic while I'm thinking about function
parameters.
2024-02-27 19:58:19 +00:00
Jon Ross-Perkins 85ce06f854 Make Function member comments align with Class/Interface (#3727)
In `Class` we have:

```
  // The following members always have values, and do not change throughout the
  // lifetime of the class.

  // The following members are set at the `{` of the class definition.

  // The following members are accumulated throughout the class definition.

  // The following members are set at the `}` of the class definition.
```

`Interface` has similar, minus the "accumulated" members. I'm echoing
this, except `Function` has no `}` members; at present, nothing
differentiates between "started definition" and "completed definition",
unlike the other two.

Also removing a slightly inconsistent default value for decl_id.
2024-02-27 01:21:46 +00:00
Jon Ross-Perkins abe8ce6653 Add support for importing interfaces. (#3726)
Interface support is pretty skeletal so this may need additions later,
but I think it's still worthwhile to fill in the necessary bits now.
With this change, the expectation is then that everything we have right
now which _can_ be imported, is supported for import (at least for the
"current package, no overlap" case).
2024-02-26 22:55:22 +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
Calvin f9f9ed2092 Remove obsolete __init__.py files (#3723)
I noticed that there are some empty `__init__.py` files in the repo,
with no immediately clear reason to have them. I asked [in
Discord](https://discord.com/channels/655572317891461132/655578254970716160/1211088334894534686)
and it looks like these are likely artifacts from when `lit` was used
for testing, now left over and obsolete from the migration. To keep the
repo tidy, this PR deletes the files.
2024-02-26 16:02:27 +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
Richard Smith 8e8eeb3243 Add diagnostics for extend impl misuse. (#3721)
To make the implementation simpler, make `PopWithParseNodeIf` return
`pair<NodeId, optional<value>>` rather than `optional<pair<NodeId,
value>>`. While wrapping the whole result in `optional` seems more
principled, it's significantly harder to work with.
2024-02-23 22:07:29 +00:00
Jon Ross-Perkins 8ad0c70f9f Add ClassDecl/Type import functionality. (#3709)
I believe this PR is sufficient to pull in all current class features,
including the current bits of inheritance which have been implemented.
Because a class declaration can reference its own type, this creates an
incomplete type prior to constant loading.

Right now, the object representation is imported proactively, but
individual fields are left as ImportRefUnused. This means that member
functions and similar will only be imported if called.

This also adjusts how function parameters are being handled, to match
the expectations of Self param structure.

When formatting, I'm starting to look into constants. Otherwise we get
"unexpected instref".

Overall, there are a few things that may be worth further discussion:

- The lack of a constant corresponding to the ClassType on ClassDecl is
inconvenient -- I'd like to see how zygoloid feels about trying to
restructure this. i.e., I'm setting a constant in order to be able to
track things down later, it'd be nice if the normal IR did this simply
for consistency, or if we were able to combine these rather than having
separate instructions.
- Should we shift the parse node tracking further, and go with a setup
wherein imports can embed import references into that? e.g., negative
values go to another array which includes a ImportIRId for printing
diagnostics, replacing the invalid NodeId.
- Can the formatter switch to a more general scan of instructions for
naming, to eliminate the ImportRef constant approach added here?
- GetExprValueForLookupResult special-casing instructions felt
surprising, I might see if there's a way to restructure to avoid that.

But I think these issues are things that can be separated out.
2024-02-22 22:29:06 +00:00
Richard Smith 81004c302b Avoid private inheritance in DiagnosticAnnotationScope. (#3719)
The style guide doesn't permit private inheritance, so switch to a
member instead. Keep storing the callable to ensure it lives long
enough, but type-erase it using `function_ref` instead of a hand-rolled
mechanism.
2024-02-22 22:28:37 +00:00
Richard Smith eed33c3b8c Redeclaration support for impl declarations. (#3717)
Maintain a mapping from (self type, constraint) to `ImplId` on the
`Impl` value store so that we can perform redeclaration lookup.
2024-02-22 20:26:36 +00:00
Richard Smith b1850920e4 Add diagnostic for impl as outside a class. (#3716) 2024-02-22 20:01:10 +00:00
Richard Smith 14388fe081 Remove unnecessary pop and re-push of same value. (#3715)
We don't need to do this any more after #3691, but I forgot to remove
it.
2024-02-22 08:19:26 +00:00
CJ Johnson 518e361328 Address TODO to change GenericBindingPattern to CompileTimeBindingPattern (#3713) 2024-02-21 22:09:40 +00:00
Jon Ross-Perkins 03347793cc Switch VariableInitializer order to accommodate GlobalInit (#3708)
This undoes parts of #3515 in order to allow PushGlobalInit to be called
when the initializer is called, instead of at the end of the binding
pattern. The current approach is fragile because supported patterns will
become more complex. We also will likely want similar support in `let`,
which puts the initializer first, so this offers a consistent approach
for both.

[Looking
back](https://discord.com/channels/655572317891461132/655578254970716160/1184237511766179840),
this is more or less the second option in that message, but using the
PeekNextIs to avoid vagueness about what's being popped first.

Note I'm putting in PeekNextIs for what I'm hoping will be a pretty
narrow use-case. I could've added depth arguments to the Peek functions,
but that would've rippled through a number of APIs and it's not clear to
me that this has generic utility. I mean, right now it could just be
PeekNextIsVariableInitializer, since it's only optional in that case.
2024-02-21 22:03:32 +00:00
Jon Ross-Perkins bd0f761842 Add import handling for FunctionDecl (#3703)
This works by creating a faux FunctionDecl in the context of the current
IR, which seems to be working for function calls. Deduced params are
there, but won't really be tested until classes are up and running. Also
I may need to look further at return_slot_id to ensure it's working. But
the basics, I think, are here.

Reorganizes some other ImportRef work from `has_unresolved` that'd
relied on manual calls to a more detection-based `HasUnresolved`
approach that doesn't require as much checking.
2024-02-21 16:44:12 +00:00
josh11bandJosh L b58db50f9b Change alias test so aliased entity is in diagnostic (#3710)
The [intent of this
test](https://github.com/carbon-language/carbon-lang/pull/3701#discussion_r1488717934)
was to have a diagnostic that mentioned an aliased entity.

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2024-02-20 19:21:09 +00:00
Jon Ross-Perkins 4ab42c0712 Fix for MakeUnqualifiedName conflicting with a namespace (#3707)
Unqualified names don't handle scopes the way that typical names do, so
a name conflict with a namespace needs to be handled specially. I'm
still favoring keeping code close as much as possible, particularly
since long-term this syntax will probably shift to be more consistent.
For now I'm just flagging when we shouldn't push scopes, so that
MakeUnqualifiedName doesn't need to clean up.

Note, a different approach would basically be:

```
PushScopeAndStartName
ApplyNameQualifierTo
result = decl_name_stack_.back();
decl_name_stack_.back().state = NameContext::State::Finished;
PopScope
return result;
```

But that approach feels worse to me, due to the additional stack
manipulations and the need to duplicate some of the FinishName logic
just to be able to pop the scope that didn't really need to be added.
2024-02-20 18:43:57 +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 1974e44fd9 Rename factory functions from 'Create' to 'Make' (#3706)
Similar to #3705, we actually have a mix of `Make` and `Create` in
factory functions too, so this PR is normalizing on `Make`. It's
intended to be consistent with the naming choice for Carbon factory
functions.

Note, MakeSyntheticBlock is the only one I feel a little weird about
because llvm's own APIs use Create, and this is essentially wrapping
LLVM calls. But the flipside is it also feels like a vague line to draw,
when we also differ from LLVM coding style in other ways.
2024-02-14 18:26:56 +00:00
czapiga 4873160acc Parse auto type (#3704)
Handles `auto` in `parse` phase.
2024-02-14 17:47:37 +00:00
josh11bandJosh L 0a0f66857d Fix some lingering Expression -> Expr in state.def (#3702)
Original change is #3375 .

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
2024-02-13 23:11:53 +00:00
Jon Ross-Perkins f76bc733f4 Add 'let' handling for ImportRefUsed. (#3700)
- File::StringifyTypeExpr now has a case that hits the ImportRefUsed
TODO, so implementing that. I think the `static` approach will be
helpful in ensuring there aren't access bugs, particularly when future
support is added.

- `let` wasn't adding to exports because it doesn't use
`decl_name_stack` the way `var` does. This now adds to exports, but we
might want to unify logic for issues such as this.

- BuildImportRefUsedValueRepr is now called for another inst kind, and
it seemed like calling back to BuildValueRepr was the best way to
resolve this. I don't *think* that's going to cause recursion.
2024-02-13 00:53:13 +00:00
czapiga 99bc9734d9 Add match parsing (#3664)
Adds `match` parsing to toolchain
2024-02-13 00:27:06 +00:00
Jon Ross-Perkins 57948c63e0 Small cleanup for DiagnosticType (#3697)
I was thinking about #3695 a little further after comments; this is a
small cleanup.
2024-02-09 20:57:19 +00:00
Jon Ross-Perkins 7e7e87056a Add diagnostic support to pass in NameId. (#3696)
Builds on #3695 to provide equivalent support for NameId.
2024-02-09 17:26:03 +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
Gıyaseddin Tanrıkulu bdff7ccf28 Add GlobalInit to blocks to emit initialization instructions for globals (#3687)
`GlobalInit` block is now static block within a `SemIR` which will be
used to emit initialization instructions for variables in the `Package`
scope.

inst_block_stack now has additional methods to handle `GlobalInit` block
separately, this block can be popped without being finalized allowing to
accumulate between all instances of variables.

At the end of the `check` phase, if this block is not empty , the
function `__global_init` will be added with this block being inserted
into it.

This block is pushed to `inst_block_scope` at the end `BindName`,
allowing instruction to be emitted into it, then popped at the semicolon
(VariableDecl).

This significantly changes the `SemIR` output, that's why this commit
updates a lot of the test cases.
2024-02-09 16:21:57 +00:00
Jon Ross-Perkins 475ecca339 Implement constant handling for types of imports. (#3693)
This provides support for Const, Pointer, Struct, and Tuple types. It
does not cover Class, Function, or Interface which have their own Id and
are tracked slightly differently.
2024-02-09 00:11:37 +00:00
Richard Smith 4d0c3811c9 Add a diagnostic for trying to extend an undefined interface. (#3689) 2024-02-06 22:31:49 +00:00
Richard Smith 5ab26072fd Use the DeclNameStack for impl declarations. (#3691)
They don't have names, but using the DeclNameStack anyway keeps our
behavior more consistent, and keeps track of the enclosing name scope
and the prior state of the scope stack for us.

Depends on #3683.
2024-02-06 22:28:31 +00:00
josh11b da34f61ef9 Define and use AnyImplAsId (#3692)
`NodeCategory::ImplAs` was introduced in #3683.
2024-02-06 21:57:44 +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
Richard Smith ead4dbbbe3 Refactor SemIR::InstNamer (#3690)
- Rename `ScopeIndex` to `ScopeId`, because the order is not meaningful.
This avoids collisions with `SemIR::ScopeIndex`.
- Change `GetScopeFor` to use an `if constexpr` chain rather than
duplicating the numbering logic across multiple functions.
- Simplify `GetNameFor`, avoiding multiple identical overloads.

As requested in review of #3683.
2024-02-06 01:56:04 +00:00
Richard Smith fdfb1fb5ef Factor the scope stack and lexical lookups out of Check::Context. (#3688) 2024-02-06 00:59:52 +00:00
Richard Smith c35e0fea64 Tidy up and refactor the node stack. (#3685)
Add a type representing a non-discriminated union of IDs. Refactor the
node stack to use it. Plus a few other refactorings aiming to clean up
and simplify the code. The overall goal here is that adding a new kind
of ID, node category, or instruction should only require changing one
place in the node stack rather than a bunch of different changes.

One minor functionality change: crash backtraces now use the correct
type for IDs when dumping the node stack rather than using `InstID`
printing for all but one case.
2024-02-05 22:07:38 +00:00
Jon Ross-Perkins 7e06b703bf Clean up some redundant name qualifiers. (#3681) 2024-02-02 04:25:50 +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
Jon Ross-Perkins ee467900ed Use llvm:: for specializations instead of 'namespace llvm' (#3682)
We already do this with things like llvm::DenseMapInfo, I don't know why
I was doing this with format_provider. But this should be more
consistent, and slightly better for not entering another library's
namespace.
2024-02-01 22:58:04 +00:00
josh11bandJon Ross-Perkins 03bf22e55e Parse tree for impl that is better for check stage (#3678)
Use two different nodes for "<type> followed by `as`" and "<type>
omitted before `as`, use `self`", so it is easier to determine which
case. Later the second case will push the type id for `self` onto the
node stack, making the two paths more similar.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-02-01 22:23:21 +00:00
Jon Ross-Perkins 134766d50c Refactor File constructors to share logic. (#3675)
I was considering this again while working on #3674, it would be helpful
to share initialization for both regular and builtin File constructors.
2024-02-01 03:32:57 +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
Richard Smith 44fca1669a Keep parameters in scope throughout the entity that they parameterize. (#3671)
Previously, we created scopes for implicit parameter lists and tuple
patterns, but that meant that bindings went out of scope too soon. We
now keep them in scope until the end of the enclosing declaration. This
is accomplished by pushing a scope for parameters when we handle a name
that might have them, and then popping the scope again if it turns out
that there were no parameters.

For a case such as:

```carbon
fn A(T:! type).B(U:! type).F(x: T, y: U) {
  var z: T;
}
```

... we now have the following scopes in the stack:

-   A parameter scope containing `T`.
-   A class scope for `A(T:! type)`.
-   A parameter scope containing `U`.
-   A class scope for `A(T:! type).B(U:! type)`.
-   A parameter scope containing `x: T` and `y: U`.
-   A function body scope containing `z: T`.

The innermost scope when check processes a declaration of a function,
class, or similar is now often a parameter scope rather than the
enclosing scope in which the class or function is declared, so the
target scope is now passed explicitly into the modifier checking code
that wants to inspect that enclosing scope.
2024-01-31 21:40:45 +00:00
Chandler CarruthandJon Ross-Perkins 5e88fe72c9 Switch remaining relational operator overloads to spaceship. (#3668)
This doesn't matter too much as these were expanded by the LLVM iterator
facade, but eventually this should enable that facade to be a little
less fancy and should also simplify the dispatch to directly use the
three-way comparison.

One case is a bit subtle and didn't have a comment so I added one to
explain a bit what is going on there.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-01-31 03:29:02 +00:00
Chandler CarruthandJon Ross-Perkins 1529538ad2 Use concepts and better comparisons from C++20 in IndexBase. (#3666)
This is one of the nicer improvements to boiler-plate as we benefit from
concepts simplifying the constraints on the templates, defaulted `!=`
finding `==`, and the `<=>` operator for a single definition of all
relational operators.

I've checked and the `!=` usages do seem to be effective at finding the
`==` definitions, but we still need both the RHS- and LHS-based
overloads of `==` as far as I can tell.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-01-31 02:47:34 +00:00
Jon Ross-Perkins e583493e9f Implement some basic ImportRef handling for builtins. (#3663)
I'm basically just nudging down the path I think is right here. Adding a
small bit more support, but also more tests to capture cases that I
think will need to be verified as working.

With diagnostics like "Value of type `<function>` is not callable.",
that's because it expects a FunctionDecl but is instead finding a
ImportRefUsed. I'll need to work out the necessary support for a
callable function.
2024-01-30 17:38:38 +00:00
Richard SmithandChandler Carruth 3fa70de101 Remove some C++17 workarounds now we build in C++20 mode. (#3653)
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2024-01-30 02:19:38 +00:00
Jon Ross-Perkins 7f11012f58 CrossRefIRId -> ImportIRId (#3662)
One more (hopefully last) rename on the Import instruction renaming.

I was kind of tempted to rename to just "IRId", since the IRs aren't all
imports. However, this felt easier to read, and a better choice than
CrossRef because it's more consistent with the other ways imports exist
in code. (even if IRs aren't all imports, most use-cases are derived
from imports)

Note though that import_irs may include IRs not just from direct
imports. Beyond the builtin IR, I'm thinking that for indirect imports,
or the prelude, we may end up adding them. e.g., so that constants can
be generated for indirect imports and still correspond to a directly
known IR, and for a given IR that's indirectly imported multiple times
to be deduplicated locally. I'm not there yet, I'm just mentioning this
to help give background for naming thoughts.
2024-01-29 23:05:47 +00:00
Chandler Carruth bf02d1f4b0 Remove headers marked as unused by ClangD. (#3661)
This required adding a few headers that were found transitively before,
but not too many. This is sadly a fairly manual process of opening every
file in my IDE, but I think I got everything in `//common` and
`//toolchain`.

There are a few cases where technically we don't need `foo.h` to be
included into `foo.cpp`, but I've forced those to stay with a pragma.

I've tried to catch the places where we can cut deps in Bazel as well,
but not sure I got all of those.

I had been noticing these in other PRs and it seemed better to isolate
the change.
2024-01-29 16:15:35 +00:00
josh11bandRichard Smith afd7115c0e Support determining IdKind from NodeCategory, in addition to NodeKind (#3648)
The categories `Expr`, `MemberName`, `Decl`, `Statement`, and `Modifier`
are usable since they are associated with a consistent `IdKind`. The
mapping to `IdKind` for NodeKinds that have those categories are no
longer listed explicitly, ensuring that the `NodeCategory` mapping is
the source of truth.

Also: fixes the category of the `FunctionDefinitionStart` and
`ArrayExprStart` node kinds.

Note: I've added [a section on defining constexpr constants to the
Toolchain architecture
doc](https://docs.google.com/document/d/1RRYMm42osyqhI2LyjrjockYCutQ5dOf8Abu50kTrkX0/edit?resourcekey=0-kHyqOESbOHmzZphUbtLrTw&tab=t.0#heading=h.f7682a2tpvxr).

FUTURE:

* We should switch `TuplePattern` to put an `InstId` on the `NodeStack`
instead of an `InstBlockId`, so we can handle the pattern category.
* We should make a category for names to replace uses of the `NameId`
`IdKind`.
* We should make use of these new APIs more, and propagate more-precise
types through the codebase.

QUESTION: Should I use a different approach for determining the number
of members of the `NodeKind` enum?

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-01-27 01:04:01 +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