New Luau type checker: callback function arguments' types ignored, inferred as unknown

With the new Luau type checker enabled, write this in a Script and check the type of a0 by hovering the mouse over it or using the Invoke Hover action.

--!strict
local function foo(fn: (Instance) -> ()) end
foo(function(a0)
	-- a0.Name = "123"
end)

a0 is unknown even though it’s specified to be Instance in foo’s signature.
With the Name assignment uncommented, it becomes {Name: string}

I expected it to be inferred as Instance as with the previous solver. Is this behavior still intended and supported?

The workaround is to write a0: Instance or to disable the new solver.

Hello! That is not expected: while this behavior isn’t perfect in the new solver, I tried pasting in your snippet exactly into Roblox Studio with the new solver enabled, and it appears to work as you expect:

I also see autocomplete working as expected. Is it possible there’s an issue with a larger snippet? If you have a place file, would you be able to share it?

Studio has updated in the days since and I’ve gotten some time, so I’ve looked into this again.

I have all betas disabled except for Dragger QoL Improvements, Live Animation Creator, Next Gen Studio Preview, Reimport.

For me, the code in the OP still shows that a0 is unknown.

I sent this bug report after reading the code of one of my personal kitchen-sink plugins, which I’m going to attach… (here)
It had no orange squiggles before.

The modules have no warnings, but the main script uses callbacks and has a lot of inane warnings with the new type checker even if pwarnmod is integrated into the script instead of coming from a ModuleScript.

LuauTypeCheckMode is Strict, UseNewLuauTypeSolver is Enabled.

57: workspace.Terrain.FindFirstChild underlined with `Type Error: Type ‘nil’ could not be converted into ‘Instance’. I’ve always assumed Terrain is a property of Workspace that’s not optional and even if it isn’t, the “Explorer type” of workspace must have a child named Terrain, so seeing it get typed optional is surprising. I’ve never had trouble indexing workspace.Terrain in strict mode before.

66: fn underlined, type error is word salad

70: entire line underlined with Type Error: Type pack 'PluginAction' could not be converted into '()', this is legitimate, although I’d sooner expect this function to be inferred PluginAction?, not a premature () from the early return and a subsequent type error. The old solver also typed this (), but didn’t warn when there are more than 0 return values.

80: class underlined with Type Error: Type 'unknown' could not be converted into 'string', argument in function signature is unknown. It feels like it can no longer reason that if the variable is unannotated and is only used as a string argument, then it must be a string.

Anything to do with pforeach and pforinstdesc is what I was talking about in the OP of this thread. These take callback functions and the callbacks are specified to take an Instance, but the instance types are discarded, only i remains a number.

211: resultMouse.Instance.Remove underlined, this makes sense although I have never heard of any case where RaycastResult.Instance can be nil. I haven’t read the docs for that in years… The warning is word salad (Type Error: Type '(Instance) -> ()' could not be converted into '(A...) -> (R...)'; this is because * it returns `()` and it returns a tail of `R...`, and `()` is not a subtype of `R...` * it takes the portion of the type pack starting at index 0 to the end`Instance` and it takes a tail of `A` )

221: table.insert underlined, warning is Type Error: No valid instantiation could be inferred for generic type parameter V. It was expected to be at least: Instance | { read Parent: unknown } & { read Parent: ~(false?) } and at most: Instance but these types are not compatible with one another. and v has a nonsense inferred type instead of the Instance that it’s supposed to be.

function weld(toLast): that first pforeach clearly operates on a table of Instances from Selection:Get(), but the Instance type disappears, parts is filled with unknown and then last is squiggled on line 248 with Type Error: Type ‘~(false?)’ could not be converted into ‘BasePart?’`

asdasdasdasdasdasd did this even paste my etire message?

Hello! Sorry that it has taken so long to get back to you on this. We’ve made some improvements here, though I see several of the issues you are citing still occur.

I believe the original bug you cited is with respect to code like:

	pforeach(sel, function(v, i, sel)
		sel[i] = v.Parent
	end, sel)	

… we hope to fix this class of error in the new solver, you can see similar issues when using table.sort.