luau-lang / luau

A fast, small, safe, gradually typed embeddable scripting language derived from Lua
https://luau-lang.org
MIT License
3.85k stars 356 forks source link

`if then else` assignments fail to simplify unions of the same type #1045

Open ThatOnePuppyGirl opened 10 months ago

ThatOnePuppyGirl commented 10 months ago
local b, c, d, f = true, true, true, true

local a = if b then {} elseif c then {} elseif d then {"a"} elseif f then {"a"} else {}

results in a being of type { } | { } | { } | {string} | {string}, as shown in the photo below: I am using the Inlay Hints setting in luau-lsp, and I have been told this is a Luau issue and to bring it here.

image

Luau should recognize that T | T == T, or at least attempt something like this.

ThatOnePuppyGirl commented 10 months ago

If someone could add the bug tag that would be very helpful, as I don't seem to be able to.

vegorov-rbx commented 10 months ago

As a work-around, I would recommend just helping out the inference by providing local a: {string}.

ThatOnePuppyGirl commented 10 months ago

As a work-around, I would recommend just helping out the inference by providing local a: {string}.

This happens with all data types, I just used those specific values as an example.

mxruben commented 1 month ago

Just ran into this issue today with something like the following code (yes, what I am doing is hacky):

local module = if string.sub(_VERSION, 1, 4) == "Lune" then require("../lib/module") else require(script.Parent.Parent.lib.module)

This creates type errors whenever I try to call functions in my module because it create unions for all of the functions that look something like (() -> ()) | (() -> ()) , which luau doesn't consider to be a function. The workaround does not work in my situation because I don't have access to the type until after the require function is executed. Instead I must expand the statement into a full if statement like so:

local module
if string.sub(_VERSION, 1, 4) == "Lune" then
    module = require("../lib/module")
else
    module = require(script.Parent.Parent.lib.module)
end

A little more cluttered but it works and figures out all of the types correctly.