CONTRIBUTING: establish builtins prefix convention for prelude#449123
CONTRIBUTING: establish builtins prefix convention for prelude#449123trueNAHO wants to merge 1 commit into
Conversation
| @@ -683,6 +661,15 @@ If you have any problems with formatting, please ping the [formatting team](http | |||
| As an exception, an explicit conditional expression with null can be used when fixing a important bug without triggering a mass rebuild. | |||
| If this is done a follow up pull request _should_ be created to change the code to `lib.optional(s)`. | |||
|
|
|||
| - Certain [prelude | |||
| attributes](https://nix.dev/manual/nix/latest/language/builtins.html) should | |||
There was a problem hiding this comment.
The NixOS/nix#14015 change is not yet visible on this link. Is this the correct one?
There was a problem hiding this comment.
It'll be part of the next release of Nix.
| - Certain [prelude | ||
| attributes](https://nix.dev/manual/nix/latest/language/builtins.html) should | ||
| explicitly use the `builtins` prefix, while others should conveniently omit | ||
| it: | ||
|
|
||
| | Use `builtins` | Omit `builtins` | | ||
| |----------------|-----------------| | ||
| | <li>`builtins.abort`</li><li>`builtins.baseNameOf`</li><li>`builtins.break`</li><li>`builtins.derivation`</li><li>`builtins.derivationStrict`</li><li>`builtins.dirOf`</li><li>`builtins.false`</li><li>`builtins.fetchGit`</li><li>`builtins.fetchMercurial`</li><li>`builtins.fetchTarball`</li><li>`builtins.fetchTree`</li><li>`builtins.fromTOML`</li><li>`builtins.import`</li><li>`builtins.isNull`</li><li>`builtins.map`</li><li>`builtins.null`</li><li>`builtins.placeholder`</li><li>`builtins.removeAttrs`</li><li>`builtins.scopedImport`</li><li>`builtins.throw`</li><li>`builtins.toString`</li><li>`builtins.true`</li> | <li>`abort`</li><li>`baseNameOf`</li><li>`break`</li><li>`derivation`</li><li>`derivationStrict`</li><li>`dirOf`</li><li>`false`</li><li>`fetchGit`</li><li>`fetchMercurial`</li><li>`fetchTarball`</li><li>`fetchTree`</li><li>`fromTOML`</li><li>`import`</li><li>`isNull`</li><li>`map`</li><li>`null`</li><li>`placeholder`</li><li>`removeAttrs`</li><li>`scopedImport`</li><li>`throw`</li><li>`toString`</li><li>`true`</li> | |
There was a problem hiding this comment.
This is written as a placeholder to make it easier to later decide what should be added to each category.
For convenience, here is the rendered table:
Use builtins |
Omit builtins |
|---|---|
builtins.abortbuiltins.baseNameOfbuiltins.breakbuiltins.derivationbuiltins.derivationStrictbuiltins.dirOfbuiltins.falsebuiltins.fetchGitbuiltins.fetchMercurialbuiltins.fetchTarballbuiltins.fetchTreebuiltins.fromTOMLbuiltins.importbuiltins.isNullbuiltins.mapbuiltins.nullbuiltins.placeholderbuiltins.removeAttrsbuiltins.scopedImportbuiltins.throwbuiltins.toStringbuiltins.true |
abortbaseNameOfbreakderivationderivationStrictdirOffalsefetchGitfetchMercurialfetchTarballfetchTreefromTOMLimportisNullmapnullplaceholderremoveAttrsscopedImportthrowtoStringtrue |
There was a problem hiding this comment.
This isn't the correct "Use builtins" list. Here's what I get:
Save this as t.nix:
builtins.attrNames (removeAttrs builtins [ "abort" "baseNameOf" "break" "derivation" "derivationStrict" "dirOf" "false" "fetchGit" "fetchMercurial" "fetchTarball" "fetchTree" "fromTOML" "import" "isNull" "map" "null" "placeholder" "removeAttrs" "scopedImport" "throw" "toString" "true" ])
Run it with nix-instantiate --strict --json --eval t.nix | jq -r '.[] | "1. " + .':
- add
- addDrvOutputDependencies
- addErrorContext
- all
- any
- appendContext
- attrNames
- attrValues
- bitAnd
- bitOr
- bitXor
- builtins
- catAttrs
- ceil
- compareVersions
- concatLists
- concatMap
- concatStringsSep
- convertHash
- currentSystem
- currentTime
- deepSeq
- div
- elem
- elemAt
- fetchurl
- filter
- filterSource
- findFile
- flakeRefToString
- floor
- foldl'
- fromJSON
- functionArgs
- genList
- genericClosure
- getAttr
- getContext
- getEnv
- getFlake
- groupBy
- hasAttr
- hasContext
- hashFile
- hashString
- head
- intersectAttrs
- isAttrs
- isBool
- isFloat
- isFunction
- isInt
- isList
- isPath
- isString
- langVersion
- length
- lessThan
- listToAttrs
- mapAttrs
- match
- mul
- nixPath
- nixVersion
- parseDrvName
- parseFlakeRef
- partition
- path
- pathExists
- readDir
- readFile
- readFileType
- replaceStrings
- seq
- sort
- split
- splitVersion
- storeDir
- storePath
- stringLength
- sub
- substring
- tail
- toFile
- toJSON
- toPath
- toXML
- trace
- traceVerbose
- tryEval
- typeOf
- unsafeDiscardOutputDependency
- unsafeDiscardStringContext
- unsafeGetAttrPos
- warn
- zipAttrsWith
There was a problem hiding this comment.
Maybe I misunderstood your table, though.
There was a problem hiding this comment.
This isn't the correct use builtins list. Here's what I get:
Save this as
t.nix:builtins.attrNames (removeAttrs builtins [ "abort" "baseNameOf" "break" "derivation" "derivationStrict" "dirOf" "false" "fetchGit" "fetchMercurial" "fetchTarball" "fetchTree" "fromTOML" "import" "isNull" "map" "null" "placeholder" "removeAttrs" "scopedImport" "throw" "toString" "true" ])[...]
Maybe I misunderstood your table, though.
Yes, sorry for the confusing placeholder template and not providing any real explanations.
The idea was to declare which prelude attributes go into the "Use builtins" or "Omit builtins" category. For example, if true is preferred over builtins.true, then true would be added to the "Omit builtins" category and would be removed from "Use builtins":
Use builtins |
Omit builtins |
|---|---|
true |
For conciseness, the table should only focus on prelude attributes and ignore the other builtins that require the builtins prefix. With that in mind, feel free to propose better table formats.
Currently, both categories contain all prelude attributes to make it easier to remove them from each category later on.
See #449123 (comment) for a real table example.
Establish the builtins prefix convention for prelude attributes to
progress [1] ("Unwritten style guides should be written"), following the
treewide removal of the builtins prefix for prelude attributes [2] [3]
[4] [5] [6].
[1]: NixOS#387072
[2]: NixOS#444432
[3]: NixOS#447401
[4]: NixOS#447402
[5]: NixOS#447403
[6]: NixOS#447404
20fa8fd to
abc82de
Compare
Let's ping @NixOS/nix-formatting too; although focused on formatting nix code, some members may have an interest in style guides too. Since you pinged statix, let's cc the nixf-diagnose maintainer too @inclyc
Most things can be decided in issues and PRs. That's even more true now we have a @NixOS/nixpkgs-core team who can make controversial decisions when necessary. RFCs are only useful when we need to have complex and in depth discussion over a long drawn out period of time. Also, they are only effective when someone is able to proactively steer the RFC towards a conclusion. Personally, I'd like to avoid introducing trivial style rules that need to be enforced manually by authors and reviews.* They usually result in nit-picky reviews that frustrate both the reviewer themselves and the PR author. Unless there's a good reason to add specific guidance, I strongly prefer having linters and formatters define and enforce the style guide where possible. *Of course, with enough effort this could be enforced by a linter. I'm not opposed to discussing what the ideal style should be, assuming there is one; that way someone can go off and implement linting rules for that ideal style. |
Agreed. Implementing this in statix has already been proposed in oppiliappan/statix#140. IIUC, https://github.com/oppiliappan/statix/milestone/1 would allow enforcing this in CI with statix. |
|
|
I'm in favor of this on purely "it's shorter" grounds. Now that it's documented as part of upstream Nix, it's not just esoteric knowledge. But it's also not a huge deal. |
wolfgangwalther
left a comment
There was a problem hiding this comment.
We should only make the contribution guides even longer if we can't encode something as a linter rule or so (yet).
AFAICT, this has been implemented in nix-community/nixd#721. We already have nixf-diagnose in CI now, so this is just a question of updating nixd in nixpkgs, waiting for it to reach the channel, updating the pin, running it via nixf-diagnose.
From what I can tell, this also supports auto-fix.
Thus, I think we shouldn't do any of this PR.
If it merely enforces the treewide removal of the builtins prefix for all prelude attributes, then the main point of this proposal has not been addressed yet:
For example, following up on the #449123 (comment) discussion, one possible prelude convention could be:
For example, Furthermore, we should carefully consider extending the prelude:
Enforcing the convention this proposal is trying to establish can be done at a later stage:
|
This is certainly out of scope for Nixpkgs. This needs to be done in Nix - and also Lix. Before any of that could be relevant for Nixpkgs, that would take a few years, because we keep compatibility here. The most consistent and least controversial thing we can do is to enforce removal of the We could also force the addition of the |
I commented this on the nixf PR as well, but for coherence I'll mention it here: Every globally-exposed primop (not prefixed with
|
👍🏼 |
I agree that discussing adding new things to the prelude is out of scope for a Nixpkgs issue, but whether we want to encourage or discourage specific uses of the prelude is definitely in scope for this issue. E.g. do we want to encourage using With nixpkgs' compatibility in mind, we should also note that any decisions to add to the prelude would mean the nixd (libnixf) implementation needs to change to support an explicit list, version pinning, or similar. Currently it extracts the list automatically from nix's C++. Given the prelude hasn't changed in a long time (thanks @eclairevoyant for confirming), I assume the nix team(s) would now prefer to avoid adding new names to it. But that is an assumption. If we wanted to discourage specific prelude usage (e.g. I guess
Agreed, I don't think we should merge verbose and prescriptive documentation here when we can enforce it automatically. At the most, I'd expect the docs to say something brief like: :::{.note}
Some builtins can be access directly, without typing `builtins.`.
Nixpkgs enforces this style automatically in `treefmt`.
:::Although this PR isn't just about its actual changes, it also servs as a discussion thread to talk about the broarder issue. Maybe an issue would've been better for that, but we're here now with relevant parties already pinged. |
Unlike removing builtins prefixes, adding them back in a follow-up PR should be fully automatable, including updates to code comments and documentation.
As pointed out in #447402 (comment), it seems inconsistent that
builtins.fromTOMLis in the prelude whilebuiltins.toJSONis not. I suppose this stems from historical reasons to avoid breaking language changes.Beyond establishing builtins prefix conventions, this proposal should decide whether to add more attributes to the prelude or discourage existing ones. For example, should
builtins.fromJSONbe added, or shouldfromTOMLbe discouraged in favor ofbuiltins.fromTOML? Since expanding the prelude increases language complexity, this requires careful consideration.Although this proposal is a non-functional change, it has far-reaching consequences for the Nix style guide. I am pinging several people to raise awareness:
statix: @mightyiam, @oppiliappanConsidering the far-reaching consequences of this proposal, should this be elevated to an RFC, or is a PR discussion fine?
Things done
passthru.tests.nixpkgs-reviewon this PR. See nixpkgs-review usage../result/bin/.Add a 👍 reaction to pull requests you find important.