Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong return type for file:read #81

Closed
rillig opened this issue Jun 15, 2021 · 5 comments
Closed

Wrong return type for file:read #81

rillig opened this issue Jun 15, 2021 · 5 comments

Comments

@rillig
Copy link

rillig commented Jun 15, 2021

Luanalysis v1.2.3

local function file_contains(filename, text)
  local f = assert(io.open(filename, "r"))
  local found = f:read("a"):find(text, 1, true)
  f:close()
  return found
end

What happens?

No such member 'find' found on type 'void'

What were you expecting to happen?

No error message since f:read("a") returns a string.

This is related to #80, where the return type depends on the string value of the first argument as well. Since the type system allows string values as separate types, this one should be solvable with a few overrides though, at least for the most common formats.

@adriweb
Copy link

adriweb commented Jun 15, 2021

Ideally we'd be able to annotate assert as having a passthru return type (for the success case anyway), i.e. whatever the type of the first argument is, it would return that as well... which would be a useful feature in general :)

@rillig
Copy link
Author

rillig commented Jun 15, 2021

Isn't assert already annotated as <T> fun(T): T?

The issue here is that there is no type annotation at all for file:read in io.defs.lua.

@adriweb
Copy link

adriweb commented Jun 15, 2021

Yes I suppose using generics that would work here, although I swear I had a similar issue in a project of mine just a few days ago, hmm.

Anyway, indeed annotations are missing for file:read

@Benjamin-Dobell
Copy link
Owner

Benjamin-Dobell commented Jun 15, 2021

I still need to write tests, but seems as this is being actively discussed. I'm currently looking at typing file:read and io.read as:

5.0-5.1

---@overload fun(): nil | string
---@overload fun(format: "*a"): string
---@overload fun(...: "*n"): (nil | number), (nil | number)...
---@overload fun(...: "*l"): (nil | string), (nil | string)...
---@overload fun(...: number): (nil | string), (nil | string)...
---@vararg "*a" | "*n" | "*l" | number
---@return nil | string | number, (nil | string | number)...

5.2

---@overload fun(): nil | string
---@overload fun(format: "*a"): string
---@overload fun(...: "*n"): (nil | number), (nil | number)...
---@overload fun(...: "*l"): (nil | string), (nil | string)...
---@overload fun(...: "*L"): (nil | string), (nil | string)...
---@overload fun(...: number): (nil | string), (nil | string)...
---@vararg "*a" | "*n" | "*l" | "*L" | number
---@return nil | string | number, (nil | string | number)...

5.3-5.4

---@overload fun(): nil | string
---@overload fun(format: "a" | "*a"): string
---@overload fun(...: "n" | "*n"): (nil | number), (nil | number)...
---@overload fun(...: "l" | "*l"): (nil | string), (nil | string)...
---@overload fun(...: "L" | "*L"): (nil | string), (nil | string)...
---@overload fun(...: number): (nil | string), (nil | string)...
---@vararg "n" | "a" | "l" | "L" | number | "*a" | "*n" | "*l" | "*L"
---@return nil | string | number, (nil | string | number)...

Basically, at present it's impossible to properly type this function. We'd need some pretty elaborate type transform logic to make it work 100% reliably i.e. the nth output type is dependent on the nth input type.

However, I believe the above should cover off the most common use cases.

@rillig
Copy link
Author

rillig commented Jun 15, 2021

Wow, that already looks impressively accurate, given that the specification of file:read would stretch each and every type system beyond its limits. Well, except for human brains, which apparently are even more flexible at accepting exceptional rules. 🙂

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

No branches or pull requests

3 participants