Commit Graph
14 Commits
Author SHA1 Message Date
Jon Ross-Perkins 5c567b892d Address invalid redeclaration and definitions across imports. (#3842)
Note, there's still a TODO "Allow non-extern declarations in the same
library."
2024-04-02 18:01:25 +00:00
Jon Ross-Perkins dffe4a36de When merging functions, detect uses of imports prior to a redecl. (#3836)
LookupNameInDecl is only called from DeclNameStack, but I'm adding
mark_imports_used there because it feels more consistent. Not sure if we
want a better API boundary. I admit I'm also suspicious of its call to
LookupInCurrentScope but maybe it's okay due to how imports work.

I was choosing to print multiple diagnostics when a declaration is
previously used _and_ doesn't match because I think the "previously
used" is more important, but the "doesn't match" may give an additional
hint about why it didn't work.

The merge.h utility function is because I think we can follow a similar
model for identifying errors with other declarations: classes,
interfaces, etc.
2024-04-02 17:44:55 +00:00
Jon Ross-Perkins f8c8861e5f Change ImportRef to a triple state: Unloaded, Loaded, Used (#3831)
This doesn't significantly change logic, although I'm trying to add the
location to used state.

The issue I'm trying to address is how to identify a declaration as
"allowed to be redeclared". Consider:

```
library "a" api;
extern fn F();
```
```
library "b" api;
extern fn F();
```
```
library "c" api;
import library "a";
import library "b";
var x: auto = F();
fn F();
```

What currently happens is:

1. On import of "a", `F` becomes ImportRefUnused
2. On import of "b", `F` becomes ImportRefUsed in order to merge.
3. In "c", the call `F()` doesn't change the state.
4. In "c", the declaration `fn F();` needs some breadcrumb to understand
whether "F" has been referenced, as in step (3) here.

What I want to happen is:

1. On import of "a", `F` becomes ImportRefUnloaded
2. On import of "b", `F` becomes ImportRefLoaded in order to merge.
3. In "c", the call `F()` causes `F` to become ImportRefUsed
4. In "c", the declaration `fn F();` detects that `F` is already
ImportRefUsed, and can use the associated `used_id` for a diagnostic
about why redeclaring is invalid.

Note this PR isn't implementing (4). I'm focused on the refactoring to
add a new ImportRef state here.
2024-04-02 17:20:09 +00:00
Jon Ross-Perkins 0001f53ec1 Implement merging of conflicts found during import. (#3819)
Note we only identify conflicts between libraries in the current package
during import.

This restructures the BUILD because of dependency cycles between cpp
files... We're going to need context's name lookup to handle things such
as merging, merging requires function logic, function logic requires
context access. Per discussion, going with a single large cc_library for
now rather than trying to split out small libraries.

I'm envisioning the new merge.* as a hub for cross-declaration merge
logic. Note function.cpp is already pretty sizable, and I think it may
lean a little function-specific even if there are some utilities that
could be split out.
2024-03-27 23:38:10 +00:00
Jon Ross-Perkins a79027120a Start adding extern logic for functions. (#3809)
This starts propagating is_extern on import, and warns when merging an
imported non-extern declaration with a local non-extern declaration.
Note this doesn't address import conflicts yet (i.e., two libraries
define an equivalent name) because they don't call merge logic.

On merge, I'm only setting values when new_is_definition because I think
it better matches the comment and resulting behavior. Note I now set
them even for bad redefinitions; I think this matches the comment, and
there's not a perfect choice here. I could change the flow back if
preferred.

Note this puts a spotlight on invalid nodes on imported decls, which I
think I'm going to need to address now. This isn't addressed by
ImportRef logic directly because the Function's decl_id is a
FunctionDecl, rather than the ImportRef that led to it. While I could
add the ImportRef link to each decl, I think adjusting the associated
NodeId is a better approach.
2024-03-27 22:40:28 +00:00
Jon Ross-PerkinsandChandler Carruth 15932ac990 Start filling in extern support on functions. (#3795)
Still needs more merge/redeclaration logic for import semantics, but
this felt like a reasonable point to send a PR.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2024-03-19 17:40:13 +00:00
Richard Smith 064123d93f If a SemIR instruction has a braced block and a constant value, print the constant value first. (#3734) 2024-02-29 23:51:32 +00:00
Richard Smith 5543602a50 Make namespace formatting more consistent with other declaration block instructions. (#3732)
List names vertically rather than horizontally.
2024-02-28 22:20:37 +00:00
Richard Smith 5f4e6c768a Format the decl block for a declaration as a trailing block. (#3731)
Previously we used the default inst block formatting, which writes out a
parenthesized list of references, which would always be 'unexpected
instref's because nothing else prints the instructions in the decl
block.

In addition, track the decl block for function declarations like we do
for other kinds of declaration. This means that the parameter
declarations for a function are now properly rendered into the formatted
IR. Note that this adds a lot of verbosity to `function_decl`, but it
does accurately reflect the IR, and we'll probably want this information
to be printed once we start supporting more complex generic function
declarations.

This removes almost all the 'unexpected instref's in our formatted
output. There are remaining cases when a declarative scope contains
multiple blocks, where we only track one of those blocks. That happens
when there is control flow within declarative scopes, and for error
recovery when a class or interface or similar is defined more than once.

As requested in #3730.
2024-02-28 21:28:59 +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
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
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
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
Jon Ross-Perkins f4a741903f Add import support for remaining decl types. (#3651)
I'd excluded these initially just because I was thinking towards copies,
but under the current model I'm trying to catch all the decl types just
for consistency. Note references will still be a TODO error
(LazyImportRef is already tested for this, it just didn't feel necessary
to add individual tests while I try to sort out behavior).

Fixes an oversight where declarations in an entity's scope were being
added to the list of exports.

Note I'm trimming some Import API arguments as now-unused.
2024-01-25 18:19:22 +00:00