|
| 1 | +--- |
| 2 | +feature: no-nested-with |
| 3 | +start-date: 2021-01-11 |
| 4 | +author: Ellen Emilia Anna Zscheile (@fogti) |
| 5 | +co-authors: @sternenseemann |
| 6 | +shepherd-team: (names, to be nominated and accepted by RFC steering committee) |
| 7 | +shepherd-leader: (name to be appointed by RFC steering committee) |
| 8 | +related-issues: (will contain links to implementation PRs) |
| 9 | +--- |
| 10 | + |
| 11 | +# Summary |
| 12 | +[summary]: #summary |
| 13 | + |
| 14 | +Disallow or discourage usage of multiple `with` expressions covering |
| 15 | +the same expression / forbid nesting `with` expressions, even indirectly. |
| 16 | +If infeasible in general (e.g. forbidding it in all nix expressions), |
| 17 | +this can be limited to nixpkgs. |
| 18 | + |
| 19 | +# Motivation |
| 20 | +[motivation]: #motivation |
| 21 | + |
| 22 | +It makes static analysis of nixpkgs easier, because as soon as `with` |
| 23 | +expressions are nested, it becomes basically impossible to [statically |
| 24 | +deduce where any free variable comes from] without implementing a |
| 25 | +full-blown nix evaluator including lazy evaluation, which is difficult as |
| 26 | +soon as `with` expressions and mutually recursive imports are involved |
| 27 | +(e.g. as currently present in `nixpkgs/lib/systems/{inspect,parse}.nix`). |
| 28 | + |
| 29 | +# Detailed design |
| 30 | +[design]: #detailed-design |
| 31 | + |
| 32 | +At least warn about any nested usage of `with` expressions, |
| 33 | +at least when they get evaluated, possibly even when they get parsed. |
| 34 | +After a grace period ("real time", probably a few months or years, not as in |
| 35 | +"a timeout when interpreting" because that wouldn't make sense), |
| 36 | +abort instead. |
| 37 | + |
| 38 | +When the full approach (aborting instead of warning) is applied, |
| 39 | +any reference to any free variable can be easily resolved |
| 40 | +to the enclosing `with` expression "scope-include", and because |
| 41 | +this `with` expression couldn't then be enclosed by another |
| 42 | +one, even indirectly, no lookup ambiguity exists. |
| 43 | + |
| 44 | +# Examples and Interactions |
| 45 | +[examples-and-interactions]: #examples-and-interactions |
| 46 | + |
| 47 | +```nix |
| 48 | +pkgs: { |
| 49 | + # allowed |
| 50 | + a = with pkgs; patchelf; |
| 51 | +
|
| 52 | + # disallowed |
| 53 | + b = with pkgs; with lib; patchelf; |
| 54 | +
|
| 55 | + # also disallowed |
| 56 | + c = with pkgs; { |
| 57 | + meta = with lib; { |
| 58 | + license = with licenses; [ mit ]; |
| 59 | + }; |
| 60 | + }; |
| 61 | +} |
| 62 | +``` |
| 63 | + |
| 64 | +# Drawbacks |
| 65 | +[drawbacks]: #drawbacks |
| 66 | + |
| 67 | +* Backward-incompatible, requires changing Nix code used "in the wild". |
| 68 | + |
| 69 | +# Alternatives |
| 70 | +[alternatives]: #alternatives |
| 71 | + |
| 72 | +* Introduce a kind of `with-only` expression which allows bringing an attrset |
| 73 | + into scope while simultaneously hiding the outer scope, such that all |
| 74 | + inner free variables are either resolved via the given attrset, or |
| 75 | + result in an error. |
| 76 | + Similar to this is [RFC 110](https://github.com/NixOS/rfcs/pull/110), |
| 77 | + which introduces an `inherit-as-list` construct which solves the primary |
| 78 | + application of `with-only`, list specification in `meta` attributes of |
| 79 | + nixpkgs derivatons. |
| 80 | + |
| 81 | +* Completely ban the usage of `with` in nixpkgs; |
| 82 | + seems unnecessarily excessive for this problem. |
| 83 | + |
| 84 | +# Unresolved questions |
| 85 | +[unresolved]: #unresolved-questions |
| 86 | + |
| 87 | +Decide if this is enough. |
| 88 | + |
| 89 | +e.g. |
| 90 | +* Mutually recursive imports combined with `with` expressions also make static |
| 91 | + analysis harder, because they require lazyness at the level of scope lookups, |
| 92 | + which is difficult to implement corrently. e.g. [nix2js#2](https://github.com/YZITE/nix2js/issues/2) |
| 93 | +* Check if any use case is too much negatively impacted by this. |
| 94 | + |
| 95 | +# Future work |
| 96 | +[future]: #future-work |
| 97 | + |
| 98 | +* Static analyzers and transpilers for Nix |
0 commit comments