LSP unknown type - working with generics especially with @typeInfo(...).@"fn".return_type.?

Take this example of a function that returns a type.

pub fn CallableFunction(comptime FnType: type) type {
    return struct {
        address: *anyopaque,
        pub fn init(function: Function) @This() {
            return .{
                .address = function.codegen.allocation,
            };
        }
        pub fn call(self: @This(), args: anytype) @typeInfo(FnType).@"fn".return_type.? {
            const fn_ptr: *const FnType = @ptrCast(self.address);
            return @call(.never_inline, fn_ptr, args);
        }
    };
}

And now this example usage:

    const some_function = try context.chimera.create(0); // : (Function)
    const callbable_function = Chimera.CallableFunction(fn (u32) u32).init(some_function); // : (CallableFunction(fn (u32) u32))
    const result = callbable_function.call(.{67}); // ((unknown type))

This block compiles fine but the lsp (ZLS) marks result as: ((unknown type))

This is really frustrating as I have to now add another comptime type parameter that will contain the return type which is redundent so I can get the lsp to work properly, for example:
pub fn CallableFunction(comptime FnType: type, comptime Ret: type) type
And then replace any occurence of @typeInfo(FnType).@"fn".return_type.? with Ret.

Is there anyway, I don’t care how complicated but a hack to doing this without having to directly specify the return type (double specifying) like shown: CallableFunction(fn (u32) u32, u32) in hopes of getting rid of unknown_type?

Thanks in advance, really love the language (I came from C++23) but the lsp needs some work (thinking about contributing but don’t know where to start) as I have encountered quite some problems with it.

1 Like

well yeah, the name the lsp shows you is the name you gave the type, since the type has no name ig it marked it as ((unknown type))

    const callbable_function = Chimera.CallableFunction(fn (u32) u32).init(some_function); // : (CallableFunction(fn (u32) u32))

even the name here, it did not give it a new name, it just told you that it’s “the result of these params passed to this function”

ZLS is a community effort. It is a well done project.
However, they have to implement their own type resolution/comptime interpreter and its a hard target to keep up with. The ZLS devs do their best.
What you are experiencing is the limit of what ZLS can resolve. For these types of more complicated types, ZLS currently can’t resolve it, hence the unknown type.

2 Likes

Hey, I didn’t quite understand your reply. The lsp doesn’t give names, it is supposed to better your developer experience by resolving types without needing to go through the overhead of compiling, now in this code snippet I provided a function type fn (u32) u32 and then used builtin @typeInfo to get its return type which is also the return type of call, in theory the lsp should mark it as returning u32 but it doesn’t. From what @Southporter said I guess it is really a limitation as of right now.

Sounds good, I’ll check the repo out! Thanks for the fast reply.

1 Like

I just didn’t know if I should call it a limitation right away, since I remember some things about types and zls are just ‘not planned [for now?]’, but maybe I was wrong in wording.

anyways, the workaround I usually do is by setting the type on the result value:
const result = ... would become const result: u32 = ...