Skip to content

Proposal: @Result to match cast builtins inference API #16313

@candrewlee14

Description

@candrewlee14

Note: This is a formalized proposal based on discussion here: #5909 (comment)

Proposal started with the addition of @ResultType, like pub inline fn intCast(x: anytype) @ResultType.
It has been revised to use @Result and anytype in a function declarations, pub inline fn intCast(x: anytype) anytype

Problem: Builtin-exclusive inference API

With the recent merging of #16163, cast builtins now use an API that can't be replicated in regular userspace.
For example, take the std.fmt.parseInt function:

fn parseInt(comptime T: type, buf: []const u8, base: u8) std.fmt.ParseIntError!T

which currently has to be used like:

const foo = std.fmt.parseInt(u32, content, 10); // T must be explictly provided

compared to the usage of a cast builtin which can be used like

const bar: u32 = @intCast(x - y); // T is inferred

For the sake of consistency, it seems like parseInt should be able to be used in a similar fashion.

const bar: u32 = try std.fmt.parseInt(content, 10);

Proposal: @Result

The introduction of a builtin @Result could allow the declaration of std.fmt.parseInt to look like this:

fn parseInt(buf: []const u8, base: u8) std.fmt.ParseIntError!anytype {
    const T = @Result();
    ...
}

pub fn main() !void {
    const word1 = "12";
    const word2 = "42";
    const foo: u32 = try parseInt(word1, 10); // @Result is u32
    const bar: u64 = try parseInt(word2, 10); // @Result is u64 
    ...
}

Benefits

  • This democratizes this kind of inference API currently exclusive to builtins.
  • This may improve the consistency of callsites of functions with inferable types.
  • Could benefit from cast-builtin-related improvements in type inference resolution, like in the case of something like:
    // possible builtin inference improvement
    const foo: u32 = @intCast(a + b) * @intCast(c);
    // potential downstream benefit
    const bar: u32 = try parseInt(word1, 10) + try parseInt(word2, 10);
  • This also allows for the user to implement a function that looks like cast builtins from a caller's perspective, like this (via remove the destination type parameter from all cast builtins #5909 (comment)):
    pub inline fn intCast(x: anytype) anytype {
        return @intCast(x);
    }

Drawbacks

  • Allows functions with identical functionality to be defined with 2 different APIs.
    When should a user define a function with @Result inference vs. having a comptime T: type parameter?
  • ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions