Skip to content

fix(flow): preserve self-assignment antecedent types#1182

Open
lewis6991 wants to merge 1 commit into
EmmyLuaLs:mainfrom
lewis6991:codex/issue-1180-self-assignment-flow
Open

fix(flow): preserve self-assignment antecedent types#1182
lewis6991 wants to merge 1 commit into
EmmyLuaLs:mainfrom
lewis6991:codex/issue-1180-self-assignment-flow

Conversation

@lewis6991

Copy link
Copy Markdown
Collaborator

Problem

Self-dependent assignments replaced the RHS read with unknown to avoid
recursive replay. For expressions such as index = index - 1, this discarded
the pre-assignment integer type and widened the result to number.

Solution

  • resolve unavoidable self-reads through the iterative flow scheduler
  • distinguish variable versions by both VarRefId and FlowId
  • preserve linear repeated-assignment replay without bypassing skippable index
    dependencies
  • remove the unknown injection and its and/or exception

Tests

  • cargo test -p emmylua_code_analysis issue_1180
  • cargo test -p emmylua_code_analysis test_issue_1114_repeated_self_dependent_assignments_build_semantic_model
  • cargo test -p emmylua_code_analysis test_issue_1116_generic_call_index_replay_builds_semantic_model
  • cargo test -p emmylua_code_analysis (1,079 tests)
  • cargo fmt --all --check
  • git diff upstream/main...HEAD --check

Fixes #1180

Resolve self-dependent assignment reads through the flow scheduler instead of
injecting unknown. Hoist only unavoidable self reads so repeated replay stays
linear without bypassing skippable index dependencies.

Add regressions for the minimal assignment and original while-loop cases.

Fixes EmmyLuaLs#1180

Assisted-by: Codex

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Summary

Issues Identified:

  1. Logic Error in has_unskippable_dependency method

    • The method iterates through dependencies but only checks if query.var_ref_id == *var_ref_id && query.flow_id == flow_id. This doesn't account for the case where the same variable appears at different flow IDs, potentially causing false positives.
    • Recommendation: Add a check to ensure the dependency is actually a self-reference (i.e., the variable being assigned to itself) before returning true.
  2. Potential Infinite Loop Risk

    • The AssignmentSelfAntecedent continuation creates a recursive pattern where resolving a self-assignment could trigger another self-assignment resolution, potentially leading to infinite recursion.
    • Recommendation: Add a recursion depth counter or visited set to prevent infinite loops.
  3. Missing Error Handling for has_unskippable_dependency

    • If has_unskippable_dependency returns true but the antecedent type resolution fails, the error handling in resume_assignment_self_antecedent could leave the system in an inconsistent state.
    • Recommendation: Add proper cleanup or fallback logic when antecedent resolution fails.
  4. Removed contains_short_circuit_binary_expr Function

    • The function was removed without replacement. This function was previously used to handle and/or operators specially. The new logic might not correctly handle short-circuit operators.
    • Recommendation: Verify that short-circuit operators are still handled correctly in the new implementation.
  5. Test Coverage Gap

    • The new tests only cover basic integer self-assignment cases. Missing edge cases:
      • Self-assignment with short-circuit operators
      • Nested self-assignments
      • Self-assignment in different scopes
    • Recommendation: Add more comprehensive test cases.

Suggestions for Improvement:

  1. Add documentation explaining the new AssignmentSelfAntecedent continuation and its purpose.

  2. Consider performance impact: The new logic adds additional queries for self-assignments. Profile to ensure no significant performance regression.

  3. Simplify has_unskippable_dependency: The current implementation is complex. Consider using a simpler approach like checking if the variable appears in the RHS expression directly.

  4. Add defensive checks: In resume_assignment_self_antecedent, verify that the resolved antecedent type is compatible with expected types before proceeding.

Overall Assessment:

The changes address the issue of self-assignment type inference but introduce complexity and potential edge cases. The core logic appears sound but needs better error handling and more comprehensive testing.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request resolves issue #1180 by improving the type inference of self-dependent assignments (such as index = index - 1) during flow analysis. Instead of defaulting self-reads in RHS expressions to Unknown, the engine now queries the variable's pre-assignment (antecedent) type first and resumes the RHS replay once that type is resolved. This is implemented via a new Continuation::AssignmentSelfAntecedent variant, the has_unskippable_dependency helper, and corresponding engine methods. Unit tests have been added to verify that self-assignments and loops correctly preserve and replay their antecedent types. No review comments were provided, and I have no additional feedback to offer.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@xuhuanzy

xuhuanzy commented Jul 16, 2026

Copy link
Copy Markdown
Member

I think you can also take a look at this #1178
This issue is related to it.

@lewis6991

lewis6991 commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks, I checked #1178. This PR fixes the original example: position remains a Vector after the self-assignment, so v = position should not report an error.

The other example in the comments still fails, but it does not involve self-assignment and looks like a separate custom-operator issue. I think that should be handled separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flow analysis breaks the integer property of the index after assignment.

2 participants