Skip to content

string.gmatch and string.match have invalid return types #3357

Closed

Description

@sewbacca

How are you using the lua-language-server?

NeoVim

Which OS are you using?

Windows

What is the issue affecting?

Annotations, Type Checking

Expected Behaviour

The return type of string.match should be string|integer? and the return type of string.gmatch, should be a function which returns multiple string|integer ...

Actual Behaviour

The return type of string.match is any and the return type of string.gmatch is (fun(): string, ...), which causes #2487

See

---#DES 'string.match'
---@param s string|number
---@param pattern string|number
---@param init? integer
---@return any ...
---@nodiscard
function string.match(s, pattern, init) end

and
---#DES 'string.gmatch'
---#if VERSION <= 5.3 then
---@param s string|number
---@param pattern string|number
---@return fun():string, ...
---@nodiscard
function string.gmatch(s, pattern) end
---#else
---@param s string|number
---@param pattern string|number
---@param init? integer
---@return fun():string, ...
function string.gmatch(s, pattern, init) end
---#end

Reproduction steps

Try casting the first for loop variable from a :gmatch() into an integer (---@cast x integer), it throws an invalid warning; see no completion of return values from a :match().

Additional Notes

It seems to be currently not possible to specify types for ... return types using the fun() syntax. As a workaround at least define the first return value as string|integer instead of string.

Log File

No response

Activity

  1. changed the title [-]string.gmatch[/-] [+]`string.gmatch` and `string.match` have invalid return types[/+] on Feb 19, 2026
  2. carsakiller commented on Feb 26, 2026

    @carsakiller
    Collaborator

    I was very confused by string|number until I remembered that there is the "index" syntax for patterns ()! Good catch!

    local header = "i\ttype\tmatched text"
    local txt = "name=steve,color=blue"
    
    print("string.match")
    
    local str = header
    local t = { string.match(txt, "()(%w+)=([%w]+)()") }
    for k, v in ipairs(t) do
    	str = str .. string.format("\n%s\t%s\t%s", k, type(v), v)
    end
    
    print(str)
    
    --
    
    print("\nstring.gmatch")
    
    local str = header
    local f = string.gmatch(txt, "()(%w+)=()([%w.]+)")
    local i = 0
    while true do
        i = i + 1
    	local t = { f() }
        if #t == 0 then break end
    
    	for k, v in ipairs(t) do
    		str = str .. string.format("\n%i-%s\t%s\t%s", i, k, type(v), v)
    	end
    end
    
    print(str)

    string.match

    i type matched text
    1 number 1
    2 string name
    3 number 6
    4 string steve

    string.gmatch

    i type matched text
    1-1 number 1
    1-2 string name
    1-3 number 6
    1-4 string steve
    2-1 number 12
    2-2 string color
    2-3 number 18
    2-4 string blue

    I'll take a look at this in a bit. If only we could append ... for variadic returns like fun(): string|integer... for gmatch.

  3. self-assigned this
    on Feb 27, 2026
  4. added a commit that references this issue on Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

feat/LuaCats AnnotationsRelated to Lua Language Server Annotations (LuaCats)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions