Type inference on return type?

I’m dropping an idea here, no clue if it is feasible, let’s see how it goes.

Thanks to anytype, I can access type inference of the function’s parameters with @TypeOf and @typeInfo.

I think it could be very convenient to do the same with the return type of a function - effectively declaring a function fn func() anytype.

For example, a small helper function that applies a transformation on its parameter so the result matches the desired type of another’s function parameter.

What do you think? Would it be useful? Am I missing a footgun here? Or is it incompatible with how the type inference works as of now?

2 Likes

Rejected. (anytype was called var back then).

I like the idea it goes more into the direction Strong Typing without Types, which I really like and anytype as a parameter already can. It is probably really hard to provide this feature on a compiler level and to provide proper tooling.

There are two different forms of “return type inference” reflected in the proposals @Sze and @LucasSantos91 linked above, and I think they warrant a more detailed explanation/comparison to avoid confusion and determine which one best matches your expectations.


return type inference · Issue #447 · ziglang/zig · GitHub (rejected): infers the return type based on the function body. For example, in the following simple function, the return type could be inferred as u32, since the compiler knows that the result of a + b (both u32s) is a u32:

fn add(a: u32, b: u32) anytype {
    return a + b;
}

The closest analogy to this in Zig today is inferred error sets (!void, etc.), which do this sort of analysis, but only on the error set and not the “value” part of the return type.


Proposal: `@Result` to match cast builtins inference API · Issue #16313 · ziglang/zig · GitHub (neither accepted nor rejected as of now): infers the return type based on the result type where the function is called. Many builtins in Zig today do this sort of inference, such as @intCast:

const a: u64 = 123;
const b: u32 = @intCast(a); // u32 is the result type of @intCast here

This would be useful for writing transformation functions in userspace, such as the one mentioned in the proposal description:

// Current:
const foo = std.fmt.parseInt(u32, content, 10);
// If the proposal were accepted:
const bar: u32 = try std.fmt.parseInt(content, 10);

While this may not look that useful in this simple example, result types become much more useful when used in function parameters, struct field initializers, etc., which might be what you are getting at with

4 Likes

That is definitely what I had in mind.

2 Likes