Skip to content

fix: handle semantic flow edge cases#1086

Open
lewis6991 wants to merge 6 commits into
EmmyLuaLs:mainfrom
lewis6991:fix/small-flow-fixes
Open

fix: handle semantic flow edge cases#1086
lewis6991 wants to merge 6 commits into
EmmyLuaLs:mainfrom
lewis6991:fix/small-flow-fixes

Conversation

@lewis6991
Copy link
Copy Markdown
Collaborator

Problem:

  • Several semantic-flow edge cases produced false diagnostics or imprecise types.
  • The fixes cover union array keys, empty generic varargs, non-terminating return paths, guarded pcall callbacks, and call-condition replay.

Solution:

  • Keep the fixes split into focused commits with targeted regressions.
  • Tighten flow replay and branch narrowing where the existing model already had the right seam.

Testing:

  • cargo test -p emmylua_code_analysis

lewis6991 added 6 commits May 14, 2026 11:17
Use key type compatibility for dynamic array indexes so integer and numeric
union aliases behave like their base key domains. This keeps undefined-field
diagnostics quiet for valid array access and preserves strict array fallback
inference.

Assisted-by: Codex
Bind exhausted generic vararg templates to an empty sequence instead of one
nil slot. This keeps calls like assert(value) from looking like they return an
extra value when no varargs were passed.

Assisted-by: Codex
Treat functions as satisfying @return when every reachable path either returns
or cannot terminate. Only report missing-return when a path can leave the
function body without returning.

Assisted-by: Codex
Allow callable return inference to run with empty forwarded args, and
infer forwarded call arguments through the no-flow table-literal overlay
when matching generic callback parameters.

This lets guarded pcall-style helpers infer callback results for
zero-arg, forwarded-arg, and direct table-literal calls without
retaining the non-callable union member.

Assisted-by: Codex
Flow RHS replay only walked direct LuaExpr children, so call arguments
hidden under LuaCallArgList missed flow-aware overlays. That made
assignments like a = assert(arr[i]) lose the narrowed index type and
report table return fields as nil.

Assisted-by: Codex
Replay call condition result types when the call itself does not narrow the
queried variable, so always truthy/falsy returns can remove unreachable
condition branches.

Assisted-by: Codex
@github-actions
Copy link
Copy Markdown

Code Review Summary

Changes Overview

This PR modifies the return type of analyze_func_body_missing_return_flags_with from (bool, bool, bool) to (bool, bool), removing the is_infinite flag. It also includes several test additions and semantic inference improvements.

Issues Found

1. Inconsistent Function Signature Across Files

  • Problem: The function analyze_func_body_missing_return_flags_with is defined in three files (func_body.rs, mod.rs, compilation/mod.rs) with identical signatures. This violates DRY principle and creates maintenance burden.
  • Suggestion: Consider consolidating to a single definition or using a re-export pattern.

2. Potential Logic Regression in check_return_count.rs

  • Problem: The condition !can_fall_through && !can_break replaces the previous !can_fall_through && !can_break && !is_infinite. This may cause false positives for functions that are truly infinite but not detected by can_fall_through or can_break.
  • Suggestion: Verify that the removal of is_infinite doesn't miss cases where a function has no return path but isn't captured by the remaining two flags.

3. Test Assertion Change in check_return_count_test.rs

  • Problem: Line 309 changes assert!(!ws.has_no_diagnostic(...)) to assert!(ws.has_no_diagnostic(...)) for MissingReturn diagnostic. This is a significant behavioral change that should be documented.
  • Suggestion: Add a comment explaining why this test expectation changed.

4. New Function infer_call_arg_type Logic

  • Problem: The condition !cache.is_no_flow() || !matches!(&arg_expr, LuaExpr::TableExpr(_)) is complex and may be error-prone. The double negative makes it hard to understand.
  • Suggestion: Simplify to: if cache.is_no_flow() && matches!(&arg_expr, LuaExpr::TableExpr(_)) { ... } else { infer_expr(...) }

5. Potential Performance Impact

  • Problem: The new key_type_matches function in infer_array.rs calls check_type_compact which may be expensive for frequently accessed array indices.
  • Suggestion: Consider caching results or adding a fast-path for common integer types before calling check_type_compact.

6. Missing Error Handling in infer_call_arg_type

  • Problem: The function returns InferResult but doesn't handle the case where infer_expr returns an error after with_replay_overlay.
  • Suggestion: Add proper error propagation or fallback.

Positive Aspects

  • ✅ Comprehensive test coverage for new functionality
  • ✅ Clear separation of concerns in the ExprTypeContinuation::Truthiness variant
  • ✅ Good documentation of the MissingReturn logic change in comments

Recommendations

  1. Add a changelog entry explaining the behavioral change in MissingReturn diagnostic
  2. Consider adding integration tests for edge cases where is_infinite was previously required
  3. Document the rationale for removing is_infinite from the return tuple

Copy link
Copy Markdown
Contributor

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

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 refactors the function body analysis by removing the is_infinite flag from return flag tracking, simplifying the logic for detecting missing return statements. It also improves type inference for pcall return values, array indexing with integer literal unions, and variadic generic parameters, specifically handling empty vararg sequences more accurately. Additionally, the PR enhances flow-sensitive type narrowing for call expressions and adds comprehensive test cases for these scenarios. I have no feedback to provide as there were no review comments.

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.

1 participant