Return type of a generic function which calls another generic function

i have the following generic function, whose return type i’m not sure how to specify:

fn declare(comptime name: []const u8, T: type) NotSure {
    const longer_name = ... ++ name;
    return Gen(longer_name, T) {};
}

what is the NotSure type returned by declare??? if i say Gen(name, T) i receive errors from the compiler which effectively boils down to longer_name being different from name

in general, is there some equivalent of anytype i could use for my function return types???

As Gen starts with uppercase, I guess it will return a type, so you can do it just like T: type with the type type.

1 Like

What about?

fn declare(comptime name: []const u8, T: type) type {
    const longer_name = ... ++ name;
    return Gen(longer_name, T) {};
}
1 Like

Presumably Gen(longer_name, T) is a struct type and thus Gen(longer_name, T){} is an instance of that type, not a type itself.

I don’t think there is a way around writing some extra boilerplate like

fn Declare(comptime name: []const u8, T: type) type {
    const longer_name = ... ++ name;
    return Gen(longer_name, T);
}

fn declare(comptime name: []const u8, T: type) Declare(name, T) {
    return .{};
}
2 Likes

That depends on if you can invoke your function at comptime. We do this in Fluent to chain unary calls that could have multiple intermediate type transformations. You can invoke a function and analyze its return directly:

fn foo(comptime x: anytype) @TypeOf(bar(x)) {
    return bar(x);
}

The reason this pattern may help is if you have function signatures like this:

fn bar(x: anytype) @TypeOf(x) ...

As the @typeInfo’s Fn.return_type will be null and it makes them hard to analyze. If you directly invoke it, it can save a lot of time (not applicable in all circumstances though).

3 Likes

Hint 1) You can call functions to derive the return type.

fn declare(comptime name: []const u8, T: type) NotSure(@TypeOf(name), T) {}

fn NotSure(Name: type, T: type) type {
    ...
}

Hint 2) For any function the return type is @TypeOf(return/body of function)

fn declare(comptime name: []const u8, T: type) NotSure(@TypeOf(name, T)) {
    const longer_name = ... ++ name;
    return Gen(longer_name, T) {};
}

fn NotSure(Name: type, T: type) type {
    return @TypeOf(Gen(Name, T) {});
}

Example: zig-recover/src/recover.zig at 65f958bd3dca78ea345e36d194eb2b5445971fe8 · dimdin/zig-recover · GitHub

5 Likes

all of this was quite helpful…

it turns out my use-case had an additional layer of complexity, in that the return type from declare itself turns out to conditional on some comptime test…

this actually worked splendly in VSCode – where the result type of declare appeared as an either type… more important, when i typed a “.” in the editor i was presented with a set of all possible pub names i could select (with a nice “comment” that effectively told me under which condition these would actually be available)…

this is incredibly impressive, in that some additional contextual information is available to users operating on the object returned by declare