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

New Solver: Optional generic parameter in table type can result in type error #1543

Open
claylittlehorse opened this issue Nov 23, 2024 · 4 comments
Labels
bug Something isn't working new solver This issue is specific to the new solver.

Comments

@claylittlehorse
Copy link

claylittlehorse commented Nov 23, 2024

These return type errors:

type foo<T> = { bar: T? }

local foo: foo<any> = { bar = "foobar" }
-- TypeError: Type '{ bar: string }' could not be converted into 'foo<any>'; type { bar: string }[read "bar"] (string) is not exactly foo<any>[read "bar"][0] (any)
--	type { bar: string }[read "bar"] (string) is not exactly foo<any>[read "bar"][1] (nil)
local foo: foo<any> = { } -- TypeError: Type '{  }' could not be converted into 'foo<any>
local foo: foo<nil> = { } -- TypeError: Type '{  }' could not be converted into 'foo<nil>

The following will not error:

local foo: foo<any> = { bar = "foobar" :: any }
local foo: foo<any> = { bar = nil }
local foo: foo<any> = { bar = "foobar" :: any? }
local foo: foo<nil> = {bar = nil}
local foo = { bar = "foobar" } :: foo<any>
@claylittlehorse claylittlehorse added the bug Something isn't working label Nov 23, 2024
@hgoldstein hgoldstein added the new solver This issue is specific to the new solver. label Nov 25, 2024
@hgoldstein
Copy link
Contributor

hgoldstein commented Nov 25, 2024

Thanks for the report! This is for the new solver correct? I agree that the last two examples seem like bugs: we should be able to infer that {} is a { bar: T? }.

local foo: foo<any> = { bar = "foobar" }

I'm not actually sure that should be legal though. The rules for typing any / error can be tricky.

@claylittlehorse
Copy link
Author

This is for the new solver correct?

This is for the new solver!

I'm not actually sure that should be legal though. The rules for typing any / error can be tricky.

My intuition is that any should allow any type to be used for that field-- and that generics shouldn't change this behavior. This is the behavior in the old solver. If the example in question was illegal, I would have a hard time understanding why these would be legal:

local dict: { [string]: any } = {}
dict.foo = "string"

type foo<T> = { bar: T }
local foo: foo<any> = { bar = "foobar" }

Is the issue here that any? is somewhat redundant, because any already contains the nil type?

@hgoldstein
Copy link
Contributor

My intuition is that any should allow any type to be used for that field ...

Yes, that's the right intuition, I wasn't sure if that fully applied in a generic position.

There's some logic in the new solver that ensures when you write table literals we infer the correct type. For example, if I write {}, that's an empty table and gets the type {}. It could be a { foo: number? }, but those are different types (only one allows you to assign a number to foo). I'm guessing that logic is not working here. It seems like any works as you'd expect in other scenarios, e.g.:

type Foo<T> = { bar: T? }
local function castFoo(f: Foo<string>): Foo<any>
    return f
end

@claylittlehorse
Copy link
Author

Thank you for the information!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working new solver This issue is specific to the new solver.
Development

No branches or pull requests

2 participants