Skip to content
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

add @reflectDecl and @reflectFn builtins #10706

Open
andrewrk opened this issue Jan 27, 2022 · 5 comments
Open

add @reflectDecl and @reflectFn builtins #10706

andrewrk opened this issue Jan 27, 2022 · 5 comments
Labels
breaking Implementing this issue could cause existing code to no longer compile or have different behavior. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@andrewrk
Copy link
Member

If you use @typeInfo on a struct, you get this structure:

    pub const Struct = struct {
        layout: ContainerLayout,
        fields: []const StructField,
        decls: []const Declaration,
        is_tuple: bool,
    };

Declaration looks like this:

    pub const Declaration = struct {
        name: []const u8,
        is_pub: bool,
        data: Data,

        pub const Data = union(enum) {
            Type: type,
            Var: type,
            Fn: FnDecl,

            pub const FnDecl = struct {
                fn_type: type,
                is_noinline: bool,
                is_var_args: bool,
                is_extern: bool,
                is_export: bool,
                lib_name: ?[]const u8,
                return_type: type,
                arg_names: []const []const u8,
            };
        };
    };

name and is_pub are cool. But Data requires doing a lot of semantic analysis to provide this information. However most usages of @typeInfo do not need access to this information.

stage1 solves this problem by making Data lazy. But this is complicated and slow.

This proposal is to remove the data field from Declaration, and add a new builtin function to reflect on declarations:

@reflectDecl - given a type which is used as a namespace, and a decl name, provides meta information about the decl. The type returned is:

pub const Declaration = struct {
    type: type,
    alignment: u16,
    link_section: [:0]const u8,
};

If you then looked at the type and learned that it was a function, you could use @reflectFunc to learn information about its function body (not to be confused with its function type which can be learned via @typeInfo(type).Fn.

pub const FunctionBody = struct {
    type: type,
    is_noinline: bool,
    is_extern: bool,
    is_export: bool,
    lib_name: ?[]const u8,
    arg_names: []const []const u8,
};

Related: #10705

@andrewrk andrewrk added breaking Implementing this issue could cause existing code to no longer compile or have different behavior. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. labels Jan 27, 2022
@andrewrk andrewrk added this to the 0.10.0 milestone Jan 27, 2022
@andrewrk andrewrk added the accepted This proposal is planned. label Feb 1, 2022
andrewrk added a commit that referenced this issue Feb 1, 2022
@nektro
Copy link
Contributor

nektro commented Feb 1, 2022

can this change still preserve the enum tag from Data as Kind ?

@andrewrk
Copy link
Member Author

andrewrk commented Feb 1, 2022

The Data tagged union in master branch is completely bogus. All decls are Var. The type is available with @TypeOf(@field(T, decl.name)). There's no such thing as a Type or Fn decl. That's just a decl where typeof gives you .Fn or .Type.

Consider: const mystery = if (foo) fn() void {} else i32;

@topolarity
Copy link
Contributor

topolarity commented Feb 1, 2022

Since @Type already disallows creating decls, this change sounds pretty reasonable to me. Status quo reflection (and esp. reification) is mostly for types-as-data-containers, not types-as-namespaces.

Some small thoughts:

  • @fnInfo/@declInfo might be a nicer name for @reflectFunc/@reflectDecl, more consistent with @typeInfo
  • It seems like @reflectDecl could almost be dropped completely:
const decl_type = @TypeOf(@field(T, "..."));
const decl_align = @typeInfo(@TypeOf(&@field(T,"..."))).Pointer.alignment;

The only thing missing is reflection for the linksection

@andrewrk
Copy link
Member Author

andrewrk commented Feb 1, 2022

I don't like "Info" in the name. It's redundant. Literally everything in programming is "info".

@andrewrk andrewrk changed the title reflection: make @typeInfo not resolve declarations add @reflectDecl and @reflectFn builtins Feb 1, 2022
@andrewrk andrewrk removed the accepted This proposal is planned. label Feb 1, 2022
@andrewrk andrewrk modified the milestones: 0.10.0, 0.11.0 Feb 1, 2022
@jibal
Copy link

jibal commented Mar 29, 2022

I don't like "Info" in the name. It's redundant. Literally everything in programming is "info".

fooInfo usually means info about a foo, vs. a foo. It's easier to write fooInfo(foo: Foo) FooInfo {...} than informationAboutThisFoo(foo: Foo) InformationAboutFoo { ... } . Just calling it foo(foo: Foo) Foo { ... } makes no sense and is clearly wrong. Trying to replace "Info" due to a misconception leads to nothing good. (Like renaming TypeInfo to Type--it's not a type and it's not the type of a type, its a struct that contains information about a type.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking Implementing this issue could cause existing code to no longer compile or have different behavior. 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

4 participants