New Type Solver [Beta]

Ditto, it says “Type inference failed to complete” in a bunch of scripts and incorrectly guesses on types like comparing a number to a number in a table. Restarting studio has not fixed the type inference warning.
This is in the Roblox-provided Animate script, by the way
image
image

does anyone even use type solver lol??? it looks so inefficient and never in my almost 10 years on the platform i have used it.

The type inference failed to complete “error” is intended to indicate to you that you’re encountering a particular flavor of bug in that script that is leading to unexpected errors. In the particular case, those math.random calls should succeed, but type inference seems to have gotten stuck on the generalization step that turns that free type 'a in the error into its bound number?. We’re working hard to fix the underlying cause of these sorts of problems before shipping the new type solver more broadly!

You might be surprised to learn that the autocompletion engine in Studio (and also in external editors like Visual Studio Code via luau-lsp) are powered entirely by Luau’s type inference engine. Some creators use types to document invariants of their APIs and rule out errors statically, but if you feel that’s inefficient for your workflow, it’s perfectly fine for you to only rely on these systems to power autocomplete. That’s why we support the three different operation modes! :smile:

3 Likes

Apologies if this is not the right thread to ask but, is there any way to refine the contents of a type whose fields are optional on cases where I know they’ll be filled in?

I’ve tried both on the new and old type solver and I can’t seem to get it to work.

My use case is as follows:

  • I have a typewritter module whose constructor takes a table with optional properties for richtext markups.
    • Said properties get reconciled with the defaults upon constructing, meaning the end user and the subclasses can expect the properties to always be filled in


  • Issue arises when I attempt to use the type, as the type solver thinks the field might be empty (thus I have to assert each field to silence the warn).

Pics are taken on the old solver, but i’ve tried the new one, it’s keyof/index functions, and nothing seems to work, only solution is to write the type twice which is inconvenient for a table with lots of properties.

Memory Leak Issue

I have no idea what is wrong in this part of code but after a long time of deleting Instances and then lines of code, I came to this function that keeps increasing the Roblox Studio’s RAM usage (reaching over 10 GB at times) and then crashing the Roblox Studio after a while, sometimes leading to whole OS shutdown. (I have Windows and got “CRITICAL_PROCESS_DIED” with every “blue death”.)

First I thought it was a global issue and so I did describe what happens in this post but now I already know it was specific to just one place due to the following code. I am also 100 % sure it is connected with the new Type Solver as with disabling the “New Luau type solver” Beta Feature the memory usage didn’t raise upon reopening the place and my friends have tested this on their computers, too.

Code
type Endpoint = {
	name: string,
	connections: { RBXScriptConnection },
	endpoints: { [string]: Endpoint },
	host: Subdomain | Domain,
	messager: BindableEvent,
	parent: Endpoint | Subdomain | Domain?,
	threads: {},
	
	createEndpoint: (name: string) -> Endpoint?,
	Destroy: (self: Endpoint) -> nil
}

type Domain = Endpoint & {
	domain: Domain,
	subdomains: { [string]: Subdomain },

	createSubdomain: (name: string) -> Subdomain
}

type Subdomain = Domain & {
	parentHost: Domain | Subdomain
}

local function destroyEndpoint(self: Endpoint)
	if self.parent == self then return end
	self.parent.endpoints[self.name] = nil

	for _, endpoint in pairs(self.endpoints) do
		endpoint:Destroy()
	end

	for _, connection in pairs(self.connections) do
		connection:Disconnect()
	end self.messager:Destroy()

	while true do
		local threads = table.remove(self.threads)
		if threads == nil then break end
		task.cancel(threads[1])
		task.defer(threads[2])
	end return nil
end

Edit: Found the line causing this:

	if self.parent == self then return end

Test Place: MemoryLeak_test.rbxl (47.7 KB)

Could someone tell me what I did wrong and if it is not my fault, could the problem be fixed?

Just wanted to give an update, I still cannot fully transfer my module to the new type solver due to there still being blocked warnings. I have waited a while on purpose so that when I come back, these bugs would be fixed by now. However, the same bug I encountered 2 months ago still remains today. Is there an estimate time on when the blocked warnings will be gone for the most part? I really want to continue my development.


If a type is defined to be a table containing a boolean and you prove that boolean to be either true or false, it refuses to let you use that type where you should be able to because it’s considered a different type altogether.

In the example above, we’ve proven that the custom terrain cell is water. Before proving that the cell worked and was able to pass itself into its methods, but once we proved the boolean to be true it thinks it’s a different type and refuses to let you pass it into its own methods.

Hoping for a fix, or if someone could help me figure out a workaround that’d be great.

without the error covering everything:
image

I think there might be a studio crash bug with this beta feature. For some reason my studio keeps crashing when trying to index my module’s class. The old type checker handles this effortlessly.
image

It’s a behemoth of a module so maybe that’s the problem.
image

To reproduce this bug, you can edit or download the test place (where i publish experimental changes) in the studio, open up the “Audio Player” app in the script editor while the beta type solver is enabled, go to line 433, uncomment line 433, remove the ., and then try to index the table using a ..

Hopefully this could be a useful information. The crash report when studio crashes will probably have the crash reason.

I don’t have any bug reporting privileges in the forum, so this thread is the best option that I have. By the way, here’s my system information if it’s helpful:

OS: Microsoft Windows 11 Home Single Language (x64), Version 10.0.26100 Build 26100
CPU: 13th Gen Intel(R) Core™ i7-13650HX, 2600 Mhz, 14 Core(s), 20 Logical Processor(s)
RAM: Capacity 17179869184 B, Speed 4800 MT/s, Memory Type LPDDR5
GPU: NVIDIA GeForce RTX 4050 Laptop GPU, VRAM 5921 MB

image
on v.Name:find() v is “unknown” even though its type checked as instance on i,v:Instance

		for i,v:Instance in pairs(workspace:GetChildren()) do
			if v.Name:find("active") and not v:FindFirstChild("Thermal") then
				script.Thermal:Clone().Parent = v
			end
		end

this “unknown” “never” and blocked typecheck is very common(and annoying) on most of my scripts and it also sometimes creates a orange warning bar at the top of my script

it also sometimes disable autocomplete on that variable (and in some cases for some reason i cant autocomplete things like enums anywhere outside of the scope (i think) which it was in and that is VERY annoying)

if its all filled in, you should have a seperate type where theres no optionals. you’re going to need to do some :: any casting in the function that reconciles with its return value though

bit of a complicated solution im providing using type functions, but it works and is easiest if you want to do something like this for something else


type function Optional(v)
     return types.unionof(v, types. singleton(nil))
end

type function OptProps(t)
     if not t:is("table") then
          error("type provided is not of type 'table'")
     end
 
     for k, v in t:properties() do
         t:setproperty(k, Optional(v.read or v.write))
     end
     return t
end 

type Properties = {
     ...
}

type OptionalProperties = OptProps<Properties>
2 Likes

i just caught a bug

Thanks, that worked wonderfully (it does break when the type passed inherits a previous one, but that’s nothing I can’t deal with, hopefully it’s a solver bug).

Do you happen to know if there’s an equivalent to “find” for these functions? I’ve tried the following without much luck:

export type function FilterType(t, f)
	if not t:is("table") or not f:is("table") then
		error("types provided are not of type 'table'")
	end
	for k, v in t:properties() do
		t:setproperty(k, f[k] and v)
	end
	return t
end

Expected use case would be filtering out object methods from modules (ideally i’d use varargs but they don’t work rn):

return SleekText :: Types.FilterType(typeof(SleekText), {"new", "Shortcuts", "Properties"})

I was curious on where you found the “t:properties()” documentation and came across this page, so i’m gonna leave it here in case it helps someone:
https://rfcs.luau.org/user-defined-type-functions.html

i found performance issue

before

after

almost 2x ram usage

maybe memory leak?

1 Like