How can I get the type of the current function?

For the current struct there is the @This built-in. Is there a similar thing for the current function?

For example, notice this from the stdlib:

pub fn min(x: anytype, y: anytype) Min(@TypeOf(x), @TypeOf(y)) {
    const Result = Min(@TypeOf(x), @TypeOf(y));

The return type of the function is an awkward expression, and it has to be repeated to define Result. I’m in a similar situation, where I’d like to capture the return type but I have to duplicate a type expression.

I’m hoping there’s something like @Func that will return a useful handle that can be queried?

const Result = @Func.result_type;

Or am I doomed to copy and paste?

As with many things Zig, this isn’t builtin, but you can make it yourself. mlugg supplied this useful bit of code on discord not long ago for a similar purpose:

fn ErrorReturn(comptime T: type) type {
    const Ret = @typeInfo(T).Fn.return_type.?;
    return @typeInfo(Ret).ErrorUnion.error_set;

So while you might have to keep something like Min(@TypeOf(x), ...) in the function declaration I believe you’ll have no trouble making a helper function with a short name that takes @TypeOf(func) as a parameter and returns its return_type to grab that for your Result.

i would love it if that were possible but i’m having trouble doing it. i get:

main.zig:3261:13: error: dependency loop detected
        pub fn min(x: anytype, y: anytype) MinResult(@TypeOf(min))

oh, you said it wouldn’t work in the function declaration, sorry. but that’s where the redundancy is

Indeed. The type of min( param1, ... ) T { is fully and completely defined by T there, so you have to make it anytype at the very least. Everything after that can use the function’s return type.

Beware that the @TypeOf(min) is a function type, not a return type.

So this is an unsolved problem as I thought. I deal with it by avoiding anytype and using the comptime T: type style instead. The min function is unusual in that it’s combining two types, usually the situation is simpler.

This is not likely an unsolved problem. To be clear, the min function is taking the minimum of two values. The Min function is declared with pub fn Min(comptime A: type, comptime B: type) type {, but is useless for processing non-type values.

Yes, I meant the min function returns a value of a type that is derived from two types.

It (the OP issue) is unsolved in the sense that this text duplication in min can’t be avoided:

Min(@TypeOf(x), @TypeOf(y))

I believe that text doesn’t need to be duplicated, because once the type of the function is defined:

pub fn min(x: anytype, y: anytype) Min(@TypeOf(x), @TypeOf(y)) {

The return type of min is exposed with @typeInfo(@TypeOf(min)).Fn.returntype.?. Of course, that is a bit of a mouthful, so that can be shorted by putting that in a function that takes @TypeOf(min) as a parameter.

Ah, I didn’t realize you were suggesting two different expressions in the function decl and body.


I was slightly optimistic, but unfortunately this doesn’t work because return_type is null for generic functions, I get:

main.zig:3262:56: error: unable to unwrap null
            return @typeInfo(@TypeOf(f)).Fn.return_type.?;

Bummer, huh? :cry:

Maybe someday the return_type will be filled in for generic fns.

Edit: Or maybe not, since this requires a different Type struct for each generic fn instantiation.

Based on the suggestions here:

  1. It seems there is no convenient way to grab the outer function, except by copying the name.

  2. I have written a helper function to take a function and return the return type:

    fn ReturnType(comptime func: anytype) type {                                   
        if (@typeInfo(@TypeOf(func)) != .Fn) {                                     
            @compileError("Argument 1 (func) to ReturnType must be a function");   

        return @typeInfo(@TypeOf(func)).Fn.return_type.?;                          
    test "ReturnType" {                                                            
        // _ = ReturnType(1);                                                      

I think we posted at the same time. Your ReturnType function works, but unfortunately not in the case you want it to, which is for generic functions. The return_type field is optional because it is null for generic functions. I had forgotten this and rediscovered it during this conversation! :slight_smile:

Here’s the issue about return_type and generic functions.

Oh, I’m more than a little silly here. Grabbing the function by name, as I was intending to do, won’t help because the function doesn’t return any particular type until it is called with a type, even within the scope of the function itself. So getting the actual function after the compiler determines its types is tricky enough that you can’t actually pass it to @TypeOf in the first place.

Nice find on the issue.

I was able to pass the function name to @TypeOf in the body … but the return_type and arg_type of the anytype params were all null, so you’re right that there is no value in doing this.

My rule of thumb is to stick to simple use of generics in Zig, and wait to see how this part of the language evolves. It works really well you have a T type param and you keep things simple.

So getting the actual function after the compiler determines its types is tricky enough that you can’t actually pass it to @TypeOf in the first place.

I was able to pass the function name

Right, I may have edited my post to clarify. In any case, as you said, the way to avoid duplicating the type expression in the function call atm appears to be to be explicit about the type everywhere you call it, which may or may not be less burdensome:

fn min(comptime T: type, x: T, y: T) T {