-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
std.zig.fmtId
: conditionally escape primitives/_
(breaking)
#18920
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
Conversation
This is a breaking change. This updates `std.zig.fmtId` to support conditionally escaping primitives and the reserved `_` identifier via format specifiers: - `{}`: escape invalid identifiers, identifiers that shadow primitives and the reserved `_` identifier. - `{p}`: same as `{}`, but don't escape identifiers that shadow primitives. - `{_}`: same as `{}`, but don't escape the reserved `_` identifier. - `{p_}` or `{_p}`: only escape invalid identifiers. (The idea is that `p`/`_` mean "allow primitives/underscores".) Any other format specifiers will result in compile errors. Additionally, `isValidId` now considers `_` a valid identifier. If this distinction is important, consider combining existing uses of this function with the new `isUnderscore` function.
`{}` for decls `{p}` for enum fields `{p_}` for struct fields and in contexts following a `.` Elsewhere, `{p}` was used since it's equivalent to the old behavior.
This might fix a CI failure for powerpc64le-linux-musl.
I have absolutely no idea why this failed on the Linux runners, I don't see how the changes in this PR are related to I replaced it with |
Related: |
This updates
std.zig.fmtId
to support conditionally@""
escaping primitives and the reserved_
identifier via format specifiers:{}
: escape invalid identifiers, identifiers that shadow primitives and the reserved_
identifier.{p}
: same as{}
, but don't escape identifiers that shadow primitives.{_}
: same as{}
, but don't escape the reserved_
identifier.{p_}
or{_p}
: only escape invalid identifiers.In other words, the default empty
{}
specifier is as conservative as possible and you addp
and/or_
to add primitives/_
to the set of identifiers that can be rendered unescaped.Any other format specifier is a compile error.
Motivation
Correctly formatted and escaped code generation. Status quo
fmtId
is problematic because it doesn't escape primitives, which means programs that generate Zig code currently need to implement their own formatters that also checkstd.zig.primitives.isPrimitive
for rendering declaration identifiers.Breaking changes and mitigations
print("{}", .{std.zig.fmtId(foo)})
did not@""
escape primitives before, but now does. Use{p}
for the old behavior.print("{s}", .{std.zig.fmtId(foo)})
(or any other unrecognized specifier) is now a compile error. Again, use{p}
for the old behavior.isValidId
now considers_
to be a valid identifier (which it is, in certain contexts). If this distinction is important, consider combining existing uses of this function with the newisUnderscore
function;std.zig.isValidId(foo)
should be replaced withstd.zig.isValidId(foo) and !std.zig.isUnderscore(foo)
.Additional considerations
fmtId
can currently render illegal identifiers like@""
and@"\x00"
. It could be updated to return an error for these cases, but I would suggest accepting #14534 instead since it would ease the burden of code generators and mean that every possible identifier can be represented in Zig in some form, either escaped or unescaped.