Skip to content

fix: stop flow inference from hanging on large self-assignments#1116

Open
lewis6991 wants to merge 1 commit into
EmmyLuaLs:mainfrom
lewis6991:flow-budget-fallback
Open

fix: stop flow inference from hanging on large self-assignments#1116
lewis6991 wants to merge 1 commit into
EmmyLuaLs:mainfrom
lewis6991:flow-budget-fallback

Conversation

@lewis6991

Copy link
Copy Markdown
Collaborator

Problem

  • Repeated self-dependent assignments can make flow inference spend too long in a single query.
  • The issue is not limited to concat; similar repeated arithmetic or comparison assignments can hit the same path.
  • When this happens, semantic model construction can stall.

Solution

  • Add a per-flow-query step budget to the iterative flow scheduler.
  • When the budget is exceeded, log a warning, clear in-progress flow cache guards, cache unknown for active/pending queries, and keep analysis moving.
  • Add an internal development/test option to disable the fallback when a runaway query needs to be reproduced.

Tests

  • cargo test -p emmylua_code_analysis test_issue_1114_repeated_self_dependent_assignments_build_semantic_model -- --nocapture
  • cargo test -p emmylua_code_analysis flow
  • cargo fmt --all --check
  • git -c core.fsmonitor=false diff --check

Fixes #1114

Log a warning and return unknown when a single flow query exceeds the step
budget. This keeps semantic model construction moving for pathological repeated
assignments while preserving normal flow precision.

Add a development/test switch that can turn the fallback off when a runaway
flow query needs to be reproduced.

Fixes EmmyLuaLs#1114
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.

Here's my code review of the changes:

Issues Found:

1. Potential Logic Error: cache_options field not used in get_infer_cache

  • File: infer_cache_manager.rs
  • Issue: The cache_options field is stored but only analysis_phase is being modified. Other fields in CacheOptions (like disable_flow_inference_step_budget) are being overridden/ignored.
  • Suggestion: Either use the full cache_options or document why only analysis_phase needs to be overridden.

2. Missing Clone implementation for CacheOptions

  • File: cache_options.rs
  • Issue: CacheOptions is Clone + Copy but LuaAnalysisPhase is only Clone + Copy. This is fine, but ensure all consumers expect this behavior.
  • Suggestion: Verify that no code depends on CacheOptions being mutable after creation.

3. Potential Performance Issue: Cloning cache_options on every cache access

  • File: infer_cache_manager.rs line 22
  • Issue: let mut cache_options = self.cache_options; creates a copy on every cache lookup, which is unnecessary since it's Copy.
  • Suggestion: Use self.cache_options directly or reference it without copying.

4. Inconsistent Budget Handling

  • File: get_type_at_flow.rs
  • Issue: The budget check in evaluate_walk returns ContinueWalk without consuming a step, while start_query consumes a step. This could lead to inconsistent budget tracking.
  • Suggestion: Ensure step consumption is consistent across all code paths.

5. Missing Error Handling for Budget Exhaustion

  • File: get_type_at_flow.rs
  • Issue: When budget is exhausted, the function returns LuaType::Unknown silently (except for a warning log). This could mask real issues.
  • Suggestion: Consider returning a more specific error type or adding a metric/counter for budget exhaustion events.

6. Test Coverage Gap

  • File: flow.rs
  • Issue: The test only checks if get_semantic_model returns Some, not the actual type inference results.
  • Suggestion: Add assertions to verify the inferred types are correct (e.g., string, number, boolean).

Recommendations:

  1. Document the budget constant - Add a comment explaining why 50_000 was chosen and how to tune it.

  2. Consider making budget configurable - The disable_flow_inference_step_budget flag is good for debugging, but consider making the budget value configurable too.

  3. Add budget exhaustion metrics - Track how often the budget is exceeded to help tune the constant.

  4. Review thread safety - Ensure CacheOptions being Copy doesn't cause issues in concurrent scenarios.

Overall, the changes look well-structured and address the performance issue with flow inference. The budget mechanism is a good addition to prevent infinite loops or excessive computation.

@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 introduces a step budget (FLOW_INFERENCE_STEP_BUDGET) for flow inference queries to prevent semantic model construction from stalling on complex or deeply nested self-dependent assignments. It propagates CacheOptions through the analysis pipeline to allow disabling this budget during testing, and adds a regression test for issue 1114. I have no feedback to provide as there are no review comments to address.

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.

@lewis6991

Copy link
Copy Markdown
Collaborator Author

This is a more general mitigation for issues like #1114 , it loses precision but avoids flow getting stuck. #1115 is more specific solution for #1114 that doesn't lose precision.

I'm not 100% sure about this. It improves user experience, but will mask issues in the flow engine. I added a flag so we can at least disable this for tests.

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.

Stuck loading

1 participant