Skip to content

fix(infer): infer integer lengths and guarded last elements - #1311

Open
lewis6991 wants to merge 1 commit into
EmmyLuaLs:mainfrom
lewis6991:rewrite-length-inference
Open

lewis6991 wants to merge 1 commit into
EmmyLuaLs:mainfrom
lewis6991:rewrite-length-inference

Conversation

@lewis6991

@lewis6991 lewis6991 commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Infer integer for built-in string and table lengths through aliases and unions. Preserve custom len operators and the existing fallback for invalid or unresolved operands.

Allow a nonempty guard to prove that a[#a] has the array's element type:

---@type string[]
local a = {'first'}
if not a[1] then return end
local last = a[#a] -- string

Limit this proof to direct local table literals with no writes, aliases, captures, or escapes anywhere in the function. A guard must hold on every incoming path.

Correct existing constant-index inference so an upper bound alone does not prove an element exists:

if #a <= 1 then local first = a[1] end -- string|nil
if #a == 1 then local first = a[1] end -- string

Keep equality as a lower-bound proof and handle reversed length comparisons under the same rules.

Related to #886.

@lewis6991
lewis6991 force-pushed the rewrite-length-inference branch from 9586aca to c94888d Compare October 19, 2026 20:03
@lewis6991 lewis6991 changed the title fix(infer): restore length types and guarded array reads fix(infer): improve array length checking Oct 19, 2026
@lewis6991
lewis6991 force-pushed the rewrite-length-inference branch from c94888d to c7b0ccc Compare October 20, 2026 09:59
@lewis6991
lewis6991 marked this pull request as draft October 20, 2026 14:25
Built-in length expressions can keep the operand type. Infer integer for
strings and tables, including aliases and unions. Preserve custom length
operators and the existing fallback for invalid or unresolved operands.

Narrow a[#a] to the element type after a nonempty guard on every path:

    ---@type string[]
    local a = {'first'}
    if not a[1] then return end
    local last = a[#a] -- string

Limit the proof to direct local tables with no writes, aliases, captures
or escapes anywhere in the function. Check all references once and reuse
the existing flow graph to keep the proof independent of call effects.

Correct constant-index inference so upper bounds keep nil:

    if #a <= 1 then local first = a[1] end -- string|nil

Keep equality as a lower-bound proof and handle reversed comparisons.
@lewis6991
lewis6991 force-pushed the rewrite-length-inference branch from c7b0ccc to d1fc6e7 Compare October 21, 2026 10:07
@lewis6991 lewis6991 changed the title fix(infer): improve array length checking fix(infer): infer integer lengths and guarded last elements Oct 21, 2026
@lewis6991
lewis6991 marked this pull request as ready for review October 21, 2026 10:08
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