Skip to content

fix: avoid flow replay for unrelated call conditions#1101

Merged
CppCXY merged 1 commit into
EmmyLuaLs:mainfrom
lewis6991:issue1100
Jun 8, 2026
Merged

fix: avoid flow replay for unrelated call conditions#1101
CppCXY merged 1 commit into
EmmyLuaLs:mainfrom
lewis6991:issue1100

Conversation

@lewis6991

Copy link
Copy Markdown
Collaborator

Problem

Repeated unrelated call conditions like if enabled(...) then could make condition flow replay the call's expression type against prior flow for every branch. Large generated highlight tables then spent too much time repeatedly re-inferring unrelated table field reads.

Solution

When a call condition does not narrow the queried ref, infer the call without flow and only use the result to reject impossible branches. The existing flow-aware call paths still handle calls that narrow the queried ref, such as type guards and return casts.

Tests

  • cargo test -p emmylua_code_analysis
  • cargo test -p emmylua_code_analysis flow
  • cargo fmt --all --check
  • git diff --check

@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

Changes Overview

This PR modifies the condition flow inference logic in the Lua type checker, specifically handling call expressions in condition contexts. It replaces the Truthiness continuation pattern with direct inline inference using try_infer_expr_no_flow.

Issues Found

  1. Potential Performance Regression 🔴

    • The new code calls try_infer_expr_no_flow for every call expression encountered in condition flow, even when the result may not be needed. The old approach deferred this computation via the Truthiness continuation.
    • Recommendation: Consider adding a quick pre-check (e.g., checking if the call expression has side effects or is a known pure function) before invoking the full inference.
  2. Missing Error Handling for try_infer_expr_no_flow ⚠️

    • The match statement handles Ok(Some(...)) and _ cases, but try_infer_expr_no_flow could return Ok(None) which falls through to ConditionFlowAction::Continue. This might hide legitimate inference failures.
    • Recommendation: Log or track cases where try_infer_expr_no_flow returns Ok(None) to aid debugging.
  3. Redundant is_never() Check 🟡

    • The first arm checks expr_type.is_never() and returns LuaType::Never. However, the subsequent arms for is_always_falsy() and is_always_truthy() would also catch Never types (since Never is typically both falsy and truthy). This creates dead code.
    • Recommendation: Remove the first arm or add a comment explaining why it's necessary (e.g., if Never doesn't satisfy is_always_falsy() in your type system).
  4. Test Coverage Gap 🟡

    • The test only verifies the happy path (successful inference). It doesn't test edge cases like:
      • Call expressions that return never
      • Call expressions with side effects
      • Nested condition flows with multiple call expressions
    • Recommendation: Add more comprehensive tests covering these scenarios.
  5. Code Duplication 🟡

    • The logic for checking is_never(), is_always_falsy(), and is_always_truthy() is duplicated between the new inline code and the removed Truthiness continuation handler.
    • Recommendation: Extract this logic into a helper function to improve maintainability.

Positive Aspects

  • ✅ The change simplifies the control flow by removing the Truthiness continuation variant
  • ✅ The test is well-structured and includes a timeout to prevent infinite loops
  • ✅ The constant ISSUE_1100_HIGHLIGHT_GROUPS makes the test configurable

Security Considerations

  • No security vulnerabilities identified in this change

Overall Assessment

The change is functionally correct but introduces potential performance concerns and code duplication. Consider optimizing the call to try_infer_expr_no_flow and consolidating the repeated type-checking logic.

@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 optimizes type inference in condition flows by avoiding flow-aware replays for call expressions that do not narrow the reference. Instead, it evaluates call expressions directly using try_infer_expr_no_flow and handles unreachable branches accordingly. A test case for issue 1100 has been added to verify performance and correctness. Feedback suggests refactoring the new match statement in get_type_at_condition_flow to reduce repetition and improve readability.

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.

When a call condition does not narrow the queried ref, infer the call
without flow and only use it to reject impossible branches.

This avoids recursively replaying previous flow for every unrelated call
condition while preserving the flow-aware paths that perform narrowing.

Fixes EmmyLuaLs#1100

Assisted-by: Codex
@CppCXY CppCXY merged commit dd3d904 into EmmyLuaLs:main Jun 8, 2026
16 checks passed
@lewis6991 lewis6991 deleted the issue1100 branch June 8, 2026 12:45
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.

2 participants