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

Move callconv, align, addrspace, and linksection annotation before function parameter list #22263

Open
mlugg opened this issue Dec 17, 2024 · 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

@mlugg
Copy link
Member

mlugg commented Dec 17, 2024

Split out from #11834. Depends on #22261.

If callconv etc cannot reference function parameters, then it seems inconsistent for them to be written after the parameter list:

// why can't I do this? `b` is declared before the `callconv(...)` expression!
fn f(comptime b: u32) callconv(if (b) .c else .auto) void {}

So, this proposal is for a simple syntax change. callconv(...), align(...), addrspace(...), and linksection(...) annotations on functions should be moved before the parameter list, just after the fn keyword, to make it clear that function parameters are inaccessible in those expressions.

fn callconv(.c) f(comptime b: u32) void {
    _ = b;
}

A zig fmt fixup can exist for one release cycle which just moves these annotations to their new location.

@mlugg mlugg 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 Dec 17, 2024
@mlugg mlugg added this to the 0.15.0 milestone Dec 17, 2024
@rohlem
Copy link
Contributor

rohlem commented Dec 17, 2024

Other (const and var) declaration names aren't allowed to appear in their own align, addrspace, and linksection specifiers/annotations either, right? How about we move them to the left everywhere?
EDIT: or, as suggested below, even before the introductory keyword:
fn f() align(16) void {} -> align(16) fn f() void {}
const x: u8 align(8) = 15; -> align(8) const x: u8 = 15;
ptr: ?*anyopaque align(1) = null, -> align(1) ptr: ?*anyopaque = null,

@xdBronch
Copy link
Contributor

xdBronch commented Dec 18, 2024

i think this very badly hurts the readability and searchability of functions. i assume this would also change the placement for function types? fn callconv(.c)() void looks very strange imo, maybe the current place isnt the best option if #22261 happens but im not a fan of this one.
not sure i like this either but what about even before the fn? callconv(.@"inline") fn foo() meshes reasonably with inline fn foo() for example

@paperdave
Copy link
Contributor

a strategy i use to locate code is by a project wide search for fn nameOfFunction(, with the fn and ( tokens refining the search to just definitions of the identifier, as every function definition in Zig currently matches that pattern.

@castholm
Copy link
Contributor

castholm commented Dec 18, 2024

I realize I'm reiterating what has already been said above, but being able to easily and reliably grep/search for names of types and functions using fairly basic patterns like (const|var|fn) foobar\b is very important for productivity (at least for me personally, but I suspect for many other developers as well). Placing annotations like callconv between the fn keyword and the identifier would make grepping less reliable, especially in code bases that interface heavily with C or otherwise make frequent use of these annotations.

@xdBronch's suggestion of placing the annotations before the fn keyword would preserve the current greppability, but if that for some reason is problematic for grammar/parsing reasons, another option is placing them between the identifier and the parameter list, i.e.

fn foobar callconv(.c) (a: u32, b: []const u8) !void

It might look and read a bit awkward, but at least it remains matched by patterns like fn foobar\b.

(I'm also not sure if I personally agree with the idea that "some things that come after the parameters can't reference the parameters" is a big issue or potential source of confusion in the first place. A little inelegant, maybe, but as a user it's pretty easy to accept and live with.)

@mlugg
Copy link
Member Author

mlugg commented Dec 21, 2024

Thanks for the feedback, everyone.

I'm actually starting to think that moving these annotations before the fn keyword would actually work quite nicely; it brings the desired property that parameters can always be referenced after they're declared, it maintains greppability, and it meshes nicely with pub, inline, and noinline. So:

// (should `pub`, `inline`, `noinline` go before or after these annotations? I have no idea)
pub align(4) addrspace(.something) linksection(".foo") callconv(.c) fn foo() void {
    // ...
}

If we're doing that, then it makes sense to also move them for const and var:

pub align(128) addrspace(.foo) linksection(".bar") var x: u32 = 123;

I'd be interested in getting some more thoughts on this. I don't think it would introduce any grammar problems.

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

5 participants