Skip to content

Conversation

danakj
Copy link
Contributor

@danakj danakj commented Jun 3, 2025

Deduction does SubstConstant() to apply enclosing specifics, and deduced arguments, to the arguments. This process creates new instructions with the applied substitutions, which may include LookupImplWitness. If the conversion fails, those instructions will not be used, but they have been added to the enclosing generic when there is one. This leaves behind a LookupImplWitness instruction with a runtime constant value as a dependent instruction and in the eval block. When the generic's eval block is re-evaluated later, the LookupImplWitness instruction fails to produce a constant value (again), which violates its contract and we crash.

To avoid this, we scope the SubstConstant and Convert steps in deduce with a "commit" for the generic stack. If the conversion fails, we drop all instructions created by SubstConstant and Convert from the enclosing generic context. Such instructions must not be referred to again, but they will not be as they are not stored anywhere or returned if Convert failed.

This fixes the crash demonstrated in https://carbon.godbolt.org/z/1EjMroT6e

@github-actions github-actions bot requested a review from chandlerc June 3, 2025 20:07
@danakj danakj requested a review from zygoloid June 3, 2025 20:07
@danakj danakj changed the title Dont keep insts in eval block from failed deduce Don't keep insts in eval block from failed deduce Jun 3, 2025
@danakj
Copy link
Contributor Author

danakj commented Jun 3, 2025

This is based on #5597, in order to place the tests together. The changes are in related code but it's not strictly dependent on the former PR.

Comment on lines +74 to +79
if (stack_) {
stack_->dependent_inst_stack_.PopArray();
stack_->pending_eval_block_stack_.PopArray();
stack_->ongoing_commit_ = false;
stack_ = nullptr;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we'll need to do something with the ConstantsInGenericMap too -- either removing the entries from there corresponding to the things we removed from the eval block, or re-adding the items in that map back into the eval block if they're referenced again.

Specifically, if a generic references constant X during a transaction that gets reverted, and then later references the constant X again, if it's still in the ConstantsInGenericMap then I think we won't re-add it to the eval block, but we presumably need to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is much more tricky, and the immediate crash is solved, so I am going to mark this WIP to come back to.

@danakj danakj marked this pull request as draft June 4, 2025 13:44
@danakj danakj removed the request for review from chandlerc June 4, 2025 13:45
Copy link

github-actions bot commented Sep 3, 2025

We triage inactive PRs and issues in order to make it easier to find active work. If this PR should remain active, please comment or remove the inactive label.

This PR is labeled inactive because the last activity was over 90 days ago. This PR will be closed and archived after 14 additional days without activity.

@github-actions github-actions bot added the inactive Issues and PRs which have been inactive for at least 90 days. label Sep 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
inactive Issues and PRs which have been inactive for at least 90 days. toolchain
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants