-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Proposal: code annotations #14656
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
Comments
lots of downvotes. Any comments why? Can you steelman this argument? Did you read the part where I mention |
For what it's worth, I completely ignore the emojis on any proposal. They mean nothing to me |
Related proposal: #1099 |
sure, but if folks are truly displeased with it it would at least be good to understand why so that maybe a better alternative can be forged. I'm not particularly tied to this specific way of achieving this, but I noticed this when developing zigler (and TBQF felt a little bit dirty about how I achieved it) and forsee the issue of collisions if it continues to be a wild west. |
I like the feel of various tags (and that it's structured data) in #1099, (e.g. assigning to pub const) but as it is it only really lets you tag structs, you would need some indirection to tag functions, but for the purposes of 3rd party stuff it think it might be hard to get at them either through ZIR analysis or side-compiling and doing SEMA, if they're inside a non-public struct at the to level of any given file. |
What do level 0 and level 1 provide over the status quo of
I could see plenty of scenarios where this isn't true if
is true. If an external tool can be triggered during Parse, AstGen, or Sema, then it could create or modify a file that later gets imported. Ultimately, having hooks into Compilation like this easily allow for Probably Bad Things. |
I think having some form of structured annotations is useful and even a good idea. However, level 2 is probably a bad idea. The "build tools" integration should just be a This could solve multiple things in one generic way:
/// A helpful doc comment
///: a: the left param
///: b: the right param
///: return: the sum of a and b
fn add(a: usize, b: usize) void{
return a + b;
} |
I actually like that idea. May help with zig document generation, and would help with the use case of documenting parameter names in functions that don't have many parameters. E.g., right now, documenting the exemplified /// A helpful doc comment
fn add(
/// the left param
a: usize,
/// the right param
b: usize,
) usize {
return a + b;
} And there isn't even a way to explicitly add a doc comment for the "return". Another documentation-related use case this may help address is "related function mentions". Often times functions will mention other functions, which is helpful, but it comes with the unfortunate downside that they will sometimes go out of date, when mentioned functions get renamed, deprecated, etc. A third party tool could detect something like ///: See also: `bar`, `baz`
fn foo() void {} and help ensure that the declarations And another pretty simple one would be depreciation annotations, a la I was a bit skeptical of this proposal on first reading, but I now think it would actually make sense to standardize on "comment annotations", beyond hard-coded stuff like |
I will say no because this will make people write a ton of useless comment lines and pages worth of information that is not critical and traiting every function silently instead of designing good api. |
the one use case i see this mainly potentially helping with is being able to label anytype parameters as interfaces for tooling eg |
@eLeCtrOssSnake it allows one to annotate with static checks which cannot (or won't) be performed by zig similar to liquidhaskell in a standard format rather than having multiple tools defining their own special format which may collide or clutter things even more. |
I like the idea of "basic" (level 0) annotations (they're like Go's struct tags, just a bit more general). It'd definitely be useful for [de]serializers, HTTP servers, etc if it were exposed at comptime. I'd suggest that the data, rather than being a part of |
This proposal is 1. missing on how the Zig compiler ensures that a tag has a correct semantic mapping and no duplicates or missing semantics attached to it. Also, 2. Consider the following:
To prevent having to repeat the C trap of adding incompatible things, I would suggest to combine the semantics of an annotation to "a required source of truth" like how Zig file references work. Think of it as something like required "mypy version + semantics" document, but it could be also a versioned link to the standard document or a fully versioned git repository. I think a declarative approach to specify the code annotation in each file should be sufficient: //: annotation special_json semantic_file
//: special_json: some_annotation
fn create() !void {
..
} However, the most problematic tradeoffs to be made are (to me) that annotations either 1. are compact and inline with comments, but this means at worst external parser-library complexity, 2. compact, but limited in expressivity or 3. create rather ugly and verbose newlines. Implementation detail(s) for code annotations on newline approach If the AST would have comments and spacing separated from code,
This is missing more design work/experimentation on how this could or should work with comptime-resolving plus, more importantly, a very convincing + general use case. |
Point taken. Presuming each library has a consistent idea of what it's using for annotations, you could have something in build.zig that remaps its tags. So, suppose library 1 has tags called "tracker" that map to the "footracker" plugin There could be a mechanism to map your software (which wishes to use both footracker and bartracker) to the "footracker" and "bartracker" tags) -- or say you could map footracker to "tracker1" and bartracker to "tracker_a", whatever, you want, in build.zig
I don't love this required on a file-by-file basis, but I think build.zig would be okay.
Agreed. I do like the @tag proposal elsewhere, in that it literally creates something that must be zig parseable syntax (and therefore "pretty") |
Right, this should be considered "disallowed behaviour". Of course it will be impossible? [*] to enforce this, but just provide guidance and the community I think is strong enough to call it out and refuse to use software that behaves badly. [*] I mean, maybe? It is likely possible to run an integrity check. |
I was intending to specify it better. I think it should link to an arbitrary, but required to be semantically versioned package. However, the package should be "optional", so that the analyzer can do its own thing and download is done by the analyzer/prover on demand (if no incompatibility exists etc). Ideally, Zig can guide this, but I have not thought yet on how exactly optional downloads could work in practice for (potentially) recursive dependencies.
The main reason I dislike |
Go has a similar feature, where you can tie any string as a "tag" to a struct's field. However, this has actually caused quite a bit of frustration because it's just a string. There's a very well-liked proposal (golang/go#23637) which allows any data structure to be tied to a field, which provides a number of benefits (fixes name clashing, autocomplete issues, typos are caught at compile-time, better expressibility, etc). It may be good to learn from Go's mistake, and allow tying any data structure to containers/fields rather than only strings. |
closing in favor of #1099 |
Uh oh!
There was an error while loading. Please reload this page.
The proposal is to introduce "code annotations", these are a special type of comment that, like doc comments, are tied to a specific piece of code. These are hints for 3rd party tooling to do things such as autogenerate surrounding code, or do static analysis.
Might be considered to be similar to pragmas in other languages, but see the Restrictions
Basic - level 0
Example (tags a function as BEAM-nif):
Example (for a hypothetical http server framework):
The (tentative) syntax of a annotation is:
//:<whitespace>identifier<colon> <any string>
More advanced - level 1
Internally make doc comments
///
and//!
special cases of//:
Even more advanced - level 2
create a way for the zig compiler to register 3rd party static analysis tools that can asynchronously subscribe to zig parser events, sema completion, zir generation, mir generation events, and code annotations. An analyzer could then track the code's custodianship, like responsibility to clean up resources (memory, file descriptors, etc). The analyzer could halt zig compilation.
Example (resource tracking):
Example (contract checking):
Cons
This is potentially embedding other languages in zig, which does break simplicity. However, I think in many cases there already is the temptation to do this anyways, as was the case with zigler's annotations hijacking docstrings (even though future elixir versions of zigler will not use this mechanism -- still may need to do it with erlang).
In other words, if we don't provide guidelines, people will probably find a way to do it anyways, and interop between colliding toolchain could be a problem.
Restrictions
unlike pragmas, code annotations are never allowed to affect the final compiled artifact of the code (aside from possibly halting compilation altogether, as in level 3). Otherwise this really runs afoul of breaking the principle of zig's simplicity and readability... As it is it's a little bit dangerous since this is tantamount to embedding other languages in zig.
Unopinionated
//:
The text was updated successfully, but these errors were encountered: