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

Proposal: Make main and panic attributes, rather than reserved names #5224

Closed
ghost opened this issue Apr 30, 2020 · 5 comments
Closed

Proposal: Make main and panic attributes, rather than reserved names #5224

ghost opened this issue Apr 30, 2020 · 5 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@ghost
Copy link

ghost commented Apr 30, 2020

(REVISED -- see below)

Say someone didn't know about the implementation of the panic handler, and tried to implement a function by the name of panic. Their crashes would be very confusing, and they wouldn't know where to look to fix the problem.

I propose, instead of reserving function names, we instead expose an attribute to mark a function as the entry point, the panic handler, or neither. Not only would this make clear the privileged nature of these functions, it would also allow us to implement more idiomatic names, like this (syntax inspired by #4285):

const master = fn (
    num_args: usize,
    args: [*:0]const [*:0]const u8,
) void .{ .access = .Entry } {
    // ...
};

const hang = fn (
    message: []const u8,
    trace: ?*builtin.StackTrace,
) noreturn .{ .access = .Panic } {
    while (true) {}
};

(.access is just a first idea -- I'm sure there's a better name.)
There are three possibilities -- .Entry for the entry point, .Panic for the panic handler, and .Common for everything else. .Common is the default. .Entry and .Panic enforce parameter and return types. Exactly one .Entry and at most one .Panic is required per project -- if we liked, we could fall back to main and panic if these were not present, so this change doesn't have to be breaking.

@Vexu Vexu added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Apr 30, 2020
@Vexu Vexu added this to the 0.7.0 milestone Apr 30, 2020
@ghost
Copy link
Author

ghost commented Apr 30, 2020

Some cons from discussion on Discord:

Added here for fairness.

@rohlem
Copy link
Contributor

rohlem commented Apr 30, 2020

I'm generally in favour of getting rid of "magic reserved names" if possible, even if it doesn't seem high-priority to me personally. The two downsides I see in the proposed approach is that

  • .access is a "global" function attribute for solving this (to me seemingly) "local" problem (only applicable to special functions that the standard library defines).
    We either allow arbitrary attributes (which I'm not against), or we've moved the magic from function names to function attributes (which you could argue is still an improvement).
  • If you think about the standard library querying code, currently we look for a special name, which is O(1). Additionally indexing functions by their attributes would work, but is again a special case scenario. Otherwise, looking over all functions defined in the root source file equally would be an O(N) approach.

Here's an alternative idea that communicates the "magic" more clearly: providing a comptime function, to call in a comptime block of code. I.e., any source file (usually the root source file) could include the following:

comptime {
 const std = @import("std");
 std.start.registerMainFunction(myMainFunction); //pro: clearly identify that we're communicating configuration for std/start.zig 
 std.builtin.registerPanicHandler(myPanicHandler); //more fitting location I think, since @panic is a language-level construct, though I don't know where the handling code for this currently is.
 std.io.setGlobalDefaultIoMode(.evented); //This strategy would also be applicable for other declarations we currently expect in the "root source file".
}

This would clearly indicate that we're configuring comptime logic.

  • con: I don't know if this would actually work. We would need to enforce a sort of "comptime order" so that the registration calls can use the functions defined by std/start.zig, before std/start.zig does its own comptime-logic of detecting main functions and exporting symbols. Although in this particular use case, if we know the number of registrees, we could insert that logic into the first (expected last) invocation of the registration functions.
    If I think of it in terms of an acyclic dependency graph, I would argue we should find a way to make this structure generally work for Zig code, but this might impose a stricter ordering and inter-module dependency than is planned for the compiler execution.
  • pro (I think): Now any source file could define a main function or panic handler. We could also check for multiple registrations and emit a fitting @compileError.
  • pro: We could potentially use this registration idea to get rid of the "root source file" special casing of @import. (You could still preserve the old behaviour, by restricting these configurations to root source files, and making sure nothing else in your project references the root source files.)

@ghost
Copy link
Author

ghost commented May 1, 2020

I do like that idea better. I hadn't even thought of io_mode. The question is, do we want to permit arbitrary distance between a function declaration and its "access"? The laziest thing to do would be to define all the external hooks in one block -- on the one hand, this would make it easier to find them if they were in strange places; on the other hand it wouldn't be obvious by looking at the functions themselves which ones were hooks. To me personally, that could go either way, but the inclusion of io_mode in the latter approach sways me.

@ghost
Copy link
Author

ghost commented May 1, 2020

Actually, we could just make registerMainFunction the entry point to start.zig, and that way we'd even adhere more closely to the paradigm of an optional std.

@ghost
Copy link
Author

ghost commented May 1, 2020

Upon further reflection, this would be a large amount of work for little to no benefit, a lot of compiler complexity, and even some end user detriment -- there is now no longer a single place to look for all the entry points. I see no reason this should stay open.

@ghost ghost closed this as completed May 1, 2020
This issue was closed.
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