Type Checker: incorrect nil on a value that is already guarded by a nil check

image

As you can see in the image above, I’m clearly guarding the “Occupant” variable by doing “(Occupant ~= nil)”

Now the typechecker still considers it as “Humanoid?” even tho the guard before should cancel it.

Here is a minimal reproduction code :

local function Test(Occupant: Humanoid?)
	local IsSeated = (Occupant ~= nil)

	if IsSeated then
		local character = Occupant:FindFirstAncestorOfClass("Model")
	end
end

Now, direct check like “if Occupant ~= nil then..” doesn’t create this issue as shown in the code below :

local function Test(Occupant: Humanoid?)
	if (Occupant ~= nil) then
		local character = Occupant:FindFirstAncestorOfClass("Model")
	end
end

No type check error as expected :

image

My system informations :

CPU

AMD Ryzen 7 3700X 8-Core Processor 

Base speed:	3,60 GHz
Sockets:	1
Cores:	8
Logical processors:	16
Virtualization:	Disabled
Hyper-V support:	Yes
L1 cache:	512 KB
L2 cache:	4,0 MB
L3 cache:	32,0 MB

Utilization	13%
Speed	4,09 GHz
Up time	0:04:11:22
Processes	280
Threads	5914
Handles	147609

Memory

64,0 GB

Speed:	3200 MHz
Slots used:	4 of 4
Form factor:	DIMM
Hardware reserved:	78,3 MB

Available	40,9 GB
Cached	16,7 GB
Committed	27,0/67,9 GB
Paged pool	992 MB
Non-paged pool	804 MB
In use (Compressed)	22,4 GB (0 MB)

GPU 0

NVIDIA GeForce RTX 4060

Driver version:	32.0.15.9144
Driver date:	02/12/2025
DirectX version:	12 (FL 12.2)
Physical location:	PCI bus 45, device 0, function 0

Utilization	7%
Dedicated GPU memory	2,6/8,0 GB
Shared GPU memory	0,1/32,0 GB
GPU Memory	2,7/40,0 GB

Expected behavior

No type check error to happen on a value that is already guarded in a variable.

Hello!

This kind of more general inductive inference would be really cool but it’s extremely challenging to get right and impossible in the general case.

Your best bet is to write your refining expressions within the actual if conditional as in your second code snippet.

1 Like