When overloading functions with implied "self", lua type checking bugs out (typechecking)

Not sure if this counts as a bug report, scripting support, or a feature request BUT:

I noticed when setting a function to have multiple different possible parameters using roblox’s typechecking overloading feature, functions (seem to) break as soon as the function implies self as the first parameter, resulting in the overloaded values not changing when writing their corresponding type:

Expected behavior:
image
When fully typing in “Damage”, all of the needed variables show up. This is using a normal local function.

Actual behavior:
image
(Note than a.foo(self, value) does have the same expected autocomplete as the Expected behavior, as self is a variable that must be given) This is using an object.

Code that resulted in the following behaviors:

Expected, using foo()
type VersionValue = "Damage" | "Spin" | "Delete" | "Stun" | "Mix"

type func1 = typeof(
	--[[Foo text!]]
	function(version: "Spin"): any
		return nil
	end
)
type func2 = typeof(
	--[[Foo text!]]
	function(version: "Stun", person: any): any
		return nil
	end
)
type func3 = typeof(
	--[[Foo text!]]
	function(version: "Delete", instance: any): any
		return nil
	end
)
type func4 = typeof(
	--[[Foo text!]]
	function(version: "Damage", victim: any, hitter: any): any
		return nil
	end
)
type func5 = typeof(
	--[[Foo text!]]
	function(version: "Mix", person1: any, person2: any): any
		return nil
	end
)

local foo: func1 & func2 & func3 & func4 & func5 = function(version: VersionValue, value: any, value2: any)
	
end

foo("Damage")
Actual, using a:foo()
--!strict
type VersionValue = "Damage" | "Spin" | "Delete" | "Stun" | "Mix"

type func1 = typeof(
	--[[Foo text!]]
	function(self: any, version: "Spin"): any
		return nil
	end
)
type func2 = typeof(
	--[[Foo text!]]
	function(self: any, version: "Stun", person: any): any
		return nil
	end
)
type func3 = typeof(
	--[[Foo text!]]
	function(self: any, version: "Delete", instance: any): any
		return nil
	end
)
type func4 = typeof(
	--[[Foo text!]]
	function(self: any, version: "Damage", victim: any, hitter: any): any
		return nil
	end
)
type func5 = typeof(
	--[[Foo text!]]
	function(self: any, version: "Mix", person1: any, person2: any): any
		return nil
	end
)
local a: {foo: func1 & func2 & func3 & func4 & func5} = {} :: {foo: func1 & func2 & func3 & func4 & func5}

a:foo("Damage")

Am I using typechecking wrong (am I even using the correct name for it haha), or is this something that hasn’t been caught before due to how specific it is?

Does this happen when the self parameter of the functions is properly typed (and not just any)?

1 Like

Hopefully I’m understanding your question right, but if you’re talking about properly typing in a.foo(a, string) then yes:


This works with or without self being defined as an any or “aType” (defined type)

For defining a specific type that self will be in the parameters (this time using implied self, my goal) no:

(Also if the solution has something to do with metatables please let me know because I am NOT well versed in them, but it seems odd to need them for this specific scenario)

Don’t use any when you’re doing the overload. it creates a lot of ambiguity.

--!strict
type FooOverload = 
	& ((version: "Spin") -> nil)
	& ((version: "Delete", instance: BasePart) -> nil)
	& ((version: "Stun", person: Model) -> nil)
	& ((version: "Damage", victim: Model, hitter: Model) -> nil)
	& ((version: "Mix", person1: Model, person2: Model) -> nil)
local foo: FooOverload = nil :: any
local i: BasePart = nil :: any

--OK
foo("Spin")
foo("Delete", i)
foo("Stun",workspace)
foo("Damage", workspace, workspace)
foo("Stun", workspace)

--Error
foo("Delete", workspace)
foo("Stun")
foo("Damage", workspace)
--!strict
type MySystem = {
	foo: 
		& ((self: MySystem, version: "Spin") -> nil)
		& ((self: MySystem, version: "Stun", person: Model) -> nil)
		& ((self: MySystem, version: "Delete", instance: Instance) -> nil)
		& ((self: MySystem, version: "Damage", victim: Model, hitter: Model) -> nil)
		& ((self: MySystem, version: "Mix", person1: Model, person2: Model) -> nil)
}
local a: MySystem = {} :: any

--OK
a:foo("Spin") 
a:foo("Damage", workspace, workspace)
a:foo("Stun", workspace)

As an extra note, some people only care about autocomplete and that kind of editor help, not really about code safety. If autocomplete is your main goal, this probably won’t be that useful for you.

1 Like

Luau is currently unable to properly infer the type of self, especially not when you annotate its type to any, which is essentially a typechecking opt-out.

You must properly annotate the type of self manually.

1 Like

I do notice with strict it now gives a warning for putting in the incorrect type (using this code), which is good! I’ll keep the “any” thing in mind going forward.
However, the original problem still persists (hopefully this video is a better example):

Again, note that when typing in a.foo(a, “Damage”) the autocomplete shows up like the expected example. I know this doesn’t change anything coding wise, but it seems incredibly odd and specific that the autocorrect doesn’t work here

Took me a while to realize you’re on the old type solver!
Interestingly, this kind of overload selection seems to be completely absent from the new solver, which by the way I suggest you migrate to soon, as they’ll eventually remove the old solver.

I’m not entirely sure if this is a bug or just a missed feature in the new solver, but you can submit a bug report for this in Bug Reports > Studio Bugs!

1 Like

Just made a bug report on it! In the future the solution to the problem should be to use the new type solver once the bug is fixed, right?

Probably.

The new solver also brings a complete overhaul to the type system, you can read about it here: An introduction to Luau types | Luau.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.