Skip to content

Proposal: Add function pointer field to TypeInfo.Definition.Data.FnDef #1135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
alexnask opened this issue Jun 19, 2018 · 6 comments
Closed
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@alexnask
Copy link
Contributor

alexnask commented Jun 19, 2018

Proposed structure:

pub const FnDef = struct {
    fn_type: type,
    inline_type: Inline,
    calling_convention: CallingConvention,
    is_var_args: bool,
    is_extern: bool,
    is_export: bool,
    lib_name: ?[]const u8,
    return_type: type,
    arg_names: [][] const u8,
    ptr: *const u8, // <- New field, guaranteed to point to fn of type 'fn_type'

    pub const Inline = enum {
        Auto,
        Always,
        Never,
    };
};

With the current structure, if @reify/@makeType was implemented, there would be no way to generate methods for a type.

This change would allow us to use the anonymous structure function trick or (eventually) function literals to generate methods for the types created.

EDIT:
Actually, this is just one of the changes that would need to be made to allow for method generation, the other issue being specifying the first argument type of the method when the type is not generated yet.

@andrewrk andrewrk added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Jun 19, 2018
@andrewrk andrewrk added this to the 0.4.0 milestone Jun 19, 2018
@andrewrk
Copy link
Member

This is a bit tricky because the pointer type of the field would not be correct (*u8 instead of fn proto) - or we would have to make FnDef generic. If we went with the "you have to cast the ptr field" approach, we might need to improve the comptime mechanism to support a comptime known pointer value that has the wrong type.

@alexnask
Copy link
Contributor Author

alexnask commented Jun 19, 2018

@andrewrk
I don't think making the struct generic can be achieved.
I believe this is achievable in the current master build, I've tested some type erasure comptime techniques before, here is a simple example that does work:

const assert = @import("std").debug.assert;

const WrappedFn = struct {
    const Self = this;

    fn_type: type,
    fn_ptr: *const u8,

    fn init(f: var) Self {
        return Self { .fn_type=@typeOf(f), .fn_ptr=@ptrCast(*const u8, f), };
    }

    fn get_fn(comptime self: *const Self) self.fn_type {
        return @ptrCast(self.fn_type, self.fn_ptr);
    }
};

fn foo(arg: u8) u8 {
    return arg;
}

test "comptime fn to u8 pointer casts" {
    comptime {
        const wrapped_foo = WrappedFn.init(foo);
        assert(wrapped_foo.get_fn()(42) == 42);
    }
}

EDIT

So something similar could be used in FnDef:

pub const FnDef = struct {
    const Self = this;

    fn_type: type,
    inline_type: Inline,
    calling_convention: CallingConvention,
    is_var_args: bool,
    is_extern: bool,
    is_export: bool,
    lib_name: ?[]const u8,
    return_type: type,
    arg_names: [][] const u8,
    ptr: *const u8, // <- New field, guaranteed to point to fn of type 'fn_type'

    pub const Inline = enum {
        Auto,
        Always,
        Never,
    };

    // TODO: https://github.com/ziglang/zig/issues/1124
    pub fn fn_ptr(comptime self: Self) self.fn_type {
        return @ptrCast(self.fn_type, self.ptr);
    }
};

So that the user needs only use the type safe fn_ptr method.

@andrewrk
Copy link
Member

I think this is a reasonable approach. Let me have a discussion about @reify with @thejoshwolfe and see if we can come up with an accepted proposal.

@alexnask
Copy link
Contributor Author

In addition to this, TypeInfo.Definition.Data.Var could be some type erased value (to allow reify-ing non type definitions)

@andrewrk andrewrk modified the milestones: 0.4.0, 0.5.0 Nov 21, 2018
@andrewrk andrewrk modified the milestones: 0.5.0, 0.6.0 Aug 19, 2019
@andrewrk
Copy link
Member

We now have the ability to have fields of type var when the struct is comptime known. So the problem this issue tackles is solved. Whether to put function definitions into that struct is the same issue as #383.

@alexnask
Copy link
Contributor Author

alexnask commented Feb 11, 2020

Great to see the comptime capabilities increasing, I'll have to catch up on the changes so I can maybe take a stab at fixing some bugs :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

2 participants