Skip to content

Don't keep insts in eval block from failed deduce #5601

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: trunk
Choose a base branch
from

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
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