Skip to content

Conversation

zygoloid
Copy link
Contributor

@zygoloid zygoloid commented Aug 8, 2024

This avoids import cycles, and reduces the number of temporary vectors we build (and potentially throw away on retry). Import the self specific when importing a generic, now that there's no risk that will introduce cycles.

Note that we could take the same approach to import classes, interfaces, and so on, instead of the current third phase of resolution for those instructions, but in this PR I'm just addressing the import cycle I'm currently seeing in a work-in-progress PR.

specifics until we've finished other resolution work.

This avoids import cycles, and reduces the amount of temporary vectors
we build before retrying.

Import the self specific when importing a generic, now that doing so
doesn't introduce cycles.
Copy link
Contributor

@jonmeow jonmeow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG, just a few minor things that had me looking closer. Per separate discussion, I'd also missed in the PR description the mention that Self is now imported, explaining the test changes.

@@ -1811,6 +1798,106 @@ class ImportRefResolver {
.element_type_id = context_.GetTypeIdForTypeConstant(elem_const_id)});
}

// Perform any work that we deferred until the end of the main Resolve loop.
auto PerformPendingWork() -> void {
while (!pending_generics_.empty() || !pending_specifics_.empty()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is weird, can you comment it. :)

Comment on lines 1852 to 1864
auto* local_generic = &context_.generics().Get(pending.local_id);
local_generic->decl_block_id = decl_block_id;

auto self_specific_id = MakeSelfSpecific(context_, pending.local_id);
local_generic->self_specific_id = self_specific_id;
pending_specifics_.push_back({.import_id = import_generic.self_specific_id,
.local_id = self_specific_id});

auto definition_block_id =
ResolveLocalEvalBlock(import_generic, pending.local_id,
SemIR::GenericInstIndex::Region::Definition);
local_generic = &context_.generics().Get(pending.local_id);
local_generic->definition_block_id = definition_block_id;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of a pointer (and reassignment) looked a little odd to me, maybe:

Suggested change
auto* local_generic = &context_.generics().Get(pending.local_id);
local_generic->decl_block_id = decl_block_id;
auto self_specific_id = MakeSelfSpecific(context_, pending.local_id);
local_generic->self_specific_id = self_specific_id;
pending_specifics_.push_back({.import_id = import_generic.self_specific_id,
.local_id = self_specific_id});
auto definition_block_id =
ResolveLocalEvalBlock(import_generic, pending.local_id,
SemIR::GenericInstIndex::Region::Definition);
local_generic = &context_.generics().Get(pending.local_id);
local_generic->definition_block_id = definition_block_id;
auto& local_generic = context_.generics().Get(pending.local_id);
local_generic.decl_block_id = decl_block_id;
auto self_specific_id = MakeSelfSpecific(context_, pending.local_id);
local_generic.self_specific_id = self_specific_id;
pending_specifics_.push_back({.import_id = import_generic.self_specific_id,
.local_id = self_specific_id});
// This may invalidate local_generic.
auto definition_block_id =
ResolveLocalEvalBlock(import_generic, pending.local_id,
SemIR::GenericInstIndex::Region::Definition);
context_.generics().Get(pending.local_id).definition_block_id = definition_block_id;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started with something like this, but it seemed error-prone to me and harder to systematically get right. Changed to a different approach, what do you think?

Comment on lines 1896 to 1897
local_specific = &context_.specifics().Get(pending.local_id);
local_specific->definition_block_id = definition_block_id;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the above, I'd suggest only reusing the same variable when it's significant (which for line 1892, it is, but that doesn't look true here).

Suggested change
local_specific = &context_.specifics().Get(pending.local_id);
local_specific->definition_block_id = definition_block_id;
context_.specifics().Get(pending.local_id).definition_block_id = definition_block_id;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, suggesting this mainly because I find it easier to figure out what the source is when it's assigned in fewer places.

Comment on lines 1849 to 1853
// Don't store this between calls: the generics list can be reallocated by
// ResolveLocalEvalBlock importing more generics.
auto local_generic = [&]() -> auto& {
return context_.generics().Get(pending.local_id);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe move onto the type as a function, so calls look like pending.Get(context)? (lambdas always make me hesitant)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not, discussed offline, just inlining the fetches

@zygoloid zygoloid added this pull request to the merge queue Aug 9, 2024
Merged via the queue into carbon-language:trunk with commit b2a13af Aug 9, 2024
7 checks passed
@zygoloid zygoloid deleted the toolchain-defer-import branch August 9, 2024 00:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants