From 1cbffdbd9cf1ee0192949faa1f377b6977a6bf88 Mon Sep 17 00:00:00 2001 From: Ryan Burns Date: Sun, 17 Oct 2021 18:35:34 -0700 Subject: [PATCH] Add "inherit-as-list" syntax construct to the Nix language --- rfcs/0110-inherit-as-list.md | 120 +++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 rfcs/0110-inherit-as-list.md diff --git a/rfcs/0110-inherit-as-list.md b/rfcs/0110-inherit-as-list.md new file mode 100644 index 0000000..d1a3436 --- /dev/null +++ b/rfcs/0110-inherit-as-list.md @@ -0,0 +1,120 @@ +--- +feature: inherit-as-list +start-date: 2021-10-17 +author: Ryan Burns (@r-burns) +co-authors: (find a buddy later to help out with the RFC) +shepherd-team: (names, to be nominated and accepted by RFC steering committee) +shepherd-leader: (name to be appointed by RFC steering committee) +related-issues: (will contain links to implementation PRs) +--- + +# Summary +[summary]: #summary + +This RFC proposes a new Nix syntax `inherit () [ ]`, which +constructs a list from the values of an attrset. + +The goal is to provide a similarly-terse but more principled alternative +to the often-used `with ; [ ]`. + +# Motivation +[motivation]: #motivation + +It is currently cumbersome to create a list from the values of an attrset. +If one has an attrset `attrs` and wishes to create a list containing some of +its values, one could naively write: + +```nix +[ attrs.a attrs.b attrs.c ] +``` + +To avoid typing `attrs` many times, one will typically use `with` instead: + +```nix +with attrs; [ a b c ] +``` + +However, the `with` expression has many well-known drawbacks, such as +unintuitive shadowing behavior [1], prevention of static scope checking [2], +and reduced evaluation performance [2]. + +* [1] https://github.com/NixOS/nix/issues/1361 +* [2] https://github.com/NixOS/nixpkgs/pull/101139 + +Nonetheless, Nix expression authors are subtly guided toward the `with` form +because it is (or at least appears) simpler than any existing alternatives. + +The goal of this RFC is to provide a similarly-terse alternative which avoids +these drawbacks. + +# Detailed design +[design]: #detailed-design + +The proposed expression syntax is: + +```nix +inherit (attrs) [ a b c ] +``` + +The `inherit` keyword is intentionally reused so as to not add any new +keywords to the Nix grammar. + +As this expression is currently a syntax error, a Nix interpreter which +supports this language feature will be compatible with existing Nix code. + +An implementation PR is pending. + +For MVP functionality, only minor additions to `src/libexpr/parser.y` are +needed. If accepted, the changes to the Nix interpreter can be backported +to current releases if desired. Relevant language documentation and +third-party parsers/linters would also need to be updated. + +# Examples and Interactions +[examples-and-interactions]: #examples-and-interactions + +This would be useful for many languages and frameworks in Nixpkgs which +extract packages from a package set argument. + +For example, `python3.withPackages (ps: inherit (ps) [ ... ])` will serve as a +more fine-grained alternative to `python3.withPackages (ps: with ps; [ ... ])`. +This would apply similarly to `vim.withPlugins`, `lua.withPackages`, etc. + +Certain list-typed `meta` fields could also make use of this feature, e.g.: +```nix +meta.licenses = inherit (lib.licenses) [ bsd3 mit ]; +meta.maintainers = inherit (lib.maintainers) [ johndoe janedoe ]; +``` + +And build inputs which are commonly extracted from attrsets: +```nix +buildInputs = inherit (darwin.apple_sdk.frameworks) [ + IOKit +] ++ inherit (llvmPackages) [ + llvm +]; +``` + +# Drawbacks +[drawbacks]: #drawbacks + +* This will add complexity to the Nix grammar and any third-party tools which + operate on Nix expressions. +* Expressions reliant on the new syntax will be incompatible with + Nix versions prior to the introduction of this feature. + +# Alternatives +[alternatives]: #alternatives + +* Skillful use of `with` to avoid its drawbacks +* Fine-grained attribute selection via existing (more verbose) language + features, such as `builtins.attrValues (inherit (attrs) a b c;)` + +# Unresolved questions +[unresolved]: #unresolved-questions + +How would this feature be adopted, if accepted? + +# Future work +[future]: #future-work + +Determine best practices regarding when this language construct should be used